@ckeditor/ckeditor5-font 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 (387) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/LICENSE.md +23 -0
  3. package/README.md +31 -0
  4. package/build/font.js +5 -0
  5. package/build/translations/ar.js +1 -0
  6. package/build/translations/az.js +1 -0
  7. package/build/translations/bg.js +1 -0
  8. package/build/translations/bn.js +1 -0
  9. package/build/translations/bs.js +1 -0
  10. package/build/translations/ca.js +1 -0
  11. package/build/translations/cs.js +1 -0
  12. package/build/translations/da.js +1 -0
  13. package/build/translations/de-ch.js +1 -0
  14. package/build/translations/de.js +1 -0
  15. package/build/translations/el.js +1 -0
  16. package/build/translations/en-au.js +1 -0
  17. package/build/translations/en-gb.js +1 -0
  18. package/build/translations/es-co.js +1 -0
  19. package/build/translations/es.js +1 -0
  20. package/build/translations/et.js +1 -0
  21. package/build/translations/fa.js +1 -0
  22. package/build/translations/fi.js +1 -0
  23. package/build/translations/fr.js +1 -0
  24. package/build/translations/gl.js +1 -0
  25. package/build/translations/he.js +1 -0
  26. package/build/translations/hi.js +1 -0
  27. package/build/translations/hr.js +1 -0
  28. package/build/translations/hu.js +1 -0
  29. package/build/translations/id.js +1 -0
  30. package/build/translations/it.js +1 -0
  31. package/build/translations/ja.js +1 -0
  32. package/build/translations/jv.js +1 -0
  33. package/build/translations/ko.js +1 -0
  34. package/build/translations/ku.js +1 -0
  35. package/build/translations/lt.js +1 -0
  36. package/build/translations/lv.js +1 -0
  37. package/build/translations/ms.js +1 -0
  38. package/build/translations/nb.js +1 -0
  39. package/build/translations/ne.js +1 -0
  40. package/build/translations/nl.js +1 -0
  41. package/build/translations/no.js +1 -0
  42. package/build/translations/pl.js +1 -0
  43. package/build/translations/pt-br.js +1 -0
  44. package/build/translations/pt.js +1 -0
  45. package/build/translations/ro.js +1 -0
  46. package/build/translations/ru.js +1 -0
  47. package/build/translations/sk.js +1 -0
  48. package/build/translations/sl.js +1 -0
  49. package/build/translations/sq.js +1 -0
  50. package/build/translations/sr-latn.js +1 -0
  51. package/build/translations/sr.js +1 -0
  52. package/build/translations/sv.js +1 -0
  53. package/build/translations/th.js +1 -0
  54. package/build/translations/tk.js +1 -0
  55. package/build/translations/tr.js +1 -0
  56. package/build/translations/ug.js +1 -0
  57. package/build/translations/uk.js +1 -0
  58. package/build/translations/ur.js +1 -0
  59. package/build/translations/uz.js +1 -0
  60. package/build/translations/vi.js +1 -0
  61. package/build/translations/zh-cn.js +1 -0
  62. package/build/translations/zh.js +1 -0
  63. package/ckeditor5-metadata.json +111 -0
  64. package/dist/augmentation.d.ts +62 -0
  65. package/dist/font.d.ts +41 -0
  66. package/dist/fontbackgroundcolor/fontbackgroundcolorcommand.d.ts +30 -0
  67. package/dist/fontbackgroundcolor/fontbackgroundcolorediting.d.ts +34 -0
  68. package/dist/fontbackgroundcolor/fontbackgroundcolorui.d.ts +26 -0
  69. package/dist/fontbackgroundcolor.d.ts +38 -0
  70. package/dist/fontcolor/fontcolorcommand.d.ts +29 -0
  71. package/dist/fontcolor/fontcolorediting.d.ts +34 -0
  72. package/dist/fontcolor/fontcolorui.d.ts +26 -0
  73. package/dist/fontcolor.d.ts +37 -0
  74. package/dist/fontcommand.d.ts +52 -0
  75. package/dist/fontconfig.d.ts +377 -0
  76. package/dist/fontfamily/fontfamilycommand.d.ts +29 -0
  77. package/dist/fontfamily/fontfamilyediting.d.ts +47 -0
  78. package/dist/fontfamily/fontfamilyui.d.ts +38 -0
  79. package/dist/fontfamily/utils.d.ts +19 -0
  80. package/dist/fontfamily.d.ts +37 -0
  81. package/dist/fontsize/fontsizecommand.d.ts +29 -0
  82. package/dist/fontsize/fontsizeediting.d.ts +52 -0
  83. package/dist/fontsize/fontsizeui.d.ts +39 -0
  84. package/dist/fontsize/utils.d.ts +16 -0
  85. package/dist/fontsize.d.ts +45 -0
  86. package/dist/index-content.css +16 -0
  87. package/dist/index-editor.css +4 -0
  88. package/dist/index.css +27 -0
  89. package/dist/index.css.map +1 -0
  90. package/dist/index.d.ts +31 -0
  91. package/dist/index.js +1634 -0
  92. package/dist/index.js.map +1 -0
  93. package/dist/translations/ar.d.ts +8 -0
  94. package/dist/translations/ar.js +5 -0
  95. package/dist/translations/ar.umd.js +11 -0
  96. package/dist/translations/az.d.ts +8 -0
  97. package/dist/translations/az.js +5 -0
  98. package/dist/translations/az.umd.js +11 -0
  99. package/dist/translations/bg.d.ts +8 -0
  100. package/dist/translations/bg.js +5 -0
  101. package/dist/translations/bg.umd.js +11 -0
  102. package/dist/translations/bn.d.ts +8 -0
  103. package/dist/translations/bn.js +5 -0
  104. package/dist/translations/bn.umd.js +11 -0
  105. package/dist/translations/bs.d.ts +8 -0
  106. package/dist/translations/bs.js +5 -0
  107. package/dist/translations/bs.umd.js +11 -0
  108. package/dist/translations/ca.d.ts +8 -0
  109. package/dist/translations/ca.js +5 -0
  110. package/dist/translations/ca.umd.js +11 -0
  111. package/dist/translations/cs.d.ts +8 -0
  112. package/dist/translations/cs.js +5 -0
  113. package/dist/translations/cs.umd.js +11 -0
  114. package/dist/translations/da.d.ts +8 -0
  115. package/dist/translations/da.js +5 -0
  116. package/dist/translations/da.umd.js +11 -0
  117. package/dist/translations/de-ch.d.ts +8 -0
  118. package/dist/translations/de-ch.js +5 -0
  119. package/dist/translations/de-ch.umd.js +11 -0
  120. package/dist/translations/de.d.ts +8 -0
  121. package/dist/translations/de.js +5 -0
  122. package/dist/translations/de.umd.js +11 -0
  123. package/dist/translations/el.d.ts +8 -0
  124. package/dist/translations/el.js +5 -0
  125. package/dist/translations/el.umd.js +11 -0
  126. package/dist/translations/en-au.d.ts +8 -0
  127. package/dist/translations/en-au.js +5 -0
  128. package/dist/translations/en-au.umd.js +11 -0
  129. package/dist/translations/en-gb.d.ts +8 -0
  130. package/dist/translations/en-gb.js +5 -0
  131. package/dist/translations/en-gb.umd.js +11 -0
  132. package/dist/translations/en.d.ts +8 -0
  133. package/dist/translations/en.js +5 -0
  134. package/dist/translations/en.umd.js +11 -0
  135. package/dist/translations/es-co.d.ts +8 -0
  136. package/dist/translations/es-co.js +5 -0
  137. package/dist/translations/es-co.umd.js +11 -0
  138. package/dist/translations/es.d.ts +8 -0
  139. package/dist/translations/es.js +5 -0
  140. package/dist/translations/es.umd.js +11 -0
  141. package/dist/translations/et.d.ts +8 -0
  142. package/dist/translations/et.js +5 -0
  143. package/dist/translations/et.umd.js +11 -0
  144. package/dist/translations/fa.d.ts +8 -0
  145. package/dist/translations/fa.js +5 -0
  146. package/dist/translations/fa.umd.js +11 -0
  147. package/dist/translations/fi.d.ts +8 -0
  148. package/dist/translations/fi.js +5 -0
  149. package/dist/translations/fi.umd.js +11 -0
  150. package/dist/translations/fr.d.ts +8 -0
  151. package/dist/translations/fr.js +5 -0
  152. package/dist/translations/fr.umd.js +11 -0
  153. package/dist/translations/gl.d.ts +8 -0
  154. package/dist/translations/gl.js +5 -0
  155. package/dist/translations/gl.umd.js +11 -0
  156. package/dist/translations/he.d.ts +8 -0
  157. package/dist/translations/he.js +5 -0
  158. package/dist/translations/he.umd.js +11 -0
  159. package/dist/translations/hi.d.ts +8 -0
  160. package/dist/translations/hi.js +5 -0
  161. package/dist/translations/hi.umd.js +11 -0
  162. package/dist/translations/hr.d.ts +8 -0
  163. package/dist/translations/hr.js +5 -0
  164. package/dist/translations/hr.umd.js +11 -0
  165. package/dist/translations/hu.d.ts +8 -0
  166. package/dist/translations/hu.js +5 -0
  167. package/dist/translations/hu.umd.js +11 -0
  168. package/dist/translations/id.d.ts +8 -0
  169. package/dist/translations/id.js +5 -0
  170. package/dist/translations/id.umd.js +11 -0
  171. package/dist/translations/it.d.ts +8 -0
  172. package/dist/translations/it.js +5 -0
  173. package/dist/translations/it.umd.js +11 -0
  174. package/dist/translations/ja.d.ts +8 -0
  175. package/dist/translations/ja.js +5 -0
  176. package/dist/translations/ja.umd.js +11 -0
  177. package/dist/translations/jv.d.ts +8 -0
  178. package/dist/translations/jv.js +5 -0
  179. package/dist/translations/jv.umd.js +11 -0
  180. package/dist/translations/ko.d.ts +8 -0
  181. package/dist/translations/ko.js +5 -0
  182. package/dist/translations/ko.umd.js +11 -0
  183. package/dist/translations/ku.d.ts +8 -0
  184. package/dist/translations/ku.js +5 -0
  185. package/dist/translations/ku.umd.js +11 -0
  186. package/dist/translations/lt.d.ts +8 -0
  187. package/dist/translations/lt.js +5 -0
  188. package/dist/translations/lt.umd.js +11 -0
  189. package/dist/translations/lv.d.ts +8 -0
  190. package/dist/translations/lv.js +5 -0
  191. package/dist/translations/lv.umd.js +11 -0
  192. package/dist/translations/ms.d.ts +8 -0
  193. package/dist/translations/ms.js +5 -0
  194. package/dist/translations/ms.umd.js +11 -0
  195. package/dist/translations/nb.d.ts +8 -0
  196. package/dist/translations/nb.js +5 -0
  197. package/dist/translations/nb.umd.js +11 -0
  198. package/dist/translations/ne.d.ts +8 -0
  199. package/dist/translations/ne.js +5 -0
  200. package/dist/translations/ne.umd.js +11 -0
  201. package/dist/translations/nl.d.ts +8 -0
  202. package/dist/translations/nl.js +5 -0
  203. package/dist/translations/nl.umd.js +11 -0
  204. package/dist/translations/no.d.ts +8 -0
  205. package/dist/translations/no.js +5 -0
  206. package/dist/translations/no.umd.js +11 -0
  207. package/dist/translations/pl.d.ts +8 -0
  208. package/dist/translations/pl.js +5 -0
  209. package/dist/translations/pl.umd.js +11 -0
  210. package/dist/translations/pt-br.d.ts +8 -0
  211. package/dist/translations/pt-br.js +5 -0
  212. package/dist/translations/pt-br.umd.js +11 -0
  213. package/dist/translations/pt.d.ts +8 -0
  214. package/dist/translations/pt.js +5 -0
  215. package/dist/translations/pt.umd.js +11 -0
  216. package/dist/translations/ro.d.ts +8 -0
  217. package/dist/translations/ro.js +5 -0
  218. package/dist/translations/ro.umd.js +11 -0
  219. package/dist/translations/ru.d.ts +8 -0
  220. package/dist/translations/ru.js +5 -0
  221. package/dist/translations/ru.umd.js +11 -0
  222. package/dist/translations/sk.d.ts +8 -0
  223. package/dist/translations/sk.js +5 -0
  224. package/dist/translations/sk.umd.js +11 -0
  225. package/dist/translations/sl.d.ts +8 -0
  226. package/dist/translations/sl.js +5 -0
  227. package/dist/translations/sl.umd.js +11 -0
  228. package/dist/translations/sq.d.ts +8 -0
  229. package/dist/translations/sq.js +5 -0
  230. package/dist/translations/sq.umd.js +11 -0
  231. package/dist/translations/sr-latn.d.ts +8 -0
  232. package/dist/translations/sr-latn.js +5 -0
  233. package/dist/translations/sr-latn.umd.js +11 -0
  234. package/dist/translations/sr.d.ts +8 -0
  235. package/dist/translations/sr.js +5 -0
  236. package/dist/translations/sr.umd.js +11 -0
  237. package/dist/translations/sv.d.ts +8 -0
  238. package/dist/translations/sv.js +5 -0
  239. package/dist/translations/sv.umd.js +11 -0
  240. package/dist/translations/th.d.ts +8 -0
  241. package/dist/translations/th.js +5 -0
  242. package/dist/translations/th.umd.js +11 -0
  243. package/dist/translations/tk.d.ts +8 -0
  244. package/dist/translations/tk.js +5 -0
  245. package/dist/translations/tk.umd.js +11 -0
  246. package/dist/translations/tr.d.ts +8 -0
  247. package/dist/translations/tr.js +5 -0
  248. package/dist/translations/tr.umd.js +11 -0
  249. package/dist/translations/ug.d.ts +8 -0
  250. package/dist/translations/ug.js +5 -0
  251. package/dist/translations/ug.umd.js +11 -0
  252. package/dist/translations/uk.d.ts +8 -0
  253. package/dist/translations/uk.js +5 -0
  254. package/dist/translations/uk.umd.js +11 -0
  255. package/dist/translations/ur.d.ts +8 -0
  256. package/dist/translations/ur.js +5 -0
  257. package/dist/translations/ur.umd.js +11 -0
  258. package/dist/translations/uz.d.ts +8 -0
  259. package/dist/translations/uz.js +5 -0
  260. package/dist/translations/uz.umd.js +11 -0
  261. package/dist/translations/vi.d.ts +8 -0
  262. package/dist/translations/vi.js +5 -0
  263. package/dist/translations/vi.umd.js +11 -0
  264. package/dist/translations/zh-cn.d.ts +8 -0
  265. package/dist/translations/zh-cn.js +5 -0
  266. package/dist/translations/zh-cn.umd.js +11 -0
  267. package/dist/translations/zh.d.ts +8 -0
  268. package/dist/translations/zh.js +5 -0
  269. package/dist/translations/zh.umd.js +11 -0
  270. package/dist/ui/colorui.d.ts +67 -0
  271. package/dist/utils.d.ts +84 -0
  272. package/lang/contexts.json +12 -0
  273. package/lang/translations/ar.po +58 -0
  274. package/lang/translations/az.po +58 -0
  275. package/lang/translations/bg.po +58 -0
  276. package/lang/translations/bn.po +58 -0
  277. package/lang/translations/bs.po +58 -0
  278. package/lang/translations/ca.po +58 -0
  279. package/lang/translations/cs.po +58 -0
  280. package/lang/translations/da.po +58 -0
  281. package/lang/translations/de-ch.po +58 -0
  282. package/lang/translations/de.po +58 -0
  283. package/lang/translations/el.po +58 -0
  284. package/lang/translations/en-au.po +58 -0
  285. package/lang/translations/en-gb.po +58 -0
  286. package/lang/translations/en.po +58 -0
  287. package/lang/translations/es-co.po +58 -0
  288. package/lang/translations/es.po +58 -0
  289. package/lang/translations/et.po +58 -0
  290. package/lang/translations/fa.po +58 -0
  291. package/lang/translations/fi.po +58 -0
  292. package/lang/translations/fr.po +58 -0
  293. package/lang/translations/gl.po +58 -0
  294. package/lang/translations/he.po +58 -0
  295. package/lang/translations/hi.po +58 -0
  296. package/lang/translations/hr.po +58 -0
  297. package/lang/translations/hu.po +58 -0
  298. package/lang/translations/id.po +58 -0
  299. package/lang/translations/it.po +58 -0
  300. package/lang/translations/ja.po +58 -0
  301. package/lang/translations/jv.po +58 -0
  302. package/lang/translations/ko.po +58 -0
  303. package/lang/translations/ku.po +58 -0
  304. package/lang/translations/lt.po +58 -0
  305. package/lang/translations/lv.po +58 -0
  306. package/lang/translations/ms.po +58 -0
  307. package/lang/translations/nb.po +58 -0
  308. package/lang/translations/ne.po +58 -0
  309. package/lang/translations/nl.po +58 -0
  310. package/lang/translations/no.po +58 -0
  311. package/lang/translations/pl.po +58 -0
  312. package/lang/translations/pt-br.po +58 -0
  313. package/lang/translations/pt.po +58 -0
  314. package/lang/translations/ro.po +58 -0
  315. package/lang/translations/ru.po +58 -0
  316. package/lang/translations/sk.po +58 -0
  317. package/lang/translations/sl.po +58 -0
  318. package/lang/translations/sq.po +58 -0
  319. package/lang/translations/sr-latn.po +58 -0
  320. package/lang/translations/sr.po +58 -0
  321. package/lang/translations/sv.po +58 -0
  322. package/lang/translations/th.po +58 -0
  323. package/lang/translations/tk.po +58 -0
  324. package/lang/translations/tr.po +58 -0
  325. package/lang/translations/ug.po +58 -0
  326. package/lang/translations/uk.po +58 -0
  327. package/lang/translations/ur.po +58 -0
  328. package/lang/translations/uz.po +58 -0
  329. package/lang/translations/vi.po +58 -0
  330. package/lang/translations/zh-cn.po +58 -0
  331. package/lang/translations/zh.po +58 -0
  332. package/package.json +42 -0
  333. package/src/augmentation.d.ts +58 -0
  334. package/src/augmentation.js +5 -0
  335. package/src/font.d.ts +37 -0
  336. package/src/font.js +43 -0
  337. package/src/fontbackgroundcolor/fontbackgroundcolorcommand.d.ts +26 -0
  338. package/src/fontbackgroundcolor/fontbackgroundcolorcommand.js +25 -0
  339. package/src/fontbackgroundcolor/fontbackgroundcolorediting.d.ts +30 -0
  340. package/src/fontbackgroundcolor/fontbackgroundcolorediting.js +129 -0
  341. package/src/fontbackgroundcolor/fontbackgroundcolorui.d.ts +22 -0
  342. package/src/fontbackgroundcolor/fontbackgroundcolorui.js +33 -0
  343. package/src/fontbackgroundcolor.d.ts +34 -0
  344. package/src/fontbackgroundcolor.js +40 -0
  345. package/src/fontcolor/fontcolorcommand.d.ts +25 -0
  346. package/src/fontcolor/fontcolorcommand.js +24 -0
  347. package/src/fontcolor/fontcolorediting.d.ts +30 -0
  348. package/src/fontcolor/fontcolorediting.js +140 -0
  349. package/src/fontcolor/fontcolorui.d.ts +22 -0
  350. package/src/fontcolor/fontcolorui.js +33 -0
  351. package/src/fontcolor.d.ts +33 -0
  352. package/src/fontcolor.js +39 -0
  353. package/src/fontcommand.d.ts +48 -0
  354. package/src/fontcommand.js +79 -0
  355. package/src/fontconfig.d.ts +373 -0
  356. package/src/fontconfig.js +5 -0
  357. package/src/fontfamily/fontfamilycommand.d.ts +25 -0
  358. package/src/fontfamily/fontfamilycommand.js +24 -0
  359. package/src/fontfamily/fontfamilyediting.d.ts +43 -0
  360. package/src/fontfamily/fontfamilyediting.js +121 -0
  361. package/src/fontfamily/fontfamilyui.d.ts +34 -0
  362. package/src/fontfamily/fontfamilyui.js +150 -0
  363. package/src/fontfamily/utils.d.ts +15 -0
  364. package/src/fontfamily/utils.js +80 -0
  365. package/src/fontfamily.d.ts +33 -0
  366. package/src/fontfamily.js +39 -0
  367. package/src/fontsize/fontsizecommand.d.ts +25 -0
  368. package/src/fontsize/fontsizecommand.js +24 -0
  369. package/src/fontsize/fontsizeediting.d.ts +48 -0
  370. package/src/fontsize/fontsizeediting.js +171 -0
  371. package/src/fontsize/fontsizeui.d.ts +35 -0
  372. package/src/fontsize/fontsizeui.js +158 -0
  373. package/src/fontsize/utils.d.ts +12 -0
  374. package/src/fontsize/utils.js +166 -0
  375. package/src/fontsize.d.ts +41 -0
  376. package/src/fontsize.js +49 -0
  377. package/src/index.d.ts +27 -0
  378. package/src/index.js +21 -0
  379. package/src/ui/colorui.d.ts +63 -0
  380. package/src/ui/colorui.js +179 -0
  381. package/src/utils.d.ts +80 -0
  382. package/src/utils.js +97 -0
  383. package/theme/fontsize.css +26 -0
  384. package/theme/icons/font-background.svg +1 -0
  385. package/theme/icons/font-color.svg +1 -0
  386. package/theme/icons/font-family.svg +1 -0
  387. package/theme/icons/font-size.svg +1 -0
