8
0

utils.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. /**
  2. * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
  4. */
  5. /**
  6. * @module font/fontsize/utils
  7. */
  8. import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
  9. /**
  10. * Normalizes and translates the {@link module:font/fontsize~FontSizeConfig#options configuration options}
  11. * to the {@link module:font/fontsize~FontSizeOption} format.
  12. *
  13. * @param {Array.<String|Number|Object>} configuredOptions An array of options taken from the configuration.
  14. * @returns {Array.<module:font/fontsize~FontSizeOption>}
  15. */
  16. export function normalizeOptions( configuredOptions ) {
  17. // Convert options to objects.
  18. return configuredOptions
  19. .map( item => getOptionDefinition( item ) )
  20. // Filter out undefined values that `getOptionDefinition` might return.
  21. .filter( option => !!option );
  22. }
  23. // Default named presets map. Always create a new instance of the preset object in order to avoid modifying references.
  24. const namedPresets = {
  25. get tiny() {
  26. return {
  27. title: 'Tiny',
  28. model: 'tiny',
  29. view: {
  30. name: 'span',
  31. classes: 'text-tiny',
  32. priority: 7
  33. }
  34. };
  35. },
  36. get small() {
  37. return {
  38. title: 'Small',
  39. model: 'small',
  40. view: {
  41. name: 'span',
  42. classes: 'text-small',
  43. priority: 7
  44. }
  45. };
  46. },
  47. get big() {
  48. return {
  49. title: 'Big',
  50. model: 'big',
  51. view: {
  52. name: 'span',
  53. classes: 'text-big',
  54. priority: 7
  55. }
  56. };
  57. },
  58. get huge() {
  59. return {
  60. title: 'Huge',
  61. model: 'huge',
  62. view: {
  63. name: 'span',
  64. classes: 'text-huge',
  65. priority: 7
  66. }
  67. };
  68. }
  69. };
  70. // Returns an option definition either from preset or creates one from number shortcut.
  71. // If object is passed then this method will return it without alternating it. Returns undefined for item than cannot be parsed.
  72. //
  73. // @param {String|Number|Object} item
  74. // @returns {undefined|module:font/fontsize~FontSizeOption}
  75. function getOptionDefinition( option ) {
  76. // Check whether passed option is a full item definition provided by user in configuration.
  77. if ( isFullItemDefinition( option ) ) {
  78. return attachPriority( option );
  79. }
  80. const preset = findPreset( option );
  81. // Item is a named preset.
  82. if ( preset ) {
  83. return attachPriority( preset );
  84. }
  85. // 'Default' font size. It will be used to remove the fontSize attribute.
  86. if ( option === 'default' ) {
  87. return {
  88. model: undefined,
  89. title: 'Default'
  90. };
  91. }
  92. // At this stage we probably have numerical value to generate a preset so parse it's value.
  93. // Discard any faulty values.
  94. if ( isNumericalDefinition( option ) ) {
  95. return;
  96. }
  97. // Return font size definition from size value.
  98. return generatePixelPreset( option );
  99. }
  100. // Creates a predefined preset for pixel size.
  101. //
  102. // @param {Number} definition Font size in pixels.
  103. // @returns {module:font/fontsize~FontSizeOption}
  104. function generatePixelPreset( definition ) {
  105. // Extend a short (numeric value) definition.
  106. if ( typeof definition === 'number' || typeof definition === 'string' ) {
  107. definition = {
  108. title: String( definition ),
  109. model: `${ parseFloat( definition ) }px`
  110. };
  111. }
  112. definition.view = {
  113. name: 'span',
  114. styles: {
  115. 'font-size': definition.model
  116. }
  117. };
  118. return attachPriority( definition );
  119. }
  120. // Adds the priority to the view element definition if missing. It's required due to ckeditor/ckeditor5#2291
  121. //
  122. // @param {Object} definition
  123. // @param {Object} definition.title
  124. // @param {Object} definition.model
  125. // @param {Object} definition.view
  126. // @returns {Object}
  127. function attachPriority( definition ) {
  128. if ( !definition.view.priority ) {
  129. definition.view.priority = 7;
  130. }
  131. return definition;
  132. }
  133. // Returns a prepared preset definition. If passed an object, a name of preset should be defined as `model` value.
  134. //
  135. // @param {String|Object} definition
  136. // @param {String} definition.model A preset name.
  137. // @returns {Object|undefined}
  138. function findPreset( definition ) {
  139. return namedPresets[ definition ] || namedPresets[ definition.model ];
  140. }
  141. // We treat `definition` as completed if it is an object that contains `title`, `model` and `view` values.
  142. //
  143. // @param {Object} definition
  144. // @param {String} definition.title
  145. // @param {String} definition.model
  146. // @param {Object} definition.view
  147. // @returns {Boolean}
  148. function isFullItemDefinition( definition ) {
  149. return typeof definition === 'object' && definition.title && definition.model && definition.view;
  150. }
  151. // We treat `definition` as numerical if it is a number, number-like (string) or an object with the `title` key.
  152. //
  153. // @param {Object|Number|String} definition
  154. // @param {Object} definition.title
  155. // @returns {Boolean}
  156. function isNumericalDefinition( definition ) {
  157. let numberValue;
  158. if ( typeof definition === 'object' ) {
  159. if ( !definition.model ) {
  160. /**
  161. * Provided value as an option for {@link module:font/fontsize~FontSize} seems to invalid.
  162. *
  163. * See valid examples described in the {@link module:font/fontsize~FontSizeConfig#options plugin configuration}.
  164. *
  165. * @error font-size-invalid-definition
  166. */
  167. throw new CKEditorError( 'font-size-invalid-definition', null, definition );
  168. } else {
  169. numberValue = parseFloat( definition.model );
  170. }
  171. } else {
  172. numberValue = parseFloat( definition );
  173. }
  174. return isNaN( numberValue );
  175. }