@ckeditor/ckeditor5-ckbox 0.0.0-nightly-20231205.0 → 0.0.0-nightly-20231207.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. package/build/ckbox.js +2 -2
  2. package/build/translations/ar.js +1 -1
  3. package/build/translations/az.js +1 -1
  4. package/build/translations/bg.js +1 -1
  5. package/build/translations/bn.js +1 -1
  6. package/build/translations/ca.js +1 -1
  7. package/build/translations/cs.js +1 -1
  8. package/build/translations/da.js +1 -1
  9. package/build/translations/de.js +1 -1
  10. package/build/translations/el.js +1 -1
  11. package/build/translations/en-au.js +1 -1
  12. package/build/translations/es-co.js +1 -1
  13. package/build/translations/es.js +1 -1
  14. package/build/translations/et.js +1 -1
  15. package/build/translations/fa.js +1 -1
  16. package/build/translations/fi.js +1 -1
  17. package/build/translations/fr.js +1 -1
  18. package/build/translations/gl.js +1 -1
  19. package/build/translations/he.js +1 -1
  20. package/build/translations/hi.js +1 -1
  21. package/build/translations/hr.js +1 -1
  22. package/build/translations/hu.js +1 -1
  23. package/build/translations/id.js +1 -1
  24. package/build/translations/it.js +1 -1
  25. package/build/translations/ja.js +1 -1
  26. package/build/translations/ko.js +1 -1
  27. package/build/translations/lt.js +1 -1
  28. package/build/translations/lv.js +1 -1
  29. package/build/translations/ms.js +1 -1
  30. package/build/translations/nl.js +1 -1
  31. package/build/translations/no.js +1 -1
  32. package/build/translations/pl.js +1 -1
  33. package/build/translations/pt-br.js +1 -1
  34. package/build/translations/pt.js +1 -1
  35. package/build/translations/ro.js +1 -1
  36. package/build/translations/ru.js +1 -1
  37. package/build/translations/sk.js +1 -1
  38. package/build/translations/sq.js +1 -1
  39. package/build/translations/sr-latn.js +1 -1
  40. package/build/translations/sr.js +1 -1
  41. package/build/translations/sv.js +1 -1
  42. package/build/translations/th.js +1 -1
  43. package/build/translations/tr.js +1 -1
  44. package/build/translations/ug.js +1 -1
  45. package/build/translations/uk.js +1 -1
  46. package/build/translations/ur.js +1 -1
  47. package/build/translations/uz.js +1 -1
  48. package/build/translations/vi.js +1 -1
  49. package/build/translations/zh-cn.js +1 -1
  50. package/build/translations/zh.js +1 -1
  51. package/lang/contexts.json +2 -1
  52. package/lang/translations/ar.po +18 -2
  53. package/lang/translations/az.po +18 -2
  54. package/lang/translations/bg.po +18 -2
  55. package/lang/translations/bn.po +18 -2
  56. package/lang/translations/ca.po +18 -2
  57. package/lang/translations/cs.po +18 -2
  58. package/lang/translations/da.po +18 -2
  59. package/lang/translations/de.po +18 -2
  60. package/lang/translations/el.po +18 -2
  61. package/lang/translations/en-au.po +18 -2
  62. package/lang/translations/en.po +18 -2
  63. package/lang/translations/es-co.po +18 -2
  64. package/lang/translations/es.po +18 -2
  65. package/lang/translations/et.po +18 -2
  66. package/lang/translations/fa.po +18 -2
  67. package/lang/translations/fi.po +18 -2
  68. package/lang/translations/fr.po +18 -2
  69. package/lang/translations/gl.po +18 -2
  70. package/lang/translations/he.po +18 -2
  71. package/lang/translations/hi.po +18 -2
  72. package/lang/translations/hr.po +18 -2
  73. package/lang/translations/hu.po +18 -2
  74. package/lang/translations/id.po +18 -2
  75. package/lang/translations/it.po +18 -2
  76. package/lang/translations/ja.po +18 -2
  77. package/lang/translations/ko.po +18 -2
  78. package/lang/translations/lt.po +18 -2
  79. package/lang/translations/lv.po +18 -2
  80. package/lang/translations/ms.po +18 -2
  81. package/lang/translations/nl.po +18 -2
  82. package/lang/translations/no.po +18 -2
  83. package/lang/translations/pl.po +18 -2
  84. package/lang/translations/pt-br.po +18 -2
  85. package/lang/translations/pt.po +18 -2
  86. package/lang/translations/ro.po +18 -2
  87. package/lang/translations/ru.po +18 -2
  88. package/lang/translations/sk.po +18 -2
  89. package/lang/translations/sq.po +18 -2
  90. package/lang/translations/sr-latn.po +18 -2
  91. package/lang/translations/sr.po +18 -2
  92. package/lang/translations/sv.po +18 -2
  93. package/lang/translations/th.po +18 -2
  94. package/lang/translations/tr.po +18 -2
  95. package/lang/translations/ug.po +18 -2
  96. package/lang/translations/uk.po +18 -2
  97. package/lang/translations/ur.po +18 -2
  98. package/lang/translations/uz.po +18 -2
  99. package/lang/translations/vi.po +18 -2
  100. package/lang/translations/zh-cn.po +18 -2
  101. package/lang/translations/zh.po +18 -2
  102. package/package.json +2 -2
  103. package/src/ckboxconfig.d.ts +18 -0
  104. package/src/ckboxediting.d.ts +5 -12
  105. package/src/ckboxediting.js +7 -55
  106. package/src/ckboximageedit/ckboximageeditcommand.d.ts +10 -1
  107. package/src/ckboximageedit/ckboximageeditcommand.js +55 -23
  108. package/src/ckboximageedit/ckboximageeditediting.d.ts +3 -1
  109. package/src/ckboximageedit/ckboximageeditediting.js +3 -1
  110. package/src/ckboximageedit/utils.d.ts +10 -0
  111. package/src/ckboximageedit/utils.js +48 -0
  112. package/src/ckboximageedit.d.ts +1 -2
  113. package/src/ckboximageedit.js +1 -2
  114. package/src/ckboxui.js +28 -1
  115. package/src/ckboxuploadadapter.d.ts +0 -5
  116. package/src/ckboxuploadadapter.js +10 -111
  117. package/src/ckboxutils.d.ts +51 -0
  118. package/src/ckboxutils.js +184 -0
  119. package/src/utils.d.ts +8 -0
  120. package/src/utils.js +36 -0
  121. package/theme/icons/ckbox-image-edit.svg +1 -1
