@ckeditor/ckeditor5-ckbox 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 (309) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/LICENSE.md +21 -0
  3. package/README.md +24 -0
  4. package/build/ckbox.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/ca.js +1 -0
  10. package/build/translations/cs.js +1 -0
  11. package/build/translations/da.js +1 -0
  12. package/build/translations/de.js +1 -0
  13. package/build/translations/el.js +1 -0
  14. package/build/translations/en-au.js +1 -0
  15. package/build/translations/es-co.js +1 -0
  16. package/build/translations/es.js +1 -0
  17. package/build/translations/et.js +1 -0
  18. package/build/translations/fa.js +1 -0
  19. package/build/translations/fi.js +1 -0
  20. package/build/translations/fr.js +1 -0
  21. package/build/translations/gl.js +1 -0
  22. package/build/translations/he.js +1 -0
  23. package/build/translations/hi.js +1 -0
  24. package/build/translations/hr.js +1 -0
  25. package/build/translations/hu.js +1 -0
  26. package/build/translations/id.js +1 -0
  27. package/build/translations/it.js +1 -0
  28. package/build/translations/ja.js +1 -0
  29. package/build/translations/ko.js +1 -0
  30. package/build/translations/lt.js +1 -0
  31. package/build/translations/lv.js +1 -0
  32. package/build/translations/ms.js +1 -0
  33. package/build/translations/nl.js +1 -0
  34. package/build/translations/no.js +1 -0
  35. package/build/translations/pl.js +1 -0
  36. package/build/translations/pt-br.js +1 -0
  37. package/build/translations/pt.js +1 -0
  38. package/build/translations/ro.js +1 -0
  39. package/build/translations/ru.js +1 -0
  40. package/build/translations/sk.js +1 -0
  41. package/build/translations/sq.js +1 -0
  42. package/build/translations/sr-latn.js +1 -0
  43. package/build/translations/sr.js +1 -0
  44. package/build/translations/sv.js +1 -0
  45. package/build/translations/th.js +1 -0
  46. package/build/translations/tr.js +1 -0
  47. package/build/translations/ug.js +1 -0
  48. package/build/translations/uk.js +1 -0
  49. package/build/translations/ur.js +1 -0
  50. package/build/translations/uz.js +1 -0
  51. package/build/translations/vi.js +1 -0
  52. package/build/translations/zh-cn.js +1 -0
  53. package/build/translations/zh.js +1 -0
  54. package/ckeditor5-metadata.json +58 -0
  55. package/dist/augmentation.d.ts +36 -0
  56. package/dist/ckbox.d.ts +41 -0
  57. package/dist/ckboxcommand.d.ts +130 -0
  58. package/dist/ckboxconfig.d.ts +434 -0
  59. package/dist/ckboxediting.d.ts +65 -0
  60. package/dist/ckboximageedit/ckboximageeditcommand.d.ts +109 -0
  61. package/dist/ckboximageedit/ckboximageeditediting.d.ts +36 -0
  62. package/dist/ckboximageedit/ckboximageeditui.d.ts +32 -0
  63. package/dist/ckboximageedit/utils.d.ts +14 -0
  64. package/dist/ckboximageedit.d.ts +32 -0
  65. package/dist/ckboxui.d.ts +60 -0
  66. package/dist/ckboxuploadadapter.d.ts +41 -0
  67. package/dist/ckboxutils.d.ts +58 -0
  68. package/dist/index-content.css +4 -0
  69. package/dist/index-editor.css +46 -0
  70. package/dist/index.css +55 -0
  71. package/dist/index.css.map +1 -0
  72. package/dist/index.d.ts +21 -0
  73. package/dist/index.js +1787 -0
  74. package/dist/index.js.map +1 -0
  75. package/dist/translations/ar.d.ts +8 -0
  76. package/dist/translations/ar.js +5 -0
  77. package/dist/translations/ar.umd.js +11 -0
  78. package/dist/translations/az.d.ts +8 -0
  79. package/dist/translations/az.js +5 -0
  80. package/dist/translations/az.umd.js +11 -0
  81. package/dist/translations/bg.d.ts +8 -0
  82. package/dist/translations/bg.js +5 -0
  83. package/dist/translations/bg.umd.js +11 -0
  84. package/dist/translations/bn.d.ts +8 -0
  85. package/dist/translations/bn.js +5 -0
  86. package/dist/translations/bn.umd.js +11 -0
  87. package/dist/translations/ca.d.ts +8 -0
  88. package/dist/translations/ca.js +5 -0
  89. package/dist/translations/ca.umd.js +11 -0
  90. package/dist/translations/cs.d.ts +8 -0
  91. package/dist/translations/cs.js +5 -0
  92. package/dist/translations/cs.umd.js +11 -0
  93. package/dist/translations/da.d.ts +8 -0
  94. package/dist/translations/da.js +5 -0
  95. package/dist/translations/da.umd.js +11 -0
  96. package/dist/translations/de.d.ts +8 -0
  97. package/dist/translations/de.js +5 -0
  98. package/dist/translations/de.umd.js +11 -0
  99. package/dist/translations/el.d.ts +8 -0
  100. package/dist/translations/el.js +5 -0
  101. package/dist/translations/el.umd.js +11 -0
  102. package/dist/translations/en-au.d.ts +8 -0
  103. package/dist/translations/en-au.js +5 -0
  104. package/dist/translations/en-au.umd.js +11 -0
  105. package/dist/translations/en.d.ts +8 -0
  106. package/dist/translations/en.js +5 -0
  107. package/dist/translations/en.umd.js +11 -0
  108. package/dist/translations/es-co.d.ts +8 -0
  109. package/dist/translations/es-co.js +5 -0
  110. package/dist/translations/es-co.umd.js +11 -0
  111. package/dist/translations/es.d.ts +8 -0
  112. package/dist/translations/es.js +5 -0
  113. package/dist/translations/es.umd.js +11 -0
  114. package/dist/translations/et.d.ts +8 -0
  115. package/dist/translations/et.js +5 -0
  116. package/dist/translations/et.umd.js +11 -0
  117. package/dist/translations/fa.d.ts +8 -0
  118. package/dist/translations/fa.js +5 -0
  119. package/dist/translations/fa.umd.js +11 -0
  120. package/dist/translations/fi.d.ts +8 -0
  121. package/dist/translations/fi.js +5 -0
  122. package/dist/translations/fi.umd.js +11 -0
  123. package/dist/translations/fr.d.ts +8 -0
  124. package/dist/translations/fr.js +5 -0
  125. package/dist/translations/fr.umd.js +11 -0
  126. package/dist/translations/gl.d.ts +8 -0
  127. package/dist/translations/gl.js +5 -0
  128. package/dist/translations/gl.umd.js +11 -0
  129. package/dist/translations/he.d.ts +8 -0
  130. package/dist/translations/he.js +5 -0
  131. package/dist/translations/he.umd.js +11 -0
  132. package/dist/translations/hi.d.ts +8 -0
  133. package/dist/translations/hi.js +5 -0
  134. package/dist/translations/hi.umd.js +11 -0
  135. package/dist/translations/hr.d.ts +8 -0
  136. package/dist/translations/hr.js +5 -0
  137. package/dist/translations/hr.umd.js +11 -0
  138. package/dist/translations/hu.d.ts +8 -0
  139. package/dist/translations/hu.js +5 -0
  140. package/dist/translations/hu.umd.js +11 -0
  141. package/dist/translations/id.d.ts +8 -0
  142. package/dist/translations/id.js +5 -0
  143. package/dist/translations/id.umd.js +11 -0
  144. package/dist/translations/it.d.ts +8 -0
  145. package/dist/translations/it.js +5 -0
  146. package/dist/translations/it.umd.js +11 -0
  147. package/dist/translations/ja.d.ts +8 -0
  148. package/dist/translations/ja.js +5 -0
  149. package/dist/translations/ja.umd.js +11 -0
  150. package/dist/translations/ko.d.ts +8 -0
  151. package/dist/translations/ko.js +5 -0
  152. package/dist/translations/ko.umd.js +11 -0
  153. package/dist/translations/lt.d.ts +8 -0
  154. package/dist/translations/lt.js +5 -0
  155. package/dist/translations/lt.umd.js +11 -0
  156. package/dist/translations/lv.d.ts +8 -0
  157. package/dist/translations/lv.js +5 -0
  158. package/dist/translations/lv.umd.js +11 -0
  159. package/dist/translations/ms.d.ts +8 -0
  160. package/dist/translations/ms.js +5 -0
  161. package/dist/translations/ms.umd.js +11 -0
  162. package/dist/translations/nl.d.ts +8 -0
  163. package/dist/translations/nl.js +5 -0
  164. package/dist/translations/nl.umd.js +11 -0
  165. package/dist/translations/no.d.ts +8 -0
  166. package/dist/translations/no.js +5 -0
  167. package/dist/translations/no.umd.js +11 -0
  168. package/dist/translations/pl.d.ts +8 -0
  169. package/dist/translations/pl.js +5 -0
  170. package/dist/translations/pl.umd.js +11 -0
  171. package/dist/translations/pt-br.d.ts +8 -0
  172. package/dist/translations/pt-br.js +5 -0
  173. package/dist/translations/pt-br.umd.js +11 -0
  174. package/dist/translations/pt.d.ts +8 -0
  175. package/dist/translations/pt.js +5 -0
  176. package/dist/translations/pt.umd.js +11 -0
  177. package/dist/translations/ro.d.ts +8 -0
  178. package/dist/translations/ro.js +5 -0
  179. package/dist/translations/ro.umd.js +11 -0
  180. package/dist/translations/ru.d.ts +8 -0
  181. package/dist/translations/ru.js +5 -0
  182. package/dist/translations/ru.umd.js +11 -0
  183. package/dist/translations/sk.d.ts +8 -0
  184. package/dist/translations/sk.js +5 -0
  185. package/dist/translations/sk.umd.js +11 -0
  186. package/dist/translations/sq.d.ts +8 -0
  187. package/dist/translations/sq.js +5 -0
  188. package/dist/translations/sq.umd.js +11 -0
  189. package/dist/translations/sr-latn.d.ts +8 -0
  190. package/dist/translations/sr-latn.js +5 -0
  191. package/dist/translations/sr-latn.umd.js +11 -0
  192. package/dist/translations/sr.d.ts +8 -0
  193. package/dist/translations/sr.js +5 -0
  194. package/dist/translations/sr.umd.js +11 -0
  195. package/dist/translations/sv.d.ts +8 -0
  196. package/dist/translations/sv.js +5 -0
  197. package/dist/translations/sv.umd.js +11 -0
  198. package/dist/translations/th.d.ts +8 -0
  199. package/dist/translations/th.js +5 -0
  200. package/dist/translations/th.umd.js +11 -0
  201. package/dist/translations/tr.d.ts +8 -0
  202. package/dist/translations/tr.js +5 -0
  203. package/dist/translations/tr.umd.js +11 -0
  204. package/dist/translations/ug.d.ts +8 -0
  205. package/dist/translations/ug.js +5 -0
  206. package/dist/translations/ug.umd.js +11 -0
  207. package/dist/translations/uk.d.ts +8 -0
  208. package/dist/translations/uk.js +5 -0
  209. package/dist/translations/uk.umd.js +11 -0
  210. package/dist/translations/ur.d.ts +8 -0
  211. package/dist/translations/ur.js +5 -0
  212. package/dist/translations/ur.umd.js +11 -0
  213. package/dist/translations/uz.d.ts +8 -0
  214. package/dist/translations/uz.js +5 -0
  215. package/dist/translations/uz.umd.js +11 -0
  216. package/dist/translations/vi.d.ts +8 -0
  217. package/dist/translations/vi.js +5 -0
  218. package/dist/translations/vi.umd.js +11 -0
  219. package/dist/translations/zh-cn.d.ts +8 -0
  220. package/dist/translations/zh-cn.js +5 -0
  221. package/dist/translations/zh-cn.umd.js +11 -0
  222. package/dist/translations/zh.d.ts +8 -0
  223. package/dist/translations/zh.js +5 -0
  224. package/dist/translations/zh.umd.js +11 -0
  225. package/dist/utils.d.ts +67 -0
  226. package/lang/contexts.json +10 -0
  227. package/lang/translations/ar.po +50 -0
  228. package/lang/translations/az.po +50 -0
  229. package/lang/translations/bg.po +50 -0
  230. package/lang/translations/bn.po +50 -0
  231. package/lang/translations/ca.po +50 -0
  232. package/lang/translations/cs.po +50 -0
  233. package/lang/translations/da.po +50 -0
  234. package/lang/translations/de.po +50 -0
  235. package/lang/translations/el.po +50 -0
  236. package/lang/translations/en-au.po +50 -0
  237. package/lang/translations/en.po +50 -0
  238. package/lang/translations/es-co.po +50 -0
  239. package/lang/translations/es.po +50 -0
  240. package/lang/translations/et.po +50 -0
  241. package/lang/translations/fa.po +50 -0
  242. package/lang/translations/fi.po +50 -0
  243. package/lang/translations/fr.po +50 -0
  244. package/lang/translations/gl.po +50 -0
  245. package/lang/translations/he.po +50 -0
  246. package/lang/translations/hi.po +50 -0
  247. package/lang/translations/hr.po +50 -0
  248. package/lang/translations/hu.po +50 -0
  249. package/lang/translations/id.po +50 -0
  250. package/lang/translations/it.po +50 -0
  251. package/lang/translations/ja.po +50 -0
  252. package/lang/translations/ko.po +50 -0
  253. package/lang/translations/lt.po +50 -0
  254. package/lang/translations/lv.po +50 -0
  255. package/lang/translations/ms.po +50 -0
  256. package/lang/translations/nl.po +50 -0
  257. package/lang/translations/no.po +50 -0
  258. package/lang/translations/pl.po +50 -0
  259. package/lang/translations/pt-br.po +50 -0
  260. package/lang/translations/pt.po +50 -0
  261. package/lang/translations/ro.po +50 -0
  262. package/lang/translations/ru.po +50 -0
  263. package/lang/translations/sk.po +50 -0
  264. package/lang/translations/sq.po +50 -0
  265. package/lang/translations/sr-latn.po +50 -0
  266. package/lang/translations/sr.po +50 -0
  267. package/lang/translations/sv.po +50 -0
  268. package/lang/translations/th.po +50 -0
  269. package/lang/translations/tr.po +50 -0
  270. package/lang/translations/ug.po +50 -0
  271. package/lang/translations/uk.po +50 -0
  272. package/lang/translations/ur.po +50 -0
  273. package/lang/translations/uz.po +50 -0
  274. package/lang/translations/vi.po +50 -0
  275. package/lang/translations/zh-cn.po +50 -0
  276. package/lang/translations/zh.po +50 -0
  277. package/package.json +45 -0
  278. package/src/augmentation.d.ts +32 -0
  279. package/src/augmentation.js +5 -0
  280. package/src/ckbox.d.ts +37 -0
  281. package/src/ckbox.js +43 -0
  282. package/src/ckboxcommand.d.ts +126 -0
  283. package/src/ckboxcommand.js +364 -0
  284. package/src/ckboxconfig.d.ts +430 -0
  285. package/src/ckboxconfig.js +5 -0
  286. package/src/ckboxediting.d.ts +61 -0
  287. package/src/ckboxediting.js +389 -0
  288. package/src/ckboximageedit/ckboximageeditcommand.d.ts +105 -0
  289. package/src/ckboximageedit/ckboximageeditcommand.js +310 -0
  290. package/src/ckboximageedit/ckboximageeditediting.d.ts +32 -0
  291. package/src/ckboximageedit/ckboximageeditediting.js +42 -0
  292. package/src/ckboximageedit/ckboximageeditui.d.ts +28 -0
  293. package/src/ckboximageedit/ckboximageeditui.js +57 -0
  294. package/src/ckboximageedit/utils.d.ts +10 -0
  295. package/src/ckboximageedit/utils.js +48 -0
  296. package/src/ckboximageedit.d.ts +28 -0
  297. package/src/ckboximageedit.js +34 -0
  298. package/src/ckboxui.d.ts +56 -0
  299. package/src/ckboxui.js +136 -0
  300. package/src/ckboxuploadadapter.d.ts +37 -0
  301. package/src/ckboxuploadadapter.js +136 -0
  302. package/src/ckboxutils.d.ts +54 -0
  303. package/src/ckboxutils.js +189 -0
  304. package/src/index.d.ts +17 -0
  305. package/src/index.js +14 -0
  306. package/src/utils.d.ts +63 -0
  307. package/src/utils.js +175 -0
  308. package/theme/ckboximageedit.css +53 -0
  309. package/theme/icons/ckbox-image-edit.svg +1 -0