package/dist/index.js ADDED
@@ -0,0 +1,1634 @@
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 { Command, Plugin } from '@ckeditor/ckeditor5-core/dist/index.js';
6
+ import { ColorSelectorView, createDropdown, addListToDropdown, MenuBarMenuView, MenuBarMenuListView, MenuBarMenuListItemView, MenuBarMenuListItemButtonView, ViewModel, normalizeColorOptions, getLocalizedColorOptions, focusChildOnDropdownOpen } from '@ckeditor/ckeditor5-ui/dist/index.js';
7
+ import { Collection, CKEditorError } from '@ckeditor/ckeditor5-utils/dist/index.js';
8
+ import { isLength, isPercentage, addBackgroundRules } from '@ckeditor/ckeditor5-engine/dist/index.js';
9
+
10
+ /**
11
+ * The base font command.
12
+ */ class FontCommand extends Command {
13
+ /**
14
+ * A model attribute on which this command operates.
15
+ */ attributeKey;
16
+ /**
17
+ * Creates an instance of the command.
18
+ *
19
+ * @param editor Editor instance.
20
+ * @param attributeKey The name of a model attribute on which this command operates.
21
+ */ constructor(editor, attributeKey){
22
+ super(editor);
23
+ this.attributeKey = attributeKey;
24
+ }
25
+ /**
26
+ * @inheritDoc
27
+ */ refresh() {
28
+ const model = this.editor.model;
29
+ const doc = model.document;
30
+ this.value = doc.selection.getAttribute(this.attributeKey);
31
+ this.isEnabled = model.schema.checkAttributeInSelection(doc.selection, this.attributeKey);
32
+ }
33
+ /**
34
+ * Executes the command. Applies the `value` of the {@link #attributeKey} to the selection.
35
+ * If no `value` is passed, it removes the attribute from the selection.
36
+ *
37
+ * @param options Options for the executed command.
38
+ * @param options.value The value to apply.
39
+ * @fires execute
40
+ */ execute(options = {}) {
41
+ const model = this.editor.model;
42
+ const document = model.document;
43
+ const selection = document.selection;
44
+ const value = options.value;
45
+ const batch = options.batch;
46
+ const updateAttribute = (writer)=>{
47
+ if (selection.isCollapsed) {
48
+ if (value) {
49
+ writer.setSelectionAttribute(this.attributeKey, value);
50
+ } else {
51
+ writer.removeSelectionAttribute(this.attributeKey);
52
+ }
53
+ } else {
54
+ const ranges = model.schema.getValidRanges(selection.getRanges(), this.attributeKey);
55
+ for (const range of ranges){
56
+ if (value) {
57
+ writer.setAttribute(this.attributeKey, value, range);
58
+ } else {
59
+ writer.removeAttribute(this.attributeKey, range);
60
+ }
61
+ }
62
+ }
63
+ };
64
+ // In some scenarios, you may want to use a single undo step for multiple changes (e.g. in color picker).
65
+ if (batch) {
66
+ model.enqueueChange(batch, (writer)=>{
67
+ updateAttribute(writer);
68
+ });
69
+ } else {
70
+ model.change((writer)=>{
71
+ updateAttribute(writer);
72
+ });
73
+ }
74
+ }
75
+ }
76
+
77
+ /**
78
+ * The name of the font size plugin.
79
+ */ const FONT_SIZE = 'fontSize';
80
+ /**
81
+ * The name of the font family plugin.
82
+ */ const FONT_FAMILY = 'fontFamily';
83
+ /**
84
+ * The name of the font color plugin.
85
+ */ const FONT_COLOR = 'fontColor';
86
+ /**
87
+ * The name of the font background color plugin.
88
+ */ const FONT_BACKGROUND_COLOR = 'fontBackgroundColor';
89
+ /**
90
+ * Builds a proper converter definition out of input data.
91
+ */ function buildDefinition(modelAttributeKey, options) {
92
+ const definition = {
93
+ model: {
94
+ key: modelAttributeKey,
95
+ values: []
96
+ },
97
+ view: {},
98
+ upcastAlso: {}
99
+ };
100
+ for (const option of options){
101
+ definition.model.values.push(option.model);
102
+ definition.view[option.model] = option.view;
103
+ if (option.upcastAlso) {
104
+ definition.upcastAlso[option.model] = option.upcastAlso;
105
+ }
106
+ }
107
+ return definition;
108
+ }
109
+ /**
110
+ * A {@link module:font/fontcolor~FontColor font color} and
111
+ * {@link module:font/fontbackgroundcolor~FontBackgroundColor font background color} helper
112
+ * responsible for upcasting data to the model.
113
+ *
114
+ * **Note**: The `styleAttr` parameter should be either `'color'` or `'background-color'`.
115
+ */ function renderUpcastAttribute(styleAttr) {
116
+ return (viewElement)=>normalizeColorCode(viewElement.getStyle(styleAttr));
117
+ }
118
+ /**
119
+ * A {@link module:font/fontcolor~FontColor font color} and
120
+ * {@link module:font/fontbackgroundcolor~FontBackgroundColor font background color} helper
121
+ * responsible for downcasting a color attribute to a `<span>` element.
122
+ *
123
+ * **Note**: The `styleAttr` parameter should be either `'color'` or `'background-color'`.
124
+ */ function renderDowncastElement(styleAttr) {
125
+ return (modelAttributeValue, { writer })=>writer.createAttributeElement('span', {
126
+ style: `${styleAttr}:${modelAttributeValue}`
127
+ }, {
128
+ priority: 7
129
+ });
130
+ }
131
+ /**
132
+ * A helper that adds {@link module:ui/colorselector/colorselectorview~ColorSelectorView} to the color dropdown with proper initial values.
133
+ *
134
+ * @param config.dropdownView The dropdown view to which a {@link module:ui/colorselector/colorselectorview~ColorSelectorView}
135
+ * will be added.
136
+ * @param config.colors An array with definitions representing colors to be displayed in the color selector.
137
+ * @param config.removeButtonLabel The label for the button responsible for removing the color.
138
+ * @param config.documentColorsLabel The label for the section with document colors.
139
+ * @param config.documentColorsCount The number of document colors inside the dropdown.
140
+ * @param config.colorPickerViewConfig Configuration of the color picker view.
141
+ * @returns The new color selector view.
142
+ */ function addColorSelectorToDropdown({ dropdownView, colors, columns, removeButtonLabel, colorPickerLabel, documentColorsLabel, documentColorsCount, colorPickerViewConfig }) {
143
+ const locale = dropdownView.locale;
144
+ const colorSelectorView = new ColorSelectorView(locale, {
145
+ colors,
146
+ columns,
147
+ removeButtonLabel,
148
+ colorPickerLabel,
149
+ documentColorsLabel,
150
+ documentColorsCount,
151
+ colorPickerViewConfig
152
+ });
153
+ dropdownView.colorSelectorView = colorSelectorView;
154
+ dropdownView.panelView.children.add(colorSelectorView);
155
+ return colorSelectorView;
156
+ }
157
+ /**
158
+ * Fixes the color value string.
159
+ */ function normalizeColorCode(value) {
160
+ return value.replace(/\s/g, '');
161
+ }
162
+
163
+ /**
164
+ * The font family command. It is used by {@link module:font/fontfamily/fontfamilyediting~FontFamilyEditing}
165
+ * to apply the font family.
166
+ *
167
+ * ```ts
168
+ * editor.execute( 'fontFamily', { value: 'Arial' } );
169
+ * ```
170
+ *
171
+ * **Note**: Executing the command without the value removes the attribute from the model.
172
+ */ class FontFamilyCommand extends FontCommand {
173
+ /**
174
+ * @inheritDoc
175
+ */ constructor(editor){
176
+ super(editor, FONT_FAMILY);
177
+ }
178
+ }
179
+
180
+ /**
181
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
182
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
183
+ */ /**
184
+ * @module font/fontfamily/utils
185
+ */ /**
186
+ * Normalizes the {@link module:font/fontconfig~FontFamilyConfig#options configuration options}
187
+ * to the {@link module:font/fontconfig~FontFamilyOption} format.
188
+ *
189
+ * @param configuredOptions An array of options taken from the configuration.
190
+ */ function normalizeOptions$1(configuredOptions) {
191
+ // Convert options to objects.
192
+ return configuredOptions.map(getOptionDefinition$1)// Filter out undefined values that `getOptionDefinition` might return.
193
+ .filter((option)=>option !== undefined);
194
+ }
195
+ /**
196
+ * Returns an option definition either created from string shortcut.
197
+ * If object is passed then this method will return it without alternating it. Returns undefined for item than cannot be parsed.
198
+ *
199
+ */ function getOptionDefinition$1(option) {
200
+ // Treat any object as full item definition provided by user in configuration.
201
+ if (typeof option === 'object') {
202
+ return option;
203
+ }
204
+ // Handle 'default' string as a special case. It will be used to remove the fontFamily attribute.
205
+ if (option === 'default') {
206
+ return {
207
+ title: 'Default',
208
+ model: undefined
209
+ };
210
+ }
211
+ // Ignore values that we cannot parse to a definition.
212
+ if (typeof option !== 'string') {
213
+ return undefined;
214
+ }
215
+ // Return font family definition from font string.
216
+ return generateFontPreset(option);
217
+ }
218
+ /**
219
+ * Creates a predefined preset for pixel size. It deconstructs font-family like string into full configuration option.
220
+ * A font definition is passed as coma delimited set of font family names. Font names might be quoted.
221
+ *
222
+ * @param fontDefinition A font definition form configuration.
223
+ */ function generateFontPreset(fontDefinition) {
224
+ // Remove quotes from font names. They will be normalized later.
225
+ const fontNames = fontDefinition.replace(/"|'/g, '').split(',');
226
+ // The first matched font name will be used as dropdown list item title and as model value.
227
+ const firstFontName = fontNames[0];
228
+ // CSS-compatible font names.
229
+ const cssFontNames = fontNames.map(normalizeFontNameForCSS).join(', ');
230
+ return {
231
+ title: firstFontName,
232
+ model: cssFontNames,
233
+ view: {
234
+ name: 'span',
235
+ styles: {
236
+ 'font-family': cssFontNames
237
+ },
238
+ priority: 7
239
+ }
240
+ };
241
+ }
242
+ /**
243
+ * Normalizes font name for the style attribute. It adds braces (') if font name contains spaces.
244
+ */ function normalizeFontNameForCSS(fontName) {
245
+ fontName = fontName.trim();
246
+ // Compound font names should be quoted.
247
+ if (fontName.indexOf(' ') > 0) {
248
+ fontName = `'${fontName}'`;
249
+ }
250
+ return fontName;
251
+ }
252
+
253
+ /**
254
+ * The font family editing feature.
255
+ *
256
+ * It introduces the {@link module:font/fontfamily/fontfamilycommand~FontFamilyCommand command} and
257
+ * the `fontFamily` attribute in the {@link module:engine/model/model~Model model} which renders
258
+ * in the {@link module:engine/view/view view} as an inline `<span>` element (`<span style="font-family: Arial">`),
259
+ * depending on the {@link module:font/fontconfig~FontFamilyConfig configuration}.
260
+ */ class FontFamilyEditing extends Plugin {
261
+ /**
262
+ * @inheritDoc
263
+ */ static get pluginName() {
264
+ return 'FontFamilyEditing';
265
+ }
266
+ /**
267
+ * @inheritDoc
268
+ */ static get isOfficialPlugin() {
269
+ return true;
270
+ }
271
+ /**
272
+ * @inheritDoc
273
+ */ constructor(editor){
274
+ super(editor);
275
+ // Define default configuration using font families shortcuts.
276
+ editor.config.define(FONT_FAMILY, {
277
+ options: [
278
+ 'default',
279
+ 'Arial, Helvetica, sans-serif',
280
+ 'Courier New, Courier, monospace',
281
+ 'Georgia, serif',
282
+ 'Lucida Sans Unicode, Lucida Grande, sans-serif',
283
+ 'Tahoma, Geneva, sans-serif',
284
+ 'Times New Roman, Times, serif',
285
+ 'Trebuchet MS, Helvetica, sans-serif',
286
+ 'Verdana, Geneva, sans-serif'
287
+ ],
288
+ supportAllValues: false
289
+ });
290
+ }
291
+ /**
292
+ * @inheritDoc
293
+ */ init() {
294
+ const editor = this.editor;
295
+ // Allow fontFamily attribute on text nodes.
296
+ editor.model.schema.extend('$text', {
297
+ allowAttributes: FONT_FAMILY
298
+ });
299
+ editor.model.schema.setAttributeProperties(FONT_FAMILY, {
300
+ isFormatting: true,
301
+ copyOnEnter: true
302
+ });
303
+ // Get configured font family options without "default" option.
304
+ const options = normalizeOptions$1(editor.config.get('fontFamily.options')).filter((item)=>item.model);
305
+ const definition = buildDefinition(FONT_FAMILY, options);
306
+ // Set-up the two-way conversion.
307
+ if (editor.config.get('fontFamily.supportAllValues')) {
308
+ this._prepareAnyValueConverters();
309
+ this._prepareCompatibilityConverter();
310
+ } else {
311
+ editor.conversion.attributeToElement(definition);
312
+ }
313
+ editor.commands.add(FONT_FAMILY, new FontFamilyCommand(editor));
314
+ }
315
+ /**
316
+ * These converters enable keeping any value found as `style="font-family: *"` as a value of an attribute on a text even
317
+ * if it is not defined in the plugin configuration.
318
+ */ _prepareAnyValueConverters() {
319
+ const editor = this.editor;
320
+ editor.conversion.for('downcast').attributeToElement({
321
+ model: FONT_FAMILY,
322
+ view: (attributeValue, { writer })=>{
323
+ return writer.createAttributeElement('span', {
324
+ style: 'font-family:' + attributeValue
325
+ }, {
326
+ priority: 7
327
+ });
328
+ }
329
+ });
330
+ editor.conversion.for('upcast').elementToAttribute({
331
+ model: {
332
+ key: FONT_FAMILY,
333
+ value: (viewElement)=>viewElement.getStyle('font-family')
334
+ },
335
+ view: {
336
+ name: 'span',
337
+ styles: {
338
+ 'font-family': /.*/
339
+ }
340
+ }
341
+ });
342
+ }
343
+ /**
344
+ * Adds support for legacy `<font face="..">` formatting.
345
+ */ _prepareCompatibilityConverter() {
346
+ const editor = this.editor;
347
+ editor.conversion.for('upcast').elementToAttribute({
348
+ view: {
349
+ name: 'font',
350
+ attributes: {
351
+ 'face': /.*/
352
+ }
353
+ },
354
+ model: {
355
+ key: FONT_FAMILY,
356
+ value: (viewElement)=>viewElement.getAttribute('face')
357
+ }
358
+ });
359
+ }
360
+ }
361
+
362
+ var fontFamilyIcon = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M11.03 3h6.149a.75.75 0 1 1 0 1.5h-5.514L11.03 3zm1.27 3h4.879a.75.75 0 1 1 0 1.5h-4.244L12.3 6zm1.27 3h3.609a.75.75 0 1 1 0 1.5h-2.973L13.57 9zm-2.754 2.5L8.038 4.785 5.261 11.5h5.555zm.62 1.5H4.641l-1.666 4.028H1.312l5.789-14h1.875l5.789 14h-1.663L11.436 13z\"/></svg>";
363
+
364
+ /**
365
+ * The font family UI plugin. It introduces the `'fontFamily'` dropdown.
366
+ */ class FontFamilyUI extends Plugin {
367
+ /**
368
+ * @inheritDoc
369
+ */ static get pluginName() {
370
+ return 'FontFamilyUI';
371
+ }
372
+ /**
373
+ * @inheritDoc
374
+ */ static get isOfficialPlugin() {
375
+ return true;
376
+ }
377
+ /**
378
+ * @inheritDoc
379
+ */ init() {
380
+ const editor = this.editor;
381
+ const t = editor.t;
382
+ const options = this._getLocalizedOptions();
383
+ const command = editor.commands.get(FONT_FAMILY);
384
+ const accessibleLabel = t('Font Family');
385
+ const listOptions = _prepareListOptions$1(options, command);
386
+ // Register UI component.
387
+ editor.ui.componentFactory.add(FONT_FAMILY, (locale)=>{
388
+ const dropdownView = createDropdown(locale);
389
+ addListToDropdown(dropdownView, listOptions, {
390
+ role: 'menu',
391
+ ariaLabel: accessibleLabel
392
+ });
393
+ dropdownView.buttonView.set({
394
+ label: accessibleLabel,
395
+ icon: fontFamilyIcon,
396
+ tooltip: true
397
+ });
398
+ dropdownView.extendTemplate({
399
+ attributes: {
400
+ class: 'ck-font-family-dropdown'
401
+ }
402
+ });
403
+ dropdownView.bind('isEnabled').to(command);
404
+ // Execute command when an item from the dropdown is selected.
405
+ this.listenTo(dropdownView, 'execute', (evt)=>{
406
+ editor.execute(evt.source.commandName, {
407
+ value: evt.source.commandParam
408
+ });
409
+ editor.editing.view.focus();
410
+ });
411
+ return dropdownView;
412
+ });
413
+ editor.ui.componentFactory.add(`menuBar:${FONT_FAMILY}`, (locale)=>{
414
+ const menuView = new MenuBarMenuView(locale);
415
+ menuView.buttonView.set({
416
+ label: accessibleLabel,
417
+ icon: fontFamilyIcon
418
+ });
419
+ menuView.bind('isEnabled').to(command);
420
+ const listView = new MenuBarMenuListView(locale);
421
+ for (const definition of listOptions){
422
+ const listItemView = new MenuBarMenuListItemView(locale, menuView);
423
+ const buttonView = new MenuBarMenuListItemButtonView(locale);
424
+ buttonView.set({
425
+ role: 'menuitemradio',
426
+ isToggleable: true
427
+ });
428
+ buttonView.bind(...Object.keys(definition.model)).to(definition.model);
429
+ buttonView.delegate('execute').to(menuView);
430
+ buttonView.on('execute', ()=>{
431
+ editor.execute(definition.model.commandName, {
432
+ value: definition.model.commandParam
433
+ });
434
+ editor.editing.view.focus();
435
+ });
436
+ listItemView.children.add(buttonView);
437
+ listView.items.add(listItemView);
438
+ }
439
+ menuView.panelView.children.add(listView);
440
+ return menuView;
441
+ });
442
+ }
443
+ /**
444
+ * Returns options as defined in `config.fontFamily.options` but processed to account for
445
+ * editor localization, i.e. to display {@link module:font/fontconfig~FontFamilyOption}
446
+ * in the correct language.
447
+ *
448
+ * Note: The reason behind this method is that there is no way to use {@link module:utils/locale~Locale#t}
449
+ * when the user configuration is defined because the editor does not exist yet.
450
+ */ _getLocalizedOptions() {
451
+ const editor = this.editor;
452
+ const t = editor.t;
453
+ const options = normalizeOptions$1(editor.config.get(FONT_FAMILY).options);
454
+ return options.map((option)=>{
455
+ // The only title to localize is "Default" others are font names.
456
+ if (option.title === 'Default') {
457
+ option.title = t('Default');
458
+ }
459
+ return option;
460
+ });
461
+ }
462
+ }
463
+ /**
464
+ * Prepares FontFamily dropdown items.
465
+ */ function _prepareListOptions$1(options, command) {
466
+ const itemDefinitions = new Collection();
467
+ // Create dropdown items.
468
+ for (const option of options){
469
+ const def = {
470
+ type: 'button',
471
+ model: new ViewModel({
472
+ commandName: FONT_FAMILY,
473
+ commandParam: option.model,
474
+ label: option.title,
475
+ role: 'menuitemradio',
476
+ withText: true
477
+ })
478
+ };
479
+ def.model.bind('isOn').to(command, 'value', (value)=>{
480
+ // "Default" or check in strict font-family converters mode.
481
+ if (value === option.model) {
482
+ return true;
483
+ }
484
+ if (!value || !option.model) {
485
+ return false;
486
+ }
487
+ return value.split(',')[0].replace(/'/g, '').toLowerCase() === option.model.toLowerCase();
488
+ });
489
+ // Try to set a dropdown list item style.
490
+ if (option.view && typeof option.view !== 'string' && option.view.styles) {
491
+ def.model.set('labelStyle', `font-family: ${option.view.styles['font-family']}`);
492
+ }
493
+ itemDefinitions.add(def);
494
+ }
495
+ return itemDefinitions;
496
+ }
497
+
498
+ /**
499
+ * The font family plugin.
500
+ *
501
+ * For a detailed overview, check the {@glink features/font font feature} documentatiom
502
+ * and the {@glink api/font package page}.
503
+ *
504
+ * This is a "glue" plugin which loads the {@link module:font/fontfamily/fontfamilyediting~FontFamilyEditing} and
505
+ * {@link module:font/fontfamily/fontfamilyui~FontFamilyUI} features in the editor.
506
+ */ class FontFamily extends Plugin {
507
+ /**
508
+ * @inheritDoc
509
+ */ static get requires() {
510
+ return [
511
+ FontFamilyEditing,
512
+ FontFamilyUI
513
+ ];
514
+ }
515
+ /**
516
+ * @inheritDoc
517
+ */ static get pluginName() {
518
+ return 'FontFamily';
519
+ }
520
+ /**
521
+ * @inheritDoc
522
+ */ static get isOfficialPlugin() {
523
+ return true;
524
+ }
525
+ }
526
+
527
+ /**
528
+ * The font size command. It is used by {@link module:font/fontsize/fontsizeediting~FontSizeEditing}
529
+ * to apply the font size.
530
+ *
531
+ * ```ts
532
+ * editor.execute( 'fontSize', { value: 'small' } );
533
+ * ```
534
+ *
535
+ * **Note**: Executing the command without the value removes the attribute from the model.
536
+ */ class FontSizeCommand extends FontCommand {
537
+ /**
538
+ * @inheritDoc
539
+ */ constructor(editor){
540
+ super(editor, FONT_SIZE);
541
+ }
542
+ }
543
+
544
+ /**
545
+ * Normalizes and translates the {@link module:font/fontconfig~FontSizeConfig#options configuration options}
546
+ * to the {@link module:font/fontconfig~FontSizeOption} format.
547
+ *
548
+ * @param configuredOptions An array of options taken from the configuration.
549
+ */ function normalizeOptions(configuredOptions) {
550
+ // Convert options to objects.
551
+ return configuredOptions.map((item)=>getOptionDefinition(item))// Filter out undefined values that `getOptionDefinition` might return.
552
+ .filter((option)=>option !== undefined);
553
+ }
554
+ // Default named presets map. Always create a new instance of the preset object in order to avoid modifying references.
555
+ const namedPresets = {
556
+ get tiny () {
557
+ return {
558
+ title: 'Tiny',
559
+ model: 'tiny',
560
+ view: {
561
+ name: 'span',
562
+ classes: 'text-tiny',
563
+ priority: 7
564
+ }
565
+ };
566
+ },
567
+ get small () {
568
+ return {
569
+ title: 'Small',
570
+ model: 'small',
571
+ view: {
572
+ name: 'span',
573
+ classes: 'text-small',
574
+ priority: 7
575
+ }
576
+ };
577
+ },
578
+ get big () {
579
+ return {
580
+ title: 'Big',
581
+ model: 'big',
582
+ view: {
583
+ name: 'span',
584
+ classes: 'text-big',
585
+ priority: 7
586
+ }
587
+ };
588
+ },
589
+ get huge () {
590
+ return {
591
+ title: 'Huge',
592
+ model: 'huge',
593
+ view: {
594
+ name: 'span',
595
+ classes: 'text-huge',
596
+ priority: 7
597
+ }
598
+ };
599
+ }
600
+ };
601
+ /**
602
+ * Returns an option definition either from preset or creates one from number shortcut.
603
+ * If object is passed then this method will return it without alternating it. Returns undefined for item than cannot be parsed.
604
+ */ function getOptionDefinition(option) {
605
+ if (typeof option === 'number') {
606
+ option = String(option);
607
+ }
608
+ // Check whether passed option is a full item definition provided by user in configuration.
609
+ if (typeof option === 'object' && isFullItemDefinition(option)) {
610
+ return attachPriority(option);
611
+ }
612
+ const preset = findPreset(option);
613
+ // Item is a named preset.
614
+ if (preset) {
615
+ return attachPriority(preset);
616
+ }
617
+ // 'Default' font size. It will be used to remove the fontSize attribute.
618
+ if (option === 'default') {
619
+ return {
620
+ model: undefined,
621
+ title: 'Default'
622
+ };
623
+ }
624
+ // At this stage we probably have numerical value to generate a preset so parse it's value.
625
+ // Discard any faulty values.
626
+ if (isNumericalDefinition(option)) {
627
+ return undefined;
628
+ }
629
+ // Return font size definition from size value.
630
+ return generatePixelPreset(option);
631
+ }
632
+ /**
633
+ * Creates a predefined preset for pixel size.
634
+ * @param definition Font size in pixels.
635
+ * @returns
636
+ */ function generatePixelPreset(definition) {
637
+ // Extend a short (numeric value) definition.
638
+ if (typeof definition === 'string') {
639
+ definition = {
640
+ title: definition,
641
+ model: `${parseFloat(definition)}px`
642
+ };
643
+ }
644
+ definition.view = {
645
+ name: 'span',
646
+ styles: {
647
+ 'font-size': definition.model
648
+ }
649
+ };
650
+ return attachPriority(definition);
651
+ }
652
+ /**
653
+ * Adds the priority to the view element definition if missing. It's required due to ckeditor/ckeditor5#2291
654
+ */ function attachPriority(definition) {
655
+ if (definition.view && typeof definition.view !== 'string' && !definition.view.priority) {
656
+ definition.view.priority = 7;
657
+ }
658
+ return definition;
659
+ }
660
+ /**
661
+ * Returns a prepared preset definition. If passed an object, a name of preset should be defined as `model` value.
662
+ *
663
+ * @param definition.model A preset name.
664
+ */ function findPreset(definition) {
665
+ return typeof definition === 'string' ? namedPresets[definition] : namedPresets[definition.model];
666
+ }
667
+ /**
668
+ * We treat `definition` as completed if it is an object that contains `title`, `model` and `view` values.
669
+ */ function isFullItemDefinition(definition) {
670
+ return definition.title && definition.model && definition.view;
671
+ }
672
+ function isNumericalDefinition(definition) {
673
+ let numberValue;
674
+ if (typeof definition === 'object') {
675
+ if (!definition.model) {
676
+ /**
677
+ * Provided value as an option for {@link module:font/fontsize~FontSize} seems to invalid.
678
+ *
679
+ * See valid examples described in the {@link module:font/fontconfig~FontSizeConfig#options plugin configuration}.
680
+ *
681
+ * @error font-size-invalid-definition
682
+ */ throw new CKEditorError('font-size-invalid-definition', null, definition);
683
+ } else {
684
+ numberValue = parseFloat(definition.model);
685
+ }
686
+ } else {
687
+ numberValue = parseFloat(definition);
688
+ }
689
+ return isNaN(numberValue);
690
+ }
691
+
692
+ // Mapping of `<font size="..">` styling to CSS's `font-size` values.
693
+ const styleFontSize = [
694
+ 'x-small',
695
+ 'x-small',
696
+ 'small',
697
+ 'medium',
698
+ 'large',
699
+ 'x-large',
700
+ 'xx-large',
701
+ 'xxx-large'
702
+ ];
703
+ /**
704
+ * The font size editing feature.
705
+ *
706
+ * It introduces the {@link module:font/fontsize/fontsizecommand~FontSizeCommand command} and the `fontSize`
707
+ * attribute in the {@link module:engine/model/model~Model model} which renders in the {@link module:engine/view/view view}
708
+ * as a `<span>` element with either:
709
+ * * a style attribute (`<span style="font-size:12px">...</span>`),
710
+ * * or a class attribute (`<span class="text-small">...</span>`)
711
+ *
712
+ * depending on the {@link module:font/fontconfig~FontSizeConfig configuration}.
713
+ */ class FontSizeEditing extends Plugin {
714
+ /**
715
+ * @inheritDoc
716
+ */ static get pluginName() {
717
+ return 'FontSizeEditing';
718
+ }
719
+ /**
720
+ * @inheritDoc
721
+ */ static get isOfficialPlugin() {
722
+ return true;
723
+ }
724
+ /**
725
+ * @inheritDoc
726
+ */ constructor(editor){
727
+ super(editor);
728
+ // Define default configuration using named presets.
729
+ editor.config.define(FONT_SIZE, {
730
+ options: [
731
+ 'tiny',
732
+ 'small',
733
+ 'default',
734
+ 'big',
735
+ 'huge'
736
+ ],
737
+ supportAllValues: false
738
+ });
739
+ }
740
+ /**
741
+ * @inheritDoc
742
+ */ init() {
743
+ const editor = this.editor;
744
+ // Allow fontSize attribute on text nodes.
745
+ editor.model.schema.extend('$text', {
746
+ allowAttributes: FONT_SIZE
747
+ });
748
+ editor.model.schema.setAttributeProperties(FONT_SIZE, {
749
+ isFormatting: true,
750
+ copyOnEnter: true
751
+ });
752
+ const supportAllValues = editor.config.get('fontSize.supportAllValues');
753
+ // Define view to model conversion.
754
+ const options = normalizeOptions(this.editor.config.get('fontSize.options')).filter((item)=>item.model);
755
+ const definition = buildDefinition(FONT_SIZE, options);
756
+ // Set-up the two-way conversion.
757
+ if (supportAllValues) {
758
+ this._prepareAnyValueConverters(definition);
759
+ this._prepareCompatibilityConverter();
760
+ } else {
761
+ editor.conversion.attributeToElement(definition);
762
+ }
763
+ // Add FontSize command.
764
+ editor.commands.add(FONT_SIZE, new FontSizeCommand(editor));
765
+ }
766
+ /**
767
+ * These converters enable keeping any value found as `style="font-size: *"` as a value of an attribute on a text even
768
+ * if it is not defined in the plugin configuration.
769
+ *
770
+ * @param definition Converter definition out of input data.
771
+ */ _prepareAnyValueConverters(definition) {
772
+ const editor = this.editor;
773
+ // If `fontSize.supportAllValues=true`, we do not allow to use named presets in the plugin's configuration.
774
+ const presets = definition.model.values.filter((value)=>{
775
+ return !isLength(String(value)) && !isPercentage(String(value));
776
+ });
777
+ if (presets.length) {
778
+ /**
779
+ * If {@link module:font/fontconfig~FontSizeConfig#supportAllValues `config.fontSize.supportAllValues`} is `true`,
780
+ * you need to use numerical values as font size options.
781
+ *
782
+ * See valid examples described in the {@link module:font/fontconfig~FontSizeConfig#options plugin configuration}.
783
+ *
784
+ * @error font-size-invalid-use-of-named-presets
785
+ * @param {Array.<String>} presets Invalid values.
786
+ */ throw new CKEditorError('font-size-invalid-use-of-named-presets', null, {
787
+ presets
788
+ });
789
+ }
790
+ editor.conversion.for('downcast').attributeToElement({
791
+ model: FONT_SIZE,
792
+ view: (attributeValue, { writer })=>{
793
+ if (!attributeValue) {
794
+ return;
795
+ }
796
+ return writer.createAttributeElement('span', {
797
+ style: 'font-size:' + attributeValue
798
+ }, {
799
+ priority: 7
800
+ });
801
+ }
802
+ });
803
+ editor.conversion.for('upcast').elementToAttribute({
804
+ model: {
805
+ key: FONT_SIZE,
806
+ value: (viewElement)=>viewElement.getStyle('font-size')
807
+ },
808
+ view: {
809
+ name: 'span',
810
+ styles: {
811
+ 'font-size': /.*/
812
+ }
813
+ }
814
+ });
815
+ }
816
+ /**
817
+ * Adds support for legacy `<font size="..">` formatting.
818
+ */ _prepareCompatibilityConverter() {
819
+ const editor = this.editor;
820
+ editor.conversion.for('upcast').elementToAttribute({
821
+ view: {
822
+ name: 'font',
823
+ attributes: {
824
+ // Documentation mentions sizes from 1 to 7. To handle old content we support all values
825
+ // up to 999 but clamp it to the valid range. Why 999? It should cover accidental values
826
+ // similar to percentage, e.g. 100%, 200% which could be the usual mistake for font size.
827
+ 'size': /^[+-]?\d{1,3}$/
828
+ }
829
+ },
830
+ model: {
831
+ key: FONT_SIZE,
832
+ value: (viewElement)=>{
833
+ const value = viewElement.getAttribute('size');
834
+ const isRelative = value[0] === '-' || value[0] === '+';
835
+ let size = parseInt(value, 10);
836
+ if (isRelative) {
837
+ // Add relative size (which can be negative) to the default size = 3.
838
+ size = 3 + size;
839
+ }
840
+ const maxSize = styleFontSize.length - 1;
841
+ const clampedSize = Math.min(Math.max(size, 0), maxSize);
842
+ return styleFontSize[clampedSize];
843
+ }
844
+ }
845
+ });
846
+ }
847
+ }
848
+
849
+ var fontSizeIcon = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M9.816 11.5 7.038 4.785 4.261 11.5h5.555zm.62 1.5H3.641l-1.666 4.028H.312l5.789-14h1.875l5.789 14h-1.663L10.436 13zm7.55 2.279.779-.779.707.707-2.265 2.265-2.193-2.265.707-.707.765.765V4.825c0-.042 0-.083.002-.123l-.77.77-.707-.707L17.207 2.5l2.265 2.265-.707.707-.782-.782c.002.043.003.089.003.135v10.454z\"/></svg>";
850
+
851
+ /**
852
+ * The font size UI plugin. It introduces the `'fontSize'` dropdown.
853
+ */ class FontSizeUI extends Plugin {
854
+ /**
855
+ * @inheritDoc
856
+ */ static get pluginName() {
857
+ return 'FontSizeUI';
858
+ }
859
+ /**
860
+ * @inheritDoc
861
+ */ static get isOfficialPlugin() {
862
+ return true;
863
+ }
864
+ /**
865
+ * @inheritDoc
866
+ */ init() {
867
+ const editor = this.editor;
868
+ const t = editor.t;
869
+ const options = this._getLocalizedOptions();
870
+ const command = editor.commands.get(FONT_SIZE);
871
+ const accessibleLabel = t('Font Size');
872
+ const listOptions = _prepareListOptions(options, command);
873
+ // Register UI component.
874
+ editor.ui.componentFactory.add(FONT_SIZE, (locale)=>{
875
+ const dropdownView = createDropdown(locale);
876
+ addListToDropdown(dropdownView, listOptions, {
877
+ role: 'menu',
878
+ ariaLabel: accessibleLabel
879
+ });
880
+ // Create dropdown model.
881
+ dropdownView.buttonView.set({
882
+ label: accessibleLabel,
883
+ icon: fontSizeIcon,
884
+ tooltip: true
885
+ });
886
+ dropdownView.extendTemplate({
887
+ attributes: {
888
+ class: [
889
+ 'ck-font-size-dropdown'
890
+ ]
891
+ }
892
+ });
893
+ dropdownView.bind('isEnabled').to(command);
894
+ // Execute command when an item from the dropdown is selected.
895
+ this.listenTo(dropdownView, 'execute', (evt)=>{
896
+ editor.execute(evt.source.commandName, {
897
+ value: evt.source.commandParam
898
+ });
899
+ editor.editing.view.focus();
900
+ });
901
+ return dropdownView;
902
+ });
903
+ editor.ui.componentFactory.add(`menuBar:${FONT_SIZE}`, (locale)=>{
904
+ const menuView = new MenuBarMenuView(locale);
905
+ menuView.buttonView.set({
906
+ label: accessibleLabel,
907
+ icon: fontSizeIcon
908
+ });
909
+ menuView.bind('isEnabled').to(command);
910
+ const listView = new MenuBarMenuListView(locale);
911
+ for (const definition of listOptions){
912
+ const listItemView = new MenuBarMenuListItemView(locale, menuView);
913
+ const buttonView = new MenuBarMenuListItemButtonView(locale);
914
+ buttonView.set({
915
+ role: 'menuitemradio',
916
+ isToggleable: true
917
+ });
918
+ buttonView.bind(...Object.keys(definition.model)).to(definition.model);
919
+ buttonView.delegate('execute').to(menuView);
920
+ buttonView.on('execute', ()=>{
921
+ editor.execute(definition.model.commandName, {
922
+ value: definition.model.commandParam
923
+ });
924
+ editor.editing.view.focus();
925
+ });
926
+ listItemView.children.add(buttonView);
927
+ listView.items.add(listItemView);
928
+ }
929
+ menuView.panelView.children.add(listView);
930
+ return menuView;
931
+ });
932
+ }
933
+ /**
934
+ * Returns options as defined in `config.fontSize.options` but processed to account for
935
+ * editor localization, i.e. to display {@link module:font/fontconfig~FontSizeOption}
936
+ * in the correct language.
937
+ *
938
+ * Note: The reason behind this method is that there is no way to use {@link module:utils/locale~Locale#t}
939
+ * when the user configuration is defined because the editor does not exist yet.
940
+ */ _getLocalizedOptions() {
941
+ const editor = this.editor;
942
+ const t = editor.t;
943
+ const localizedTitles = {
944
+ Default: t('Default'),
945
+ Tiny: t('Tiny'),
946
+ Small: t('Small'),
947
+ Big: t('Big'),
948
+ Huge: t('Huge')
949
+ };
950
+ const options = normalizeOptions(editor.config.get(FONT_SIZE).options);
951
+ return options.map((option)=>{
952
+ const title = localizedTitles[option.title];
953
+ if (title && title != option.title) {
954
+ // Clone the option to avoid altering the original `namedPresets` from `./utils.js`.
955
+ option = Object.assign({}, option, {
956
+ title
957
+ });
958
+ }
959
+ return option;
960
+ });
961
+ }
962
+ }
963
+ /**
964
+ * Prepares FontSize dropdown items.
965
+ */ function _prepareListOptions(options, command) {
966
+ const itemDefinitions = new Collection();
967
+ for (const option of options){
968
+ const def = {
969
+ type: 'button',
970
+ model: new ViewModel({
971
+ commandName: FONT_SIZE,
972
+ commandParam: option.model,
973
+ label: option.title,
974
+ class: 'ck-fontsize-option',
975
+ role: 'menuitemradio',
976
+ withText: true
977
+ })
978
+ };
979
+ if (option.view && typeof option.view !== 'string') {
980
+ if (option.view.styles) {
981
+ def.model.set('labelStyle', `font-size:${option.view.styles['font-size']}`);
982
+ }
983
+ if (option.view.classes) {
984
+ def.model.set('class', `${def.model.class} ${option.view.classes}`);
985
+ }
986
+ }
987
+ def.model.bind('isOn').to(command, 'value', (value)=>value === option.model);
988
+ // Add the option to the collection.
989
+ itemDefinitions.add(def);
990
+ }
991
+ return itemDefinitions;
992
+ }
993
+
994
+ /**
995
+ * The font size plugin.
996
+ *
997
+ * For a detailed overview, check the {@glink features/font font feature} documentation
998
+ * and the {@glink api/font package page}.
999
+ *
1000
+ * This is a "glue" plugin which loads the {@link module:font/fontsize/fontsizeediting~FontSizeEditing} and
1001
+ * {@link module:font/fontsize/fontsizeui~FontSizeUI} features in the editor.
1002
+ */ class FontSize extends Plugin {
1003
+ /**
1004
+ * @inheritDoc
1005
+ */ static get requires() {
1006
+ return [
1007
+ FontSizeEditing,
1008
+ FontSizeUI
1009
+ ];
1010
+ }
1011
+ /**
1012
+ * @inheritDoc
1013
+ */ static get pluginName() {
1014
+ return 'FontSize';
1015
+ }
1016
+ /**
1017
+ * @inheritDoc
1018
+ */ static get isOfficialPlugin() {
1019
+ return true;
1020
+ }
1021
+ /**
1022
+ * Normalizes and translates the {@link module:font/fontconfig~FontSizeConfig#options configuration options}
1023
+ * to the {@link module:font/fontconfig~FontSizeOption} format.
1024
+ *
1025
+ * @param configuredOptions An array of options taken from the configuration.
1026
+ */ normalizeSizeOptions(options) {
1027
+ return normalizeOptions(options);
1028
+ }
1029
+ }
1030
+
1031
+ /**
1032
+ * The font color command. It is used by {@link module:font/fontcolor/fontcolorediting~FontColorEditing}
1033
+ * to apply the font color.
1034
+ *
1035
+ * ```ts
1036
+ * editor.execute( 'fontColor', { value: 'rgb(250, 20, 20)' } );
1037
+ * ```
1038
+ *
1039
+ * **Note**: Executing the command with the `null` value removes the attribute from the model.
1040
+ */ class FontColorCommand extends FontCommand {
1041
+ /**
1042
+ * @inheritDoc
1043
+ */ constructor(editor){
1044
+ super(editor, FONT_COLOR);
1045
+ }
1046
+ }
1047
+
1048
+ /**
1049
+ * The font color editing feature.
1050
+ *
1051
+ * It introduces the {@link module:font/fontcolor/fontcolorcommand~FontColorCommand command} and
1052
+ * the `fontColor` attribute in the {@link module:engine/model/model~Model model} which renders
1053
+ * in the {@link module:engine/view/view view} as a `<span>` element (`<span style="color: ...">`),
1054
+ * depending on the {@link module:font/fontconfig~FontColorConfig configuration}.
1055
+ */ class FontColorEditing extends Plugin {
1056
+ /**
1057
+ * @inheritDoc
1058
+ */ static get pluginName() {
1059
+ return 'FontColorEditing';
1060
+ }
1061
+ /**
1062
+ * @inheritDoc
1063
+ */ static get isOfficialPlugin() {
1064
+ return true;
1065
+ }
1066
+ /**
1067
+ * @inheritDoc
1068
+ */ constructor(editor){
1069
+ super(editor);
1070
+ editor.config.define(FONT_COLOR, {
1071
+ colors: [
1072
+ {
1073
+ color: 'hsl(0, 0%, 0%)',
1074
+ label: 'Black'
1075
+ },
1076
+ {
1077
+ color: 'hsl(0, 0%, 30%)',
1078
+ label: 'Dim grey'
1079
+ },
1080
+ {
1081
+ color: 'hsl(0, 0%, 60%)',
1082
+ label: 'Grey'
1083
+ },
1084
+ {
1085
+ color: 'hsl(0, 0%, 90%)',
1086
+ label: 'Light grey'
1087
+ },
1088
+ {
1089
+ color: 'hsl(0, 0%, 100%)',
1090
+ label: 'White',
1091
+ hasBorder: true
1092
+ },
1093
+ {
1094
+ color: 'hsl(0, 75%, 60%)',
1095
+ label: 'Red'
1096
+ },
1097
+ {
1098
+ color: 'hsl(30, 75%, 60%)',
1099
+ label: 'Orange'
1100
+ },
1101
+ {
1102
+ color: 'hsl(60, 75%, 60%)',
1103
+ label: 'Yellow'
1104
+ },
1105
+ {
1106
+ color: 'hsl(90, 75%, 60%)',
1107
+ label: 'Light green'
1108
+ },
1109
+ {
1110
+ color: 'hsl(120, 75%, 60%)',
1111
+ label: 'Green'
1112
+ },
1113
+ {
1114
+ color: 'hsl(150, 75%, 60%)',
1115
+ label: 'Aquamarine'
1116
+ },
1117
+ {
1118
+ color: 'hsl(180, 75%, 60%)',
1119
+ label: 'Turquoise'
1120
+ },
1121
+ {
1122
+ color: 'hsl(210, 75%, 60%)',
1123
+ label: 'Light blue'
1124
+ },
1125
+ {
1126
+ color: 'hsl(240, 75%, 60%)',
1127
+ label: 'Blue'
1128
+ },
1129
+ {
1130
+ color: 'hsl(270, 75%, 60%)',
1131
+ label: 'Purple'
1132
+ }
1133
+ ],
1134
+ columns: 5
1135
+ });
1136
+ editor.conversion.for('upcast').elementToAttribute({
1137
+ view: {
1138
+ name: 'span',
1139
+ styles: {
1140
+ 'color': /[\s\S]+/
1141
+ }
1142
+ },
1143
+ model: {
1144
+ key: FONT_COLOR,
1145
+ value: renderUpcastAttribute('color')
1146
+ }
1147
+ });
1148
+ // Support legacy `<font color="..">` formatting.
1149
+ editor.conversion.for('upcast').elementToAttribute({
1150
+ view: {
1151
+ name: 'font',
1152
+ attributes: {
1153
+ 'color': /^#?\w+$/
1154
+ }
1155
+ },
1156
+ model: {
1157
+ key: FONT_COLOR,
1158
+ value: (viewElement)=>viewElement.getAttribute('color')
1159
+ }
1160
+ });
1161
+ editor.conversion.for('downcast').attributeToElement({
1162
+ model: FONT_COLOR,
1163
+ view: renderDowncastElement('color')
1164
+ });
1165
+ editor.commands.add(FONT_COLOR, new FontColorCommand(editor));
1166
+ // Allow the font color attribute on text nodes.
1167
+ editor.model.schema.extend('$text', {
1168
+ allowAttributes: FONT_COLOR
1169
+ });
1170
+ editor.model.schema.setAttributeProperties(FONT_COLOR, {
1171
+ isFormatting: true,
1172
+ copyOnEnter: true
1173
+ });
1174
+ }
1175
+ }
1176
+
1177
+ /**
1178
+ * The color UI plugin which isolates the common logic responsible for displaying dropdowns with color grids.
1179
+ *
1180
+ * It is used to create the `'fontBackgroundColor'` and `'fontColor'` dropdowns, each hosting
1181
+ * a {@link module:ui/colorselector/colorselectorview~ColorSelectorView}.
1182
+ */ class ColorUI extends Plugin {
1183
+ /**
1184
+ * The name of the command which will be executed when a color tile is clicked.
1185
+ */ commandName;
1186
+ /**
1187
+ * The name of this component in the {@link module:ui/componentfactory~ComponentFactory}.
1188
+ * Also the configuration scope name in `editor.config`.
1189
+ */ componentName;
1190
+ /**
1191
+ * The SVG icon used by the dropdown.
1192
+ */ icon;
1193
+ /**
1194
+ * The label used by the dropdown.
1195
+ */ dropdownLabel;
1196
+ /**
1197
+ * The number of columns in the color grid.
1198
+ */ columns;
1199
+ /**
1200
+ * Creates a plugin which introduces a dropdown with a pre–configured
1201
+ * {@link module:ui/colorselector/colorselectorview~ColorSelectorView}.
1202
+ *
1203
+ * @param config The configuration object.
1204
+ * @param config.commandName The name of the command which will be executed when a color tile is clicked.
1205
+ * @param config.componentName The name of the dropdown in the {@link module:ui/componentfactory~ComponentFactory}
1206
+ * and the configuration scope name in `editor.config`.
1207
+ * @param config.icon The SVG icon used by the dropdown.
1208
+ * @param config.dropdownLabel The label used by the dropdown.
1209
+ */ constructor(editor, { commandName, componentName, icon, dropdownLabel }){
1210
+ super(editor);
1211
+ this.commandName = commandName;
1212
+ this.componentName = componentName;
1213
+ this.icon = icon;
1214
+ this.dropdownLabel = dropdownLabel;
1215
+ this.columns = editor.config.get(`${this.componentName}.columns`);
1216
+ }
1217
+ /**
1218
+ * @inheritDoc
1219
+ */ init() {
1220
+ const editor = this.editor;
1221
+ const locale = editor.locale;
1222
+ const t = locale.t;
1223
+ const command = editor.commands.get(this.commandName);
1224
+ const componentConfig = editor.config.get(this.componentName);
1225
+ const colorsConfig = normalizeColorOptions(componentConfig.colors);
1226
+ const localizedColors = getLocalizedColorOptions(locale, colorsConfig);
1227
+ const documentColorsCount = componentConfig.documentColors;
1228
+ const hasColorPicker = componentConfig.colorPicker !== false;
1229
+ // Register the UI component.
1230
+ editor.ui.componentFactory.add(this.componentName, (locale)=>{
1231
+ const dropdownView = createDropdown(locale);
1232
+ // Font color dropdown rendering is deferred once it gets open to improve performance (#6192).
1233
+ let dropdownContentRendered = false;
1234
+ const colorSelectorView = addColorSelectorToDropdown({
1235
+ dropdownView,
1236
+ colors: localizedColors.map((option)=>({
1237
+ label: option.label,
1238
+ color: option.model,
1239
+ options: {
1240
+ hasBorder: option.hasBorder
1241
+ }
1242
+ })),
1243
+ columns: this.columns,
1244
+ removeButtonLabel: t('Remove color'),
1245
+ colorPickerLabel: t('Color picker'),
1246
+ documentColorsLabel: documentColorsCount !== 0 ? t('Document colors') : '',
1247
+ documentColorsCount: documentColorsCount === undefined ? this.columns : documentColorsCount,
1248
+ colorPickerViewConfig: hasColorPicker ? componentConfig.colorPicker || {} : false
1249
+ });
1250
+ colorSelectorView.bind('selectedColor').to(command, 'value');
1251
+ dropdownView.buttonView.set({
1252
+ label: this.dropdownLabel,
1253
+ icon: this.icon,
1254
+ tooltip: true
1255
+ });
1256
+ dropdownView.extendTemplate({
1257
+ attributes: {
1258
+ class: 'ck-color-ui-dropdown'
1259
+ }
1260
+ });
1261
+ dropdownView.bind('isEnabled').to(command);
1262
+ colorSelectorView.on('execute', (evt, data)=>{
1263
+ if (dropdownView.isOpen) {
1264
+ editor.execute(this.commandName, {
1265
+ value: data.value,
1266
+ batch: this._undoStepBatch
1267
+ });
1268
+ }
1269
+ if (data.source !== 'colorPicker') {
1270
+ editor.editing.view.focus();
1271
+ }
1272
+ if (data.source === 'colorPickerSaveButton') {
1273
+ dropdownView.isOpen = false;
1274
+ }
1275
+ });
1276
+ colorSelectorView.on('colorPicker:show', ()=>{
1277
+ this._undoStepBatch = editor.model.createBatch();
1278
+ });
1279
+ colorSelectorView.on('colorPicker:cancel', ()=>{
1280
+ if (this._undoStepBatch.operations.length) {
1281
+ // We need to close the dropdown before the undo batch.
1282
+ // Otherwise, ColorUI treats undo as a selected color change,
1283
+ // propagating the update to the whole selection.
1284
+ // That's an issue if spans with various colors were selected.
1285
+ dropdownView.isOpen = false;
1286
+ editor.execute('undo', this._undoStepBatch);
1287
+ }
1288
+ editor.editing.view.focus();
1289
+ });
1290
+ dropdownView.on('change:isOpen', (evt, name, isVisible)=>{
1291
+ if (!dropdownContentRendered) {
1292
+ dropdownContentRendered = true;
1293
+ dropdownView.colorSelectorView.appendUI();
1294
+ }
1295
+ if (isVisible) {
1296
+ if (documentColorsCount !== 0) {
1297
+ colorSelectorView.updateDocumentColors(editor.model, this.componentName);
1298
+ }
1299
+ colorSelectorView.updateSelectedColors();
1300
+ colorSelectorView.showColorGridsFragment();
1301
+ }
1302
+ });
1303
+ // Accessibility: focus the first active color when opening the dropdown.
1304
+ focusChildOnDropdownOpen(dropdownView, ()=>dropdownView.colorSelectorView.colorGridsFragmentView.staticColorsGrid.items.find((item)=>item.isOn));
1305
+ return dropdownView;
1306
+ });
1307
+ // Register menu bar button..
1308
+ editor.ui.componentFactory.add(`menuBar:${this.componentName}`, (locale)=>{
1309
+ const menuView = new MenuBarMenuView(locale);
1310
+ menuView.buttonView.set({
1311
+ label: this.dropdownLabel,
1312
+ icon: this.icon
1313
+ });
1314
+ menuView.bind('isEnabled').to(command);
1315
+ // Font color sub-menu rendering is deferred once it gets open to improve performance (#6192).
1316
+ let contentRendered = false;
1317
+ const colorSelectorView = new ColorSelectorView(locale, {
1318
+ colors: localizedColors.map((option)=>({
1319
+ label: option.label,
1320
+ color: option.model,
1321
+ options: {
1322
+ hasBorder: option.hasBorder
1323
+ }
1324
+ })),
1325
+ columns: this.columns,
1326
+ removeButtonLabel: t('Remove color'),
1327
+ colorPickerLabel: t('Color picker'),
1328
+ documentColorsLabel: documentColorsCount !== 0 ? t('Document colors') : '',
1329
+ documentColorsCount: documentColorsCount === undefined ? this.columns : documentColorsCount,
1330
+ colorPickerViewConfig: false
1331
+ });
1332
+ colorSelectorView.bind('selectedColor').to(command, 'value');
1333
+ colorSelectorView.delegate('execute').to(menuView);
1334
+ colorSelectorView.on('execute', (evt, data)=>{
1335
+ editor.execute(this.commandName, {
1336
+ value: data.value,
1337
+ batch: this._undoStepBatch
1338
+ });
1339
+ editor.editing.view.focus();
1340
+ });
1341
+ menuView.on('change:isOpen', (evt, name, isVisible)=>{
1342
+ if (!contentRendered) {
1343
+ contentRendered = true;
1344
+ colorSelectorView.appendUI();
1345
+ }
1346
+ if (isVisible) {
1347
+ if (documentColorsCount !== 0) {
1348
+ colorSelectorView.updateDocumentColors(editor.model, this.componentName);
1349
+ }
1350
+ colorSelectorView.updateSelectedColors();
1351
+ colorSelectorView.showColorGridsFragment();
1352
+ }
1353
+ });
1354
+ menuView.panelView.children.add(colorSelectorView);
1355
+ return menuView;
1356
+ });
1357
+ }
1358
+ }
1359
+
1360
+ var fontColorIcon = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M12.4 10.3 10 4.5l-2.4 5.8h4.8zm.5 1.2H7.1L5.7 15H4.2l5-12h1.6l5 12h-1.5L13 11.5zm3.1 7H4a1 1 0 0 1 0-2h12a1 1 0 0 1 0 2z\"/></svg>";
1361
+
1362
+ /**
1363
+ * The font color UI plugin. It introduces the `'fontColor'` dropdown.
1364
+ */ class FontColorUI extends ColorUI {
1365
+ /**
1366
+ * @inheritDoc
1367
+ */ constructor(editor){
1368
+ const t = editor.locale.t;
1369
+ super(editor, {
1370
+ commandName: FONT_COLOR,
1371
+ componentName: FONT_COLOR,
1372
+ icon: fontColorIcon,
1373
+ dropdownLabel: t('Font Color')
1374
+ });
1375
+ }
1376
+ /**
1377
+ * @inheritDoc
1378
+ */ static get pluginName() {
1379
+ return 'FontColorUI';
1380
+ }
1381
+ }
1382
+
1383
+ /**
1384
+ * The font color plugin.
1385
+ *
1386
+ * For a detailed overview, check the {@glink features/font font feature} documentation
1387
+ * and the {@glink api/font package page}.
1388
+ *
1389
+ * This is a "glue" plugin which loads the {@link module:font/fontcolor/fontcolorediting~FontColorEditing} and
1390
+ * {@link module:font/fontcolor/fontcolorui~FontColorUI} features in the editor.
1391
+ */ class FontColor extends Plugin {
1392
+ /**
1393
+ * @inheritDoc
1394
+ */ static get requires() {
1395
+ return [
1396
+ FontColorEditing,
1397
+ FontColorUI
1398
+ ];
1399
+ }
1400
+ /**
1401
+ * @inheritDoc
1402
+ */ static get pluginName() {
1403
+ return 'FontColor';
1404
+ }
1405
+ /**
1406
+ * @inheritDoc
1407
+ */ static get isOfficialPlugin() {
1408
+ return true;
1409
+ }
1410
+ }
1411
+
1412
+ /**
1413
+ * The font background color command. It is used by
1414
+ * {@link module:font/fontbackgroundcolor/fontbackgroundcolorediting~FontBackgroundColorEditing}
1415
+ * to apply the font background color.
1416
+ *
1417
+ * ```ts
1418
+ * editor.execute( 'fontBackgroundColor', { value: 'rgb(250, 20, 20)' } );
1419
+ * ```
1420
+ *
1421
+ * **Note**: Executing the command with the `null` value removes the attribute from the model.
1422
+ */ class FontBackgroundColorCommand extends FontCommand {
1423
+ /**
1424
+ * @inheritDoc
1425
+ */ constructor(editor){
1426
+ super(editor, FONT_BACKGROUND_COLOR);
1427
+ }
1428
+ }
1429
+
1430
+ /**
1431
+ * The font background color editing feature.
1432
+ *
1433
+ * It introduces the {@link module:font/fontbackgroundcolor/fontbackgroundcolorcommand~FontBackgroundColorCommand command} and
1434
+ * the `fontBackgroundColor` attribute in the {@link module:engine/model/model~Model model} which renders
1435
+ * in the {@link module:engine/view/view view} as a `<span>` element (`<span style="background-color: ...">`),
1436
+ * depending on the {@link module:font/fontconfig~FontColorConfig configuration}.
1437
+ */ class FontBackgroundColorEditing extends Plugin {
1438
+ /**
1439
+ * @inheritDoc
1440
+ */ static get pluginName() {
1441
+ return 'FontBackgroundColorEditing';
1442
+ }
1443
+ /**
1444
+ * @inheritDoc
1445
+ */ static get isOfficialPlugin() {
1446
+ return true;
1447
+ }
1448
+ /**
1449
+ * @inheritDoc
1450
+ */ constructor(editor){
1451
+ super(editor);
1452
+ editor.config.define(FONT_BACKGROUND_COLOR, {
1453
+ colors: [
1454
+ {
1455
+ color: 'hsl(0, 0%, 0%)',
1456
+ label: 'Black'
1457
+ },
1458
+ {
1459
+ color: 'hsl(0, 0%, 30%)',
1460
+ label: 'Dim grey'
1461
+ },
1462
+ {
1463
+ color: 'hsl(0, 0%, 60%)',
1464
+ label: 'Grey'
1465
+ },
1466
+ {
1467
+ color: 'hsl(0, 0%, 90%)',
1468
+ label: 'Light grey'
1469
+ },
1470
+ {
1471
+ color: 'hsl(0, 0%, 100%)',
1472
+ label: 'White',
1473
+ hasBorder: true
1474
+ },
1475
+ {
1476
+ color: 'hsl(0, 75%, 60%)',
1477
+ label: 'Red'
1478
+ },
1479
+ {
1480
+ color: 'hsl(30, 75%, 60%)',
1481
+ label: 'Orange'
1482
+ },
1483
+ {
1484
+ color: 'hsl(60, 75%, 60%)',
1485
+ label: 'Yellow'
1486
+ },
1487
+ {
1488
+ color: 'hsl(90, 75%, 60%)',
1489
+ label: 'Light green'
1490
+ },
1491
+ {
1492
+ color: 'hsl(120, 75%, 60%)',
1493
+ label: 'Green'
1494
+ },
1495
+ {
1496
+ color: 'hsl(150, 75%, 60%)',
1497
+ label: 'Aquamarine'
1498
+ },
1499
+ {
1500
+ color: 'hsl(180, 75%, 60%)',
1501
+ label: 'Turquoise'
1502
+ },
1503
+ {
1504
+ color: 'hsl(210, 75%, 60%)',
1505
+ label: 'Light blue'
1506
+ },
1507
+ {
1508
+ color: 'hsl(240, 75%, 60%)',
1509
+ label: 'Blue'
1510
+ },
1511
+ {
1512
+ color: 'hsl(270, 75%, 60%)',
1513
+ label: 'Purple'
1514
+ }
1515
+ ],
1516
+ columns: 5
1517
+ });
1518
+ editor.data.addStyleProcessorRules(addBackgroundRules);
1519
+ editor.conversion.for('upcast').elementToAttribute({
1520
+ view: {
1521
+ name: 'span',
1522
+ styles: {
1523
+ 'background-color': /[\s\S]+/
1524
+ }
1525
+ },
1526
+ model: {
1527
+ key: FONT_BACKGROUND_COLOR,
1528
+ value: renderUpcastAttribute('background-color')
1529
+ }
1530
+ });
1531
+ editor.conversion.for('downcast').attributeToElement({
1532
+ model: FONT_BACKGROUND_COLOR,
1533
+ view: renderDowncastElement('background-color')
1534
+ });
1535
+ editor.commands.add(FONT_BACKGROUND_COLOR, new FontBackgroundColorCommand(editor));
1536
+ // Allow the font backgroundColor attribute on text nodes.
1537
+ editor.model.schema.extend('$text', {
1538
+ allowAttributes: FONT_BACKGROUND_COLOR
1539
+ });
1540
+ editor.model.schema.setAttributeProperties(FONT_BACKGROUND_COLOR, {
1541
+ isFormatting: true,
1542
+ copyOnEnter: true
1543
+ });
1544
+ }
1545
+ }
1546
+
1547
+ var fontBackgroundColorIcon = "<svg viewBox=\"0 0 20 20\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M4 2h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2zm8.38 9.262H7.62L10 5.506l2.38 5.756zm.532 1.285L14.34 16h1.426L10.804 4H9.196L4.234 16H5.66l1.428-3.453h5.824z\"/></svg>";
1548
+
1549
+ /**
1550
+ * The font background color UI plugin. It introduces the `'fontBackgroundColor'` dropdown.
1551
+ */ class FontBackgroundColorUI extends ColorUI {
1552
+ /**
1553
+ * @inheritDoc
1554
+ */ constructor(editor){
1555
+ const t = editor.locale.t;
1556
+ super(editor, {
1557
+ commandName: FONT_BACKGROUND_COLOR,
1558
+ componentName: FONT_BACKGROUND_COLOR,
1559
+ icon: fontBackgroundColorIcon,
1560
+ dropdownLabel: t('Font Background Color')
1561
+ });
1562
+ }
1563
+ /**
1564
+ * @inheritDoc
1565
+ */ static get pluginName() {
1566
+ return 'FontBackgroundColorUI';
1567
+ }
1568
+ }
1569
+
1570
+ /**
1571
+ * The font background color plugin.
1572
+ *
1573
+ * For a detailed overview, check the {@glink features/font font feature} documentation
1574
+ * and the {@glink api/font package page}.
1575
+ *
1576
+ * This is a "glue" plugin which loads
1577
+ * the {@link module:font/fontbackgroundcolor/fontbackgroundcolorediting~FontBackgroundColorEditing} and
1578
+ * {@link module:font/fontbackgroundcolor/fontbackgroundcolorui~FontBackgroundColorUI} features in the editor.
1579
+ */ class FontBackgroundColor extends Plugin {
1580
+ /**
1581
+ * @inheritDoc
1582
+ */ static get requires() {
1583
+ return [
1584
+ FontBackgroundColorEditing,
1585
+ FontBackgroundColorUI
1586
+ ];
1587
+ }
1588
+ /**
1589
+ * @inheritDoc
1590
+ */ static get pluginName() {
1591
+ return 'FontBackgroundColor';
1592
+ }
1593
+ /**
1594
+ * @inheritDoc
1595
+ */ static get isOfficialPlugin() {
1596
+ return true;
1597
+ }
1598
+ }
1599
+
1600
+ /**
1601
+ * A plugin that enables a set of text styling features:
1602
+ *
1603
+ * * {@link module:font/fontsize~FontSize},
1604
+ * * {@link module:font/fontfamily~FontFamily}.
1605
+ * * {@link module:font/fontcolor~FontColor},
1606
+ * * {@link module:font/fontbackgroundcolor~FontBackgroundColor}.
1607
+ *
1608
+ * For a detailed overview, check the {@glink features/font Font feature} documentation
1609
+ * and the {@glink api/font package page}.
1610
+ */ class Font extends Plugin {
1611
+ /**
1612
+ * @inheritDoc
1613
+ */ static get requires() {
1614
+ return [
1615
+ FontFamily,
1616
+ FontSize,
1617
+ FontColor,
1618
+ FontBackgroundColor
1619
+ ];
1620
+ }
1621
+ /**
1622
+ * @inheritDoc
1623
+ */ static get pluginName() {
1624
+ return 'Font';
1625
+ }
1626
+ /**
1627
+ * @inheritDoc
1628
+ */ static get isOfficialPlugin() {
1629
+ return true;
1630
+ }
1631
+ }
1632
+
1633
+ export { Font, FontBackgroundColor, FontBackgroundColorEditing, FontBackgroundColorUI, FontColor, FontColorEditing, FontColorUI, FontFamily, FontFamilyEditing, FontFamilyUI, FontSize, FontSizeEditing, FontSizeUI };
1634
+ //# sourceMappingURL=index.js.map