@_sh/strapi-plugin-ckeditor
Version:
Integrates CKEditor 5 into your Strapi project as a fully customizable custom field. (Community Edition)
1,356 lines (1,280 loc) • 41.1 kB
JavaScript
;
const yup = require("yup");
const cloneDeep = require("lodash/cloneDeep");
const styledComponents = require("styled-components");
const ckeditor5 = require("ckeditor5");
const sanitizeHtml = require("sanitize-html");
const jsxRuntime = require("react/jsx-runtime");
const designSystem = require("@strapi/design-system");
const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
function _interopNamespace(e) {
if (e && e.__esModule) return e;
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
if (e) {
for (const k in e) {
if (k !== "default") {
const d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: () => e[k]
});
}
}
}
n.default = e;
return Object.freeze(n);
}
const yup__namespace = /* @__PURE__ */ _interopNamespace(yup);
const cloneDeep__default = /* @__PURE__ */ _interopDefault(cloneDeep);
const sanitizeHtml__namespace = /* @__PURE__ */ _interopNamespace(sanitizeHtml);
const colors = styledComponents.css`
${({ theme }) => styledComponents.css`
:root {
/* -- Generic colors ---------------------------------------------------------------------- */
--ck-color-focus-outer-shadow: ${theme.colors.primary600}1F ;
--ck-color-focus-disabled-shadow: ${theme.colors.primary200} ;
--ck-focus-ring: 1px solid ${theme.colors.primary600}9F ;
--ck-color-button-default-hover-background: ${theme.colors.primary100} ;
}
.ck {
/* -- Generic colors ---------------------------------------------------------------------- */
--ck-color-base-focus: ${theme.colors.primary200};
--ck-color-base-active: ${theme.colors.primary500}8F;
--ck-color-base-active-focus: ${theme.colors.primary600};
--ck-content-font-color: ${theme.colors.neutral800};
--ck-color-base-border: ${theme.colors.neutral200};
--ck-color-base-background: ${theme.colors.neutral0};
--ck-custom-foreground: ${theme.colors.neutral200};
--ck-color-base-foreground: var(--ck-color-base-background);
--ck-color-focus-border: ${theme.colors.primary500};
--ck-color-text: ${theme.colors.neutral800};
--ck-custom-white: hsl(0, 0%, 100%);
/* -- Buttons ----------------------------------------------------------------------------- */
--ck-color-button-default-background: var(--ck-color-base-background);
--ck-color-button-default-hover-background: ${theme.colors.primary100};
--ck-color-button-default-active-background: ${theme.colors.primary100};
--ck-color-button-default-active-shadow: ${theme.colors.primary100};
--ck-color-button-default-disabled-background: var(--ck-color-base-background);
--ck-color-button-on-color: ${theme.colors.primary600};
--ck-color-button-on-background: ${theme.colors.primary100};
--ck-color-button-on-hover-background: ${theme.colors.primary200};
--ck-color-button-on-active-background: ${theme.colors.primary100};
--ck-color-button-on-disabled-background: var(--ck-custom-foreground);
--ck-color-button-on-active-shadow: ${theme.colors.primary200};
--ck-color-button-action-background: ${theme.colors.success500}E5;
--ck-color-button-action-hover-background: ${theme.colors.success500}F5;
--ck-color-button-action-active-background: ${theme.colors.success500};
--ck-color-button-action-disabled-background: ${theme.colors.success500}99;
--ck-color-button-action-text: var(--ck-custom-white);
--ck-color-switch-button-off-background: ${theme.colors.neutral400};
--ck-color-switch-button-off-hover-background: ${theme.colors.neutral500};
--ck-color-switch-button-on-background: var(--ck-color-button-action-background);
--ck-color-switch-button-on-hover-background: var(--ck-color-button-action-hover-background);
--ck-color-button-save: ${theme.colors.success500};
--ck-color-button-cancel: ${theme.colors.danger500};
--ck-color-split-button-hover-background: var(--ck-color-button-default-hover-background);
--ck-color-split-button-hover-border: var(--ck-custom-foreground);
/* -- Dropdown ---------------------------------------------------------------------------- */
--ck-color-dropdown-panel-background: var(--ck-color-base-background);
--ck-color-dropdown-panel-border: var(--ck-custom-foreground);
/* -- Input ------------------------------------------------------------------------------- */
--ck-color-input-background: var(--ck-color-base-background);
--ck-color-input-border: var(--ck-color-base-border);
--ck-color-input-text: var(--ck-color-editor-base-text);
--ck-color-input-disabled-background: ${theme.colors.neutral100};
--ck-color-input-disabled-border: ${theme.colors.neutral150};
--ck-color-input-disabled-text: ${theme.colors.neutral400};
--ck-color-labeled-field-label-background: var(--ck-color-base-background);
/* -- List -------------------------------------------------------------------------------- */
--ck-color-list-background: var(--ck-color-base-background);
--ck-color-list-button-hover-background: ${theme.colors.primary100};
--ck-color-list-button-on-background: var(--ck-color-base-active);
--ck-color-list-button-on-background-focus: var(--ck-color-base-active-focus);
/* -- Panel ------------------------------------------------------------------------------- */
--ck-color-panel-background: var(--ck-color-base-background);
--ck-color-panel-border: var(--ck-color-base-border);
--ck-style-panel-button-label-background: ${theme.colors.neutral100};
--ck-style-panel-button-hover-label-background: ${theme.colors.neutral150};
--ck-style-panel-button-hover-border-color: var(--ck-color-base-border);
/* -- Toolbar ----------------------------------------------------------------------------- */
--ck-color-toolbar-background: var(--ck-color-base-background);
--ck-color-toolbar-border: var(--ck-color-base-border);
/* -- Tooltip ----------------------------------------------------------------------------- */
--ck-color-tooltip-background: ${theme.colors.neutral800};
--ck-color-tooltip-text: ${theme.colors.neutral100};
/* -- Image ------------------------------------------------------------------------------- */
--ck-content-color-image-caption-background: ${theme.colors.neutral100};
--ck-content-color-image-caption-text: ${theme.colors.neutral800};
/* -- Table ------------------------------------------------------------------------------- */
--ck-content-color-table-caption-background: ${theme.colors.neutral100};
--ck-content-color-table-caption-text: ${theme.colors.neutral800};
/* -- Widget ------------------------------------------------------------------------------ */
--ck-color-widget-blurred-border: ${theme.colors.neutral400};
--ck-color-widget-hover-border: ${theme.colors.neutral300};
--ck-color-widget-editable-focus-background: ${theme.colors.neutral150};
--ck-color-widget-type-around-button-active: var(--ck-color-focus-border);
--ck-color-widget-type-around-button-hover: ${theme.colors.neutral300};
/* -- Link -------------------------------------------------------------------------------- */
--ck-color-link-fake-selection: ${theme.colors.primary200};
--ck-color-link-selected-background: ${theme.colors.primary200};
/* -- Dialog ------------------------------------------------------------------------------ */
--ck-color-dialog-background: var(--ck-color-base-background);
--ck-color-dialog-form-header-border: var(--ck-color-base-border);
/* -- PoweredBy --------------------------------------------------------------------------- */
--ck-powered-by-background: transparrent;
}
`}
`;
const light = styledComponents.css`
${colors}
`;
const dark = styledComponents.css`
${colors}
.ck.ck-powered-by > a > svg > path:nth-child(3) {
fill: rgb(172, 156, 251);
}
`;
const reset = styledComponents.css`
${({ theme }) => styledComponents.css`
.ck {
--ck-content-color-image-caption-background: hsl(0, 0%, 97%);
--ck-content-color-image-caption-text: hsl(0, 0%, 20%);
--ck-content-color-mention-background: hsla(341, 100%, 30%, 0.1);
--ck-content-color-mention-text: hsl(341, 100%, 30%);
--ck-color-table-caption-background: hsl(0, 0%, 97%);
--ck-color-table-caption-text: hsl(0, 0%, 20%);
--ck-content-highlight-marker-blue: hsl(201, 97%, 72%);
--ck-content-highlight-marker-green: hsl(120, 93%, 68%);
--ck-content-highlight-marker-pink: hsl(345, 96%, 73%);
--ck-content-highlight-marker-yellow: hsl(60, 97%, 73%);
--ck-content-highlight-pen-green: hsl(112, 100%, 27%);
--ck-content-highlight-pen-red: hsl(0, 85%, 49%);
--ck-image-style-spacing: 1.5em;
--ck-inline-image-style-spacing: calc(var(--ck-image-style-spacing) / 2);
--ck-todo-list-checkmark-size: 16px;
--ck-border-radius: ${theme.borderRadius};
font-size: ${theme.fontSizes[2]};
}
.ck.ck-reset.ck-dropdown__panel.ck-dropdown__panel_sw.ck-dropdown__panel-visible {
border-radius: var(--ck-border-radius);
}
.ck-editor__main {
--ck-font-face:
'Source Sans Pro', system-ui, Roboto, 'Helvetica Neue', 'Helvetica', Arial, sans-serif;
font-family: var(--ck-font-face);
* {
font: revert;
margin: revert;
}
blockquote,
ol,
p,
ul {
font-size: 1em;
line-height: 1.6em;
padding-top: 0.2em;
margin-bottom: var(--ck-spacing-large);
}
figcaption {
background-color: var(--ck-content-color-image-caption-background);
caption-side: bottom;
color: var(--ck-content-color-image-caption-text);
display: table-caption;
font-size: 0.75em;
outline-offset: -1px;
padding: 0.6em;
word-break: break-word;
}
a {
text-decoration: none;
color: #1b3af2;
}
a:hover {
text-decoration: underline;
}
.table {
margin: 0;
}
ul.todo-list {
list-style: none;
margin: revert;
color: revert;
font-family: revert;
margin-left: 2rem;
}
ul,
ol {
list-style: initial;
margin-left: 2rem;
}
ol {
list-style: decimal;
}
sub {
vertical-align: sub;
}
sup {
vertical-align: super;
}
.ck-input-text.raw-html-embed__source,
.ck-button.raw-html-embed__edit-button {
color: var(--ck-color-text);
}
}
`}
`;
const plugin = styledComponents.css`
${({ theme }) => styledComponents.css`
.ck {
scrollbar-width: thin;
scrollbar-color: ${`${theme.colors.neutral300} ${theme.colors.neutral150}`};
@-moz-document url-prefix() {
scrollbar-width: auto;
}
}
.ck.ck-content.ck-editor__editable {
line-height: initial;
height: auto;
min-height: var(--ck-editor-min-height);
border: none ;
max-width: var(--ck-editor-max-width) ;
margin: 0 auto;
&.ck-focused:not(.ck-editor__nested-editable) {
box-shadow: none;
}
}
.ck.ck-editor__top .ck-sticky-panel .ck-sticky-panel__content {
border: none ;
}
[role='dialog'] .ck.ck-sticky-panel .ck-sticky-panel__content_sticky {
position: static ;
width: auto ;
}
[role='dialog'] .ck.ck-sticky-panel .ck-sticky-panel__placeholder {
display: none ;
}
.ck.ck-editor__main {
min-height: var(--ck-editor-min-height) ;
max-height: var(--ck-editor-max-height) ;
overflow-y: auto;
overflow-x: hidden;
border-top: 1px solid var(--ck-color-base-border);
border-bottom-left-radius: var(--ck-border-radius);
border-bottom-right-radius: var(--ck-border-radius);
}
.ck .ck-source-editing-area,
.ck .ck-source-editing-area textarea {
color: var(--ck-color-text);
background-color: var(--ck-color-base-background);
border: none ;
box-shadow: none ;
min-height: var(--ck-editor-min-height);
max-width: var(--ck-editor-max-width);
margin: 0 auto;
}
.ck .ck-block-toolbar-button {
min-width: 0 ;
min-height: 0 ;
width: 20px ;
height: 25px ;
margin-left: -2px ;
& svg {
color: var(--ck-color-text) ;
position: absolute;
width: 20px;
height: 20px;
}
}
.ck-word-count {
display: flex;
position: absolute;
justify-content: end;
gap: 0.3rem;
font-size: 1rem;
font-weight: 500;
text-transform: lowercase;
z-index: 2;
bottom: -2rem;
right: 0;
}
.ck[dir='rtl'] {
.ck-block-toolbar-button {
margin-left: 2px ;
}
& + div {
justify-content: flex-start;
& > .ck-word-count {
& > div:first-child {
order: 2;
}
& > div:last-child {
order: 1;
}
}
}
}
.ck.ck-editor__editable > .ck-placeholder::before {
color: var(--ck-content-font-color);
opacity: 0.65;
}
.ck.ck-powered-by > a > svg > path:first-child {
fill: ${theme.colors.neutral800};
}
`}
`;
const expanded = styledComponents.css`
.ck-editor__expanded {
max-width: var(--ck-editor-full-screen-box-max-width);
.ck.ck-content.ck-editor__editable,
.ck-source-editing-area {
min-height: 100% ;
height: auto ;
max-height: none ;
border-radius: var(--ck-border-radius) ;
border: 1px solid var(--ck-color-base-border) ;
overflow: auto ;
box-sizing: border-box;
}
.ck.ck-editor__top {
box-shadow: 0 0 5px hsla(0, 0%, 0%, 0.2);
z-index: var(--ck-z-panel);
}
.ck.ck-editor {
display: flex;
flex-direction: column;
}
.ck.ck-editor,
.ck.ck-content,
.ck.ck-editor__main {
height: calc(100% - 0px) ;
}
.ck.ck-editor__main {
min-height: none ;
max-height: none ;
overflow-y: scroll ;
padding: calc(2 * var(--ck-spacing-large));
}
.ck-word-count {
bottom: 0.3rem;
right: 1.2rem;
}
}
.ck-body-wrapper {
pointer-events: all;
}
`;
const common = styledComponents.css`
${reset}
${plugin}
${expanded}
`;
const editorSizes = styledComponents.css`
:root {
--ck-editor-full-screen-box-max-width: 1700px;
}
.ck {
--ck-editor-max-width: 1366px;
--ck-editor-min-height: 200px;
--ck-editor-max-height: 500px;
}
`;
const additional = styledComponents.css`
${editorSizes}
`;
const defaultTheme = {
light,
dark,
common,
additional
};
const mediaLibIcon = '<svg width="1em" height="1em" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><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 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 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 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"></path></svg>';
class StrapiMediaLib extends ckeditor5.Plugin {
/**
* Strapi function used to show media library modal.
* Should be provided via connect method before using toggle method.
*/
strapiToggle = null;
static get pluginName() {
return "StrapiMediaLib";
}
init() {
this.editor.ui.componentFactory.add("strapiMediaLib", () => {
const button = new ckeditor5.ButtonView();
button.set({
label: "Media Library",
icon: mediaLibIcon,
tooltip: true
});
button.on("execute", this.toggle.bind(this));
return button;
});
}
connect(strapiToggle) {
if (typeof strapiToggle !== "function") {
throw new Error("The input parameter for toggle must be a function.");
}
this.strapiToggle = strapiToggle;
}
toggle() {
if (typeof this.strapiToggle !== "function") {
throw new Error(
"The Strapi Media Library toggle function is not connected. Use the connect function first."
);
}
this.strapiToggle();
}
}
const name = "@_sh/strapi-plugin-ckeditor";
const version = "7.1.1";
const description = "Integrates CKEditor 5 into your Strapi project as a fully customizable custom field. (Community Edition)";
const keywords = [
"strapi",
"ckeditor",
"ckeditor5",
"ckeditor 5",
"wysiwyg",
"rich text",
"editor"
];
const author = {
name: "nshenderov"
};
const homepage = "https://market.strapi.io/plugins/@_sh-strapi-plugin-ckeditor";
const repository = {
type: "git",
url: "https://github.com/nshenderov/strapi-plugin-ckeditor.git"
};
const strapi = {
name: "ckeditor5",
displayName: "CKEditor 5",
description: "Integrates CKEditor 5 into your Strapi project as a fully customizable custom field. (Community Edition)",
kind: "plugin"
};
const type = "commonjs";
const exports$2 = {
"./package.json": "./package.json",
".": {
types: "./dist/admin/src/index.d.ts",
source: "./admin/src/index.ts",
"import": "./dist/admin/index.mjs",
require: "./dist/admin/index.js",
"default": "./dist/admin/index.js"
},
"./strapi-admin": {
types: "./dist/admin/src/index.d.ts",
source: "./admin/src/index.ts",
"import": "./dist/admin/index.mjs",
require: "./dist/admin/index.js",
"default": "./dist/admin/index.js"
},
"./strapi-server": {
types: "./dist/server/src/index.d.ts",
source: "./server/src/index.ts",
"import": "./dist/server/index.mjs",
require: "./dist/server/index.js",
"default": "./dist/server/index.js"
}
};
const files = [
"dist"
];
const scripts = {
build: "strapi-plugin build",
watch: "strapi-plugin watch",
"watch:link": "strapi-plugin watch:link",
verify: "strapi-plugin verify",
"test:ts:front": "run -T tsc -p admin/tsconfig.json",
"test:ts:back": "run -T tsc -p server/tsconfig.json",
release: "release-it",
"release:info": "release-it --changelog",
"lint:ts": "eslint . --ext ts,tsx --report-unused-disable-directives",
"lint:ts:fix": "eslint . --ext ts,tsx --report-unused-disable-directives --fix"
};
const dependencies = {
"@ckeditor/ckeditor5-react": "~11.0.1",
ckeditor5: "~47.6.1",
lodash: "4.17.21",
"sanitize-html": "2.13.0",
yup: "0.32.9"
};
const devDependencies = {
"@release-it/conventional-changelog": "10.0.0",
"@strapi/sdk-plugin": "5.4.0",
"@strapi/strapi": "5.33.4",
"@strapi/typescript-utils": "5.33.4",
"@types/react": "^18.0.0",
"@types/react-dom": "^18.0.0",
"@types/sanitize-html": "^2.13.0",
"@typescript-eslint/eslint-plugin": "^7.0.0",
"@typescript-eslint/parser": "^7.0.0",
eslint: "^8.2.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^18.0.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-import": "^2.25.3",
"eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-react": "^7.28.0",
"eslint-plugin-react-hooks": "^4.3.0",
prettier: "^3.4.0",
"release-it": "^18.1.2",
typescript: "5.6.3",
react: "^18.0.0",
"react-dom": "^18.0.0",
"react-router-dom": "^6.0.0",
"styled-components": "^6.0.0"
};
const peerDependencies = {
"@strapi/design-system": "^2.0.0",
"@strapi/icons": "^2.0.0",
"@strapi/strapi": "^5.0.0",
react: "^18.0.0",
"react-dom": "^18.0.0",
"react-router-dom": "^6.0.0",
"styled-components": "^6.0.0"
};
const engines = {
node: ">=20.0.0 <=24.x.x",
npm: ">=6.0.0"
};
const license = "MIT";
const pluginPkg = {
name,
version,
description,
keywords,
author,
homepage,
repository,
strapi,
type,
exports: exports$2,
files,
scripts,
dependencies,
devDependencies,
peerDependencies,
engines,
license
};
const PLUGIN_ID = pluginPkg.strapi.name;
function isImageResponsive(imgFormats) {
const formats = Object.keys(imgFormats);
const isResponsive = !(formats.length === 1 && formats[0] === "thumbnail");
return isResponsive;
}
function prefixFileUrlWithBackendUrl(fileURL) {
return !!fileURL && fileURL.startsWith("/") ? `${window.strapi.backendURL}${fileURL}` : fileURL;
}
class StrapiUploadAdapter extends ckeditor5.Plugin {
static get requires() {
return [ckeditor5.FileRepository];
}
static get pluginName() {
return "StrapiUploadAdapter";
}
init() {
}
initAdapter(config) {
if (!config.uploadUrl) {
ckeditor5.logWarning("strapi-upload-adapter-missing-uploadurl");
return;
}
this.editor.plugins.get(ckeditor5.FileRepository).createUploadAdapter = (loader) => new Adapter(loader, config);
}
}
class Adapter {
/**
* FileLoader instance to use during the upload.
*/
loader;
/**
* The configuration of the adapter.
*/
config;
xhr;
/**
* Creates a new adapter instance.
*/
constructor(loader, config) {
this.loader = loader;
this.config = config;
}
/**
* Starts the upload process.
*/
upload() {
return this.loader.file.then(
(file) => new Promise((resolve, reject) => {
this.initRequest();
this.initListeners(resolve, reject, file);
this.sendRequest(file);
})
);
}
/**
* Aborts the upload process.
*/
abort() {
if (this.xhr) {
this.xhr.abort();
}
}
/**
* Initializes the `XMLHttpRequest` object using the URL specified as
* `strapiUpload.uploadUrl` in the editor's
* configuration.
*/
initRequest() {
const xhr = new XMLHttpRequest();
this.xhr = xhr;
xhr.open("POST", this.config.uploadUrl, true);
xhr.responseType = "json";
}
/**
* Initializes XMLHttpRequest listeners
*
* resolve - Callback function to be called when the request is successful.
* reject - Callback function to be called when the request cannot be completed.
* file - Native File object.
*/
initListeners(resolve, reject, file) {
const xhr = this.xhr;
const { loader } = this;
const genericErrorText = `Couldn't upload file: ${file.name}.`;
xhr.addEventListener("error", () => reject(genericErrorText));
xhr.addEventListener("abort", () => reject());
xhr.addEventListener("load", () => {
const { response } = xhr;
if (!Array.isArray(response) || typeof response === "object" && "error" in response || response.length !== 1) {
return reject(
response && response.error && response.error.message ? response.error.message : genericErrorText
);
}
const { name: name2, url, alternativeText, formats } = response[0];
const urls = { default: prefixFileUrlWithBackendUrl(url) };
const alt = alternativeText || name2;
if (formats && isImageResponsive(formats)) {
const sortedFormatsKeys = Object.keys(formats).sort(
(a, b) => formats[a].width - formats[b].width
);
sortedFormatsKeys.forEach((k) => {
urls[formats[k].width] = prefixFileUrlWithBackendUrl(formats[k].url);
});
}
resolve(url ? { alt, urls } : {});
return void 0;
});
if (xhr.upload) {
xhr.upload.addEventListener("progress", (evt) => {
if (evt.lengthComputable) {
loader.uploadTotal = evt.total;
loader.uploaded = evt.loaded;
}
});
}
}
/**
* Prepares the data and sends the request.
*
* File - instance to be uploaded.
*/
sendRequest(file) {
const headers = this.config.headers || {};
const withCredentials = this.config.withCredentials || false;
Object.keys(headers).forEach((headerName) => {
this.xhr.setRequestHeader(headerName, headers[headerName]);
});
this.xhr.withCredentials = withCredentials;
const data = new FormData();
data.append("files", file);
this.xhr.send(data);
}
}
const editorConfig$1 = {
licenseKey: "GPL",
plugins: [
ckeditor5.Alignment,
ckeditor5.Autoformat,
ckeditor5.AutoImage,
ckeditor5.BalloonToolbar,
ckeditor5.BlockQuote,
ckeditor5.Bold,
ckeditor5.Code,
ckeditor5.CodeBlock,
ckeditor5.Essentials,
ckeditor5.FontBackgroundColor,
ckeditor5.FontColor,
ckeditor5.FontFamily,
ckeditor5.FontSize,
ckeditor5.GeneralHtmlSupport,
ckeditor5.Heading,
ckeditor5.HorizontalLine,
ckeditor5.HtmlEmbed,
ckeditor5.Image,
ckeditor5.ImageCaption,
ckeditor5.ImageInsert,
ckeditor5.ImageResize,
ckeditor5.ImageStyle,
ckeditor5.ImageToolbar,
ckeditor5.ImageUpload,
ckeditor5.Indent,
ckeditor5.IndentBlock,
ckeditor5.Italic,
ckeditor5.List,
ckeditor5.ListProperties,
ckeditor5.Link,
ckeditor5.LinkImage,
ckeditor5.MediaEmbed,
ckeditor5.Paragraph,
ckeditor5.PageBreak,
ckeditor5.PasteFromOffice,
ckeditor5.PictureEditing,
ckeditor5.RemoveFormat,
ckeditor5.SourceEditing,
ckeditor5.SpecialCharacters,
ckeditor5.SpecialCharactersEssentials,
ckeditor5.Strikethrough,
ckeditor5.Style,
ckeditor5.Subscript,
ckeditor5.Superscript,
ckeditor5.ShowBlocks,
ckeditor5.Table,
ckeditor5.TableCaption,
ckeditor5.TableCellProperties,
ckeditor5.TableColumnResize,
ckeditor5.TableProperties,
ckeditor5.TableToolbar,
ckeditor5.TodoList,
ckeditor5.Underline,
ckeditor5.WordCount,
StrapiMediaLib,
StrapiUploadAdapter
],
toolbar: [
"showBlocks",
"|",
"heading",
"|",
"fontSize",
"fontFamily",
"alignment",
{
label: "Indentation",
icon: ckeditor5.IconIndent,
items: ["outdent", "indent"]
},
"bulletedList",
"numberedList",
"todoList",
"link",
"mediaEmbed",
"insertImage",
"strapiMediaLib",
"blockquote",
"insertTable",
"codeBlock",
"htmlEmbed",
"SourceEditing",
"specialCharacters",
"horizontalLine",
"pageBreak",
"|",
"undo",
"redo"
],
balloonToolbar: [
"bold",
"italic",
"fontColor",
"fontBackgroundColor",
{
label: "Other formatting options",
icon: `
<svg width="800px" height="800px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<rect x="0" fill="none" width="24" height="24"/>
<g>
<path d="M14.348 12H21v2h-4.613c.24.515.368 1.094.368 1.748 0 1.317-.474 2.355-1.423 3.114-.947.76-2.266 1.138-3.956 1.138-1.557 0-2.934-.293-4.132-.878v-2.874c.985.44 1.818.75 2.5.928.682.18 1.306.27 1.872.27.68 0 1.2-.13 1.562-.39.363-.26.545-.644.545-1.158 0-.285-.08-.54-.24-.763-.16-.222-.394-.437-.704-.643-.18-.12-.483-.287-.88-.49H3v-2H14.347zm-3.528-2c-.073-.077-.143-.155-.193-.235-.126-.202-.19-.44-.19-.713 0-.44.157-.795.47-1.068.313-.273.762-.41 1.348-.41.492 0 .993.064 1.502.19.51.127 1.153.35 1.93.67l1-2.405c-.753-.327-1.473-.58-2.16-.76-.69-.18-1.414-.27-2.173-.27-1.544 0-2.753.37-3.628 1.108-.874.738-1.312 1.753-1.312 3.044 0 .302.036.58.088.848h3.318z"/>
</g>
</svg>`,
items: ["underline", "strikethrough", "superscript", "subscript"]
},
"|",
"removeFormat"
],
fontFamily: {
supportAllValues: true
},
fontSize: {
options: [10, 12, 14, "default", 18, 20, 22],
supportAllValues: true
},
heading: {
options: [
{ model: "paragraph", title: "Paragraph", class: "ck-heading_paragraph" },
{
model: "heading1",
view: "h1",
title: "Heading 1",
class: "ck-heading_heading1"
},
{
model: "heading2",
view: "h2",
title: "Heading 2",
class: "ck-heading_heading2"
},
{
model: "heading3",
view: "h3",
title: "Heading 3",
class: "ck-heading_heading3"
},
{
model: "heading4",
view: "h4",
title: "Heading 4",
class: "ck-heading_heading4"
},
{
model: "heading5",
view: "h5",
title: "Heading 5",
class: "ck-heading_heading5"
},
{
model: "heading6",
view: "h6",
title: "Heading 6",
class: "ck-heading_heading6"
}
]
},
htmlSupport: {
allow: [
{
name: /.*/,
attributes: true,
classes: true,
styles: true
}
],
disallow: [
{
attributes: [
{ key: /^on(.*)/i, value: true },
{
key: /.*/,
value: /(\b)(on\S+)(\s*)=|javascript:|(<\s*)(\/*)script/i
},
{ key: /.*/, value: /data:(?!image\/(png|jpeg|gif|webp))/i }
]
},
{ name: "script" }
]
},
htmlEmbed: {
showPreviews: true,
sanitizeHtml: (inputHtml) => {
const outputHtml = sanitizeHtml__namespace.default(inputHtml);
return {
html: outputHtml,
hasChanged: true
};
}
},
list: {
properties: {
styles: true,
startIndex: true,
reversed: true
}
},
table: {
contentToolbar: [
"tableColumn",
"tableRow",
"mergeTableCells",
"tableProperties",
"tableCellProperties",
"toggleTableCaption"
]
},
image: {
styles: {
options: [
"inline",
"alignLeft",
"alignRight",
"alignCenter",
"alignBlockLeft",
"alignBlockRight",
"block",
"side"
]
},
resizeOptions: [
{
name: "resizeImage:original",
label: "Default image width",
value: null
},
{
name: "resizeImage:50",
label: "50% page width",
value: "50"
},
{
name: "resizeImage:75",
label: "75% page width",
value: "75"
}
],
toolbar: [
"imageTextAlternative",
"toggleImageCaption",
"linkImage",
"|",
"imageStyle:inline",
"imageStyle:wrapText",
"imageStyle:breakText",
"imageStyle:side",
"|",
"resizeImage"
]
},
link: {
decorators: {
toggleDownloadable: {
mode: "manual",
label: "Downloadable",
attributes: {
download: "file"
}
}
},
addTargetToExternalLinks: true,
defaultProtocol: "https://"
},
ui: {
poweredBy: {
position: "inside",
side: "left",
label: "",
verticalOffset: 0,
horizontalOffset: 0
}
}
};
const defaultHtmlPreset = {
name: "defaultHtml",
description: "Default HTML editor",
editorConfig: editorConfig$1
};
const editorConfig = {
licenseKey: "GPL",
plugins: [
ckeditor5.Autoformat,
ckeditor5.BlockQuote,
ckeditor5.Bold,
ckeditor5.Code,
ckeditor5.CodeBlock,
ckeditor5.Essentials,
ckeditor5.Heading,
ckeditor5.HorizontalLine,
ckeditor5.Image,
ckeditor5.ImageToolbar,
ckeditor5.ImageUpload,
ckeditor5.ImageInsert,
ckeditor5.Italic,
ckeditor5.List,
ckeditor5.Link,
ckeditor5.Markdown,
ckeditor5.Paragraph,
ckeditor5.SourceEditing,
ckeditor5.SpecialCharacters,
ckeditor5.SpecialCharactersEssentials,
ckeditor5.Strikethrough,
ckeditor5.Table,
ckeditor5.TableToolbar,
ckeditor5.TextTransformation,
ckeditor5.TodoList,
ckeditor5.WordCount,
StrapiMediaLib,
StrapiUploadAdapter
],
toolbar: [
"sourceEditing",
"|",
"heading",
"|",
"bold",
"italic",
"fontColor",
"strikethrough",
"code",
"bulletedList",
"numberedList",
"todoList",
"link",
"insertImage",
"strapiMediaLib",
"blockQuote",
"insertTable",
"codeBlock",
"specialCharacters",
"horizontalLine",
"undo",
"redo"
],
heading: {
options: [
{ model: "paragraph", title: "Paragraph", class: "ck-heading_paragraph" },
{
model: "heading1",
view: "h1",
title: "Heading 1",
class: "ck-heading_heading1"
},
{
model: "heading2",
view: "h2",
title: "Heading 2",
class: "ck-heading_heading2"
},
{
model: "heading3",
view: "h3",
title: "Heading 3",
class: "ck-heading_heading3"
},
{
model: "heading4",
view: "h4",
title: "Heading 4",
class: "ck-heading_heading4"
},
{
model: "heading5",
view: "h5",
title: "Heading 5",
class: "ck-heading_heading5"
},
{
model: "heading6",
view: "h6",
title: "Heading 6",
class: "ck-heading_heading6"
}
]
},
image: {
toolbar: ["imageTextAlternative"]
},
table: {
contentToolbar: ["tableColumn", "tableRow", "mergeTableCells"]
},
ui: {
poweredBy: {
position: "inside",
side: "left",
label: "",
verticalOffset: 0,
horizontalOffset: 0
}
}
};
const defaultMarkdownPreset = {
name: "defaultMarkdown",
description: "Default Markdown editor",
editorConfig
};
const PLUGIN_CONFIG = {
presets: {
defaultHtml: defaultHtmlPreset,
defaultMarkdown: defaultMarkdownPreset
},
theme: defaultTheme
};
function setPluginConfig(userPluginConfig) {
const { presets: userPresets, theme: userTheme } = userPluginConfig || {};
if (userPresets) {
PLUGIN_CONFIG.presets = {};
userPresets.forEach((preset) => {
PLUGIN_CONFIG.presets[preset.name] = preset;
});
}
if (userTheme) {
PLUGIN_CONFIG.theme = userTheme;
}
}
function getPluginPresets() {
return PLUGIN_CONFIG.presets;
}
function getPluginTheme() {
return PLUGIN_CONFIG.theme;
}
function getPluginConfig() {
return PLUGIN_CONFIG;
}
const clonedDefaultTheme = cloneDeep__default.default(defaultTheme);
const clonedDefaultHtmlPreset = cloneDeep__default.default(defaultHtmlPreset);
const clonedDefaultMarkdownPreset = cloneDeep__default.default(defaultMarkdownPreset);
const exports$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
__proto__: null,
StrapiMediaLib,
StrapiUploadAdapter,
defaultHtmlPreset: clonedDefaultHtmlPreset,
defaultMarkdownPreset: clonedDefaultMarkdownPreset,
defaultTheme: clonedDefaultTheme,
getPluginPresets,
getPluginTheme,
setPluginConfig
}, Symbol.toStringTag, { value: "Module" }));
function CKEditorIcon() {
return /* @__PURE__ */ jsxRuntime.jsx(IconBox, { justifyContent: "center", alignItems: "center", width: 7, height: 6, hasRadius: true, "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx(SvgIcon, {}) });
}
function SvgIcon() {
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "-8 -7 37 37", children: [
/* @__PURE__ */ jsxRuntime.jsx(
"path",
{
d: "M15.04 16.726a3.98 3.98 0 0 0-1.535.524 3.96 3.96 0 0 0-1.402 1.364c-.108.18-.716 1.347-.716 1.347l-2.09 3.82.022.016c.097.063.2.116.308.159.317.113.65.175.987.18 1.264.058 2.529-.016 3.793-.007.725.023 1.45.005 2.172-.053.348-.017.687-.117.99-.29.31-.178.576-.423.78-.717.138-.205.283-.407.409-.62.6-1.02 1.199-2.043 1.794-3.065.187-.321.37-.644.555-.966l.281-.481c.236-.392.367-.838.381-1.294l-3.258.057s-3.147-.012-3.472.026Zm2.764.903Z",
fill: designSystem.lightTheme.colors.secondary700
}
),
/* @__PURE__ */ jsxRuntime.jsx(
"path",
{
d: "m7.12 22.61 1.901-3.477.46-.877c-.31-.168-.614-.35-.918-.528-.866-.508-1.766-.957-2.613-1.498a2.459 2.459 0 0 1-.609-.517c-.27-.336-.341-.736-.362-1.15-.052-1.022-.003-2.045-.02-3.068-.01-.487 0-.975.005-1.462.01-.806.384-1.382 1.069-1.783L8.115 7.03c.55-.322 1.102-.642 1.654-.961.127-.073.263-.13.395-.192.68-.321 1.298-.119 1.9.213.039.02.075.045.112.068.306.149.605.313.895.491.794.445 1.587.893 2.378 1.343.239.139.469.292.688.458.485.36.636.875.666 1.445.039.71.017 1.422.013 2.134-.002.698.01 1.396.003 2.094 1.478-.006 3.146 0 3.146 0l1.807-.032c-.006-.73-.016-1.46-.017-2.19 0-1.31.037-2.62-.039-3.928-.061-1.05-.34-2-1.232-2.666a12.549 12.549 0 0 0-1.264-.848c-1.454-.834-2.91-1.664-4.37-2.49-.545-.308-1.067-.659-1.644-.91-.069-.043-.135-.089-.205-.128-1.106-.613-2.24-.992-3.485-.405-.242.115-.49.218-.723.352-1.011.58-2.02 1.166-3.026 1.757-1.271.744-2.54 1.488-3.81 2.234C.705 5.602.025 6.66.012 8.144c-.008.897-.02 1.794 0 2.691.039 1.884-.045 3.77.058 5.652.042.761.174 1.499.672 2.12.32.377.698.7 1.121.956 1.556 1.001 3.209 1.835 4.8 2.775l.457.271Z",
fill: designSystem.lightTheme.colors.secondary600
}
)
] });
}
const IconBox = styledComponents.styled(designSystem.Flex)`
background-color: ${designSystem.lightTheme.colors.secondary100};
border: 1px solid ${designSystem.lightTheme.colors.secondary200};
`;
const AVAILABLE_OPTIONS = [];
function fillAvailableOptions() {
const { presets } = getPluginConfig();
Object.values(presets).forEach(({ name: name2, description: description2 }) => {
const option = {
key: name2,
value: name2,
metadatas: {
intlLabel: {
id: `${PLUGIN_ID}.preset.${name2}.label`,
defaultMessage: description2
}
}
};
AVAILABLE_OPTIONS.push(option);
});
}
const index = {
bootstrap() {
fillAvailableOptions();
},
async register(app) {
app.registerPlugin({
id: PLUGIN_ID,
isReady: true,
name: "CKEditor",
apis: exports$1
});
app.customFields.register({
name: "CKEditor",
type: "richtext",
pluginId: PLUGIN_ID,
icon: CKEditorIcon,
intlLabel: {
id: `${PLUGIN_ID}.label`,
defaultMessage: "CKEditor 5"
},
intlDescription: {
id: `${PLUGIN_ID}.description`,
defaultMessage: "The advanced rich text editor. (Community Edition)"
},
components: {
Input: async () => Promise.resolve().then(() => require("./Field-DXPrjUnm.js")).then((module2) => ({
default: module2.Field
}))
},
options: {
base: [
{
intlLabel: {
id: `${PLUGIN_ID}.preset.label`,
defaultMessage: "Preset"
},
description: {
id: `${PLUGIN_ID}.preset.description`,
defaultMessage: " "
},
name: "options.preset",
type: "select",
options: AVAILABLE_OPTIONS
}
],
advanced: [
{
name: "required",
type: "checkbox",
intlLabel: {
id: `${PLUGIN_ID}.required.label`,
defaultMessage: "Required field"
},
description: {
id: `${PLUGIN_ID}.required.description`,
defaultMessage: "You won't be able to create an entry if this field is empty"
}
},
{
sectionTitle: {
id: `${PLUGIN_ID}.options.advanced.limiters`,
defaultMessage: "Input limiters"
},
items: [
{
name: "options.maxLengthWords",
type: "checkbox-with-number-field",
intlLabel: {
id: `${PLUGIN_ID}.maxLengthWords.label`,
defaultMessage: "Words limit"
}
},
{
name: "options.maxLengthCharacters",
type: "checkbox-with-number-field",
intlLabel: {
id: `${PLUGIN_ID}.maxLengthCharacters.label`,
defaultMessage: "Characters limit"
}
}
]
}
],
validator: () => ({
preset: yup__namespace.string().required({
id: `${PLUGIN_ID}.preset.error.required`,
defaultMessage: "Editor preset is required"
})
})
}
});
}
};
exports.StrapiMediaLib = StrapiMediaLib;
exports.StrapiUploadAdapter = StrapiUploadAdapter;
exports.clonedDefaultHtmlPreset = clonedDefaultHtmlPreset;
exports.clonedDefaultMarkdownPreset = clonedDefaultMarkdownPreset;
exports.clonedDefaultTheme = clonedDefaultTheme;
exports.getPluginConfig = getPluginConfig;
exports.getPluginPresets = getPluginPresets;
exports.getPluginTheme = getPluginTheme;
exports.index = index;
exports.isImageResponsive = isImageResponsive;
exports.prefixFileUrlWithBackendUrl = prefixFileUrlWithBackendUrl;
exports.setPluginConfig = setPluginConfig;