diff --git a/CHANGELOG.md b/CHANGELOG.md
index ec78474..383c402 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,17 @@
# Changelog
+## 0.2.0 (December 2, 2024)
+
+We are happy to announce the release of CKEditor 5 Official Integration v0.2.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 0.2.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.
+
## 0.1.0 (September 19, 2024)
We are happy to announce the release of CKEditor 5 Official Integration v0.1.0.
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 29faeca..8da8cac 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.js";
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',
@@ -146,7 +148,8 @@ const CKEDITOR_BASE_CONFIG_FOR_PRESETS = {
TableColumnResize,
TableCaption,
WordCount,
- StrapiMediaLib
+ StrapiMediaLib,
+ StrapiEditorUsageDataPlugin
],
toolbar: [
'undo', 'redo',
@@ -240,7 +243,8 @@ const CKEDITOR_BASE_CONFIG_FOR_PRESETS = {
TableCaption,
WordCount,
Highlight,
- StrapiMediaLib
+ StrapiMediaLib,
+ StrapiEditorUsageDataPlugin
],
toolbar: {
items: [
@@ -372,6 +376,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.js b/admin/src/components/CKEditorInput/index.js
index 6c58282..7311da6 100644
--- a/admin/src/components/CKEditorInput/index.js
+++ b/admin/src/components/CKEditorInput/index.js
@@ -29,8 +29,8 @@ const CKEditorInput = ( props ) => {
} = props;
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 );
@@ -132,4 +132,4 @@ CKEditorInput.propTypes = {
value: PropTypes.string,
};
-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.js b/admin/src/components/CKEditorProvider/index.js
index df6219b..7466704 100644
--- a/admin/src/components/CKEditorProvider/index.js
+++ b/admin/src/components/CKEditorProvider/index.js
@@ -1,98 +1,54 @@
-import { useState, useEffect } from 'react';
+import { memo, useEffect } from 'react';
+import { useCKEditorCloud } from '@ckeditor/ckeditor5-react';
const CKEditorProvider = ( {
- attribute,
- onChange,
- name,
- value,
- disabled = false,
- labelAction = null,
- intlLabel,
- required = false,
- description = null,
- error = null
- } ) => {
- const [ importedEditor, setImportedEditor ] = useState( null );
-
+ attribute,
+ onChange,
+ name,
+ value,
+ disabled = false,
+ labelAction = null,
+ intlLabel,
+ required = false,
+ description = null,
+ error = 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.js b/admin/src/index.js
index 5ddb438..32d69b5 100644
--- a/admin/src/index.js
+++ b/admin/src/index.js
@@ -41,6 +41,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',
@@ -157,6 +169,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 ee96658..c899287 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@ckeditor/strapi-plugin-ckeditor",
- "version": "0.1.0",
+ "version": "0.2.0",
"description": "CKEditor 5 - Official Integration for Strapi.",
"strapi": {
"name": "ckeditor",
@@ -24,7 +24,7 @@
"strapi-server.js"
],
"dependencies": {
- "@ckeditor/ckeditor5-react": "^9.1.0"
+ "@ckeditor/ckeditor5-react": "^9.3.0"
},
"peerDependencies": {
"@strapi/strapi": "^4.4.0"
diff --git a/yarn.lock b/yarn.lock
index 3233f79..ad3059b 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.2.2":
+ 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.4.0"
+ resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-react/-/ckeditor5-react-9.4.0.tgz#2d750ed585a4668931be089da7a02e823c706f16"
+ integrity sha512-8PU7YUV0ZKYP10akKgarT8nq5QxEDPmuj6Wn5dl/DJ7qroDx6VuC/ysCYcgljseimbDNYDjPQKhatNEcsMd7Ew==
dependencies:
- "@ckeditor/ckeditor5-integrations-common" "^1.0.0"
+ "@ckeditor/ckeditor5-integrations-common" "^2.2.2"
prop-types "^15.7.2"
"js-tokens@^3.0.0 || ^4.0.0":