From 0ad0270c3f1e39dbdf7999839433c31f7999b5ec Mon Sep 17 00:00:00 2001 From: Witek Socha Date: Tue, 8 Aug 2023 13:15:58 +0200 Subject: [PATCH 01/16] Prepare how-to's and update the FAQ. --- docs/examples/how-tos.md | 398 +++++++++++++++++++++++++++++++++++++++ docs/support/faq.md | 149 ++------------- 2 files changed, 411 insertions(+), 136 deletions(-) create mode 100644 docs/examples/how-tos.md diff --git a/docs/examples/how-tos.md b/docs/examples/how-tos.md new file mode 100644 index 00000000000..bb14b80ee72 --- /dev/null +++ b/docs/examples/how-tos.md @@ -0,0 +1,398 @@ +--- +category: examples +order: 11 +modified_at: 2023-07-17 +--- + +# How to's + +## Basics + +### How to set the height of CKEditor 5? + +The height of the editing area can be easily controlled with CSS. + +```css +.ck.ck-content:not(.ck-comment__input *) { + height: 300px; + overflow-y: auto; +} +``` + +### How to customize the CKEditor 5 icons? + +The easiest way is to use webpack's [`NormalModuleReplacementPlugin`](https://webpack.js.org/plugins/normal-module-replacement-plugin/) plugin. For example, to replace the bold icon, use the following code in your `webpack.config.js`: + +```js +... +plugins: [ + new webpack.NormalModuleReplacementPlugin( + /bold\.svg/, + '/absolute/path/to/my/icon.svg' + ) +] +``` + +You can also use the relative path which is resolved relative to the resource that imports `bold.svg` (the {@link module:basic-styles/bold/boldui~BoldUI `BoldUI`} class file in this scenario). + +Learn more about {@link installation/advanced/integrating-from-source-webpack#webpack-configuration building CKEditor 5 using webpack}. + +### How to add an attribute to the editor editable in DOM? + +If you have a reference to the editor instance, use the {@link framework/architecture/editing-engine#changing-the-view `change()`} method of the view and set the new attribute via the {@link module:engine/view/downcastwriter~DowncastWriter view downcast writer}: + +```js +editor.editing.view.change((writer) => { + const viewEditableRoot = editor.editing.view.document.getRoot(); + + writer.setAttribute("myAttribute", "value", viewEditableRoot); +}); +``` + +If you do not have the reference to the editor instance but you have access to the editable element in the DOM, you can [access it using the `ckeditorInstance` property](#how-to-get-the-editor-instance-object-from-the-dom-element) and then use the same API to set the attribute: + +```js +const domEditableElement = document.querySelector(".ck-editor__editable"); +const editorInstance = domEditableElement.ckeditorInstance; + +editorInstance.editing.view.change((writer) => { + // Map the editable element in the DOM to the editable element in the editor's view. + const viewEditableRoot = + editorInstance.editing.view.domConverter.mapDomToView( + domEditableElement + ); + + writer.setAttribute("myAttribute", "value", viewEditableRoot); +}); +``` + +### How to check the CKEditor version? + +To check your editor version, open the JavaScript console available in the browser's developer tools. This is usually done through the browser's menu or by right-clicking anywhere on the page and choosing the `Inpect` option from the dropdown. + +Enter the `CKEDITOR_VERSION` command to check the currently used CKEditor 5 version. + +{@img assets/img/version.png 468 CKEditor 5 version displayed in the developer console.} + +## Editor's instances + +### How to get the editor instance in the plugin? + +In a simple plugin, you can get editor's instance using a plugin functions' attribute + +```js +function myPlugin(editor) { + // Interact with the API. + // ... +} + +ClassicEditor.create(document.querySelector("#editor"), { + // If you're using builds, this is going to be extraPlugins property. + plugins: [ + myPlugin, + // Other plugins. + // ... + ], +}); +``` + +### How to get the editor instance object from the DOM element? + +If you have a reference to the editor editable's DOM element (the one with the `.ck-editor__editable` class and the `contenteditable` attribute), you can access the editor instance this editable element belongs to using the `ckeditorInstance` property: + +```html + +
+ +
+``` + +```js +// A reference to the editor editable element in the DOM. +const domEditableElement = document.querySelector(".ck-editor__editable"); + +// Get the editor instance from the editable element. +const editorInstance = domEditableElement.ckeditorInstance; + +// Use the editor instance API. +editorInstance.setData("

