@_sh/strapi-plugin-ckeditor 1.1.3 → 2.0.1

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 (112) hide show
  1. package/README.md +353 -897
  2. package/admin/src/components/CKEditorIcon.js +46 -0
  3. package/admin/src/components/Input/CKEditor/configs/base.js +628 -0
  4. package/admin/src/components/Input/CKEditor/configs/blockBaloon.js +25 -0
  5. package/admin/src/components/Input/CKEditor/configs/index.js +11 -0
  6. package/admin/src/components/Input/CKEditor/configs/toolbar.js +17 -0
  7. package/admin/src/components/Input/CKEditor/configs/toolbarBaloon.js +17 -0
  8. package/admin/src/components/Input/CKEditor/configuration.js +166 -0
  9. package/admin/src/components/Input/CKEditor/index.js +120 -0
  10. package/admin/src/components/Input/CKEditor/plugins/StrapiMediaLib.js +43 -0
  11. package/admin/src/components/Input/CKEditor/plugins/StrapiUploadAdapter.js +203 -0
  12. package/admin/src/components/Input/CKEditor/plugins/index.js +2 -0
  13. package/admin/src/components/Input/CKEditor/styling.js +16 -0
  14. package/admin/src/components/Input/CKEditor/theme/additional.js +167 -0
  15. package/admin/src/components/Input/CKEditor/theme/common.js +277 -0
  16. package/admin/src/components/Input/CKEditor/theme/dark.js +144 -0
  17. package/admin/src/components/Input/CKEditor/theme/index.js +13 -0
  18. package/admin/src/components/Input/CKEditor/theme/light.js +135 -0
  19. package/admin/src/components/Input/MediaLib/index.js +79 -0
  20. package/admin/src/components/Input/index.js +48 -0
  21. package/admin/src/index.js +107 -15
  22. package/admin/src/utils/getEditorConfig.js +37 -0
  23. package/admin/src/utils/pluginId.js +5 -0
  24. package/package.json +43 -7
  25. package/server/controllers/config.js +8 -12
  26. package/server/index.js +1 -1
  27. package/server/register.js +7 -1
  28. package/server/routes/index.js +5 -6
  29. package/server/services/config.js +6 -14
  30. package/admin/src/components/CKEditor/build/ckeditor.js +0 -7
  31. package/admin/src/components/CKEditor/build/ckeditor.js.map +0 -1
  32. package/admin/src/components/CKEditor/build/translations/af.js +0 -1
  33. package/admin/src/components/CKEditor/build/translations/ar.js +0 -1
  34. package/admin/src/components/CKEditor/build/translations/ast.js +0 -1
  35. package/admin/src/components/CKEditor/build/translations/az.js +0 -1
  36. package/admin/src/components/CKEditor/build/translations/bg.js +0 -1
  37. package/admin/src/components/CKEditor/build/translations/bn.js +0 -1
  38. package/admin/src/components/CKEditor/build/translations/bs.js +0 -1
  39. package/admin/src/components/CKEditor/build/translations/ca.js +0 -1
  40. package/admin/src/components/CKEditor/build/translations/cs.js +0 -1
  41. package/admin/src/components/CKEditor/build/translations/da.js +0 -1
  42. package/admin/src/components/CKEditor/build/translations/de-ch.js +0 -1
  43. package/admin/src/components/CKEditor/build/translations/de.js +0 -1
  44. package/admin/src/components/CKEditor/build/translations/el.js +0 -1
  45. package/admin/src/components/CKEditor/build/translations/en-au.js +0 -1
  46. package/admin/src/components/CKEditor/build/translations/en-gb.js +0 -1
  47. package/admin/src/components/CKEditor/build/translations/eo.js +0 -1
  48. package/admin/src/components/CKEditor/build/translations/es.js +0 -1
  49. package/admin/src/components/CKEditor/build/translations/et.js +0 -1
  50. package/admin/src/components/CKEditor/build/translations/eu.js +0 -1
  51. package/admin/src/components/CKEditor/build/translations/fa.js +0 -1
  52. package/admin/src/components/CKEditor/build/translations/fi.js +0 -1
  53. package/admin/src/components/CKEditor/build/translations/fr.js +0 -1
  54. package/admin/src/components/CKEditor/build/translations/gl.js +0 -1
  55. package/admin/src/components/CKEditor/build/translations/gu.js +0 -1
  56. package/admin/src/components/CKEditor/build/translations/he.js +0 -1
  57. package/admin/src/components/CKEditor/build/translations/hi.js +0 -1
  58. package/admin/src/components/CKEditor/build/translations/hr.js +0 -1
  59. package/admin/src/components/CKEditor/build/translations/hu.js +0 -1
  60. package/admin/src/components/CKEditor/build/translations/id.js +0 -1
  61. package/admin/src/components/CKEditor/build/translations/it.js +0 -1
  62. package/admin/src/components/CKEditor/build/translations/ja.js +0 -1
  63. package/admin/src/components/CKEditor/build/translations/jv.js +0 -1
  64. package/admin/src/components/CKEditor/build/translations/kk.js +0 -1
  65. package/admin/src/components/CKEditor/build/translations/km.js +0 -1
  66. package/admin/src/components/CKEditor/build/translations/kn.js +0 -1
  67. package/admin/src/components/CKEditor/build/translations/ko.js +0 -1
  68. package/admin/src/components/CKEditor/build/translations/ku.js +0 -1
  69. package/admin/src/components/CKEditor/build/translations/lt.js +0 -1
  70. package/admin/src/components/CKEditor/build/translations/lv.js +0 -1
  71. package/admin/src/components/CKEditor/build/translations/ms.js +0 -1
  72. package/admin/src/components/CKEditor/build/translations/nb.js +0 -1
  73. package/admin/src/components/CKEditor/build/translations/ne.js +0 -1
  74. package/admin/src/components/CKEditor/build/translations/nl.js +0 -1
  75. package/admin/src/components/CKEditor/build/translations/no.js +0 -1
  76. package/admin/src/components/CKEditor/build/translations/oc.js +0 -1
  77. package/admin/src/components/CKEditor/build/translations/pl.js +0 -1
  78. package/admin/src/components/CKEditor/build/translations/pt-br.js +0 -1
  79. package/admin/src/components/CKEditor/build/translations/pt.js +0 -1
  80. package/admin/src/components/CKEditor/build/translations/ro.js +0 -1
  81. package/admin/src/components/CKEditor/build/translations/ru.js +0 -1
  82. package/admin/src/components/CKEditor/build/translations/si.js +0 -1
  83. package/admin/src/components/CKEditor/build/translations/sk.js +0 -1
  84. package/admin/src/components/CKEditor/build/translations/sl.js +0 -1
  85. package/admin/src/components/CKEditor/build/translations/sq.js +0 -1
  86. package/admin/src/components/CKEditor/build/translations/sr-latn.js +0 -1
  87. package/admin/src/components/CKEditor/build/translations/sr.js +0 -1
  88. package/admin/src/components/CKEditor/build/translations/sv.js +0 -1
  89. package/admin/src/components/CKEditor/build/translations/th.js +0 -1
  90. package/admin/src/components/CKEditor/build/translations/tk.js +0 -1
  91. package/admin/src/components/CKEditor/build/translations/tr.js +0 -1
  92. package/admin/src/components/CKEditor/build/translations/tt.js +0 -1
  93. package/admin/src/components/CKEditor/build/translations/ug.js +0 -1
  94. package/admin/src/components/CKEditor/build/translations/uk.js +0 -1
  95. package/admin/src/components/CKEditor/build/translations/ur.js +0 -1
  96. package/admin/src/components/CKEditor/build/translations/uz.js +0 -1
  97. package/admin/src/components/CKEditor/build/translations/vi.js +0 -1
  98. package/admin/src/components/CKEditor/build/translations/zh-cn.js +0 -1
  99. package/admin/src/components/CKEditor/build/translations/zh.js +0 -1
  100. package/admin/src/components/CKEditor/index.js +0 -247
  101. package/admin/src/components/CKEditor/styles.js +0 -511
  102. package/admin/src/components/CKEditor/theme.js +0 -313
  103. package/admin/src/components/Initializer/index.js +0 -26
  104. package/admin/src/components/MediaLib/index.js +0 -44
  105. package/admin/src/components/Wysiwyg/index.js +0 -77
  106. package/admin/src/pages/App/index.js +0 -25
  107. package/admin/src/pages/HomePage/index.js +0 -20
  108. package/admin/src/pluginId.js +0 -6
  109. package/admin/src/translations/en.json +0 -1
  110. package/admin/src/translations/fr.json +0 -1
  111. package/admin/src/utils/axiosInstance.js +0 -40
  112. package/admin/src/utils/getTrad.js +0 -5
