@ckeditor/ckeditor5-style 0.0.0-internal-20241017.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (286) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/LICENSE.md +17 -0
  3. package/README.md +26 -0
  4. package/build/style.js +5 -0
  5. package/build/translations/ar.js +1 -0
  6. package/build/translations/bg.js +1 -0
  7. package/build/translations/bn.js +1 -0
  8. package/build/translations/ca.js +1 -0
  9. package/build/translations/cs.js +1 -0
  10. package/build/translations/da.js +1 -0
  11. package/build/translations/de.js +1 -0
  12. package/build/translations/el.js +1 -0
  13. package/build/translations/en-au.js +1 -0
  14. package/build/translations/es.js +1 -0
  15. package/build/translations/et.js +1 -0
  16. package/build/translations/fi.js +1 -0
  17. package/build/translations/fr.js +1 -0
  18. package/build/translations/gl.js +1 -0
  19. package/build/translations/he.js +1 -0
  20. package/build/translations/hi.js +1 -0
  21. package/build/translations/hr.js +1 -0
  22. package/build/translations/hu.js +1 -0
  23. package/build/translations/id.js +1 -0
  24. package/build/translations/it.js +1 -0
  25. package/build/translations/ja.js +1 -0
  26. package/build/translations/ko.js +1 -0
  27. package/build/translations/lt.js +1 -0
  28. package/build/translations/lv.js +1 -0
  29. package/build/translations/ms.js +1 -0
  30. package/build/translations/nl.js +1 -0
  31. package/build/translations/no.js +1 -0
  32. package/build/translations/pl.js +1 -0
  33. package/build/translations/pt-br.js +1 -0
  34. package/build/translations/pt.js +1 -0
  35. package/build/translations/ro.js +1 -0
  36. package/build/translations/ru.js +1 -0
  37. package/build/translations/sk.js +1 -0
  38. package/build/translations/sr-latn.js +1 -0
  39. package/build/translations/sr.js +1 -0
  40. package/build/translations/sv.js +1 -0
  41. package/build/translations/th.js +1 -0
  42. package/build/translations/tr.js +1 -0
  43. package/build/translations/ug.js +1 -0
  44. package/build/translations/uk.js +1 -0
  45. package/build/translations/ur.js +1 -0
  46. package/build/translations/vi.js +1 -0
  47. package/build/translations/zh-cn.js +1 -0
  48. package/build/translations/zh.js +1 -0
  49. package/ckeditor5-metadata.json +28 -0
  50. package/dist/augmentation.d.ts +28 -0
  51. package/dist/index-content.css +4 -0
  52. package/dist/index-editor.css +28 -0
  53. package/dist/index.css +35 -0
  54. package/dist/index.css.map +1 -0
  55. package/dist/index.d.ts +18 -0
  56. package/dist/index.js +1336 -0
  57. package/dist/index.js.map +1 -0
  58. package/dist/integrations/link.d.ts +45 -0
  59. package/dist/integrations/list.d.ts +50 -0
  60. package/dist/integrations/table.d.ts +57 -0
  61. package/dist/style.d.ts +34 -0
  62. package/dist/stylecommand.d.ts +86 -0
  63. package/dist/styleconfig.d.ts +91 -0
  64. package/dist/styleediting.d.ts +41 -0
  65. package/dist/styleui.d.ts +38 -0
  66. package/dist/styleutils.d.ts +146 -0
  67. package/dist/translations/ar.d.ts +8 -0
  68. package/dist/translations/ar.js +5 -0
  69. package/dist/translations/ar.umd.js +11 -0
  70. package/dist/translations/bg.d.ts +8 -0
  71. package/dist/translations/bg.js +5 -0
  72. package/dist/translations/bg.umd.js +11 -0
  73. package/dist/translations/bn.d.ts +8 -0
  74. package/dist/translations/bn.js +5 -0
  75. package/dist/translations/bn.umd.js +11 -0
  76. package/dist/translations/ca.d.ts +8 -0
  77. package/dist/translations/ca.js +5 -0
  78. package/dist/translations/ca.umd.js +11 -0
  79. package/dist/translations/cs.d.ts +8 -0
  80. package/dist/translations/cs.js +5 -0
  81. package/dist/translations/cs.umd.js +11 -0
  82. package/dist/translations/da.d.ts +8 -0
  83. package/dist/translations/da.js +5 -0
  84. package/dist/translations/da.umd.js +11 -0
  85. package/dist/translations/de.d.ts +8 -0
  86. package/dist/translations/de.js +5 -0
  87. package/dist/translations/de.umd.js +11 -0
  88. package/dist/translations/el.d.ts +8 -0
  89. package/dist/translations/el.js +5 -0
  90. package/dist/translations/el.umd.js +11 -0
  91. package/dist/translations/en-au.d.ts +8 -0
  92. package/dist/translations/en-au.js +5 -0
  93. package/dist/translations/en-au.umd.js +11 -0
  94. package/dist/translations/en.d.ts +8 -0
  95. package/dist/translations/en.js +5 -0
  96. package/dist/translations/en.umd.js +11 -0
  97. package/dist/translations/es.d.ts +8 -0
  98. package/dist/translations/es.js +5 -0
  99. package/dist/translations/es.umd.js +11 -0
  100. package/dist/translations/et.d.ts +8 -0
  101. package/dist/translations/et.js +5 -0
  102. package/dist/translations/et.umd.js +11 -0
  103. package/dist/translations/fi.d.ts +8 -0
  104. package/dist/translations/fi.js +5 -0
  105. package/dist/translations/fi.umd.js +11 -0
  106. package/dist/translations/fr.d.ts +8 -0
  107. package/dist/translations/fr.js +5 -0
  108. package/dist/translations/fr.umd.js +11 -0
  109. package/dist/translations/gl.d.ts +8 -0
  110. package/dist/translations/gl.js +5 -0
  111. package/dist/translations/gl.umd.js +11 -0
  112. package/dist/translations/he.d.ts +8 -0
  113. package/dist/translations/he.js +5 -0
  114. package/dist/translations/he.umd.js +11 -0
  115. package/dist/translations/hi.d.ts +8 -0
  116. package/dist/translations/hi.js +5 -0
  117. package/dist/translations/hi.umd.js +11 -0
  118. package/dist/translations/hr.d.ts +8 -0
  119. package/dist/translations/hr.js +5 -0
  120. package/dist/translations/hr.umd.js +11 -0
  121. package/dist/translations/hu.d.ts +8 -0
  122. package/dist/translations/hu.js +5 -0
  123. package/dist/translations/hu.umd.js +11 -0
  124. package/dist/translations/id.d.ts +8 -0
  125. package/dist/translations/id.js +5 -0
  126. package/dist/translations/id.umd.js +11 -0
  127. package/dist/translations/it.d.ts +8 -0
  128. package/dist/translations/it.js +5 -0
  129. package/dist/translations/it.umd.js +11 -0
  130. package/dist/translations/ja.d.ts +8 -0
  131. package/dist/translations/ja.js +5 -0
  132. package/dist/translations/ja.umd.js +11 -0
  133. package/dist/translations/ko.d.ts +8 -0
  134. package/dist/translations/ko.js +5 -0
  135. package/dist/translations/ko.umd.js +11 -0
  136. package/dist/translations/lt.d.ts +8 -0
  137. package/dist/translations/lt.js +5 -0
  138. package/dist/translations/lt.umd.js +11 -0
  139. package/dist/translations/lv.d.ts +8 -0
  140. package/dist/translations/lv.js +5 -0
  141. package/dist/translations/lv.umd.js +11 -0
  142. package/dist/translations/ms.d.ts +8 -0
  143. package/dist/translations/ms.js +5 -0
  144. package/dist/translations/ms.umd.js +11 -0
  145. package/dist/translations/nl.d.ts +8 -0
  146. package/dist/translations/nl.js +5 -0
  147. package/dist/translations/nl.umd.js +11 -0
  148. package/dist/translations/no.d.ts +8 -0
  149. package/dist/translations/no.js +5 -0
  150. package/dist/translations/no.umd.js +11 -0
  151. package/dist/translations/pl.d.ts +8 -0
  152. package/dist/translations/pl.js +5 -0
  153. package/dist/translations/pl.umd.js +11 -0
  154. package/dist/translations/pt-br.d.ts +8 -0
  155. package/dist/translations/pt-br.js +5 -0
  156. package/dist/translations/pt-br.umd.js +11 -0
  157. package/dist/translations/pt.d.ts +8 -0
  158. package/dist/translations/pt.js +5 -0
  159. package/dist/translations/pt.umd.js +11 -0
  160. package/dist/translations/ro.d.ts +8 -0
  161. package/dist/translations/ro.js +5 -0
  162. package/dist/translations/ro.umd.js +11 -0
  163. package/dist/translations/ru.d.ts +8 -0
  164. package/dist/translations/ru.js +5 -0
  165. package/dist/translations/ru.umd.js +11 -0
  166. package/dist/translations/sk.d.ts +8 -0
  167. package/dist/translations/sk.js +5 -0
  168. package/dist/translations/sk.umd.js +11 -0
  169. package/dist/translations/sr-latn.d.ts +8 -0
  170. package/dist/translations/sr-latn.js +5 -0
  171. package/dist/translations/sr-latn.umd.js +11 -0
  172. package/dist/translations/sr.d.ts +8 -0
  173. package/dist/translations/sr.js +5 -0
  174. package/dist/translations/sr.umd.js +11 -0
  175. package/dist/translations/sv.d.ts +8 -0
  176. package/dist/translations/sv.js +5 -0
  177. package/dist/translations/sv.umd.js +11 -0
  178. package/dist/translations/th.d.ts +8 -0
  179. package/dist/translations/th.js +5 -0
  180. package/dist/translations/th.umd.js +11 -0
  181. package/dist/translations/tr.d.ts +8 -0
  182. package/dist/translations/tr.js +5 -0
  183. package/dist/translations/tr.umd.js +11 -0
  184. package/dist/translations/ug.d.ts +8 -0
  185. package/dist/translations/ug.js +5 -0
  186. package/dist/translations/ug.umd.js +11 -0
  187. package/dist/translations/uk.d.ts +8 -0
  188. package/dist/translations/uk.js +5 -0
  189. package/dist/translations/uk.umd.js +11 -0
  190. package/dist/translations/ur.d.ts +8 -0
  191. package/dist/translations/ur.js +5 -0
  192. package/dist/translations/ur.umd.js +11 -0
  193. package/dist/translations/vi.d.ts +8 -0
  194. package/dist/translations/vi.js +5 -0
  195. package/dist/translations/vi.umd.js +11 -0
  196. package/dist/translations/zh-cn.d.ts +8 -0
  197. package/dist/translations/zh-cn.js +5 -0
  198. package/dist/translations/zh-cn.umd.js +11 -0
  199. package/dist/translations/zh.d.ts +8 -0
  200. package/dist/translations/zh.js +5 -0
  201. package/dist/translations/zh.umd.js +11 -0
  202. package/dist/ui/stylegridbuttonview.d.ts +38 -0
  203. package/dist/ui/stylegridview.d.ts +76 -0
  204. package/dist/ui/stylegroupview.d.ts +39 -0
  205. package/dist/ui/stylepanelview.d.ts +93 -0
  206. package/lang/contexts.json +6 -0
  207. package/lang/translations/ar.po +34 -0
  208. package/lang/translations/bg.po +34 -0
  209. package/lang/translations/bn.po +34 -0
  210. package/lang/translations/ca.po +34 -0
  211. package/lang/translations/cs.po +34 -0
  212. package/lang/translations/da.po +34 -0
  213. package/lang/translations/de.po +34 -0
  214. package/lang/translations/el.po +34 -0
  215. package/lang/translations/en-au.po +34 -0
  216. package/lang/translations/en.po +34 -0
  217. package/lang/translations/es.po +34 -0
  218. package/lang/translations/et.po +34 -0
  219. package/lang/translations/fi.po +34 -0
  220. package/lang/translations/fr.po +34 -0
  221. package/lang/translations/gl.po +34 -0
  222. package/lang/translations/he.po +34 -0
  223. package/lang/translations/hi.po +34 -0
  224. package/lang/translations/hr.po +34 -0
  225. package/lang/translations/hu.po +34 -0
  226. package/lang/translations/id.po +34 -0
  227. package/lang/translations/it.po +34 -0
  228. package/lang/translations/ja.po +34 -0
  229. package/lang/translations/ko.po +34 -0
  230. package/lang/translations/lt.po +34 -0
  231. package/lang/translations/lv.po +34 -0
  232. package/lang/translations/ms.po +34 -0
  233. package/lang/translations/nl.po +34 -0
  234. package/lang/translations/no.po +34 -0
  235. package/lang/translations/pl.po +34 -0
  236. package/lang/translations/pt-br.po +34 -0
  237. package/lang/translations/pt.po +34 -0
  238. package/lang/translations/ro.po +34 -0
  239. package/lang/translations/ru.po +34 -0
  240. package/lang/translations/sk.po +34 -0
  241. package/lang/translations/sr-latn.po +34 -0
  242. package/lang/translations/sr.po +34 -0
  243. package/lang/translations/sv.po +34 -0
  244. package/lang/translations/th.po +34 -0
  245. package/lang/translations/tr.po +34 -0
  246. package/lang/translations/ug.po +34 -0
  247. package/lang/translations/uk.po +34 -0
  248. package/lang/translations/ur.po +34 -0
  249. package/lang/translations/vi.po +34 -0
  250. package/lang/translations/zh-cn.po +34 -0
  251. package/lang/translations/zh.po +34 -0
  252. package/package.json +43 -0
  253. package/src/augmentation.d.ts +24 -0
  254. package/src/augmentation.js +5 -0
  255. package/src/index.d.ts +14 -0
  256. package/src/index.js +12 -0
  257. package/src/integrations/link.d.ts +41 -0
  258. package/src/integrations/link.js +162 -0
  259. package/src/integrations/list.d.ts +46 -0
  260. package/src/integrations/list.js +148 -0
  261. package/src/integrations/table.d.ts +53 -0
  262. package/src/integrations/table.js +121 -0
  263. package/src/style.d.ts +30 -0
  264. package/src/style.js +36 -0
  265. package/src/stylecommand.d.ts +82 -0
  266. package/src/stylecommand.js +200 -0
  267. package/src/styleconfig.d.ts +87 -0
  268. package/src/styleconfig.js +5 -0
  269. package/src/styleediting.d.ts +37 -0
  270. package/src/styleediting.js +52 -0
  271. package/src/styleui.d.ts +34 -0
  272. package/src/styleui.js +100 -0
  273. package/src/styleutils.d.ts +142 -0
  274. package/src/styleutils.js +274 -0
  275. package/src/ui/stylegridbuttonview.d.ts +34 -0
  276. package/src/ui/stylegridbuttonview.js +55 -0
  277. package/src/ui/stylegridview.d.ts +72 -0
  278. package/src/ui/stylegridview.js +89 -0
  279. package/src/ui/stylegroupview.d.ts +35 -0
  280. package/src/ui/stylegroupview.js +45 -0
  281. package/src/ui/stylepanelview.d.ts +89 -0
  282. package/src/ui/stylepanelview.js +95 -0
  283. package/theme/style.css +4 -0
  284. package/theme/stylegrid.css +29 -0
  285. package/theme/stylegroup.css +4 -0
  286. package/theme/stylepanel.css +5 -0
