@_sh/strapi-plugin-ckeditor 2.0.2 → 2.0.4

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 (34) hide show
  1. package/LICENSE +20 -20
  2. package/README.md +448 -448
  3. package/admin/src/components/CKEditorIcon.js +45 -45
  4. package/admin/src/components/Input/CKEditor/configs/base.js +627 -627
  5. package/admin/src/components/Input/CKEditor/configs/blockBaloon.js +25 -25
  6. package/admin/src/components/Input/CKEditor/configs/index.js +11 -11
  7. package/admin/src/components/Input/CKEditor/configs/toolbar.js +17 -17
  8. package/admin/src/components/Input/CKEditor/configs/toolbarBaloon.js +17 -17
  9. package/admin/src/components/Input/CKEditor/configuration.js +165 -165
  10. package/admin/src/components/Input/CKEditor/index.js +119 -119
  11. package/admin/src/components/Input/CKEditor/plugins/StrapiMediaLib.js +43 -43
  12. package/admin/src/components/Input/CKEditor/plugins/StrapiUploadAdapter.js +204 -203
  13. package/admin/src/components/Input/CKEditor/plugins/index.js +1 -1
  14. package/admin/src/components/Input/CKEditor/styling.js +16 -16
  15. package/admin/src/components/Input/CKEditor/theme/additional.js +212 -166
  16. package/admin/src/components/Input/CKEditor/theme/common.js +232 -277
  17. package/admin/src/components/Input/CKEditor/theme/dark.js +144 -144
  18. package/admin/src/components/Input/CKEditor/theme/index.js +12 -12
  19. package/admin/src/components/Input/CKEditor/theme/light.js +135 -135
  20. package/admin/src/components/Input/MediaLib/index.js +78 -78
  21. package/admin/src/components/Input/index.js +47 -47
  22. package/admin/src/index.js +109 -109
  23. package/admin/src/utils/getEditorConfig.js +37 -37
  24. package/admin/src/utils/pluginId.js +4 -4
  25. package/package.json +86 -86
  26. package/server/controllers/config.js +16 -16
  27. package/server/controllers/index.js +7 -7
  28. package/server/index.js +13 -13
  29. package/server/register.js +11 -11
  30. package/server/routes/index.js +15 -15
  31. package/server/services/config.js +19 -19
  32. package/server/services/index.js +7 -7
  33. package/strapi-admin.js +3 -3
  34. package/strapi-server.js +3 -3