@@ -0,0 +1,25 @@
1
+ import { blockBaloonEditorConfig } from "./base";
2
+
3
+ export const blockBaloonEditor = {
4
+ blockBaloon: {
5
+ styles: `
6
+ .ck-content{
7
+ border-radius:4px !important;
8
+ }
9
+ .ck-sticky-panel{
10
+ display:none !important;
11
+ }
12
+ `,
13
+ field: {
14
+ key: "blockBaloon",
15
+ value: "blockBaloon",
16
+ metadatas: {
17
+ intlLabel: {
18
+ id: "ckeditor.preset.blockBaloon.label",
19
+ defaultMessage: "Block baloon version",
20
+ },
21
+ },
22
+ },
23
+ editorConfig: blockBaloonEditorConfig,
24
+ },
25
+ };
@@ -0,0 +1,11 @@
1
+ import { toolbarEditor } from './toolbar';
2
+ import { toolbarBaloonEditor } from './toolbarBaloon';
3
+ import { blockBaloonEditor } from './blockBaloon';
4
+
5
+ const baseConfigs = {
6
+ ...toolbarEditor,
7
+ ...toolbarBaloonEditor,
8
+ ...blockBaloonEditor
9
+ }
10
+
11
+ export default baseConfigs;
@@ -0,0 +1,17 @@
1
+ import { toolbarEditorConfig } from "./base";
2
+
3
+ export const toolbarEditor = {
4
+ toolbar: {
5
+ field: {
6
+ key: "toolbar",
7
+ value: "toolbar",
8
+ metadatas: {
9
+ intlLabel: {
10
+ id: "ckeditor.preset.toolbar.label",
11
+ defaultMessage: "Toolbar version",
12
+ },
13
+ },
14
+ },
15
+ editorConfig: toolbarEditorConfig,
16
+ },
17
+ };
@@ -0,0 +1,17 @@
1
+ import { toolbarBaloonEditorConfig } from "./base";
2
+
3
+ export const toolbarBaloonEditor = {
4
+ toolbarBaloon: {
5
+ field: {
6
+ key: "toolbarBaloon",
7
+ value: "toolbarBaloon",
8
+ metadatas: {
9
+ intlLabel: {
10
+ id: "ckeditor.preset.toolbarBaloon.label",
11
+ defaultMessage: "Toolbar baloon version",
12
+ },
13
+ },
14
+ },
15
+ editorConfig: toolbarBaloonEditorConfig,
16
+ },
17
+ };
@@ -0,0 +1,166 @@
1
+ import { auth, request } from "@strapi/helper-plugin";
2
+ import cloneDeep from 'lodash/cloneDeep';
3
+
4
+ import baseConfigs from "./configs";
5
+ import pluginId from "../../../utils/pluginId";
6
+
7
+ const importLang = async (config, language) => {
8
+
9
+ if (!language) return;
10
+
11
+ const { plugins: configPlugins = [] } = config;
12
+
13
+ const configPluginNames = [...configPlugins.map((p) => p.pluginName)];
14
+
15
+ const plugins = [
16
+ { name: "DocumentList", module: "ckeditor5-list" },
17
+ { name: "TextPartLanguage", module: "ckeditor5-language" },
18
+ { name: "Alignment", module: "ckeditor5-alignment" },
19
+ { name: "Autosave", module: "ckeditor5-autosave" },
20
+ { name: "BlockQuote", module: "ckeditor5-block-quote" },
21
+ { name: "CodeBlock", module: "ckeditor5-code-block" },
22
+ { name: "Heading", module: "ckeditor5-heading" },
23
+ { name: "HtmlEmbed", module: "ckeditor5-html-embed" },
24
+ { name: "GeneralHtmlSupport", module: "ckeditor5-html-support" },
25
+ { name: "HorizontalLine", module: "ckeditor5-horizontal-line" },
26
+ { name: "MediaEmbed", module: "ckeditor5-media-embed" },
27
+ { name: "Image", module: "ckeditor5-image" },
28
+ { name: "Indent", module: "ckeditor5-indent" },
29
+ { name: "Link", module: "ckeditor5-link" },
30
+ { name: "RemoveFormat", module: "ckeditor5-remove-format" },
31
+ { name: "Table", module: "ckeditor5-table" },
32
+ { name: "WordCount", module: "ckeditor5-word-count" },
33
+ { name: "FindAndReplace", module: "ckeditor5-find-and-replace" },
34
+ { name: "SpecialCharacters", module: "ckeditor5-special-characters" },
35
+ { name: "PageBreak", module: "ckeditor5-page-break" },
36
+ { name: "SourceEditing", module: "ckeditor5-source-editing" },
37
+ { name: "Highlight", module: "ckeditor5-highlight" },
38
+ { name: "Style", module: "ckeditor5-style" },
39
+ ];
40
+
41
+ const basicStylesPlugin = [
42
+ "Bold",
43
+ "Code",
44
+ "Italic",
45
+ "Strikethrough",
46
+ "Subscript",
47
+ "Superscript",
48
+ "Underline",
49
+ ];
50
+
51
+ const fontPlugin = ["FontBackgroundColor", "FontColor", "FontFamily", "FontSize"];
52
+
53
+ const listPlugin = ["List", "DocumentList"];
54
+
55
+ await Promise.all(
56
+ plugins
57
+ .filter(({ name }) => configPluginNames.includes(name))
58
+ .map(
59
+ async ({ module }) =>
60
+ await import(
61
+ /* webpackMode: "lazy-once" */ `@ckeditor/${module}/build/translations/${language}.js`
62
+ ).catch(() => null)
63
+ )
64
+ );
65
+
66
+ if (configPluginNames.some((p) => basicStylesPlugin.includes(p)))
67
+ await import(
68
+ /* webpackMode: "lazy-once" */ `@ckeditor/ckeditor5-basic-styles/build/translations/${language}.js`
69
+ ).catch(() => null);
70
+ if (configPluginNames.some((p) => listPlugin.includes(p)))
71
+ await import(
72
+ /* webpackMode: "lazy-once" */ `@ckeditor/ckeditor5-list/build/translations/${language}.js`
73
+ ).catch(() => null);
74
+ if (configPluginNames.some((p) => fontPlugin.includes(p)))
75
+ await import(
76
+ /* webpackMode: "lazy-once" */ `@_sh/ckeditor5-font-with-picker/build/translations/${language}.js`
77
+ ).catch(() => null);
78
+ };
79
+
80
+ const setLanguage = async (config) => {
81
+ const urlSearchParams = new URLSearchParams(window.location.search);
82
+ const params = Object.fromEntries(urlSearchParams.entries());
83
+ const languageContent = params["plugins[i18n][locale]"];
84
+
85
+ const preferedLanguage = auth.getUserInfo().preferedLanguage;
86
+
87
+ const { ui = preferedLanguage || 'en', content, textPartLanguage, ignorei18n } = config.language || {};
88
+
89
+ if (languageContent) {
90
+ const locale = languageContent.split("-")[0];
91
+
92
+ config.language = {
93
+ ui: typeof config.language === "string" ? config.language : ui,
94
+ content: ignorei18n ? content : locale,
95
+ textPartLanguage: textPartLanguage,
96
+ };
97
+
98
+ await importLang(config, config.language.ui);
99
+ await importLang(config, config.language.content);
100
+ } else if (typeof config.language === "object") {
101
+ await importLang(config, config.language.ui);
102
+ await importLang(config, config.language.content);
103
+ } else if (typeof config.language === "string") {
104
+ await importLang(config, config.language);
105
+ } else {
106
+ config.language = preferedLanguage;
107
+ await importLang(config, preferedLanguage);
108
+ }
109
+ };
110
+
111
+ const getCurrentConfig = (presetName) => {
112
+ const { configs: userConfigs, configsOverwrite: overwrite } = globalThis.CKEditorConfig || {};
113
+
114
+ let configs;
115
+
116
+ if (overwrite) {
117
+ configs = userConfigs;
118
+ } else {
119
+ configs = baseConfigs;
120
+ if (userConfigs) {
121
+ Object.keys(userConfigs).map(cfgName=>{
122
+ if(baseConfigs.hasOwnProperty(cfgName)){
123
+ configs[cfgName].fields = { ...baseConfigs[cfgName].field, ...userConfigs[cfgName].field };
124
+ configs[cfgName].styles = userConfigs[cfgName].styles || baseConfigs[cfgName].styles;
125
+ configs[cfgName].editorConfig = { ...baseConfigs[cfgName].editorConfig, ...userConfigs[cfgName].editorConfig };
126
+ } else { configs[cfgName] = userConfigs[cfgName] }
127
+ })
128
+ }
129
+ }
130
+
131
+ const clonedConfig = cloneDeep(configs[presetName]);
132
+
133
+ return clonedConfig;
134
+ };
135
+
136
+ const setPlugins = (config, { responsiveDimensions }, toggleMediaLib) => {
137
+ const configPluginNames = config.editorConfig?.plugins ? [ ...config.editorConfig.plugins.map((p) => p.pluginName)] : [];
138
+
139
+ if (configPluginNames.includes("StrapiMediaLib")) {
140
+ config.editorConfig.strapiMediaLib = { toggle: toggleMediaLib };
141
+ }
142
+ if (configPluginNames.includes("StrapiUploadAdapter")) {
143
+ config.editorConfig.strapiUploadAdapter = {
144
+ uploadUrl: `${strapi.backendURL}/upload`,
145
+ headers: { Authorization: "Bearer " + auth.getToken() },
146
+ backendUrl: strapi.backendURL,
147
+ responsive: responsiveDimensions,
148
+ };
149
+ }
150
+ if (configPluginNames.includes("WordCount")) {
151
+ config.editorConfig.WordCountPlugin = true;
152
+ }
153
+ };
154
+ const requestConfig = (key) => request(`/${pluginId}/config/${key}`, { method: "GET" });
155
+
156
+ export const getConfiguration = async (presetName, toggleMediaLib) => {
157
+ const currentConfig = getCurrentConfig(presetName);
158
+
159
+ const uploadPluginConfig = await requestConfig("upload");
160
+
161
+ setPlugins(currentConfig, uploadPluginConfig, toggleMediaLib);
162
+
163
+ await setLanguage(currentConfig.editorConfig);
164
+
165
+ return { currentConfig, uploadPluginConfig };
166
+ };
@@ -0,0 +1,120 @@
1
+ import React, { useEffect, useRef, useState } from "react";
2
+ import PropTypes from "prop-types";
3
+ import styled from "styled-components";
4
+ import { CKEditor } from "@ckeditor/ckeditor5-react";
5
+ import { Box, Loader } from '@strapi/design-system';
6
+
7
+ import {getConfiguration} from "./configuration";
8
+ import {getGlobalStyling} from "./styling";
9
+ import MediaLib from "../MediaLib";
10
+
11
+ import ckeditor5Dll from "ckeditor5/build/ckeditor5-dll.js";
12
+ import ckeditor5EditorClassicDll from "@ckeditor/ckeditor5-editor-classic/build/editor-classic.js";
13
+
14
+ const GlobalStyling = getGlobalStyling();
15
+
16
+ const Wrapper = styled("div")`${({ editorStyles }) => editorStyles}`;
17
+
18
+ const Editor = ({ onChange, name, value, disabled, preset, maxLength }) => {
19
+
20
+ const [ editorInstance, setEditorInstance ] = useState(false);
21
+
22
+ const [mediaLibVisible, setMediaLibVisible] = useState(false);
23
+
24
+ const [uploadPluginConfig, setUploadPluginConfig] = useState(null);
25
+
26
+ const [config, setConfig] = useState(null);
27
+
28
+ const [lengthMax, setLengthMax] = useState(false);
29
+
30
+ const wordCounter = useRef(null);
31
+
32
+ const handleToggleMediaLib = () => setMediaLibVisible(prev => !prev);
33
+
34
+ const handleCounter = (number) => number > maxLength ? setLengthMax(true) : setLengthMax(false);
35
+
36
+ useEffect(() => {
37
+ (async () => {
38
+ const {currentConfig, uploadPluginConfig} = await getConfiguration(preset, handleToggleMediaLib);
39
+ setConfig(currentConfig);
40
+ setUploadPluginConfig(uploadPluginConfig);
41
+ })();
42
+ }, []);
43
+
44
+ return (
45
+ <>
46
+ {config && <GlobalStyling />}
47
+ <Wrapper editorStyles={config?.styles} >
48
+ {!config &&
49
+ <LoaderBox hasRadius background="neutral100">
50
+ <Loader>Loading...</Loader>
51
+ </LoaderBox>}
52
+ {config &&
53
+ <CKEditor
54
+ editor={window.CKEditor5.editorClassic.ClassicEditor}
55
+ config={config?.editorConfig}
56
+ disabled={disabled}
57
+ data={value || ""}
58
+ onReady={(editor) => {
59
+ editor.setData(value || "");
60
+
61
+ if(config.editorConfig.WordCountPlugin){
62
+ const wordCountPlugin = editor.plugins.get( 'WordCount' );
63
+ wordCountPlugin.on( 'update', ( evt, stats ) =>handleCounter(stats.characters));
64
+ const wordCountWrapper = wordCounter.current;
65
+ wordCountWrapper?.appendChild( wordCountPlugin.wordCountContainer );
66
+ }
67
+
68
+ if(editor.plugins.has( 'ImageUploadEditing' )){
69
+ editor.plugins.get( 'ImageUploadEditing' ).on( 'uploadComplete', ( evt, { data, imageElement } ) =>
70
+ editor.model.change( writer => writer.setAttribute( 'alt', data.alt, imageElement ) ) );
71
+ }
72
+
73
+ setEditorInstance( editor );
74
+ }}
75
+ onChange={(event, editor) => {
76
+ const data = editor.getData();
77
+ onChange({ target: { name, value: data } });
78
+ }}
79
+ />
80
+ }
81
+ {config && config.editorConfig.WordCountPlugin &&
82
+ <CounterLoaderBox
83
+ color={lengthMax?"danger500":"neutral400"}
84
+ ref={wordCounter}>
85
+ {!editorInstance && <Loader small>Loading...</Loader>}
86
+ </CounterLoaderBox>
87
+ }
88
+ {uploadPluginConfig && <MediaLib isOpen={mediaLibVisible} onToggle={handleToggleMediaLib} editor={editorInstance} uploadConfig={uploadPluginConfig} />}
89
+ </Wrapper>
90
+ </>
91
+ );
92
+ };
93
+
94
+ Editor.defaultProps = {
95
+ value: "",
96
+ disabled: false,
97
+ };
98
+
99
+ Editor.propTypes = {
100
+ onChange: PropTypes.func.isRequired,
101
+ name: PropTypes.string.isRequired,
102
+ value: PropTypes.string,
103
+ disabled: PropTypes.bool,
104
+ };
105
+
106
+ const CounterLoaderBox = styled(Box)`
107
+ display:flex;
108
+ width: 100%;
109
+ justify-content: flex-end;
110
+ align-items: center;
111
+ `
112
+ const LoaderBox = styled(Box)`
113
+ display:flex;
114
+ height: 200px;
115
+ width: 100%;
116
+ justify-content: center;
117
+ align-items: center;
118
+ `
119
+
120
+ export default Editor;
@@ -0,0 +1,43 @@
1
+ const Plugin = window.CKEditor5.core.Plugin;
2
+ const ButtonView = window.CKEditor5.ui.ButtonView;
3
+ const mediaLibIcon = '<svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">' +
4
+ '<path fill-rule="evenodd" clip-rule="evenodd" d="M4.3.6a.9.9 0 100 1.8h15.311a.9.9 0 100-1.8H4.301zm17.1 3.7A1.6 1.6' +
5
+ ' 0 0123 5.9v15.5a1.6 1.6 0 01-1.6 1.6H2.6A1.601 1.601 0 011 21.4V8 5.915C1 5.03 1.716 4.3 2.6' +
6
+ ' 4.3h18.8zM5.032 19.18h14.336l-3.136-3.205-1.792 1.831-4.032-4.12-5.376 5.494zm13.44-8.697c0 ' +
7
+ '1.282-.985 2.289-2.24 2.289-1.254 0-2.24-1.007-2.24-2.29 0-1.281.986-2.288 2.24-2.288 1.255 0 2.24 1.007 2.24 2.289z">' +
8
+ '</path></svg>'
9
+
10
+ export default class StrapiMediaLib extends Plugin {
11
+
12
+ /**
13
+ * Strapi function used to show media library modal.
14
+ * Should be provided via connect method before using toggle method.
15
+ *
16
+ * @type {function|null}
17
+ */
18
+ strapiToggle = null;
19
+
20
+ static get pluginName() {
21
+ return 'StrapiMediaLib'
22
+ }
23
+
24
+ init() {
25
+ const editor = this.editor;
26
+ const config = editor.config.get('strapiMediaLib');
27
+ editor.ui.componentFactory.add('strapiMediaLib', () => {
28
+
29
+ const button = new ButtonView();
30
+
31
+ button.set({
32
+ label: "Media Library",
33
+ icon: mediaLibIcon,
34
+ tooltip: true
35
+ });
36
+
37
+ button.on('execute', config.toggle.bind(this));
38
+
39
+ return button;
40
+ });
41
+ }
42
+
43
+ }
@@ -0,0 +1,203 @@
1
+ const Plugin = window.CKEditor5.core.Plugin;
2
+ const FileRepository = window.CKEditor5.upload.FileRepository;
3
+
4
+ /**
5
+ * Similar to Simple upload adapter but customized for Strapi.
6
+ * Inspired by https://github.com/ckeditor/ckeditor5/blob/master/packages/ckeditor5-upload/src/adapters/simpleuploadadapter.js
7
+ */
8
+ export default class StrapiUploadAdapter extends Plugin {
9
+ /**
10
+ * @inheritDoc
11
+ */
12
+ static get requires() {
13
+ return [FileRepository];
14
+ }
15
+
16
+ /**
17
+ * @inheritDoc
18
+ */
19
+ static get pluginName() {
20
+ return "StrapiUploadAdapter";
21
+ }
22
+
23
+ /**
24
+ * @inheritDoc
25
+ */
26
+ init() {
27
+
28
+ // backendUrl
29
+ // uploadUrl
30
+ // headers
31
+ // responsive
32
+
33
+ const options = this.editor.config.get("strapiUploadAdapter");
34
+
35
+ if (!options) {
36
+ return;
37
+ }
38
+
39
+ if (!options.uploadUrl) {
40
+ console.warn(
41
+ 'strapi-upload-adapter-missing-uploadUrl: Missing the "uploadUrl" property in the "strapiUploadAdapter" editor configuration.'
42
+ );
43
+
44
+ return;
45
+ }
46
+
47
+ this.editor.plugins.get(FileRepository).createUploadAdapter = (loader) => {
48
+ return new Adapter(loader, options);
49
+ };
50
+ }
51
+ }
52
+
53
+ /**
54
+ * Upload adapter.
55
+ *
56
+ * @private
57
+ */
58
+ class Adapter {
59
+ /**
60
+ * Creates a new adapter instance.
61
+ */
62
+ constructor(loader, options) {
63
+ /**
64
+ * FileLoader instance to use during the upload.
65
+ *
66
+ */
67
+ this.loader = loader;
68
+
69
+ /**
70
+ * The configuration of the adapter.
71
+ *
72
+ */
73
+ this.options = options;
74
+ }
75
+
76
+ /**
77
+ * Starts the upload process.
78
+ *
79
+ * @returns {Promise}
80
+ */
81
+ upload() {
82
+ return this.loader.file.then(
83
+ (file) =>
84
+ new Promise((resolve, reject) => {
85
+ this._initRequest();
86
+ this._initListeners(resolve, reject, file);
87
+ this._sendRequest(file);
88
+ })
89
+ );
90
+ }
91
+
92
+ /**
93
+ * Aborts the upload process.
94
+ *
95
+ * @returns {Promise}
96
+ */
97
+ abort() {
98
+ if (this.xhr) {
99
+ this.xhr.abort();
100
+ }
101
+ }
102
+
103
+ /**
104
+ * Initializes the `XMLHttpRequest` object using the URL specified as
105
+ * `strapiUpload.uploadUrl` in the editor's
106
+ * configuration.
107
+ *
108
+ * @private
109
+ */
110
+ _initRequest() {
111
+ const xhr = (this.xhr = new XMLHttpRequest());
112
+
113
+ xhr.open("POST", this.options.uploadUrl, true);
114
+ xhr.responseType = "json";
115
+ }
116
+
117
+ /**
118
+ * Initializes XMLHttpRequest listeners
119
+ *
120
+ * @private
121
+ * @param {Function} resolve Callback function to be called when the request is successful.
122
+ * @param {Function} reject Callback function to be called when the request cannot be completed.
123
+ * @param {File} file Native File object.
124
+ */
125
+ _initListeners(resolve, reject, file) {
126
+ const xhr = this.xhr;
127
+ const loader = this.loader;
128
+ const genericErrorText = `Couldn't upload file: ${file.name}.`;
129
+
130
+ xhr.addEventListener("error", () => reject(genericErrorText));
131
+ xhr.addEventListener("abort", () => reject());
132
+ xhr.addEventListener("load", () => {
133
+ const response = xhr.response;
134
+
135
+ if (!Array.isArray(response) || response.error || response.length !== 1) {
136
+ return reject(
137
+ response && response.error && response.error.message
138
+ ? response.error.message
139
+ : genericErrorText
140
+ );
141
+ }
142
+
143
+
144
+ const { backendUrl, responsive } = this.options || {};
145
+
146
+ if (response[0].formats && responsive) {
147
+ const { name, url, alternativeText, formats } = response[0];
148
+ let urls = { default: backendUrl + url };
149
+ let keys = Object.keys(formats).sort((a, b) => formats[a].width - formats[b].width);
150
+ keys.map((k) => (urls[formats[k].width] = backendUrl + formats[k].url));
151
+ resolve({ alt: alternativeText || name, urls: urls });
152
+ } else {
153
+ resolve(
154
+ response[0].url
155
+ ? {
156
+ alt: response[0].alternativeText || response[0].name,
157
+ urls: { default: backendUrl + response[0].url },
158
+ }
159
+ : null
160
+ );
161
+ }
162
+ });
163
+
164
+ // Upload progress when it is supported.
165
+ /* istanbul ignore else */
166
+ if (xhr.upload) {
167
+ xhr.upload.addEventListener("progress", (evt) => {
168
+ if (evt.lengthComputable) {
169
+ loader.uploadTotal = evt.total;
170
+ loader.uploaded = evt.loaded;
171
+ }
172
+ });
173
+ }
174
+ }
175
+
176
+ /**
177
+ * Prepares the data and sends the request.
178
+ *
179
+ * @private
180
+ * @param {File} file File instance to be uploaded.
181
+ */
182
+ _sendRequest(file) {
183
+ // Set headers if specified.
184
+ const headers = this.options.headers || {};
185
+
186
+ // Use the withCredentials flag if specified.
187
+ const withCredentials = this.options.withCredentials || false;
188
+
189
+ for (const headerName of Object.keys(headers)) {
190
+ this.xhr.setRequestHeader(headerName, headers[headerName]);
191
+ }
192
+
193
+ this.xhr.withCredentials = withCredentials;
194
+
195
+ // Prepare the form data.
196
+ const data = new FormData();
197
+
198
+ data.append("files", file);
199
+
200
+ // Send the request.
201
+ this.xhr.send(data);
202
+ }
203
+ }
@@ -0,0 +1,2 @@
1
+ export { default as StrapiMediaLib } from './StrapiMediaLib';
2
+ export { default as StrapiUploadAdapter } from './StrapiUploadAdapter';
@@ -0,0 +1,16 @@
1
+ import baseTheme from "./theme";
2
+ import { createGlobalStyle } from "styled-components";
3
+
4
+ export const getGlobalStyling = () => {
5
+
6
+ const variant = localStorage.getItem("STRAPI_THEME") || "light";
7
+ const { theme: userTheme, themeOverwrite: overwrite } = globalThis.CKEditorConfig || {};
8
+
9
+ const theme = overwrite ? userTheme : { ...baseTheme, ...userTheme};
10
+
11
+ return createGlobalStyle`
12
+ ${theme.common}
13
+ ${theme[variant]}
14
+ ${theme.additional}
15
+ `;
16
+ }