@@ -0,0 +1,184 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2023, 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';
6
+ import { Plugin } from 'ckeditor5/src/core';
7
+ import { convertMimeTypeToExtension, getContentTypeOfUrl, getFileExtension, getWorkspaceId, sendHttpRequest } from './utils';
8
+ const DEFAULT_CKBOX_THEME_NAME = 'lark';
9
+ /**
10
+ * The CKBox editing feature. It introduces the {@link module:ckbox/ckboxcommand~CKBoxCommand CKBox command} and
11
+ * {@link module:ckbox/ckboxuploadadapter~CKBoxUploadAdapter CKBox upload adapter}.
12
+ */
13
+ export default class CKBoxUtils extends Plugin {
14
+ /**
15
+ * @inheritDoc
16
+ */
17
+ static get pluginName() {
18
+ return 'CKBoxUtils';
19
+ }
20
+ /**
21
+ * @inheritDoc
22
+ */
23
+ static get requires() {
24
+ return ['CloudServices'];
25
+ }
26
+ /**
27
+ * @inheritDoc
28
+ */
29
+ async init() {
30
+ const editor = this.editor;
31
+ const hasConfiguration = !!editor.config.get('ckbox');
32
+ const isLibraryLoaded = !!window.CKBox;
33
+ // Proceed with plugin initialization only when the integrator intentionally wants to use it, i.e. when the `config.ckbox` exists or
34
+ // the CKBox JavaScript library is loaded.
35
+ if (!hasConfiguration && !isLibraryLoaded) {
36
+ return;
37
+ }
38
+ editor.config.define('ckbox', {
39
+ serviceOrigin: 'https://api.ckbox.io',
40
+ defaultUploadCategories: null,
41
+ ignoreDataId: false,
42
+ language: editor.locale.uiLanguage,
43
+ theme: DEFAULT_CKBOX_THEME_NAME,
44
+ tokenUrl: editor.config.get('cloudServices.tokenUrl')
45
+ });
46
+ const cloudServices = editor.plugins.get('CloudServices');
47
+ const cloudServicesTokenUrl = editor.config.get('cloudServices.tokenUrl');
48
+ const ckboxTokenUrl = editor.config.get('ckbox.tokenUrl');
49
+ if (!ckboxTokenUrl) {
50
+ /**
51
+ * The {@link module:ckbox/ckboxconfig~CKBoxConfig#tokenUrl `config.ckbox.tokenUrl`} or the
52
+ * {@link module:cloud-services/cloudservicesconfig~CloudServicesConfig#tokenUrl `config.cloudServices.tokenUrl`}
53
+ * configuration is required for the CKBox plugin.
54
+ *
55
+ * ```ts
56
+ * ClassicEditor.create( document.createElement( 'div' ), {
57
+ * ckbox: {
58
+ * tokenUrl: "YOUR_TOKEN_URL"
59
+ * // ...
60
+ * }
61
+ * // ...
62
+ * } );
63
+ * ```
64
+ *
65
+ * @error ckbox-plugin-missing-token-url
66
+ */
67
+ throw new CKEditorError('ckbox-plugin-missing-token-url', this);
68
+ }
69
+ if (ckboxTokenUrl == cloudServicesTokenUrl) {
70
+ this._token = cloudServices.token;
71
+ }
72
+ else {
73
+ this._token = await cloudServices.registerTokenUrl(ckboxTokenUrl);
74
+ }
75
+ }
76
+ /**
77
+ * Returns a token used by the CKBox plugin for communication with the CKBox service.
78
+ */
79
+ getToken() {
80
+ return this._token;
81
+ }
82
+ /**
83
+ * The ID of workspace to use when uploading an image.
84
+ */
85
+ getWorkspaceId() {
86
+ const t = this.editor.t;
87
+ const cannotAccessDefaultWorkspaceError = t('Cannot access default workspace.');
88
+ const defaultWorkspaceId = this.editor.config.get('ckbox.defaultUploadWorkspaceId');
89
+ const workspaceId = getWorkspaceId(this._token, defaultWorkspaceId);
90
+ if (workspaceId == null) {
91
+ /**
92
+ * The user is not authorized to access the workspace defined in the`ckbox.defaultUploadWorkspaceId` configuration.
93
+ *
94
+ * @error ckbox-access-default-workspace-error
95
+ */
96
+ logError('ckbox-access-default-workspace-error');
97
+ throw cannotAccessDefaultWorkspaceError;
98
+ }
99
+ return workspaceId;
100
+ }
101
+ /**
102
+ * Resolves a promise with an object containing a category with which the uploaded file is associated or an error code.
103
+ */
104
+ async getCategoryIdForFile(fileOrUrl, options) {
105
+ const t = this.editor.t;
106
+ const cannotFindCategoryError = t('Cannot determine a category for the uploaded file.');
107
+ const defaultCategories = this.editor.config.get('ckbox.defaultUploadCategories');
108
+ const allCategoriesPromise = this._getAvailableCategories(options);
109
+ const extension = typeof fileOrUrl == 'string' ?
110
+ convertMimeTypeToExtension(await getContentTypeOfUrl(fileOrUrl, options)) :
111
+ getFileExtension(fileOrUrl);
112
+ const allCategories = await allCategoriesPromise;
113
+ // Couldn't fetch all categories. Perhaps the authorization token is invalid.
114
+ if (!allCategories) {
115
+ throw cannotFindCategoryError;
116
+ }
117
+ // If a user specifies the plugin configuration, find the first category that accepts the uploaded file.
118
+ if (defaultCategories) {
119
+ const userCategory = Object.keys(defaultCategories).find(category => {
120
+ return defaultCategories[category].find(e => e.toLowerCase() == extension);
121
+ });
122
+ // If found, return its ID if the category exists on the server side.
123
+ if (userCategory) {
124
+ const serverCategory = allCategories.find(category => category.id === userCategory || category.name === userCategory);
125
+ if (!serverCategory) {
126
+ throw cannotFindCategoryError;
127
+ }
128
+ return serverCategory.id;
129
+ }
130
+ }
131
+ // Otherwise, find the first category that accepts the uploaded file and returns its ID.
132
+ const category = allCategories.find(category => category.extensions.find(e => e.toLowerCase() == extension));
133
+ if (!category) {
134
+ throw cannotFindCategoryError;
135
+ }
136
+ return category.id;
137
+ }
138
+ /**
139
+ * Resolves a promise with an array containing available categories with which the uploaded file can be associated.
140
+ *
141
+ * If the API returns limited results, the method will collect all items.
142
+ */
143
+ async _getAvailableCategories(options) {
144
+ const ITEMS_PER_REQUEST = 50;
145
+ const editor = this.editor;
146
+ const token = this._token;
147
+ const { signal } = options;
148
+ const serviceOrigin = editor.config.get('ckbox.serviceOrigin');
149
+ const workspaceId = this.getWorkspaceId();
150
+ try {
151
+ const result = [];
152
+ let offset = 0;
153
+ let remainingItems;
154
+ do {
155
+ const data = await fetchCategories(offset);
156
+ result.push(...data.items);
157
+ remainingItems = data.totalCount - (offset + ITEMS_PER_REQUEST);
158
+ offset += ITEMS_PER_REQUEST;
159
+ } while (remainingItems > 0);
160
+ return result;
161
+ }
162
+ catch {
163
+ signal.throwIfAborted();
164
+ /**
165
+ * Fetching a list of available categories with which an uploaded file can be associated failed.
166
+ *
167
+ * @error ckbox-fetch-category-http-error
168
+ */
169
+ logError('ckbox-fetch-category-http-error');
170
+ return undefined;
171
+ }
172
+ function fetchCategories(offset) {
173
+ const categoryUrl = new URL('categories', serviceOrigin);
174
+ categoryUrl.searchParams.set('limit', ITEMS_PER_REQUEST.toString());
175
+ categoryUrl.searchParams.set('offset', offset.toString());
176
+ categoryUrl.searchParams.set('workspaceId', workspaceId);
177
+ return sendHttpRequest({
178
+ url: categoryUrl,
179
+ signal,
180
+ authorization: token.value
181
+ });
182
+ }
183
+ }
184
+ }
package/src/utils.d.ts CHANGED
@@ -47,3 +47,11 @@ export declare function sendHttpRequest({ url, method, data, onUploadProgress, s
47
47
  data?: FormData | null;
48
48
  onUploadProgress?: (evt: ProgressEvent) => void;
49
49
  }): Promise<any>;