package/src/ckboxui.js ADDED
@@ -0,0 +1,136 @@
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 ckbox/ckboxui
7
+ */
8
+ import { icons, Plugin } from 'ckeditor5/src/core.js';
9
+ import { ButtonView, MenuBarMenuListItemButtonView } from 'ckeditor5/src/ui.js';
10
+ /**
11
+ * Introduces UI components for the `CKBox` plugin.
12
+ *
13
+ * The plugin introduces two UI components to the {@link module:ui/componentfactory~ComponentFactory UI component factory}:
14
+ *
15
+ * * the `'ckbox'` toolbar button,
16
+ * * the `'menuBar:ckbox'` menu bar component, which is by default added to the `'Insert'` menu.
17
+ *
18
+ * It also integrates with the `insertImage` toolbar component and `menuBar:insertImage` menu component.
19
+ */
20
+ export default class CKBoxUI extends Plugin {
21
+ /**
22
+ * @inheritDoc
23
+ */
24
+ static get pluginName() {
25
+ return 'CKBoxUI';
26
+ }
27
+ /**
28
+ * @inheritDoc
29
+ */
30
+ static get isOfficialPlugin() {
31
+ return true;
32
+ }
33
+ /**
34
+ * @inheritDoc
35
+ */
36
+ afterInit() {
37
+ const editor = this.editor;
38
+ // Do not register the `ckbox` button if the command does not exist.
39
+ // This might happen when CKBox library is not loaded on the page.
40
+ if (!editor.commands.get('ckbox')) {
41
+ return;
42
+ }
43
+ editor.ui.componentFactory.add('ckbox', () => this._createFileToolbarButton());
44
+ editor.ui.componentFactory.add('menuBar:ckbox', () => this._createFileMenuBarButton());
45
+ if (editor.plugins.has('ImageInsertUI')) {
46
+ editor.plugins.get('ImageInsertUI').registerIntegration({
47
+ name: 'assetManager',
48
+ observable: () => editor.commands.get('ckbox'),
49
+ buttonViewCreator: () => this._createImageToolbarButton(),
50
+ formViewCreator: () => this._createImageDropdownButton(),
51
+ menuBarButtonViewCreator: isOnly => this._createImageMenuBarButton(isOnly ? 'insertOnly' : 'insertNested')
52
+ });
53
+ }
54
+ }
55
+ /**
56
+ * Creates the base for various kinds of the button component provided by this feature.
57
+ */
58
+ _createButton(ButtonClass) {
59
+ const editor = this.editor;
60
+ const locale = editor.locale;
61
+ const view = new ButtonClass(locale);
62
+ const command = editor.commands.get('ckbox');
63
+ view.bind('isOn', 'isEnabled').to(command, 'value', 'isEnabled');
64
+ view.on('execute', () => {
65
+ editor.execute('ckbox');
66
+ });
67
+ return view;
68
+ }
69
+ /**
70
+ * Creates a simple toolbar button for files management, with an icon and a tooltip.
71
+ */
72
+ _createFileToolbarButton() {
73
+ const t = this.editor.locale.t;
74
+ const button = this._createButton(ButtonView);
75
+ button.icon = icons.browseFiles;
76
+ button.label = t('Open file manager');
77
+ button.tooltip = true;
78
+ return button;
79
+ }
80
+ /**
81
+ * Creates a simple toolbar button for images management, with an icon and a tooltip.
82
+ */
83
+ _createImageToolbarButton() {
84
+ const t = this.editor.locale.t;
85
+ const imageInsertUI = this.editor.plugins.get('ImageInsertUI');
86
+ const button = this._createButton(ButtonView);
87
+ button.icon = icons.imageAssetManager;
88
+ button.bind('label').to(imageInsertUI, 'isImageSelected', isImageSelected => isImageSelected ? t('Replace image with file manager') : t('Insert image with file manager'));
89
+ button.tooltip = true;
90
+ return button;
91
+ }
92
+ /**
93
+ * Creates a button for images management for the dropdown view, with an icon, text and no tooltip.
94
+ */
95
+ _createImageDropdownButton() {
96
+ const t = this.editor.locale.t;
97
+ const imageInsertUI = this.editor.plugins.get('ImageInsertUI');
98
+ const button = this._createButton(ButtonView);
99
+ button.icon = icons.imageAssetManager;
100
+ button.withText = true;
101
+ button.bind('label').to(imageInsertUI, 'isImageSelected', isImageSelected => isImageSelected ? t('Replace with file manager') : t('Insert with file manager'));
102
+ button.on('execute', () => {
103
+ imageInsertUI.dropdownView.isOpen = false;
104
+ });
105
+ return button;
106
+ }
107
+ /**
108
+ * Creates a button for files management for the menu bar.
109
+ */
110
+ _createFileMenuBarButton() {
111
+ const t = this.editor.locale.t;
112
+ const button = this._createButton(MenuBarMenuListItemButtonView);
113
+ button.icon = icons.browseFiles;
114
+ button.withText = true;
115
+ button.label = t('File');
116
+ return button;
117
+ }
118
+ /**
119
+ * Creates a button for images management for the menu bar.
120
+ */
121
+ _createImageMenuBarButton(type) {
122
+ const t = this.editor.locale.t;
123
+ const button = this._createButton(MenuBarMenuListItemButtonView);
124
+ button.icon = icons.imageAssetManager;
125
+ button.withText = true;
126
+ switch (type) {
127
+ case 'insertOnly':
128
+ button.label = t('Image');
129
+ break;
130
+ case 'insertNested':
131
+ button.label = t('With file manager');
132
+ break;
133
+ }
134
+ return button;
135
+ }
136
+ }
@@ -0,0 +1,37 @@
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 ckbox/ckboxuploadadapter
7
+ */
8
+ import { Plugin } from 'ckeditor5/src/core.js';
9
+ import { FileRepository } from 'ckeditor5/src/upload.js';
10
+ import CKBoxEditing from './ckboxediting.js';
11
+ /**
12
+ * A plugin that enables file uploads in CKEditor 5 using the CKBox server–side connector.
13
+ * See the {@glink features/file-management/ckbox CKBox file manager integration} guide to learn how to configure
14
+ * and use this feature as well as find out more about the full integration with the file manager
15
+ * provided by the {@link module:ckbox/ckbox~CKBox} plugin.
16
+ *
17
+ * Check out the {@glink features/images/image-upload/image-upload Image upload overview} guide to learn about
18
+ * other ways to upload images into CKEditor 5.
19
+ */
20
+ export default class CKBoxUploadAdapter extends Plugin {
21
+ /**
22
+ * @inheritDoc
23
+ */
24
+ static get requires(): readonly ["ImageUploadEditing", "ImageUploadProgress", typeof FileRepository, typeof CKBoxEditing];
25
+ /**
26
+ * @inheritDoc
27
+ */
28
+ static get pluginName(): "CKBoxUploadAdapter";
29
+ /**
30
+ * @inheritDoc
31
+ */
32
+ static get isOfficialPlugin(): true;
33
+ /**
34
+ * @inheritDoc
35
+ */
36
+ afterInit(): Promise<void>;
37
+ }
@@ -0,0 +1,136 @@
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
+ /* globals AbortController, FormData, URL, window */
6
+ /**
7
+ * @module ckbox/ckboxuploadadapter
8
+ */
9
+ import { Plugin } from 'ckeditor5/src/core.js';
10
+ import { FileRepository } from 'ckeditor5/src/upload.js';
11
+ import CKBoxEditing from './ckboxediting.js';
12
+ import { getImageUrls, sendHttpRequest } from './utils.js';
13
+ import CKBoxUtils from './ckboxutils.js';
14
+ /**
15
+ * A plugin that enables file uploads in CKEditor 5 using the CKBox server–side connector.
16
+ * See the {@glink features/file-management/ckbox CKBox file manager integration} guide to learn how to configure
17
+ * and use this feature as well as find out more about the full integration with the file manager
18
+ * provided by the {@link module:ckbox/ckbox~CKBox} plugin.
19
+ *
20
+ * Check out the {@glink features/images/image-upload/image-upload Image upload overview} guide to learn about
21
+ * other ways to upload images into CKEditor 5.
22
+ */
23
+ export default class CKBoxUploadAdapter extends Plugin {
24
+ /**
25
+ * @inheritDoc
26
+ */
27
+ static get requires() {
28
+ return ['ImageUploadEditing', 'ImageUploadProgress', FileRepository, CKBoxEditing];
29
+ }
30
+ /**
31
+ * @inheritDoc
32
+ */
33
+ static get pluginName() {
34
+ return 'CKBoxUploadAdapter';
35
+ }
36
+ /**
37
+ * @inheritDoc
38
+ */
39
+ static get isOfficialPlugin() {
40
+ return true;
41
+ }
42
+ /**
43
+ * @inheritDoc
44
+ */
45
+ async afterInit() {
46
+ const editor = this.editor;
47
+ const hasConfiguration = !!editor.config.get('ckbox');
48
+ const isLibraryLoaded = !!window.CKBox;
49
+ // Editor supports only one upload adapter. Register the CKBox upload adapter (and potentially overwrite other one) only when the
50
+ // integrator intentionally wants to use the CKBox plugin, i.e. when the `config.ckbox` exists or the CKBox JavaScript library is
51
+ // loaded.
52
+ if (!hasConfiguration && !isLibraryLoaded) {
53
+ return;
54
+ }
55
+ const fileRepository = editor.plugins.get(FileRepository);
56
+ const ckboxUtils = editor.plugins.get(CKBoxUtils);
57
+ fileRepository.createUploadAdapter = loader => new Adapter(loader, editor, ckboxUtils);
58
+ const shouldInsertDataId = !editor.config.get('ckbox.ignoreDataId');
59
+ const imageUploadEditing = editor.plugins.get('ImageUploadEditing');
60
+ // Mark uploaded assets with the `ckboxImageId` attribute. Its value represents an ID in CKBox.
61
+ if (shouldInsertDataId) {
62
+ imageUploadEditing.on('uploadComplete', (evt, { imageElement, data }) => {
63
+ editor.model.change(writer => {
64
+ writer.setAttribute('ckboxImageId', data.ckboxImageId, imageElement);
65
+ });
66
+ });
67
+ }
68
+ }
69
+ }
70
+ /**
71
+ * Upload adapter for CKBox.
72
+ */
73
+ class Adapter {
74
+ /**
75
+ * Creates a new adapter instance.
76
+ */
77
+ constructor(loader, editor, ckboxUtils) {
78
+ this.loader = loader;
79
+ this.token = ckboxUtils.getToken();
80
+ this.ckboxUtils = ckboxUtils;
81
+ this.editor = editor;
82
+ this.controller = new AbortController();
83
+ this.serviceOrigin = editor.config.get('ckbox.serviceOrigin');
84
+ }
85
+ /**
86
+ * Starts the upload process.
87
+ *
88
+ * @see module:upload/filerepository~UploadAdapter#upload
89
+ */
90
+ async upload() {
91
+ const ckboxUtils = this.ckboxUtils;
92
+ const t = this.editor.t;
93
+ const file = (await this.loader.file);
94
+ const category = await ckboxUtils.getCategoryIdForFile(file, { signal: this.controller.signal });
95
+ const uploadUrl = new URL('assets', this.serviceOrigin);
96
+ const formData = new FormData();
97
+ uploadUrl.searchParams.set('workspaceId', await ckboxUtils.getWorkspaceId());
98
+ formData.append('categoryId', category);
99
+ formData.append('file', file);
100
+ const requestConfig = {
101
+ method: 'POST',
102
+ url: uploadUrl,
103
+ data: formData,
104
+ onUploadProgress: (evt) => {
105
+ /* istanbul ignore else -- @preserve */
106
+ if (evt.lengthComputable) {
107
+ this.loader.uploadTotal = evt.total;
108
+ this.loader.uploaded = evt.loaded;
109
+ }
110
+ },
111
+ signal: this.controller.signal,
112
+ authorization: (await this.token).value
113
+ };
114
+ return sendHttpRequest(requestConfig)
115
+ .then(async (data) => {
116
+ const imageUrls = getImageUrls(data.imageUrls);
117
+ return {
118
+ ckboxImageId: data.id,
119
+ default: imageUrls.imageFallbackUrl,
120
+ sources: imageUrls.imageSources
121
+ };
122
+ })
123
+ .catch(() => {
124
+ const genericError = t('Cannot upload file:') + ` ${file.name}.`;
125
+ return Promise.reject(genericError);
126
+ });
127
+ }
128
+ /**
129
+ * Aborts the upload process.
130
+ *
131
+ * @see module:upload/filerepository~UploadAdapter#abort
132
+ */
133
+ abort() {
134
+ this.controller.abort();
135
+ }
136
+ }
@@ -0,0 +1,54 @@
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 ckbox/ckboxutils
7
+ */
8
+ import type { InitializedToken } from '@ckeditor/ckeditor5-cloud-services';
9
+ import { Plugin } from 'ckeditor5/src/core.js';
10
+ /**
11
+ * The CKBox utilities plugin.
12
+ */
13
+ export default class CKBoxUtils extends Plugin {
14
+ /**
15
+ * CKEditor Cloud Services access token.
16
+ */
17
+ private _token;
18
+ /**
19
+ * @inheritDoc
20
+ */
21
+ static get pluginName(): "CKBoxUtils";
22
+ /**
23
+ * @inheritDoc
24
+ */
25
+ static get isOfficialPlugin(): true;
26
+ /**
27
+ * @inheritDoc
28
+ */
29
+ static get requires(): readonly ["CloudServices"];
30
+ /**
31
+ * @inheritDoc
32
+ */
33
+ init(): void;
34
+ /**
35
+ * Returns a token used by the CKBox plugin for communication with the CKBox service.
36
+ */
37
+ getToken(): Promise<InitializedToken>;
38
+ /**
39
+ * The ID of workspace to use when uploading an image.
40
+ */
41
+ getWorkspaceId(): Promise<string>;
42
+ /**
43
+ * Resolves a promise with an object containing a category with which the uploaded file is associated or an error code.
44
+ */
45
+ getCategoryIdForFile(fileOrUrl: File | string, options: {
46
+ signal: AbortSignal;
47
+ }): Promise<string>;
48
+ /**
49
+ * Resolves a promise with an array containing available categories with which the uploaded file can be associated.
50
+ *
51
+ * If the API returns limited results, the method will collect all items.
52
+ */
53
+ private _getAvailableCategories;
54
+ }
@@ -0,0 +1,189 @@
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 { CKEditorError, logError } from 'ckeditor5/src/utils.js';
6
+ import { Plugin } from 'ckeditor5/src/core.js';
7
+ import { convertMimeTypeToExtension, getContentTypeOfUrl, getFileExtension, getWorkspaceId, sendHttpRequest } from './utils.js';
8
+ const DEFAULT_CKBOX_THEME_NAME = 'lark';
9
+ /**
10
+ * The CKBox utilities plugin.
11
+ */
12
+ export default class CKBoxUtils extends Plugin {
13
+ /**
14
+ * @inheritDoc
15
+ */
16
+ static get pluginName() {
17
+ return 'CKBoxUtils';
18
+ }
19
+ /**
20
+ * @inheritDoc
21
+ */
22
+ static get isOfficialPlugin() {
23
+ return true;
24
+ }
25
+ /**
26
+ * @inheritDoc
27
+ */
28
+ static get requires() {
29
+ return ['CloudServices'];
30
+ }
31
+ /**
32
+ * @inheritDoc
33
+ */
34
+ init() {
35
+ const editor = this.editor;
36
+ const hasConfiguration = !!editor.config.get('ckbox');
37
+ const isLibraryLoaded = !!window.CKBox;
38
+ // Proceed with plugin initialization only when the integrator intentionally wants to use it, i.e. when the `config.ckbox` exists or
39
+ // the CKBox JavaScript library is loaded.
40
+ if (!hasConfiguration && !isLibraryLoaded) {
41
+ return;
42
+ }
43
+ editor.config.define('ckbox', {
44
+ serviceOrigin: 'https://api.ckbox.io',
45
+ defaultUploadCategories: null,
46
+ ignoreDataId: false,
47
+ language: editor.locale.uiLanguage,
48
+ theme: DEFAULT_CKBOX_THEME_NAME,
49
+ tokenUrl: editor.config.get('cloudServices.tokenUrl')
50
+ });
51
+ const cloudServices = editor.plugins.get('CloudServices');
52
+ const cloudServicesTokenUrl = editor.config.get('cloudServices.tokenUrl');
53
+ const ckboxTokenUrl = editor.config.get('ckbox.tokenUrl');
54
+ if (!ckboxTokenUrl) {
55
+ /**
56
+ * The {@link module:ckbox/ckboxconfig~CKBoxConfig#tokenUrl `config.ckbox.tokenUrl`} or the
57
+ * {@link module:cloud-services/cloudservicesconfig~CloudServicesConfig#tokenUrl `config.cloudServices.tokenUrl`}
58
+ * configuration is required for the CKBox plugin.
59
+ *
60
+ * ```ts
61
+ * ClassicEditor.create( document.createElement( 'div' ), {
62
+ * ckbox: {
63
+ * tokenUrl: "YOUR_TOKEN_URL"
64
+ * // ...
65
+ * }
66
+ * // ...
67
+ * } );
68
+ * ```
69
+ *
70
+ * @error ckbox-plugin-missing-token-url
71
+ */
72
+ throw new CKEditorError('ckbox-plugin-missing-token-url', this);
73
+ }
74
+ if (ckboxTokenUrl == cloudServicesTokenUrl) {
75
+ this._token = Promise.resolve(cloudServices.token);
76
+ }
77
+ else {
78
+ this._token = cloudServices.registerTokenUrl(ckboxTokenUrl);
79
+ }
80
+ }
81
+ /**
82
+ * Returns a token used by the CKBox plugin for communication with the CKBox service.
83
+ */
84
+ getToken() {
85
+ return this._token;
86
+ }
87
+ /**
88
+ * The ID of workspace to use when uploading an image.
89
+ */
90
+ async getWorkspaceId() {
91
+ const t = this.editor.t;
92
+ const cannotAccessDefaultWorkspaceError = t('Cannot access default workspace.');
93
+ const defaultWorkspaceId = this.editor.config.get('ckbox.defaultUploadWorkspaceId');
94
+ const workspaceId = getWorkspaceId(await this._token, defaultWorkspaceId);
95
+ if (workspaceId == null) {
96
+ /**
97
+ * The user is not authorized to access the workspace defined in the`ckbox.defaultUploadWorkspaceId` configuration.
98
+ *
99
+ * @error ckbox-access-default-workspace-error
100
+ */
101
+ logError('ckbox-access-default-workspace-error');
102
+ throw cannotAccessDefaultWorkspaceError;
103
+ }
104
+ return workspaceId;
105
+ }
106
+ /**
107
+ * Resolves a promise with an object containing a category with which the uploaded file is associated or an error code.
108
+ */
109
+ async getCategoryIdForFile(fileOrUrl, options) {
110
+ const t = this.editor.t;
111
+ const cannotFindCategoryError = t('Cannot determine a category for the uploaded file.');
112
+ const defaultCategories = this.editor.config.get('ckbox.defaultUploadCategories');
113
+ const allCategoriesPromise = this._getAvailableCategories(options);
114
+ const extension = typeof fileOrUrl == 'string' ?
115
+ convertMimeTypeToExtension(await getContentTypeOfUrl(fileOrUrl, options)) :
116
+ getFileExtension(fileOrUrl);
117
+ const allCategories = await allCategoriesPromise;
118
+ // Couldn't fetch all categories. Perhaps the authorization token is invalid.
119
+ if (!allCategories) {
120
+ throw cannotFindCategoryError;
121
+ }
122
+ // If a user specifies the plugin configuration, find the first category that accepts the uploaded file.
123
+ if (defaultCategories) {
124
+ const userCategory = Object.keys(defaultCategories).find(category => {
125
+ return defaultCategories[category].find(e => e.toLowerCase() == extension);
126
+ });
127
+ // If found, return its ID if the category exists on the server side.
128
+ if (userCategory) {
129
+ const serverCategory = allCategories.find(category => category.id === userCategory || category.name === userCategory);
130
+ if (!serverCategory) {
131
+ throw cannotFindCategoryError;
132
+ }
133
+ return serverCategory.id;
134
+ }
135
+ }
136
+ // Otherwise, find the first category that accepts the uploaded file and returns its ID.
137
+ const category = allCategories.find(category => category.extensions.find(e => e.toLowerCase() == extension));
138
+ if (!category) {
139
+ throw cannotFindCategoryError;
140
+ }
141
+ return category.id;
142
+ }
143
+ /**
144
+ * Resolves a promise with an array containing available categories with which the uploaded file can be associated.
145
+ *
146
+ * If the API returns limited results, the method will collect all items.
147
+ */
148
+ async _getAvailableCategories(options) {
149
+ const ITEMS_PER_REQUEST = 50;
150
+ const editor = this.editor;
151
+ const token = this._token;
152
+ const { signal } = options;
153
+ const serviceOrigin = editor.config.get('ckbox.serviceOrigin');
154
+ const workspaceId = await this.getWorkspaceId();
155
+ try {
156
+ const result = [];
157
+ let offset = 0;
158
+ let remainingItems;
159
+ do {
160
+ const data = await fetchCategories(offset);
161
+ result.push(...data.items);
162
+ remainingItems = data.totalCount - (offset + ITEMS_PER_REQUEST);
163
+ offset += ITEMS_PER_REQUEST;
164
+ } while (remainingItems > 0);
165
+ return result;
166
+ }
167
+ catch {
168
+ signal.throwIfAborted();
169
+ /**
170
+ * Fetching a list of available categories with which an uploaded file can be associated failed.
171
+ *
172
+ * @error ckbox-fetch-category-http-error
173
+ */
174
+ logError('ckbox-fetch-category-http-error');
175
+ return undefined;
176
+ }
177
+ async function fetchCategories(offset) {
178
+ const categoryUrl = new URL('categories', serviceOrigin);
179
+ categoryUrl.searchParams.set('limit', String(ITEMS_PER_REQUEST));
180
+ categoryUrl.searchParams.set('offset', String(offset));
181
+ categoryUrl.searchParams.set('workspaceId', workspaceId);
182
+ return sendHttpRequest({
183
+ url: categoryUrl,
184
+ signal,
185
+ authorization: (await token).value
186
+ });
187
+ }
188
+ }
189
+ }
package/src/index.d.ts ADDED
@@ -0,0 +1,17 @@
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 ckbox
7
+ */
8
+ export { default as CKBox } from './ckbox.js';
9
+ export { default as CKBoxEditing } from './ckboxediting.js';
10
+ export { default as CKBoxUI } from './ckboxui.js';
11
+ export { default as CKBoxImageEditEditing } from './ckboximageedit/ckboximageeditediting.js';
12
+ export { default as CKBoxImageEditUI } from './ckboximageedit/ckboximageeditui.js';
13
+ export { default as CKBoxImageEdit } from './ckboximageedit.js';
14
+ export type { default as CKBoxCommand } from './ckboxcommand.js';
15
+ export type { default as CKBoxImageEditCommand } from './ckboximageedit/ckboximageeditcommand.js';
16
+ export type { CKBoxConfig } from './ckboxconfig.js';
17
+ import './augmentation.js';
package/src/index.js ADDED
@@ -0,0 +1,14 @@
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 ckbox
7
+ */
8
+ export { default as CKBox } from './ckbox.js';
9
+ export { default as CKBoxEditing } from './ckboxediting.js';
10
+ export { default as CKBoxUI } from './ckboxui.js';
11
+ export { default as CKBoxImageEditEditing } from './ckboximageedit/ckboximageeditediting.js';
12
+ export { default as CKBoxImageEditUI } from './ckboximageedit/ckboximageeditui.js';
13
+ export { default as CKBoxImageEdit } from './ckboximageedit.js';
14
+ import './augmentation.js';
package/src/utils.d.ts ADDED
@@ -0,0 +1,63 @@
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 ckbox/utils
7
+ */
8
+ import type { InitializedToken } from '@ckeditor/ckeditor5-cloud-services';
9
+ import type { CKBoxImageUrls } from './ckboxconfig.js';
10
+ /**
11
+ * Converts image source set provided by the CKBox into an object containing:
12
+ * - responsive URLs for the "webp" image format,
13
+ * - one fallback URL for browsers that do not support the "webp" format.
14
+ */
15
+ export declare function getImageUrls(imageUrls: CKBoxImageUrls): {
16
+ imageFallbackUrl: string;
17
+ imageSources: Array<{
18
+ srcset: string;
19
+ sizes: string;
20
+ type: string;
21
+ }>;
22
+ };
23
+ /**
24
+ * Returns a workspace id to use for communication with the CKBox service.
25
+ *
26
+ * @param defaultWorkspaceId The default workspace to use taken from editor config.
27
+ */
28
+ export declare function getWorkspaceId(token: InitializedToken, defaultWorkspaceId?: string): string | null;
29
+ /**
30
+ * Generates an image data URL from its `blurhash` representation.
31
+ */
32
+ export declare function blurHashToDataUrl(hash?: string): string | undefined;
33
+ /**
34
+ * Sends the HTTP request.
35
+ *
36
+ * @internal
37
+ * @param config.url the URL where the request will be sent.
38
+ * @param config.method The HTTP method.
39
+ * @param config.data Additional data to send.
40
+ * @param config.onUploadProgress A callback informing about the upload progress.
41
+ */
42
+ export declare function sendHttpRequest({ url, method, data, onUploadProgress, signal, authorization }: {
43
+ url: URL;
44
+ signal: AbortSignal;
45
+ authorization: string;
46
+ method?: 'GET' | 'POST';
47
+ data?: FormData | null;
48
+ onUploadProgress?: (evt: ProgressEvent) => void;
49
+ }): Promise<any>;
50
+ /**
51
+ * Returns an extension a typical file in the specified `mimeType` format would have.
52
+ */
53
+ export declare function convertMimeTypeToExtension(mimeType: string): string;
54
+ /**
55
+ * Tries to fetch the given `url` and returns 'content-type' of the response.
56
+ */
57
+ export declare function getContentTypeOfUrl(url: string, options: {
58
+ signal: AbortSignal;
59
+ }): Promise<string>;
60
+ /**
61
+ * Returns an extension from the given value.
62
+ */
63
+ export declare function getFileExtension(file: File): string;