Hello world!

"); +``` + +### How to list all instances of the editor? + +By default, CKEditor 5 has no global registry of editor instances. But if necessary, such a feature can be easily implemented, as explained in this [Stack Overflow answer](https://stackoverflow.com/a/48682501/1485219). + +## Editor's API + +### How to insert some content into the editor? + +Because CKEditor 5 uses a custom {@link framework/architecture/editing-engine data model}, whenever you want to insert anything, you should modify the model first, which is then converted back to the view where the users input their content (called "editable"). In CKEditor 5, HTML is just one of many possible output formats. You can learn more about the ways of changing the model in the {@link framework/architecture/editing-engine#changing-the-model dedicated guide}. + +For example, to insert a new link at the current position, use the following snippet: + +```js +editor.model.change((writer) => { + const insertPosition = editor.model.document.selection.getFirstPosition(); + + writer.insertText( + "CKEditor 5 rocks!", + { linkHref: "https://ckeditor.com/" }, + insertPosition + ); +}); +``` + +And to insert some plain text, you can use a slightly shorter one: + +```js +editor.model.change((writer) => { + writer.insertText( + "Plain text", + editor.model.document.selection.getFirstPosition() + ); +}); +``` + +You may have noticed that a link is represented as a text with an attribute in the editor model. See the API of the {@link module:engine/model/writer~Writer model writer} to learn about other useful methods that can help you modify the editor model. + +To insert some longer HTML code, you can parse it to the {@link module:engine/model/documentfragment~DocumentFragment model fragment} first and then {@link module:engine/model/model~Model#insertContent insert} it into the editor model: + +```js +const content = + '

A paragraph with some link.