@@ -0,0 +1,142 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module style/styleutils
7
+ */
8
+ import { Plugin, type Editor } from 'ckeditor5/src/core.js';
9
+ import type { Element, DocumentSelection, Selectable } from 'ckeditor5/src/engine.js';
10
+ import type { DecoratedMethodEvent } from 'ckeditor5/src/utils.js';
11
+ import type { TemplateDefinition } from 'ckeditor5/src/ui.js';
12
+ import type { DataSchema } from '@ckeditor/ckeditor5-html-support';
13
+ import type { StyleDefinition } from './styleconfig.js';
14
+ export default class StyleUtils extends Plugin {
15
+ private _htmlSupport;
16
+ /**
17
+ * @inheritDoc
18
+ */
19
+ static get pluginName(): "StyleUtils";
20
+ /**
21
+ * @inheritDoc
22
+ */
23
+ static get isOfficialPlugin(): true;
24
+ /**
25
+ * @inheritDoc
26
+ */
27
+ constructor(editor: Editor);
28
+ /**
29
+ * @inheritDoc
30
+ */
31
+ init(): void;
32
+ /**
33
+ * Normalizes {@link module:style/styleconfig~StyleConfig#definitions} in the configuration of the styles feature.
34
+ * The structure of normalized styles looks as follows:
35
+ *
36
+ * ```ts
37
+ * {
38
+ * block: [
39
+ * <module:style/style~StyleDefinition>,
40
+ * <module:style/style~StyleDefinition>,
41
+ * ...
42
+ * ],
43
+ * inline: [
44
+ * <module:style/style~StyleDefinition>,
45
+ * <module:style/style~StyleDefinition>,
46
+ * ...
47
+ * ]
48
+ * }
49
+ * ```
50
+ *
51
+ * @returns An object with normalized style definitions grouped into `block` and `inline` categories (arrays).
52
+ */
53
+ normalizeConfig(dataSchema: DataSchema, styleDefinitions?: Array<StyleDefinition>): NormalizedStyleDefinitions;
54
+ /**
55
+ * Verifies if the given style is applicable to the provided block element.
56
+ *
57
+ * @internal
58
+ */
59
+ isStyleEnabledForBlock(definition: BlockStyleDefinition, block: Element): boolean;
60
+ /**
61
+ * Returns true if the given style is applied to the specified block element.
62
+ *
63
+ * @internal
64
+ */
65
+ isStyleActiveForBlock(definition: BlockStyleDefinition, block: Element): boolean;
66
+ /**
67
+ * Returns an array of block elements that style should be applied to.
68
+ *
69
+ * @internal
70
+ */
71
+ getAffectedBlocks(definition: BlockStyleDefinition, block: Element): Array<Element> | null;
72
+ /**
73
+ * Verifies if the given style is applicable to the provided document selection.
74
+ *
75
+ * @internal
76
+ */
77
+ isStyleEnabledForInlineSelection(definition: InlineStyleDefinition, selection: DocumentSelection): boolean;
78
+ /**
79
+ * Returns true if the given style is applied to the specified document selection.
80
+ *
81
+ * @internal
82
+ */
83
+ isStyleActiveForInlineSelection(definition: InlineStyleDefinition, selection: DocumentSelection): boolean;
84
+ /**
85
+ * Returns a selectable that given style should be applied to.
86
+ *
87
+ * @internal
88
+ */
89
+ getAffectedInlineSelectable(definition: InlineStyleDefinition, selection: DocumentSelection): Selectable;
90
+ /**
91
+ * Returns the `TemplateDefinition` used by styles dropdown to render style preview.
92
+ *
93
+ * @internal
94
+ */
95
+ getStylePreview(definition: StyleDefinition, children: Iterable<TemplateDefinition>): TemplateDefinition;
96
+ /**
97
+ * Verifies if all classes are present in the given GHS attribute.
98
+ *
99
+ * @internal
100
+ */
101
+ hasAllClasses(ghsAttributeValue: unknown, classes: Array<string>): boolean;
102
+ /**
103
+ * This is where the styles feature configures the GHS feature. This method translates normalized
104
+ * {@link module:style/styleconfig~StyleDefinition style definitions} to
105
+ * {@link module:engine/view/matcher~MatcherObjectPattern matcher patterns} and feeds them to the GHS
106
+ * {@link module:html-support/datafilter~DataFilter} plugin.
107
+ *
108
+ * @internal
109
+ */
110
+ configureGHSDataFilter({ block, inline }: NormalizedStyleDefinitions): void;
111
+ /**
112
+ * Checks the attribute value of the first node in the selection that allows the attribute.
113
+ * For the collapsed selection, returns the selection attribute.
114
+ *
115
+ * @param selection The document selection.
116
+ * @param attributeName Name of the GHS attribute.
117
+ * @returns The attribute value.
118
+ */
119
+ private _getValueFromFirstAllowedNode;
120
+ }
121
+ export interface NormalizedStyleDefinitions {
122
+ block: Array<BlockStyleDefinition>;
123
+ inline: Array<InlineStyleDefinition>;
124
+ }
125
+ export interface BlockStyleDefinition extends StyleDefinition {
126
+ isBlock: true;
127
+ modelElements: Array<string>;
128
+ previewTemplate: TemplateDefinition;
129
+ }
130
+ export interface InlineStyleDefinition extends StyleDefinition {
131
+ ghsAttributes: Array<string>;
132
+ previewTemplate: TemplateDefinition;
133
+ }
134
+ export type NormalizedStyleDefinition = BlockStyleDefinition | InlineStyleDefinition;
135
+ export type StyleUtilsIsEnabledForBlockEvent = DecoratedMethodEvent<StyleUtils, 'isStyleEnabledForBlock'>;
136
+ export type StyleUtilsIsActiveForBlockEvent = DecoratedMethodEvent<StyleUtils, 'isStyleActiveForBlock'>;
137
+ export type StyleUtilsGetAffectedBlocksEvent = DecoratedMethodEvent<StyleUtils, 'getAffectedBlocks'>;
138
+ export type StyleUtilsIsStyleEnabledForInlineSelectionEvent = DecoratedMethodEvent<StyleUtils, 'isStyleEnabledForInlineSelection'>;
139
+ export type StyleUtilsIsStyleActiveForInlineSelectionEvent = DecoratedMethodEvent<StyleUtils, 'isStyleActiveForInlineSelection'>;
140
+ export type StyleUtilsGetAffectedInlineSelectableEvent = DecoratedMethodEvent<StyleUtils, 'getAffectedInlineSelectable'>;
141
+ export type StyleUtilsGetStylePreviewEvent = DecoratedMethodEvent<StyleUtils, 'getStylePreview'>;
142
+ export type StyleUtilsConfigureGHSDataFilterEvent = DecoratedMethodEvent<StyleUtils, 'configureGHSDataFilter'>;
@@ -0,0 +1,274 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module style/styleutils
7
+ */
8
+ import { Plugin } from 'ckeditor5/src/core.js';
9
+ import { isObject } from 'lodash-es';
10
+ // These are intermediate element names that can't be rendered as style preview because they don't make sense standalone.
11
+ const NON_PREVIEWABLE_ELEMENT_NAMES = [
12
+ 'caption', 'colgroup', 'dd', 'dt', 'figcaption', 'legend', 'li', 'optgroup', 'option', 'rp',
13
+ 'rt', 'summary', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr'
14
+ ];
15
+ export default class StyleUtils extends Plugin {
16
+ /**
17
+ * @inheritDoc
18
+ */
19
+ static get pluginName() {
20
+ return 'StyleUtils';
21
+ }
22
+ /**
23
+ * @inheritDoc
24
+ */
25
+ static get isOfficialPlugin() {
26
+ return true;
27
+ }
28
+ /**
29
+ * @inheritDoc
30
+ */
31
+ constructor(editor) {
32
+ super(editor);
33
+ this.decorate('isStyleEnabledForBlock');
34
+ this.decorate('isStyleActiveForBlock');
35
+ this.decorate('getAffectedBlocks');
36
+ this.decorate('isStyleEnabledForInlineSelection');
37
+ this.decorate('isStyleActiveForInlineSelection');
38
+ this.decorate('getAffectedInlineSelectable');
39
+ this.decorate('getStylePreview');
40
+ this.decorate('configureGHSDataFilter');
41
+ }
42
+ /**
43
+ * @inheritDoc
44
+ */
45
+ init() {
46
+ this._htmlSupport = this.editor.plugins.get('GeneralHtmlSupport');
47
+ }
48
+ /**
49
+ * Normalizes {@link module:style/styleconfig~StyleConfig#definitions} in the configuration of the styles feature.
50
+ * The structure of normalized styles looks as follows:
51
+ *
52
+ * ```ts
53
+ * {
54
+ * block: [
55
+ * <module:style/style~StyleDefinition>,
56
+ * <module:style/style~StyleDefinition>,
57
+ * ...
58
+ * ],
59
+ * inline: [
60
+ * <module:style/style~StyleDefinition>,
61
+ * <module:style/style~StyleDefinition>,
62
+ * ...
63
+ * ]
64
+ * }
65
+ * ```
66
+ *
67
+ * @returns An object with normalized style definitions grouped into `block` and `inline` categories (arrays).
68
+ */
69
+ normalizeConfig(dataSchema, styleDefinitions = []) {
70
+ const normalizedDefinitions = {
71
+ block: [],
72
+ inline: []
73
+ };
74
+ for (const definition of styleDefinitions) {
75
+ const modelElements = [];
76
+ const ghsAttributes = [];
77
+ for (const ghsDefinition of dataSchema.getDefinitionsForView(definition.element)) {
78
+ const appliesToBlock = 'appliesToBlock' in ghsDefinition ? ghsDefinition.appliesToBlock : false;
79
+ if (ghsDefinition.isBlock || appliesToBlock) {
80
+ if (typeof appliesToBlock == 'string') {
81
+ modelElements.push(appliesToBlock);
82
+ }
83
+ else if (ghsDefinition.isBlock) {
84
+ const ghsBlockDefinition = ghsDefinition;
85
+ modelElements.push(ghsDefinition.model);
86
+ if (ghsBlockDefinition.paragraphLikeModel) {
87
+ modelElements.push(ghsBlockDefinition.paragraphLikeModel);
88
+ }
89
+ }
90
+ }
91
+ else {
92
+ ghsAttributes.push(ghsDefinition.model);
93
+ }
94
+ }
95
+ const previewTemplate = this.getStylePreview(definition, [
96
+ { text: 'AaBbCcDdEeFfGgHhIiJj' }
97
+ ]);
98
+ if (modelElements.length) {
99
+ normalizedDefinitions.block.push({
100
+ ...definition,
101
+ previewTemplate,
102
+ modelElements,
103
+ isBlock: true
104
+ });
105
+ }
106
+ else {
107
+ normalizedDefinitions.inline.push({
108
+ ...definition,
109
+ previewTemplate,
110
+ ghsAttributes
111
+ });
112
+ }
113
+ }
114
+ return normalizedDefinitions;
115
+ }
116
+ /**
117
+ * Verifies if the given style is applicable to the provided block element.
118
+ *
119
+ * @internal
120
+ */
121
+ isStyleEnabledForBlock(definition, block) {
122
+ const model = this.editor.model;
123
+ const attributeName = this._htmlSupport.getGhsAttributeNameForElement(definition.element);
124
+ if (!model.schema.checkAttribute(block, attributeName)) {
125
+ return false;
126
+ }
127
+ return definition.modelElements.includes(block.name);
128
+ }
129
+ /**
130
+ * Returns true if the given style is applied to the specified block element.
131
+ *
132
+ * @internal
133
+ */
134
+ isStyleActiveForBlock(definition, block) {
135
+ const attributeName = this._htmlSupport.getGhsAttributeNameForElement(definition.element);
136
+ const ghsAttributeValue = block.getAttribute(attributeName);
137
+ return this.hasAllClasses(ghsAttributeValue, definition.classes);
138
+ }
139
+ /**
140
+ * Returns an array of block elements that style should be applied to.
141
+ *
142
+ * @internal
143
+ */
144
+ getAffectedBlocks(definition, block) {
145
+ if (definition.modelElements.includes(block.name)) {
146
+ return [block];
147
+ }
148
+ return null;
149
+ }
150
+ /**
151
+ * Verifies if the given style is applicable to the provided document selection.
152
+ *
153
+ * @internal
154
+ */
155
+ isStyleEnabledForInlineSelection(definition, selection) {
156
+ const model = this.editor.model;
157
+ for (const ghsAttributeName of definition.ghsAttributes) {
158
+ if (model.schema.checkAttributeInSelection(selection, ghsAttributeName)) {
159
+ return true;
160
+ }
161
+ }
162
+ return false;
163
+ }
164
+ /**
165
+ * Returns true if the given style is applied to the specified document selection.
166
+ *
167
+ * @internal
168
+ */
169
+ isStyleActiveForInlineSelection(definition, selection) {
170
+ for (const ghsAttributeName of definition.ghsAttributes) {
171
+ const ghsAttributeValue = this._getValueFromFirstAllowedNode(selection, ghsAttributeName);
172
+ if (this.hasAllClasses(ghsAttributeValue, definition.classes)) {
173
+ return true;
174
+ }
175
+ }
176
+ return false;
177
+ }
178
+ /**
179
+ * Returns a selectable that given style should be applied to.
180
+ *
181
+ * @internal
182
+ */
183
+ getAffectedInlineSelectable(definition, selection) {
184
+ return selection;
185
+ }
186
+ /**
187
+ * Returns the `TemplateDefinition` used by styles dropdown to render style preview.
188
+ *
189
+ * @internal
190
+ */
191
+ getStylePreview(definition, children) {
192
+ const { element, classes } = definition;
193
+ return {
194
+ tag: isPreviewable(element) ? element : 'div',
195
+ attributes: {
196
+ class: classes
197
+ },
198
+ children
199
+ };
200
+ }
201
+ /**
202
+ * Verifies if all classes are present in the given GHS attribute.
203
+ *
204
+ * @internal
205
+ */
206
+ hasAllClasses(ghsAttributeValue, classes) {
207
+ return isObject(ghsAttributeValue) &&
208
+ hasClassesProperty(ghsAttributeValue) &&
209
+ classes.every(className => ghsAttributeValue.classes.includes(className));
210
+ }
211
+ /**
212
+ * This is where the styles feature configures the GHS feature. This method translates normalized
213
+ * {@link module:style/styleconfig~StyleDefinition style definitions} to
214
+ * {@link module:engine/view/matcher~MatcherObjectPattern matcher patterns} and feeds them to the GHS
215
+ * {@link module:html-support/datafilter~DataFilter} plugin.
216
+ *
217
+ * @internal
218
+ */
219
+ configureGHSDataFilter({ block, inline }) {
220
+ const ghsDataFilter = this.editor.plugins.get('DataFilter');
221
+ ghsDataFilter.loadAllowedConfig(block.map(normalizedStyleDefinitionToMatcherPattern));
222
+ ghsDataFilter.loadAllowedConfig(inline.map(normalizedStyleDefinitionToMatcherPattern));
223
+ }
224
+ /**
225
+ * Checks the attribute value of the first node in the selection that allows the attribute.
226
+ * For the collapsed selection, returns the selection attribute.
227
+ *
228
+ * @param selection The document selection.
229
+ * @param attributeName Name of the GHS attribute.
230
+ * @returns The attribute value.
231
+ */
232
+ _getValueFromFirstAllowedNode(selection, attributeName) {
233
+ const model = this.editor.model;
234
+ const schema = model.schema;
235
+ if (selection.isCollapsed) {
236
+ return selection.getAttribute(attributeName);
237
+ }
238
+ for (const range of selection.getRanges()) {
239
+ for (const item of range.getItems()) {
240
+ if (schema.checkAttribute(item, attributeName)) {
241
+ return item.getAttribute(attributeName);
242
+ }
243
+ }
244
+ }
245
+ return null;
246
+ }
247
+ }
248
+ /**
249
+ * Checks if given object has `classes` property which is an array.
250
+ *
251
+ * @param obj Object to check.
252
+ */
253
+ function hasClassesProperty(obj) {
254
+ return Boolean(obj.classes) && Array.isArray(obj.classes);
255
+ }
256
+ /**
257
+ * Decides whether an element should be created in the preview or a substitute `<div>` should
258
+ * be used instead. This avoids previewing a standalone `<td>`, `<li>`, etc. without a parent.
259
+ *
260
+ * @param elementName Name of the element
261
+ * @returns Boolean indicating whether the element can be rendered.
262
+ */
263
+ function isPreviewable(elementName) {
264
+ return !NON_PREVIEWABLE_ELEMENT_NAMES.includes(elementName);
265
+ }
266
+ /**
267
+ * Translates a normalized style definition to a view matcher pattern.
268
+ */
269
+ function normalizedStyleDefinitionToMatcherPattern({ element, classes }) {
270
+ return {
271
+ name: element,
272
+ classes
273
+ };
274
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module style/ui/stylegridbuttonview
7
+ */
8
+ import type { Locale } from 'ckeditor5/src/utils.js';
9
+ import { ButtonView, View } from 'ckeditor5/src/ui.js';
10
+ import type { NormalizedStyleDefinition } from '../styleutils.js';
11
+ /**
12
+ * A class representing an individual button (style) in the grid. Renders a rich preview of the style.
13
+ */
14
+ export default class StyleGridButtonView extends ButtonView {
15
+ /**
16
+ * Definition of the style the button will apply when executed.
17
+ */
18
+ readonly styleDefinition: NormalizedStyleDefinition;
19
+ /**
20
+ * The view rendering the preview of the style.
21
+ */
22
+ readonly previewView: View;
23
+ /**
24
+ * Creates an instance of the {@link module:style/ui/stylegridbuttonview~StyleGridButtonView} class.
25
+ *
26
+ * @param locale The localization services instance.
27
+ * @param styleDefinition Definition of the style.
28
+ */
29
+ constructor(locale: Locale, styleDefinition: NormalizedStyleDefinition);
30
+ /**
31
+ * Creates the view representing the preview of the style.
32
+ */
33
+ private _createPreview;
34
+ }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ import { ButtonView, View } from 'ckeditor5/src/ui.js';
6
+ /**
7
+ * A class representing an individual button (style) in the grid. Renders a rich preview of the style.
8
+ */
9
+ export default class StyleGridButtonView extends ButtonView {
10
+ /**
11
+ * Creates an instance of the {@link module:style/ui/stylegridbuttonview~StyleGridButtonView} class.
12
+ *
13
+ * @param locale The localization services instance.
14
+ * @param styleDefinition Definition of the style.
15
+ */
16
+ constructor(locale, styleDefinition) {
17
+ super(locale);
18
+ this.styleDefinition = styleDefinition;
19
+ this.previewView = this._createPreview();
20
+ this.set({
21
+ label: styleDefinition.name,
22
+ class: 'ck-style-grid__button',
23
+ withText: true
24
+ });
25
+ this.extendTemplate({
26
+ attributes: {
27
+ role: 'option'
28
+ }
29
+ });
30
+ this.children.add(this.previewView, 0);
31
+ }
32
+ /**
33
+ * Creates the view representing the preview of the style.
34
+ */
35
+ _createPreview() {
36
+ const previewView = new View(this.locale);
37
+ previewView.setTemplate({
38
+ tag: 'div',
39
+ attributes: {
40
+ class: [
41
+ 'ck',
42
+ 'ck-reset_all-excluded',
43
+ 'ck-style-grid__button__preview',
44
+ 'ck-content'
45
+ ],
46
+ // The preview "AaBbCcDdEeFfGgHhIiJj" should not be read by screen readers because it is purely presentational.
47
+ 'aria-hidden': 'true'
48
+ },
49
+ children: [
50
+ this.styleDefinition.previewTemplate
51
+ ]
52
+ });
53
+ return previewView;
54
+ }
55
+ }
@@ -0,0 +1,72 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module style/ui/stylegridview
7
+ */
8
+ import { View, type ViewCollection, type FocusableView } from 'ckeditor5/src/ui.js';
9
+ import { FocusTracker, KeystrokeHandler, type Locale } from 'ckeditor5/src/utils.js';
10
+ import StyleGridButtonView from './stylegridbuttonview.js';
11
+ import type { NormalizedStyleDefinition } from '../styleutils.js';
12
+ import '../../theme/stylegrid.css';
13
+ /**
14
+ * A class representing a grid of styles ({@link module:style/ui/stylegridbuttonview~StyleGridButtonView buttons}).
15
+ * Allows users to select a style.
16
+ */
17
+ export default class StyleGridView extends View<HTMLDivElement> implements FocusableView {
18
+ /**
19
+ * Tracks information about the DOM focus in the view.
20
+ */
21
+ readonly focusTracker: FocusTracker;
22
+ /**
23
+ * An instance of the {@link module:utils/keystrokehandler~KeystrokeHandler}.
24
+ */
25
+ readonly keystrokes: KeystrokeHandler;
26
+ /**
27
+ * A collection of style {@link module:style/ui/stylegridbuttonview~StyleGridButtonView buttons}.
28
+ */
29
+ readonly children: ViewCollection<StyleGridButtonView>;
30
+ /**
31
+ * Array of active style names. They must correspond to the names of styles from
32
+ * definitions passed to the {@link #constructor}.
33
+ *
34
+ * @observable
35
+ */
36
+ readonly activeStyles: Array<string>;
37
+ /**
38
+ * Array of enabled style names. They must correspond to the names of styles from
39
+ * definitions passed to the {@link #constructor}.
40
+ *
41
+ * @observable
42
+ */
43
+ readonly enabledStyles: Array<string>;
44
+ /**
45
+ * Creates an instance of the {@link module:style/ui/stylegridview~StyleGridView} class.
46
+ *
47
+ * @param locale The localization services instance.
48
+ * @param styleDefinitions Definitions of the styles.
49
+ */
50
+ constructor(locale: Locale, styleDefinitions: Array<NormalizedStyleDefinition>);
51
+ /**
52
+ * @inheritDoc
53
+ */
54
+ render(): void;
55
+ /**
56
+ * Focuses the first style button in the grid.
57
+ */
58
+ focus(): void;
59
+ /**
60
+ * @inheritDoc
61
+ */
62
+ destroy(): void;
63
+ }
64
+ /**
65
+ * Fired when a {@link module:style/ui/stylegridbuttonview~StyleGridButtonView style} was selected (clicked) by the user.
66
+ *
67
+ * @eventName ~StyleGridView#execute
68
+ */
69
+ export type StyleGridViewExecuteEvent = {
70
+ name: 'execute';
71
+ args: [];
72
+ };
@@ -0,0 +1,89 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module style/ui/stylegridview
7
+ */
8
+ import { View, addKeyboardHandlingForGrid } from 'ckeditor5/src/ui.js';
9
+ import { FocusTracker, KeystrokeHandler } from 'ckeditor5/src/utils.js';
10
+ import StyleGridButtonView from './stylegridbuttonview.js';
11
+ import '../../theme/stylegrid.css';
12
+ /**
13
+ * A class representing a grid of styles ({@link module:style/ui/stylegridbuttonview~StyleGridButtonView buttons}).
14
+ * Allows users to select a style.
15
+ */
16
+ export default class StyleGridView extends View {
17
+ /**
18
+ * Creates an instance of the {@link module:style/ui/stylegridview~StyleGridView} class.
19
+ *
20
+ * @param locale The localization services instance.
21
+ * @param styleDefinitions Definitions of the styles.
22
+ */
23
+ constructor(locale, styleDefinitions) {
24
+ super(locale);
25
+ this.focusTracker = new FocusTracker();
26
+ this.keystrokes = new KeystrokeHandler();
27
+ this.set('activeStyles', []);
28
+ this.set('enabledStyles', []);
29
+ this.children = this.createCollection();
30
+ this.children.delegate('execute').to(this);
31
+ for (const definition of styleDefinitions) {
32
+ const gridTileView = new StyleGridButtonView(locale, definition);
33
+ this.children.add(gridTileView);
34
+ }
35
+ this.on('change:activeStyles', () => {
36
+ for (const child of this.children) {
37
+ child.isOn = this.activeStyles.includes(child.styleDefinition.name);
38
+ }
39
+ });
40
+ this.on('change:enabledStyles', () => {
41
+ for (const child of this.children) {
42
+ child.isEnabled = this.enabledStyles.includes(child.styleDefinition.name);
43
+ }
44
+ });
45
+ this.setTemplate({
46
+ tag: 'div',
47
+ attributes: {
48
+ class: [
49
+ 'ck',
50
+ 'ck-style-grid'
51
+ ],
52
+ role: 'listbox'
53
+ },
54
+ children: this.children
55
+ });
56
+ }
57
+ /**
58
+ * @inheritDoc
59
+ */
60
+ render() {
61
+ super.render();
62
+ for (const child of this.children) {
63
+ this.focusTracker.add(child.element);
64
+ }
65
+ addKeyboardHandlingForGrid({
66
+ keystrokeHandler: this.keystrokes,
67
+ focusTracker: this.focusTracker,
68
+ gridItems: this.children,
69
+ numberOfColumns: 3,
70
+ uiLanguageDirection: this.locale && this.locale.uiLanguageDirection
71
+ });
72
+ // Start listening for the keystrokes coming from the grid view.
73
+ this.keystrokes.listenTo(this.element);
74
+ }
75
+ /**
76
+ * Focuses the first style button in the grid.
77
+ */
78
+ focus() {
79
+ this.children.first.focus();
80
+ }
81
+ /**
82
+ * @inheritDoc
83
+ */
84
+ destroy() {
85
+ super.destroy();
86
+ this.focusTracker.destroy();
87
+ this.keystrokes.destroy();
88
+ }
89
+ }