@@ -1,79 +1,79 @@
1
- import React from "react";
2
- import { prefixFileUrlWithBackendUrl, useLibrary } from "@strapi/helper-plugin";
3
- import PropTypes from "prop-types";
4
-
5
- const MediaLib = ({ isOpen, onChange, onToggle, editor, uploadConfig: { responsiveDimensions } }) => {
6
- const { components } = useLibrary();
7
- const MediaLibraryDialog = components["media-library"];
8
-
9
- const handleChangeAssets = (assets) => {
10
- let newValue = "";
11
-
12
- assets.map(({name, url, alt, formats, mime}) => {
13
-
14
- if (mime.includes("image")) {
15
-
16
- if (formats && responsiveDimensions) {
17
- let set = "";
18
- let keys = Object.keys(formats).sort((a, b) => formats[a].width - formats[b].width );
19
- keys.map((k) => set += prefixFileUrlWithBackendUrl(formats[k].url) + ` ${formats[k].width}w,`);
20
- newValue += `<img src="${url}" alt="${alt}" width="${formats[keys[keys.length-1]].width}px" srcset="${set}" />`;
21
- } else {
22
- newValue += `<img src="${url}" alt="${alt}" />`;
23
- }
24
-
25
- } else if (mime.includes("application/pdf")) {
26
-
27
- newValue = `<a href="${prefixFileUrlWithBackendUrl(url)}" download="${name}">${name || 'Download PDF'}</a>`;
28
-
29
- }
30
- // Handle videos and other type of files by adding some code
31
- });
32
-
33
- const viewFragment = editor.data.processor.toView( newValue );
34
- const modelFragment = editor.data.toModel( viewFragment );
35
- editor.model.insertContent( modelFragment );
36
-
37
- onToggle();
38
- };
39
-
40
- const handleSelectAssets = (files) => {
41
- const formattedFiles = files.map((f) => ({
42
- name: f.name,
43
- alt: f.alternativeText || f.name,
44
- url: prefixFileUrlWithBackendUrl(f.url),
45
- mime: f.mime,
46
- formats: f.formats
47
- }));
48
-
49
- handleChangeAssets(formattedFiles);
50
- };
51
-
52
-
53
-
54
-
55
- if (!isOpen) {
56
- return null;
57
- }
58
-
59
- return (
60
- <MediaLibraryDialog
61
- onClose={onToggle}
62
- onSelectAssets={handleSelectAssets}
63
- />
64
- );
65
- };
66
-
67
- MediaLib.defaultProps = {
68
- isOpen: false,
69
- onChange: () => {},
70
- onToggle: () => {},
71
- };
72
-
73
- MediaLib.propTypes = {
74
- isOpen: PropTypes.bool,
75
- onChange: PropTypes.func,
76
- onToggle: PropTypes.func,
77
- };
78
-
1
+ import React from "react";
2
+ import { prefixFileUrlWithBackendUrl, useLibrary } from "@strapi/helper-plugin";
3
+ import PropTypes from "prop-types";
4
+
5
+ const MediaLib = ({ isOpen, onChange, onToggle, editor, uploadConfig: { responsiveDimensions } }) => {
6
+ const { components } = useLibrary();
7
+ const MediaLibraryDialog = components["media-library"];
8
+
9
+ const handleChangeAssets = (assets) => {
10
+ let newValue = "";
11
+
12
+ assets.map(({name, url, alt, formats, mime}) => {
13
+
14
+ if (mime.includes("image")) {
15
+
16
+ if (formats && responsiveDimensions) {
17
+ let set = "";
18
+ let keys = Object.keys(formats).sort((a, b) => formats[a].width - formats[b].width );
19
+ keys.map((k) => set += prefixFileUrlWithBackendUrl(formats[k].url) + ` ${formats[k].width}w,`);
20
+ newValue += `<img src="${url}" alt="${alt}" width="${formats[keys[keys.length-1]].width}px" srcset="${set}" />`;
21
+ } else {
22
+ newValue += `<img src="${url}" alt="${alt}" />`;
23
+ }
24
+
25
+ } else if (mime.includes("application/pdf")) {
26
+
27
+ newValue = `<a href="${prefixFileUrlWithBackendUrl(url)}" download="${name}">${name || 'Download PDF'}</a>`;
28
+
29
+ }
30
+ // Handle videos and other type of files by adding some code
31
+ });
32
+
33
+ const viewFragment = editor.data.processor.toView( newValue );
34
+ const modelFragment = editor.data.toModel( viewFragment );
35
+ editor.model.insertContent( modelFragment );
36
+
37
+ onToggle();
38
+ };
39
+
40
+ const handleSelectAssets = (files) => {
41
+ const formattedFiles = files.map((f) => ({
42
+ name: f.name,
43
+ alt: f.alternativeText || f.name,
44
+ url: prefixFileUrlWithBackendUrl(f.url),
45
+ mime: f.mime,
46
+ formats: f.formats
47
+ }));
48
+
49
+ handleChangeAssets(formattedFiles);
50
+ };
51
+
52
+
53
+
54
+
55
+ if (!isOpen) {
56
+ return null;
57
+ }
58
+
59
+ return (
60
+ <MediaLibraryDialog
61
+ onClose={onToggle}
62
+ onSelectAssets={handleSelectAssets}
63
+ />
64
+ );
65
+ };
66
+
67
+ MediaLib.defaultProps = {
68
+ isOpen: false,
69
+ onChange: () => {},
70
+ onToggle: () => {},
71
+ };
72
+
73
+ MediaLib.propTypes = {
74
+ isOpen: PropTypes.bool,
75
+ onChange: PropTypes.func,
76
+ onToggle: PropTypes.func,
77
+ };
78
+
79
79
  export default MediaLib;