'; +const viewFragment = editor.data.processor.toView(content); +const modelFragment = editor.data.toModel(viewFragment); + +editor.model.insertContent(modelFragment); +``` + +TODO commands + +### How to focus the editor? + +```js +// Focus the editor. +editor.focus(); + +// Focus the editing area of the editor. +editor.editing.view.focus(); +``` + +### How to delete selected blocks? + +```js +const selectedBlocks = Array.from( + editor.model.document.selection.getSelectedBlocks() +); +const firstBlock = selectedBlocks[0]; +const lastBlock = selectedBlocks[selectedBlocks.length - 1]; + +editor.model.change((writer) => { + const range = writer.createRange( + writer.createPositionAt(firstBlock, 0), + writer.createPositionAt(lastBlock, lastBlock.maxOffset) + ); + + writer.remove(range); +}); +``` + +### How to delete all specific elements (e.g. block images) in the editor? + +```js +editor.model.change((writer) => { + const range = writer.createRangeIn(editor.model.document.getRoot()); + const itemsToRemove = []; + + for (const value of range.getWalker()) { + if (value.item.is("element", "imageBlock")) { + // a different `is` usage. + itemsToRemove.push(value.item); + } + } + + for (const item of itemsToRemove) { + writer.remove(item); // remove all of the items. + } +}); +``` + +### How to place the caret at the beginning or the end? + +```js +// Place it at the beginning. +editor.model.change((writer) => { + writer.setSelection( + writer.createPositionAt(editor.model.document.getRoot(), [0]) + ); +}); + +// Place it at the end. +editor.model.change((writer) => { + writer.setSelection( + writer.createPositionAt(editor.model.document.getRoot(), "end") + ); +}); +``` + +### How to find all specific elements (e.g. links) in the editor? + +```js +const range = editor.model.createRangeIn(editor.model.document.getRoot()); +const items = []; + +for (const value of range.getWalker()) { + if (value.type === "text" && value.item.hasAttribute("linkHref")) { + console.log(value.item); + } +} +``` + +### How to listen on a double click (e.g. link elements)? + +```js +// Add observer for double click and extend a generic DomEventObserver class by a native DOM dblclick event: +import DomEventObserver from "@ckeditor/ckeditor5-engine/src/view/observer/domeventobserver"; + +class DoubleClickObserver extends DomEventObserver { + constructor(view) { + super(view); + + this.domEventType = "dblclick"; + } + + onDomEvent(domEvent) { + this.fire(domEvent.type, domEvent); + } +} + +// Then use in the editor: +const view = editor.editing.view; +const viewDocument = view.document; + +view.addObserver(DoubleClickObserver); + +editor.listenTo( + viewDocument, + "dblclick", + (evt, data) => { + console.log("clicked"); + // Fire your custom actions here + }, + { context: "a" } +); +``` + +### How to create a widget with a single view element and multiple/nested model elements? + +```js +import { Plugin } from "ckeditor5/src/core"; +import { toWidget, toWidgetEditable } from "ckeditor5/src/widget"; + +class Forms extends Plugin { + init() { + const editor = this.editor; + const schema = editor.model.schema; + + schema.register("forms", { + inheritAllFrom: "$inlineObject", + allowAttributes: "type", + }); + + schema.register("formName", { + allowIn: "forms", + allowChildren: "$text", + isLimit: true, + }); + + // Disallow all attributes on $text inside `formName` (there won't be any bold/italic etc. inside). + schema.addAttributeCheck((context) => { + if (context.endsWith("formName $text")) { + return false; + } + }); + + // Allow only text nodes inside `formName` (without any elements that could be down-casted to HTML elements). + schema.addChildCheck((context, childDefinition) => { + if ( + context.endsWith("formName") && + childDefinition.name !== "$text" + ) { + return false; + } + }); + + // Data upcast. Convert a single element loaded by the editor to a structure of model elements. + editor.conversion.for("upcast").elementToElement({ + view: { + name: "input", + attributes: ["type", "name"], + }, + model: (viewElement, { writer }) => { + const modelElement = writer.createElement("forms", { + type: viewElement.getAttribute("type"), + }); + const nameModelElement = writer.createElement("formName"); + + // Build model structure out of a single view element. + writer.insert(nameModelElement, modelElement, 0); + writer.insertText( + viewElement.getAttribute("name"), + nameModelElement, + 0 + ); + + return modelElement; + }, + }); + + // Editing downcast. Convert model elements separately to widget and to widget-editable nested inside. + editor.conversion + .for("editingDowncast") + .elementToElement({ + model: "forms", + view: (modelElement, { writer }) => { + const viewElement = writer.createContainerElement("span", { + "data-type": modelElement.getAttribute("type"), + style: "display: inline-block", + }); + + return toWidget(viewElement, writer); + }, + }) + .elementToElement({ + model: "formName", + view: (modelElement, { writer }) => { + const viewElement = writer.createEditableElement("span"); + + return toWidgetEditable(viewElement, writer); + }, + }); + + // Data downcast. Convert the outermost model element and all its content into a single view element. + editor.conversion.for("dataDowncast").elementToElement({ + model: "forms", + view: (modelElement, { writer, consumable }) => { + let nameModelElement; + + // Find the `formName` model element and consume everything inside the model element range, + // so it won't get converted by any other downcast converters. + for (const { item } of editor.model.createRangeIn( + modelElement + )) { + if (item.is("element", "formName")) { + nameModelElement = modelElement.getChild(0); + } + + consumable.consume(item, "insert"); + } + + return writer.createContainerElement("input", { + type: modelElement.getAttribute("type"), + name: nameModelElement.getChild(0).data, + }); + }, + }); + } +} +``` diff --git a/docs/support/faq.md b/docs/support/faq.md index a219294cd00..96e08b3ded2 100644 --- a/docs/support/faq.md +++ b/docs/support/faq.md @@ -6,78 +6,11 @@ order: 60 # Frequently asked questions -## How to set the height of CKEditor 5? - -The height of the editing area can be easily controlled with CSS. - -```css -.ck.ck-content:not(.ck-comment__input *) { - height: 300px; - overflow-y: auto; -} -``` - -## Why does the editor filter out my content (styles, classes, elements)? - -CKEditor 5 implements a custom {@link framework/architecture/editing-engine data model}. This means that every piece of content that is loaded into the editor needs to be converted to that model and then rendered back to the view. - -Each kind of content must be handled by some feature. For example, the [`ckeditor5-basic-styles`](https://www.npmjs.com/package/@ckeditor/ckeditor5-basic-styles) package handles HTML elements such as ``, ``, ``, etc. along with their representation in the model. The feature defines the two–way conversion between the HTML (view) and the editor model. - -If you load some content unknown to any editor feature, it will be dropped. If you want all the HTML5 elements to be supported, you need to write plugins to support them. Once you do that, CKEditor 5 will not filter anything out. - -## The build I downloaded is missing some features. How do I add them? - -See the {@link installation/plugins/installing-plugins Installing plugins} guide to learn how to extend the editor with some additional features. - -You can learn which editor features are available in which build in the {@link installation/getting-started/predefined-builds#list-of-plugins-included-in-the-ckeditor-5-predefined-builds Predefined builds} guide. - -## How to insert some content into the editor? - -Because CKEditor 5 uses a custom {@link framework/architecture/editing-engine data model}, whenever you want to insert anything, you should modify the model first, which is then converted back to the view where the users input their content (called "editable"). In CKEditor 5, HTML is just one of many possible output formats. You can learn more about the ways of changing the model in the {@link framework/architecture/editing-engine#changing-the-model dedicated guide}. - -To insert a new link at the current position, use the following snippet: - -```js -editor.model.change( writer => { - const insertPosition = editor.model.document.selection.getFirstPosition(); - - writer.insertText( 'CKEditor 5 rocks!', { linkHref: 'https://ckeditor.com/' }, insertPosition ); -} ); -``` - -And to insert some plain text, you can use a slightly shorter one: - -```js -editor.model.change( writer => { - writer.insertText( 'Plain text', editor.model.document.selection.getFirstPosition() ); -} ); -``` - -You may have noticed that a link is represented as a text with an attribute in the editor model. See the API of the {@link module:engine/model/writer~Writer model writer} to learn about other useful methods that can help you modify the editor model. - -To insert some longer HTML code, you can parse it to the {@link module:engine/model/documentfragment~DocumentFragment model fragment} first and then {@link module:engine/model/model~Model#insertContent insert} it into the editor model: - -```js -const content = '