50
+ export declare function convertMimeTypeToExtension(mimeType: string): string;
51
+ export declare function getContentTypeOfUrl(url: string, options: {
52
+ signal: AbortSignal;
53
+ }): Promise<string>;
54
+ /**
55
+ * Returns an extension from the given value.
56
+ */
57
+ export declare function getFileExtension(file: File): string;
package/src/utils.js CHANGED
@@ -131,3 +131,39 @@ export function sendHttpRequest({ url, method = 'GET', data, onUploadProgress, s
131
131
  xhr.send(data);
132
132
  });
133
133
  }
134
+ const MIME_TO_EXTENSION = {
135
+ 'image/gif': 'gif',
136
+ 'image/jpeg': 'jpg',
137
+ 'image/png': 'png',
138
+ 'image/webp': 'webp',
139
+ 'image/bmp': 'bmp',
140
+ 'image/tiff': 'tiff'
141
+ };
142
+ export function convertMimeTypeToExtension(mimeType) {
143
+ return MIME_TO_EXTENSION[mimeType];
144
+ }
145
+ export async function getContentTypeOfUrl(url, options) {
146
+ try {
147
+ const response = await fetch(url, {
148
+ method: 'HEAD',
149
+ cache: 'force-cache',
150
+ ...options
151
+ });
152
+ if (!response.ok) {
153
+ return '';
154
+ }
155
+ return response.headers.get('content-type') || '';
156
+ }
157
+ catch {
158
+ return '';
159
+ }
160
+ }
161
+ /**
162
+ * Returns an extension from the given value.
163
+ */
164
+ export function getFileExtension(file) {
165
+ const fileName = file.name;
166
+ const extensionRegExp = /\.(?<ext>[^.]+)$/;
167
+ const match = fileName.match(extensionRegExp);
168
+ return match.groups.ext.toLowerCase();
169
+ }
@@ -1 +1 @@
1
- <svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path clip-rule="evenodd" d="M5.802 8.942a.607.607 0 0 0-.838-.029L1.429 12.8V3.158h12.93v5.25l1.429-1.319V2.758c0-.553-.467-1-1.039-1H1.05c-.582 0-1.049.447-1.049 1v11.281c0 .562.467 1.01 1.039 1.01h6.583v-.228c0-.124.052-.242.143-.326l4.504-4.157-.312-.367a.61.61 0 0 0-.829 0l-2.124 1.962-3.202-2.991Zm3.74-2.578a1.87 1.87 0 1 0 3.707-.486 1.87 1.87 0 0 0-3.707.486Z"/><path d="M8.874 15.926v2.316h2.317l6.836-6.834-2.32-2.32-6.833 6.84v-.002Zm10.944-6.312a.612.612 0 0 0 0-.87L18.372 7.3a.614.614 0 0 0-.87 0l-1.133 1.128 2.32 2.319 1.13-1.133Z"/></svg>
1
+ <svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M1.201 1C.538 1 0 1.47 0 2.1v12.86C0 15.603.534 16 1.186 16H6.45l3.647-3.596-3.48-3.254a.694.694 0 0 0-.958-.033L1.5 13.6V2.5h15v4.59a3.477 3.477 0 0 1 1.5.15V2.1c0-.63-.547-1.1-1.2-1.1H1.202Zm11.723 2.805a2.137 2.137 0 0 0-2.045 2.406 2.13 2.13 0 0 0 4.172.277 2.134 2.134 0 0 0-.76-2.244 2.13 2.13 0 0 0-1.367-.44Z"/><path d="M8.1 17.612V20h2.39l7.046-7.046-2.39-2.39L8.1 17.612Zm11.283-6.506a.638.638 0 0 0 .139-.692.603.603 0 0 0-.139-.206L17.892 8.72a.63.63 0 0 0-.898 0l-1.167 1.163 2.391 2.39 1.165-1.167Z"/></svg>