diff --git a/CHANGELOG.md b/CHANGELOG.md
index f642454..99e7bcd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,17 @@
# Changelog
+## 1.1.0 (December 2, 2024)
+
+We are happy to announce the release of CKEditor 5 Official Integration v1.1.0.
+
+### Release highlights
+
+In this release, we updated the CKEditor 5 version to [v44.0.0](https://github.com/ckeditor/ckeditor5/blob/master/CHANGELOG.md#4400-december-2-2024), which introduces high impact updates. Starting from the plugin version 1.1.0, the custom field will require passing a valid license key.
+
+### BREAKING CHANGES ℹ️
+
+* **CKEditor 5 custom field now requires the license key**. CKEditor 5 now requires a valid license key, which can be retrieved from [Customer Portal](https://portal.ckeditor.com/). You can sign up for a [commitment-free trial](https://portal.ckeditor.com/checkout?plan=free) and get instant access to your key.
+
## 1.0.2 (September 20, 2024)
### Release highlights
diff --git a/README.md b/README.md
index 854e728..02becf5 100644
--- a/README.md
+++ b/README.md
@@ -22,6 +22,9 @@ This is an official plugin, provided to you by the [CKEditor team](https://ckedi
## 🔧 Installation
+> [!IMPORTANT]
+> Before installation, make sure that you own a **valid CKEditor 5 license key**. Start a [commitment-free trial](https://portal.ckeditor.com/checkout?plan=free) to get instant access to the license key. You can also refer to our [license key and activation guide](https://ckeditor.com/docs//ckeditor5/latest/getting-started/licensing/license-key-and-activation.html) to learn more.
+
Inside your Strapi app, add the package:
With `npm`:
@@ -36,7 +39,7 @@ With `yarn`:
yarn add @ckeditor/strapi-plugin-ckeditor
```
-Then, add the Content Security Policy configuration to allow loading CKEditor 5 from https://cdn.ckeditor.com origin, by adding the rule to `config/middlewares.ts` in your Strapi project root:
+Then, add the Content Security Policy configuration to allow loading CKEditor 5 from https://cdn.ckeditor.com origin and sending the editor usage information to https://proxy-event.ckeditor.com, by adding the rule to `config/middlewares.ts` in your Strapi project root:
```js
export default [
@@ -47,7 +50,8 @@ export default [
contentSecurityPolicy: {
useDefaults: true,
directives: {
- 'script-src': ['https://cdn.ckeditor.com']
+ 'script-src': ['https://cdn.ckeditor.com'],
+ 'connect-src': ['https://proxy-event.ckeditor.com']
},
},
},
diff --git a/admin/src/components/CKEditorInput/Configurator.js b/admin/src/components/CKEditorInput/Configurator.js
index 462e652..5b0091f 100644
--- a/admin/src/components/CKEditorInput/Configurator.js
+++ b/admin/src/components/CKEditorInput/Configurator.js
@@ -1,4 +1,5 @@
import { StrapiMediaLib } from "./plugins/StrapiMediaLib";
+import { StrapiEditorUsageDataPlugin } from "./plugins/StrapiEditorUsageData";
import MaximumLength from "../../vendor/ckeditor5-maximum-length/index";
import "../../vendor/ckeditor5-maximum-length/index-editor.css";
@@ -77,7 +78,8 @@ const CKEDITOR_BASE_CONFIG_FOR_PRESETS = {
TableColumnResize,
TableCaption,
WordCount,
- StrapiMediaLib
+ StrapiMediaLib,
+ StrapiEditorUsageDataPlugin
],
toolbar: [
'undo', 'redo',
@@ -158,7 +160,8 @@ const CKEDITOR_BASE_CONFIG_FOR_PRESETS = {
TableColumnResize,
TableCaption,
WordCount,
- StrapiMediaLib
+ StrapiMediaLib,
+ StrapiEditorUsageDataPlugin
],
toolbar: [
'undo', 'redo',
@@ -264,7 +267,8 @@ const CKEDITOR_BASE_CONFIG_FOR_PRESETS = {
TableCaption,
WordCount,
Highlight,
- StrapiMediaLib
+ StrapiMediaLib,
+ StrapiEditorUsageDataPlugin
],
toolbar: {
items: [
@@ -408,6 +412,9 @@ export default class Configurator {
const maxLength = this.fieldConfig.maxLength;
const outputOption = this.fieldConfig.options.output;
+ const licenseKey = this.fieldConfig.licenseKey;
+
+ config.licenseKey = licenseKey;
if ( outputOption === 'Markdown' ) {
config.plugins.push( Markdown );
diff --git a/admin/src/components/CKEditorInput/index.jsx b/admin/src/components/CKEditorInput/index.jsx
index aa5b8d0..b11c701 100644
--- a/admin/src/components/CKEditorInput/index.jsx
+++ b/admin/src/components/CKEditorInput/index.jsx
@@ -31,8 +31,8 @@ const CKEditorInput = ( props ) => {
const { onChange, value } = useField( name );
const [ editorInstance, setEditorInstance ] = useState(false);
const { formatMessage } = useIntl();
- const { maxLengthCharacters:maxLength , ...options } = attribute.options;
- const configurator = new Configurator( { options, maxLength } );
+ const { maxLengthCharacters:maxLength, licenseKey, ...options } = attribute.options;
+ const configurator = new Configurator( { options, maxLength, licenseKey } );
const editorConfig = configurator.getEditorConfig();
const wordCounter = useRef( null );
@@ -119,4 +119,4 @@ CKEditorInput.propTypes = {
required: PropTypes.bool
};
-export default CKEditorInput;
+export { CKEditorInput };
diff --git a/admin/src/components/CKEditorInput/plugins/StrapiEditorUsageData.js b/admin/src/components/CKEditorInput/plugins/StrapiEditorUsageData.js
new file mode 100644
index 0000000..d3d097c
--- /dev/null
+++ b/admin/src/components/CKEditorInput/plugins/StrapiEditorUsageData.js
@@ -0,0 +1,9 @@
+import { createIntegrationUsageDataPlugin } from '@ckeditor/ckeditor5-integrations-common';
+import * as pkg from '../../../../../package.json'
+
+export const StrapiEditorUsageDataPlugin = createIntegrationUsageDataPlugin(
+ 'strapi',
+ {
+ version: pkg.version,
+ }
+);
diff --git a/admin/src/components/CKEditorProvider/index.jsx b/admin/src/components/CKEditorProvider/index.jsx
index c29b8d3..1e600b3 100644
--- a/admin/src/components/CKEditorProvider/index.jsx
+++ b/admin/src/components/CKEditorProvider/index.jsx
@@ -1,4 +1,5 @@
-import { useState, useEffect } from 'react';
+import { memo, useEffect } from 'react';
+import { useCKEditorCloud } from '@ckeditor/ckeditor5-react';
const CKEditorProvider = ( {
attribute,
@@ -9,85 +10,41 @@ const CKEditorProvider = ( {
description = null,
error = null,
intlLabel } ) => {
- const [ importedEditor, setImportedEditor ] = useState( null );
+ // Clean up CDN scripts after unmounting the component.
useEffect( () => {
- const importEditor = async () => {
- const module = await import( '../CKEditorInput' );
- const CKEditorInput = module.default;
-
- setImportedEditor( );
- };
-
- const injectAssetsFromCDN = setInterval( () => {
- const CDNScript = document.querySelector( '#ckeditor5-cdn-script' );
- const CDNStyles = document.querySelector( '#ckeditor5-cdn-styles' );
-
- if ( !CDNStyles ) {
- _injectStylesFromCDN();
- }
-
- if ( window.CKEDITOR ) {
- window.CKEditorCDNLoaded = true;
-
- importEditor();
-
- clearInterval( injectAssetsFromCDN );
-
- return;
- }
-
- if ( !CDNScript ) {
- _injectScriptFromCDN();
-
- }
- }, 100 )
-
return () => {
- const CDNScript = document.querySelector( '#ckeditor5-cdn-script' );
+ const assets = document.querySelectorAll( '[data-injected-by="ckeditor-integration"]' );
- if ( CDNScript ) {
- CDNScript.remove();
- }
+ assets.forEach( asset => asset.remove() );
- window.CKEditorCDNLoaded = false;
+ window.CKEDITOR_VERSION = null;
}
- }, [] );
+ }, [] )
- return (
- <>
- { window.CKEditorCDNLoaded && importedEditor }
- >
- )
-}
-
-function _injectStylesFromCDN() {
- const link = document.createElement( 'link' );
-
- link.rel = 'stylesheet';
- link.href = 'https://cdn.ckeditor.com/ckeditor5/43.0.0/ckeditor5.css';
- link.id = 'ckeditor5-cdn-styles';
-
- document.head.appendChild( link );
-}
-
-function _injectScriptFromCDN() {
- const script = document.createElement( 'script' );
+ const cloud = useCKEditorCloud( {
+ version: '44.0.0',
+ plugins: {
+ CKEditorInput: async () => ( await import('../CKEditorInput') ).CKEditorInput
+ }
+ } );
- script.src = "https://cdn.ckeditor.com/ckeditor5/43.0.0/ckeditor5.umd.js";
- script.async = true;
- script.id = 'ckeditor5-cdn-script'
+ if ( cloud.status !== 'success' ) {
+ return null;
+ }
- document.body.appendChild( script );
+ return (
+
+ )
}
-export default CKEditorProvider;
+export default memo( CKEditorProvider );
diff --git a/admin/src/index.jsx b/admin/src/index.jsx
index 6cb30a7..e1fe8c2 100644
--- a/admin/src/index.jsx
+++ b/admin/src/index.jsx
@@ -39,6 +39,18 @@ export default {
},
options: {
base: [
+ {
+ intlLabel: {
+ id: 'ckeditor.licenseKey.label',
+ defaultMessage: 'License key',
+ },
+ description: {
+ id: 'ckeditor.licenseKey.description',
+ defaultMessage: "Don't have a license key? Visit https://portal.ckeditor.com/checkout?plan=free to receive it.",
+ },
+ name: 'options.licenseKey',
+ type: 'text',
+ },
{
intlLabel: {
id: 'ckeditor.preset.label',
@@ -155,6 +167,10 @@ export default {
id: 'ckeditor.preset.error.required',
defaultMessage: 'Editor preset is required',
} ),
+ licenseKey: yup.string().required( {
+ id: 'ckeditor.licenseKey.error.required',
+ defaultMessage: 'Editor license key is required. Visit https://portal.ckeditor.com/checkout?plan=free to receive it.',
+ } ),
} ),
},
} );
diff --git a/package.json b/package.json
index e93f8c1..133e186 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@ckeditor/strapi-plugin-ckeditor",
- "version": "1.0.2",
+ "version": "1.1.0",
"description": "CKEditor 5 - Official Integration for Strapi",
"strapi": {
"name": "ckeditor",
@@ -37,6 +37,6 @@
},
"license": "MIT",
"dependencies": {
- "@ckeditor/ckeditor5-react": "^9.1.0"
+ "@ckeditor/ckeditor5-react": "^9.3.0"
}
}
diff --git a/yarn.lock b/yarn.lock
index 3233f79..3d758c1 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2,17 +2,17 @@
# yarn lockfile v1
-"@ckeditor/ckeditor5-integrations-common@^1.0.0":
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-integrations-common/-/ckeditor5-integrations-common-1.0.0.tgz#f2f73509d029398929ee30da3ae23329de5a796a"
- integrity sha512-HLToIJ7FAtKX0tu9GaGb1d39Kx0i0TFelAj2pQPiwPU/6DLgM5gi+m0WCZub+syruSonmZPONtWrrZZdUoDB/g==
-
-"@ckeditor/ckeditor5-react@^9.1.0":
- version "9.1.0"
- resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-react/-/ckeditor5-react-9.1.0.tgz#fc645a055a5c84acb41c55f0c4bffab45221d2ca"
- integrity sha512-48Y8Ffe21H3+3GOvjTtSITYJdeX4BINxCHyXp5zNvhTtyAyahMwG6jCgdZl1D3lwXxSq9R0/yCDHPWeMk9KOHQ==
+"@ckeditor/ckeditor5-integrations-common@^2.1.0":
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-integrations-common/-/ckeditor5-integrations-common-2.2.2.tgz#c494b51ad0736d087a7bc13ec634e2d66db42d5b"
+ integrity sha512-SKGBBrwFFmSEZawR8P9tHGRq/l2OoqoJxy9f7j0HbDGEwIpSOsCSgH0xudD6lcEbWG4QWrCS28p5n8lgPA5elQ==
+
+"@ckeditor/ckeditor5-react@^9.3.0":
+ version "9.3.1"
+ resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-react/-/ckeditor5-react-9.3.1.tgz#5ed94789eb5d26bf8d185185c7dfcc57f2bfb97d"
+ integrity sha512-2lc1ICGCOZ0loC6DeMFwhkhrodLYUsOnC2wdgMiaXnEWRI/fU0SWBAoLbsMH7i6zpq29s+ZWMEImRVbly8SmEA==
dependencies:
- "@ckeditor/ckeditor5-integrations-common" "^1.0.0"
+ "@ckeditor/ckeditor5-integrations-common" "^2.1.0"
prop-types "^15.7.2"
"js-tokens@^3.0.0 || ^4.0.0":