A paragraph with some link.'; -const viewFragment = editor.data.processor.toView( content ); -const modelFragment = editor.data.toModel( viewFragment ); - -editor.model.insertContent( modelFragment ); -``` - -## How to list all instances of the editor? - -By default, CKEditor 5 has no global registry of editor instances. But if necessary, such a feature can be easily implemented, as explained in this [Stack Overflow answer](https://stackoverflow.com/a/48682501/1485219). - -## How to enable image drag&drop and upload? Where should I start? - -The {@link features/images-overview image} and {@link features/image-upload image upload} features are enabled by default in all editor builds. However, to fully enable image upload when installing CKEditor 5, you need to configure one of the available upload adapters. Check out the {@link features/image-upload comprehensive "Image upload" guide} to find out the best image upload strategy for your project. - -## How to use CKEditor 5 with frameworks (Angular, React, Vue, etc.)? +## How to use CKEditor 5 with frameworks (Angular, React, Vue, etc.)? For the list of official integrations, see the {@link installation/integrations/overview#official-wysiwyg-editor-integrations "Official integrations"} section. -If an official integration for the framework of your choice does not exist yet, read the {@link installation/integrations/overview "Integrating CKEditor 5 with JavaScript frameworks"} guide. CKEditor 5 offers a rich JavaScript API and predefined builds that make it possible to use CKEditor 5 with whichever framework you need. +If an official integration for the framework of your choice does not exist yet, read the {@link installation/integrations/overview "Integrating CKEditor 5 with JavaScript frameworks"} guide. CKEditor 5 offers a rich JavaScript API and predefined builds that make it possible to use CKEditor 5 with whichever framework you need. We plan to provide more official integrations with time. [Your feedback on what we should work on next](https://github.com/ckeditor/ckeditor5/issues/1002) will be most welcome! @@ -87,80 +20,24 @@ We have prepared a build containing almost all available plugins, and it is call In the {@link installation/getting-started/predefined-builds predefined builds} guide, there are details available about the {@link installation/getting-started/predefined-builds#superbuild superbuild}, together with the {@link installation/getting-started/predefined-builds#list-of-plugins-included-in-the-ckeditor-5-predefined-builds list of features included in the superbuild}, compared to other types of builds. -## How to customize the CKEditor 5 icons? - -The easiest way is to use webpack's [`NormalModuleReplacementPlugin`](https://webpack.js.org/plugins/normal-module-replacement-plugin/) plugin. For example, to replace the bold icon, use the following code in your `webpack.config.js`: - -```js -... -plugins: [ - new webpack.NormalModuleReplacementPlugin( - /bold\.svg/, - '/absolute/path/to/my/icon.svg' - ) -] -``` - -You can also use the relative path which is resolved relative to the resource that imports `bold.svg` (the {@link module:basic-styles/bold/boldui~BoldUI `BoldUI`} class file in this scenario). - -Learn more about {@link installation/advanced/integrating-from-source-webpack#webpack-configuration building CKEditor 5 using webpack}. - -## How to get the editor instance object from the DOM element? - -If you have a reference to the editor editable's DOM element (the one with the `.ck-editor__editable` class and the `contenteditable` attribute), you can access the editor instance this editable element belongs to using the `ckeditorInstance` property: - -```html - -

- -
-``` - -```js -// A reference to the editor editable element in the DOM. -const domEditableElement = document.querySelector( '.ck-editor__editable' ); - -// Get the editor instance from the editable element. -const editorInstance = domEditableElement.ckeditorInstance; - -// Use the editor instance API. -editorInstance.setData( '

Hello world!

' ); -``` - -## How to add an attribute to the editor editable in DOM? - -If you have a reference to the editor instance, use the {@link framework/architecture/editing-engine#changing-the-view `change()`} method of the view and set the new attribute via the {@link module:engine/view/downcastwriter~DowncastWriter view downcast writer}: - -```js -editor.editing.view.change( writer => { - const viewEditableRoot = editor.editing.view.document.getRoot(); - - writer.setAttribute( 'myAttribute', 'value', viewEditableRoot ); -} ); -``` +## How to turn the source mode on? -If you do not have the reference to the editor instance but you have access to the editable element in the DOM, you can [access it using the `ckeditorInstance` property](#how-to-get-the-editor-instance-object-from-the-dom-element) and then use the same API to set the attribute: +The {@link features/source-editing source editing} feature provides basic support for viewing and editing the source of the document. -```js -const domEditableElement = document.querySelector( '.ck-editor__editable' ); -const editorInstance = domEditableElement.ckeditorInstance; +## Why does the editor filter out my content (styles, classes, elements)? -editorInstance.editing.view.change( writer => { - // Map the editable element in the DOM to the editable element in the editor's view. - const viewEditableRoot = editorInstance.editing.view.domConverter.mapDomToView( domEditableElement ); +CKEditor 5 implements a custom {@link framework/architecture/editing-engine data model}. This means that every piece of content that is loaded into the editor needs to be converted to that model and then rendered back to the view. - writer.setAttribute( 'myAttribute', 'value', viewEditableRoot ); -} ); -``` +Each kind of content must be handled by some feature. For example, the [`ckeditor5-basic-styles`](https://www.npmjs.com/package/@ckeditor/ckeditor5-basic-styles) package handles HTML elements such as ``, ``, ``, etc. along with their representation in the model. The feature defines the two–way conversion between the HTML (view) and the editor model. -## How to check the CKEditor version? +If you load some content unknown to any editor feature, it will be dropped. If you want all the HTML5 elements to be supported, you need to write plugins to support them. Once you do that, CKEditor 5 will not filter anything out. -To check your editor version, open the JavaScript console available in the browser's developer tools. This is usually done through the browser's menu or by right-clicking anywhere on the page and choosing the `Inpect` option from the dropdown. +## How to add more features to the build I downloaded? -Enter the `CKEDITOR_VERSION` command to check the currently used CKEditor 5 version. +See the {@link installation/plugins/installing-plugins Installing plugins} guide to learn how to extend the editor with some additional features. -{@img assets/img/version.png 468 CKEditor 5 version displayed in the developer console.} +You can learn which editor features are available in which build in the {@link installation/getting-started/predefined-builds#list-of-plugins-included-in-the-ckeditor-5-predefined-builds Predefined builds} guide. -## How to turn the source mode on? +## How to enable image drag&drop and upload? Where should I start? -The {@link features/source-editing source editing} feature provides basic support for viewing and editing the source of the document. +The {@link features/images-overview image} and {@link features/image-upload image upload} features are enabled by default in all editor builds. However, to fully enable image upload when installing CKEditor 5, you need to configure one of the available upload adapters. Check out the {@link features/image-upload comprehensive "Image upload" guide} to find out the best image upload strategy for your project. From c062b5d2453063f5108f839f2c75869715844fa5 Mon Sep 17 00:00:00 2001 From: Witek Socha Date: Tue, 8 Aug 2023 13:18:01 +0200 Subject: [PATCH 02/16] Prepare changes in the getting started docs. --- .../adding-simple-functions.md | 59 +++++++ .../getting-started/configuration.md | 117 ++++---------- .../getting-started/editor-lifecycle.md | 149 ++++++------------ .../getting-and-setting-data.md | 106 ++++++------- .../getting-started/using-api-and-events.md | 64 ++++++++ 5 files changed, 254 insertions(+), 241 deletions(-) create mode 100644 docs/installation/getting-started/adding-simple-functions.md create mode 100644 docs/installation/getting-started/using-api-and-events.md diff --git a/docs/installation/getting-started/adding-simple-functions.md b/docs/installation/getting-started/adding-simple-functions.md new file mode 100644 index 00000000000..f0cefe6925b --- /dev/null +++ b/docs/installation/getting-started/adding-simple-functions.md @@ -0,0 +1,59 @@ +--- +category: getting-started +order: 90 +--- + +# Adding simple functions + +You can make use of the API exposed by the editor and its plugins and extend the editor using the {@link module:core/plugin~PluginInterface plugin interface} like this: + +```js +function MyPlugin( editor ) { + // Plugin code. + // ... +} +``` + +or + +```js +class MyPlugin extends Plugin { + constructor( editor ) { + // Constructor code. + // ... + } + + init() { + // Initializations code. + // ... + } +} +``` + +This method allows writing simple plugins that will be executed during the initialization of the editor, and don't need to interact with other plugin schema's or UI. To add a newly created plugin to an editor you need to use {@link module:core/editor/editorconfig~EditorConfig#extraPlugins `config.extraPlugins`} property in configuration. + +## Example + +An example plugin that you may want to use this way is a {@link framework/deep-dive/upload-adapter custom upload adapter}. + +```js +import ClassicEditor from '@ckeditor/ckeditor5-build-classic'; + +function MyUploadAdapterPlugin( editor ) { + editor.plugins.get( 'FileRepository' ).createUploadAdapter = function( loader ) { + // Custom upload adapter. + // ... + }; +} + +// Load the custom upload adapter as a plugin of the editor. +ClassicEditor + .create( document.querySelector( '#editor' ), { + extraPlugins: [ MyUploadAdapterPlugin ], + // More of the editor's configuration. + // ... + } ) + .catch( error => { + console.log( error ); + } ); +``` diff --git a/docs/installation/getting-started/configuration.md b/docs/installation/getting-started/configuration.md index 9d0e53f6d31..ca503ceabdd 100644 --- a/docs/installation/getting-started/configuration.md +++ b/docs/installation/getting-started/configuration.md @@ -13,10 +13,10 @@ order: 40 **Quick recap** -In the {@link installation/getting-started/quick-start-other previous tutorial} you have learned about various ways for setting up CKEditor 5 in the project. Now, you know how to use online builder or create the editor from source. It is time to play a bit with the configuration! +In the {@link installation/getting-started/quick-start-other previous tutorial} you have learned about various ways for setting up CKEditor 5 in the project. Now, you know how to use the online builder or create the editor from the source. It is time to play a bit with the configuration! -When creating an editor in your page, it is possible to set up {@link module:core/editor/editorconfig~EditorConfig configurations} that change many of its aspects. For example: +When creating an editor on your page, it is possible to set up {@link module:core/editor/editorconfig~EditorConfig configurations} that change many of its aspects. For example: ```js ClassicEditor @@ -37,9 +37,35 @@ ClassicEditor As you can see, the configuration is set by a simple JavaScript object passed to the `create()` method. +See {@link module:core/editor/editorconfig~EditorConfig} to learn about all available configuration options. + +Some of the options may require loading plugins that are not available in the build you use. Return to the {@link installation/getting-started/quick-start-other Customized installation} guide for instructions on creating a custom build. + +## Toolbar setup + +In the builds that contain toolbars an optimal default configuration is defined for it. You may need a different toolbar arrangement, though, and this can be achieved through configuration. Check the detailed {@link features/toolbar toolbar feature guide} for the available options. + +When you create a {@link installation/getting-started/quick-start-other#creating-custom-builds-with-online-builder custom build using CKEditor 5 online builder}, setting up your toolbar configuration is one of the steps in the build creation process that uses an intuitive drag and drop interface. + +## Adding features + +All the features of CKEditor 5 all implemented by plugins. {@link installation/plugins/plugins Read more about the plugin concept.} + +### List of plugins + +Each build has some plugins available. You can easily list all plugins available in your build: + +```js +ClassicEditor.builtinPlugins.map( plugin => plugin.pluginName ); +``` + +### Installing plugins + +Predefined CKEditor 5 builds do not include all possible features. To add more features you can {@link installation/plugins/installing-plugins install plugins} to custom builds and to editors integrated from the source. + ## Removing features -The {@link installation/getting-started/predefined-builds predefined CKEditor 5 builds} come with all the features included in the distribution package enabled by default. They are defined as plugins for CKEditor 5. +The {@link installation/getting-started/predefined-builds predefined CKEditor 5 builds} come with all the features included in the distribution package enabled by default. They are defined as plugins for CKEditor 5. In some cases, you may want to have different editor setups in your application, all based on the same build. For that purpose, you need to control the plugins available in the editor at runtime. @@ -71,12 +97,12 @@ ClassicEditor } ); ``` -However, using this snippet with the official classic build of CKEditor 5 will result in an error thrown in the console of the browser: +However, using this snippet with the official classic build of CKEditor 5 will result in an error thrown in the console of the browser: ``` CKEditorError: plugincollection-required {"plugin":"Link","requiredBy":"CKFinder"}` Read more: [https://ckeditor.com/docs/ckeditor5/latest/support/error-codes.html#error-plugincollection-required](https://ckeditor.com/docs/ckeditor5/latest/support/error-codes.html#error-plugincollection-required) ``` -This is a good time to remind you that some plugins in CKEditor 5 depend on each other. In this case, the `CKFinder` plugin requires the `Link` plugin to work. To make the above snippet work, the `CKFinder` plugin must also be deleted: +This is a good time to remind you that some plugins in CKEditor 5 depend on each other. In this case, the `CKFinder` plugin requires the `Link` plugin to work. To make the above snippet work, the `CKFinder` plugin must also be deleted: ```js // Remove a few plugins from the default setup. @@ -94,87 +120,8 @@ ClassicEditor Be careful when removing plugins from CKEditor builds using {@link module:core/editor/editorconfig~EditorConfig#removePlugins `config.removePlugins`}. If removed plugins were providing toolbar buttons, the default toolbar configuration included in a build will become invalid. In such case you need to provide the {@link features/toolbar updated toolbar configuration} as in the example above or by providing only toolbar items that need to be removed using `config.toolbar.removeItems`. -### List of plugins - -Each build has a number of plugins available. You can easily list all plugins available in your build: - -```js -ClassicEditor.builtinPlugins.map( plugin => plugin.pluginName ); -``` - -## Adding features - -### Adding complex features - -As predefined CKEditor 5 builds do not include all possible features, the only way to add more features to them is to {@link installation/getting-started/quick-start-other create a custom build}. - -### Adding simple (standalone) features - -There is an exception to every rule. Although it is impossible to add plugins that have dependencies to {@link api/core `@ckeditor/ckeditor5-core`} or {@link api/engine `@ckeditor/ckeditor5-engine`} (that includes nearly all existing official plugins) without rebuilding the build, it is still possible to add simple, **dependency-free** plugins. - -You can do that using the {@link module:core/editor/editorconfig~EditorConfig#extraPlugins `config.extraPlugins`} configuration. The {@link module:core/plugin~PluginInterface plugin interface} allows plugins to be simple functions and you can define them in just a few lines, for instance: - -```js -function MyPlugin( editor ) { - // Plugin code. - // ... -} -``` - -or - -```js -class MyPlugin { - constructor( editor ) { - // Constructor code. - // ... - } - - init() { - // Initializations code. - // ... - } -} -``` - -An example plugin that you may want to add this way is a {@link framework/deep-dive/upload-adapter custom upload adapter}. - -```js -import ClassicEditor from '@ckeditor/ckeditor5-build-classic'; - -function MyUploadAdapterPlugin( editor ) { - editor.plugins.get( 'FileRepository' ).createUploadAdapter = function( loader ) { - // Custom upload adapter. - // ... - }; -} - -// Load the custom upload adapter as a plugin of the editor. -ClassicEditor - .create( document.querySelector( '#editor' ), { - extraPlugins: [ MyUploadAdapterPlugin ], - // More of the editor's configuration. - // ... - } ) - .catch( error => { - console.log( error ); - } ); -``` - -## Toolbar setup - -In the builds that contain toolbars an optimal default configuration is defined for it. You may need a different toolbar arrangement, though, and this can be achieved through configuration. Check the detailed {@link features/toolbar toolbar feature guide} for the available options. - -When you create a {@link installation/getting-started/quick-start-other#creating-custom-builds-with-online-builder custom build using CKEditor 5 online builder}, setting up your toolbar configuration is one of the steps in the build creation process that uses an intuitive drag and drop interface. - -## Other configuration options - -See {@link module:core/editor/editorconfig~EditorConfig} to learn about all available configuration options. - -Some of the options may require loading plugins which are not available in the build you use. Return to the {@link installation/getting-started/quick-start-other Quick start} guide for instructions on creating a custom build. - **What's next?** -You have learned how to configure your own CKEditor 5 instance. Awesome! In the next tutorial, you will learn more about extending your editor with plugins. Ready for a ride? {@link installation/plugins/installing-plugins Jump in}! +You have learned how to configure your own CKEditor 5 instance. Awesome! In the next tutorial, you will learn more about extending your editor with plugins. Ready for a ride? {@link installation/plugins/installing-plugins Jump in}! diff --git a/docs/installation/getting-started/editor-lifecycle.md b/docs/installation/getting-started/editor-lifecycle.md index 480b9918665..694163e87db 100644 --- a/docs/installation/getting-started/editor-lifecycle.md +++ b/docs/installation/getting-started/editor-lifecycle.md @@ -3,32 +3,25 @@ category: getting-started order: 60 --- -# Editor lifecycle +# Editor's lifecycle **Quick recap** -In the {@link installation/plugins/installing-plugins previous tutorial} you have explored available features and learned how to add them to your editor. This article shows the lifecycle methods used to interact with the editor. - +In the {@link installation/getting-started/configuration previous tutorial} you have explored available configuration options of the editor. This article shows the lifecycle methods to create and destroy the editor. + -Each CKEditor 5 **build** provides a different **editor class** that handles the creation of editor instances: +Each CKEditor 5 **type** provides a different **editor class** that handles the creation of editor instances. Most of the examples in the documentation use the {@link module:editor-classic/classiceditor~ClassicEditor `ClassicEditor`} class, but things should work similarly with other types. -* Classic editor – {@link module:editor-classic/classiceditor~ClassicEditor} -* Inline editor – {@link module:editor-inline/inlineeditor~InlineEditor} -* Balloon editor – {@link module:editor-balloon/ballooneditor~BalloonEditor} -* Document editor – {@link module:editor-decoupled/decouplededitor~DecoupledEditor} +## Creating an editor with `create()` -Most of the examples in the documentation use the `ClassicEditor` class, but things should work in a similar way with other builds. +Regardless of the chosen type, creating an editor is done using the static `create()` method. Usually, you start with an HTML element that will be a place where an editor will render itself on a page. - - A CKEditor 5 build compiles a specific editor class and a set of plugins. Using builds is the simplest way to include the editor in your application, but you can also {@link installation/advanced/integrating-from-source-webpack use the editor classes and plugins directly} for greater flexibility. + +Every editor class may accept different parameters in the `create()` method and may handle the initialization differently. For instance, the classic editor will **replace** the given element with an editor, while the inline editor will use the given element to initialize an editor on it. The decoupled document needs to initialize the toolbar separately from the editable area. See each editor's documentation to learn the details. -## Creating an editor with `create()` - -Regardless of the chosen build, creating an editor is done using the static `create()` method. - ### Example – classic editor Add an element that CKEditor should replace to your HTML page: @@ -39,68 +32,23 @@ Add an element that CKEditor should replace to your HTML page: ``` -Then call {@link module:editor-classic/classiceditor~ClassicEditor#create `ClassicEditor.create()`} to **replace** the `