@@ -1,48 +1,48 @@
1
- import React from "react";
2
- import PropTypes from "prop-types";
3
- import {default as CKEditor} from "./CKEditor";
4
- import { useIntl } from "react-intl";
5
- import { Field, FieldHint, FieldError, FieldLabel } from "@strapi/design-system/Field";
6
- import { Stack } from "@strapi/design-system/Stack";
7
-
8
- const Wysiwyg = ({ name, attribute, onChange, value, intlLabel, labelAction, disabled, error, description, required }) => {
9
- const { formatMessage } = useIntl();
10
- const { preset, maxLengthCharacters, ...options } = attribute.options;
11
-
12
- return (
13
- <Field name={name} id={name} error={error} hint={description && formatMessage(description)}>
14
- <Stack spacing={1}>
15
- <FieldLabel action={labelAction} required={required}>
16
- {formatMessage(intlLabel)}
17
- </FieldLabel>
18
- <CKEditor disabled={disabled} name={name} onChange={onChange} value={value} preset={preset} maxLength={maxLengthCharacters}/>
19
- <FieldHint />
20
- <FieldError />
21
- </Stack>
22
- </Field>
23
- );
24
- };
25
-
26
-
27
- Wysiwyg.defaultProps = {
28
- description: null,
29
- disabled: false,
30
- error: null,
31
- labelAction: null,
32
- required: false,
33
- value: "",
34
- };
35
-
36
- Wysiwyg.propTypes = {
37
- intlLabel: PropTypes.object.isRequired,
38
- onChange: PropTypes.func.isRequired,
39
- attribute: PropTypes.object.isRequired,
40
- name: PropTypes.string.isRequired,
41
- description: PropTypes.object,
42
- disabled: PropTypes.bool,
43
- error: PropTypes.string,
44
- labelAction: PropTypes.object,
45
- required: PropTypes.bool,
46
- value: PropTypes.string,
47
- };
1
+ import React from "react";
2
+ import PropTypes from "prop-types";
3
+ import {default as CKEditor} from "./CKEditor";
4
+ import { useIntl } from "react-intl";
5
+ import { Field, FieldHint, FieldError, FieldLabel } from "@strapi/design-system/Field";
6
+ import { Stack } from "@strapi/design-system/Stack";
7
+
8
+ const Wysiwyg = ({ name, attribute, onChange, value, intlLabel, labelAction, disabled, error, description, required }) => {
9
+ const { formatMessage } = useIntl();
10
+ const { preset, maxLengthCharacters, ...options } = attribute.options;
11
+
12
+ return (
13
+ <Field name={name} id={name} error={error} hint={description && formatMessage(description)}>
14
+ <Stack spacing={1}>
15
+ <FieldLabel action={labelAction} required={required}>
16
+ {formatMessage(intlLabel)}
17
+ </FieldLabel>
18
+ <CKEditor disabled={disabled} name={name} onChange={onChange} value={value} preset={preset} maxLength={maxLengthCharacters}/>
19
+ <FieldHint />
20
+ <FieldError />
21
+ </Stack>
22
+ </Field>
23
+ );
24
+ };
25
+
26
+
27
+ Wysiwyg.defaultProps = {
28
+ description: null,
29
+ disabled: false,
30
+ error: null,
31
+ labelAction: null,
32
+ required: false,
33
+ value: "",
34
+ };
35
+
36
+ Wysiwyg.propTypes = {
37
+ intlLabel: PropTypes.object.isRequired,
38
+ onChange: PropTypes.func.isRequired,
39
+ attribute: PropTypes.object.isRequired,
40
+ name: PropTypes.string.isRequired,
41
+ description: PropTypes.object,
42
+ disabled: PropTypes.bool,
43
+ error: PropTypes.string,
44
+ labelAction: PropTypes.object,
45
+ required: PropTypes.bool,
46
+ value: PropTypes.string,
47
+ };
48
48
  export default Wysiwyg;
@@ -1,110 +1,110 @@
1
- import React from "react";
2
- import * as yup from "yup";
3
-
4
- import baseConfigs from "./components/Input/CKEditor/configs";
5
- import getEditorConfig from "./utils/getEditorConfig";
6
- import CKEditorIcon from "./components/CKEditorIcon";
7
- import pluginId from "./utils/pluginId";
8
-
9
- export default {
10
- async register(app) {
11
-
12
- const {
13
- configs: userConfigs = baseConfigs,
14
- configsOverwrite: overwrite
15
- } = await getEditorConfig() || {};
16
-
17
- const setOptions = () => {
18
-
19
- let configs = {};
20
-
21
- if (overwrite) {
22
- configs = userConfigs;
23
- } else {
24
- configs = baseConfigs;
25
- if (userConfigs) {
26
- Object.keys(userConfigs).map(cfgName=>{
27
- if(baseConfigs.hasOwnProperty(cfgName))
28
- configs[cfgName].field = { ...baseConfigs[cfgName].field, ...userConfigs[cfgName].field };
29
- else configs[cfgName] = userConfigs[cfgName];
30
- })
31
- }
32
- }
33
-
34
- const options = [...Object.keys(configs).map(configName=>configs[configName].field)];
35
-
36
- return options;
37
- }
38
-
39
- app.customFields.register({
40
- name: "CKEditor",
41
- type: "richtext",
42
- pluginId: pluginId,
43
- icon: CKEditorIcon,
44
- intlLabel: {
45
- id: pluginId + ".label",
46
- defaultMessage: "CKEditor 5",
47
- },
48
- intlDescription: {
49
- id: pluginId + ".description",
50
- defaultMessage: "The rich text editor for every use case",
51
- },
52
- components: {
53
- Input: async () => import("./components/Input"),
54
- },
55
- options: {
56
- base: [
57
- {
58
- intlLabel: {
59
- id: pluginId + ".preset.label",
60
- defaultMessage: "Choose editor version",
61
- },
62
- description: {
63
- id: pluginId + ".preset.description",
64
- defaultMessage: " ",
65
- },
66
- name: "options.preset",
67
- type: "select",
68
- options: setOptions(),
69
- },
70
- ],
71
- advanced: [
72
- {
73
- sectionTitle: null,
74
- items: [
75
- {
76
- name: "required",
77
- type: "checkbox",
78
- intlLabel: {
79
- id: pluginId + ".required.label",
80
- defaultMessage: "Required field",
81
- },
82
- description: {
83
- id: pluginId + "required.description",
84
- defaultMessage:
85
- "You won't be able to create an entry if this field is empty",
86
- },
87
- },
88
- {
89
- name: "options.maxLengthCharacters",
90
- type: "checkbox-with-number-field",
91
- intlLabel: {
92
- id: pluginId + ".maxLength.label",
93
- defaultMessage: "Maximum length (characters)",
94
- },
95
- }
96
-
97
- ],
98
- },
99
- ],
100
- validator: (args) => ({
101
- preset: yup.string().required({
102
- id: pluginId + ".preset.error.required",
103
- defaultMessage: "Editor preset is required",
104
- }),
105
- }),
106
- },
107
- });
108
- }
109
- };
1
+ import React from "react";
2
+ import * as yup from "yup";
3
+
4
+ import baseConfigs from "./components/Input/CKEditor/configs";
5
+ import getEditorConfig from "./utils/getEditorConfig";
6
+ import CKEditorIcon from "./components/CKEditorIcon";
7
+ import pluginId from "./utils/pluginId";
8
+
9
+ export default {
10
+ async register(app) {
11
+
12
+ const {
13
+ configs: userConfigs = baseConfigs,
14
+ configsOverwrite: overwrite
15
+ } = await getEditorConfig() || {};
16
+
17
+ const setOptions = () => {
18
+
19
+ let configs = {};
20
+
21
+ if (overwrite) {
22
+ configs = userConfigs;
23
+ } else {
24
+ configs = baseConfigs;
25
+ if (userConfigs) {
26
+ Object.keys(userConfigs).map(cfgName=>{
27
+ if(baseConfigs.hasOwnProperty(cfgName))
28
+ configs[cfgName].field = { ...baseConfigs[cfgName].field, ...userConfigs[cfgName].field };
29
+ else configs[cfgName] = userConfigs[cfgName];
30
+ })
31
+ }
32
+ }
33
+
34
+ const options = [...Object.keys(configs).map(configName=>configs[configName].field)];
35
+
36
+ return options;
37
+ }
38
+
39
+ app.customFields.register({
40
+ name: "CKEditor",
41
+ type: "richtext",
42
+ pluginId: pluginId,
43
+ icon: CKEditorIcon,
44
+ intlLabel: {
45
+ id: pluginId + ".label",
46
+ defaultMessage: "CKEditor 5",
47
+ },
48
+ intlDescription: {
49
+ id: pluginId + ".description",
50
+ defaultMessage: "The rich text editor for every use case",
51
+ },
52
+ components: {
53
+ Input: async () => import("./components/Input"),
54
+ },
55
+ options: {
56
+ base: [
57
+ {
58
+ intlLabel: {
59
+ id: pluginId + ".preset.label",
60
+ defaultMessage: "Choose editor version",
61
+ },
62
+ description: {
63
+ id: pluginId + ".preset.description",
64
+ defaultMessage: " ",
65
+ },
66
+ name: "options.preset",
67
+ type: "select",
68
+ options: setOptions(),
69
+ },
70
+ ],
71
+ advanced: [
72
+ {
73
+ sectionTitle: null,
74
+ items: [
75
+ {
76
+ name: "required",
77
+ type: "checkbox",
78
+ intlLabel: {
79
+ id: pluginId + ".required.label",
80
+ defaultMessage: "Required field",
81
+ },
82
+ description: {
83
+ id: pluginId + "required.description",
84
+ defaultMessage:
85
+ "You won't be able to create an entry if this field is empty",
86
+ },
87
+ },
88
+ {
89
+ name: "options.maxLengthCharacters",
90
+ type: "checkbox-with-number-field",
91
+ intlLabel: {
92
+ id: pluginId + ".maxLength.label",
93
+ defaultMessage: "Maximum length (characters)",
94
+ },
95
+ }
96
+
97
+ ],
98
+ },
99
+ ],
100
+ validator: (args) => ({
101
+ preset: yup.string().required({
102
+ id: pluginId + ".preset.error.required",
103
+ defaultMessage: "Editor preset is required",
104
+ }),
105
+ }),
106
+ },
107
+ });
108
+ }
109
+ };
110
110
 
@@ -1,37 +1,37 @@
1
- import pluginId from "./pluginId";
2
-
3
- const insertConfigScript = () => {
4
- const url =
5
- strapi.backendURL !== "/"
6
- ? `${strapi.backendURL}/${pluginId}/ckeditor-config`
7
- : `/${pluginId}/ckeditor-config`;
8
-
9
- var script = document.createElement("script");
10
- script.id = "ckeditor-config";
11
- script.src = url;
12
- document.body.appendChild(script);
13
- };
14
-
15
- const waitForConfigToInitialize = async () => {
16
- return new Promise((resolve) => {
17
- (function checkConfigLoaded() {
18
- if (typeof globalThis.CKEditorConfig !== "undefined") {
19
- resolve(globalThis.CKEditorConfig);
20
- } else setTimeout(checkConfigLoaded, 5);
21
- })();
22
- });
23
- };
24
-
25
- const getEditorConfig = async () => {
26
- // raw config/ckeditor.[js|ts] file
27
- // Can be used with non-JSON serializable properties
28
- insertConfigScript();
29
- const configFromScript = await waitForConfigToInitialize();
30
- if (configFromScript) {
31
- return configFromScript;
32
- }
33
-
34
- return null;
35
- };
36
-
37
- export default getEditorConfig;
1
+ import pluginId from "./pluginId";
2
+
3
+ const insertConfigScript = () => {
4
+ const url =
5
+ strapi.backendURL !== "/"
6
+ ? `${strapi.backendURL}/${pluginId}/ckeditor-config`
7
+ : `/${pluginId}/ckeditor-config`;
8
+
9
+ var script = document.createElement("script");
10
+ script.id = "ckeditor-config";
11
+ script.src = url;
12
+ document.body.appendChild(script);
13
+ };
14
+
15
+ const waitForConfigToInitialize = async () => {
16
+ return new Promise((resolve) => {
17
+ (function checkConfigLoaded() {
18
+ if (typeof globalThis.CKEditorConfig !== "undefined") {
19
+ resolve(globalThis.CKEditorConfig);
20
+ } else setTimeout(checkConfigLoaded, 5);
21
+ })();
22
+ });
23
+ };
24
+
25
+ const getEditorConfig = async () => {
26
+ // raw config/ckeditor.[js|ts] file
27
+ // Can be used with non-JSON serializable properties
28
+ insertConfigScript();
29
+ const configFromScript = await waitForConfigToInitialize();
30
+ if (configFromScript) {
31
+ return configFromScript;
32
+ }
33
+
34
+ return null;
35
+ };
36
+
37
+ export default getEditorConfig;
@@ -1,5 +1,5 @@
1
- const pluginPkg = require('../../../package.json');
2
-
3
- const pluginId = pluginPkg.strapi.name || pluginPkg.name.replace(/^(@_sh\/strapi-)plugin-/i, '');
4
-
1
+ const pluginPkg = require('../../../package.json');
2
+
3
+ const pluginId = pluginPkg.strapi.name || pluginPkg.name.replace(/^(@_sh\/strapi-)plugin-/i, '');
4
+
5
5
  module.exports = pluginId;