Selaa lähdekoodia

Docs: Split the frameworks/Quick Start guide into 3 sub-gudes. Added the Development Tools guide.

Aleksander Nowodzinski 6 vuotta sitten
vanhempi
commit
a8e6cee748

+ 9 - 0
docs/_snippets/framework/development-tools/inspector.html

@@ -0,0 +1,9 @@
+<div id="snippet-classic-editor">
+	<h2>Inspector demo</h2>
+
+	<p>Click the button below to enable the <a href="https://github.com/ckeditor/ckeditor5-inspector">CKEditor 5 Inspector</a> for this editor instance.</p>
+</div>
+
+<br/>
+
+<button type="button" id="snippet-inspect-button">Inspect editor</button>

+ 29 - 0
docs/_snippets/framework/development-tools/inspector.js

@@ -0,0 +1,29 @@
+/**
+ * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/* globals console, window, document */
+
+import ClassicEditor from '@ckeditor/ckeditor5-build-classic/src/ckeditor';
+import CKEditorInspector from '@ckeditor/ckeditor5-inspector';
+import { CS_CONFIG } from '@ckeditor/ckeditor5-cloud-services/tests/_utils/cloud-services-config';
+
+ClassicEditor
+	.create( document.querySelector( '#snippet-classic-editor' ), {
+		cloudServices: CS_CONFIG,
+		toolbar: {
+			viewportTopOffset: window.getViewportTopOffsetConfig()
+		}
+	} )
+	.then( editor => {
+		window.editor = editor;
+
+		document.querySelector( '#snippet-inspect-button' ).addEventListener( 'click', () => {
+			CKEditorInspector.attach( editor );
+		} );
+	} )
+	.catch( err => {
+		console.error( err );
+	} );
+

BIN
docs/assets/img/framework-development-tools-inspector.jpg


+ 290 - 0
docs/framework/guides/creating-simple-plugin.md

@@ -0,0 +1,290 @@
+---
+category: framework-guides
+order: 30
+---
+
+# Creating a simple plugin
+
+This guide will show you how to create a simple editor plugin.
+
+<info-box>
+	Before you get to work, you should check out the {@link framework/guides/quick-start "Quick start"} guide first and set up the framework and building tools.
+</info-box>
+
+CKEditor plugins need to implement the {@link module:core/plugin~PluginInterface}. The easiest way to do that is to inherit from the {@link module:core/plugin~Plugin base `Plugin` class}, however, you can also write simple constructor functions. This guide uses the former method.
+
+The plugin that you will write will use a part of the {@link features/image image feature} and will add a simple UI to it &mdash; an "Insert image" button that will open a prompt window asking for the image URL when clicked. Submitting the URL will result in inserting the image into the content and selecting it.
+
+## Step 1. Installing dependencies
+
+Start from installing necessary dependencies:
+
+* The [`@ckeditor/ckeditor5-image`](https://www.npmjs.com/package/@ckeditor/ckeditor5-image) package that contains the image feature (on which the plugin will rely).
+* The [`@ckeditor/ckeditor5-core`](https://www.npmjs.com/package/@ckeditor/ckeditor5-core) package which contains the {@link module:core/plugin~Plugin} and {@link module:core/command~Command} classes.
+* The [`@ckeditor/ckeditor5-ui`](https://www.npmjs.com/package/@ckeditor/ckeditor5-ui) package which contains the UI library and framework.
+
+```bash
+npm install --save @ckeditor/ckeditor5-image \
+	@ckeditor/ckeditor5-core \
+	@ckeditor/ckeditor5-ui
+```
+
+<info-box>
+	Most of the time, you will also want to install the [`@ckeditor/ckeditor5-engine`](https://www.npmjs.com/package/@ckeditor/ckeditor5-engine) package (it contains the {@link framework/guides/architecture/editing-engine editing engine}). It was omitted in this guide because it is unnecessary for a simple plugin like this one.
+</info-box>
+
+Now, open the `app.js` file and start adding code there. Usually, when implementing more complex features you will want to split the code into multiple files (modules). However, to make this guide simpler the entire code will be kept in `app.js`.
+
+First thing to do will be to load the core of the image feature:
+
+```js
+import Image from '@ckeditor/ckeditor5-image/src/image';
+
+// ...
+
+ClassicEditor
+	.create( document.querySelector( '#editor' ), {
+		// Add Image to the plugin list.
+		plugins: [ Essentials, Paragraph, Bold, Italic, Image ],
+
+		// ...
+	} )
+	// ...
+```
+
+Save the file and run webpack. Refresh the page in your browser (**remember about the cache**) and... you should not see any changes. This is correct! The core of the image feature does not come with any UI, nor have you added any image to the initial HTML. Change this now:
+
+```html
+<div id="editor">
+	<p>Simple image:</p>
+
+	<figure class="image">
+		<img src="https://via.placeholder.com/1000x300/02c7cd/fff?text=Placeholder%20image" alt="CKEditor 5 rocks!">
+	</figure>
+</div>
+```
+
+{@img assets/img/framework-quick-start-classic-editor-with-image.png 837 Screenshot of a classic editor with bold, italic and image features.}
+
+<info-box>
+	Running webpack with the `-w` option will start it in the watch mode. This means that webpack will watch your files for changes and rebuild the application every time you save them.
+</info-box>
+
+## Step 2. Creating a plugin
+
+You can now start implementing your new plugin. Create the `InsertImage` plugin:
+
+```js
+import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
+
+class InsertImage extends Plugin {
+	init() {
+		console.log( 'InsertImage was initialized' );
+	}
+}
+```
+
+And add your new plugin to the `config.plugins` array. After rebuilding the application and refreshing the page you should see "InsertImage was initialized" logged to the console.
+
+<info-box hint>
+	It was said that your `InsertImage` plugin relies on the image feature represented here by the `Image` plugin. You could add the `Image` plugin as a {@link module:core/plugin~PluginInterface#requires dependency} of the `InsertImage` plugin. This would make the editor initialize `Image` automatically before initializing `InsertImage`, so you would be able to remove `Image` from `config.plugins`.
+
+	However, this means that your plugin would be coupled with the `Image` plugin. This is unnecessary &mdash; they do not need to know about each other. And while it does not change anything in this simple example, it is a good practice to keep plugins as decoupled as possible.
+</info-box>
+
+## Step 3. Registering a button
+
+Create a button now:
+
+```js
+// This SVG file import will be handled by webpack's raw-text loader.
+// This means that imageIcon will hold the source SVG.
+import imageIcon from '@ckeditor/ckeditor5-core/theme/icons/image.svg';
+
+import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';
+
+class InsertImage extends Plugin {
+	init() {
+		const editor = this.editor;
+
+		editor.ui.componentFactory.add( 'insertImage', locale => {
+			const view = new ButtonView( locale );
+
+			view.set( {
+				label: 'Insert image',
+				icon: imageIcon,
+				tooltip: true
+			} );
+
+			// Callback executed once the image is clicked.
+			view.on( 'execute', () => {
+				const imageURL = prompt( 'Image URL' );
+			} );
+
+			return view;
+		} );
+	}
+}
+```
+
+And add `insertImage` to `config.toolbar`:
+
+```js
+ClassicEditor
+	.create( document.querySelector( '#editor' ), {
+		// ...
+
+		toolbar: [ 'bold', 'italic', 'insertImage' ]
+	} )
+	// ...
+```
+
+Rebuild the application and refresh the page. You should see a new button in the toolbar. Clicking the button should open a prompt window asking you for the image URL.
+
+## Step 4. Inserting a new image
+
+Now, expand the button's `#execute` event listener, so it will actually insert a new image into the content:
+
+```js
+class InsertImage extends Plugin {
+	init() {
+		const editor = this.editor;
+
+		editor.ui.componentFactory.add( 'insertImage', locale => {
+			const view = new ButtonView( locale );
+
+			view.set( {
+				label: 'Insert image',
+				icon: imageIcon,
+				tooltip: true
+			} );
+
+			// Callback executed once the image is clicked.
+			view.on( 'execute', () => {
+				const imageUrl = prompt( 'Image URL' );
+
+				editor.model.change( writer => {
+					const imageElement = writer.createElement( 'image', {
+						src: imageUrl
+					} );
+
+					// Insert the image in the current selection location.
+					editor.model.insertContent( imageElement, editor.model.document.selection );
+				} );
+			} );
+
+			return view;
+		} );
+	}
+}
+```
+
+If you refresh the page, you should now be able to insert new images into the content:
+
+{@img assets/img/framework-quick-start-classic-editor-insert-image.gif 640 Screencast of inserting a new image.}
+
+The image is fully functional, you can undo inserting by pressing <kbd>Ctrl</kbd>+<kbd>Z</kbd> and the image is always inserted as a block element (the paragraph that contains the selection is automatically split). This is all handled by the CKEditor 5 engine.
+
+<info-box>
+	As you can see, by clicking the button you are inserting an `<image src="...">` element into the model. The image feature is represented in the model as `<image>`, while in the view (i.e. the virtual DOM) and in the real DOM it is rendered as `<figure class="image"><img src="..."></figure>`.
+
+	The `<image>` to `<figure><img></figure>` transformation is called "conversion" and it requires a separate guide. However, as you can see in this example, it is a powerful mechanism because it allows non-1:1 mappings.
+</info-box>
+
+Congratulations! You have just created your first CKEditor 5 plugin!
+
+## Bonus. Enabling image captions
+
+Thanks to the fact that all plugins operate on the model and on the view and know as little about themselves as possible, you can easily enable image captions by simply loading the {@link module:image/imagecaption~ImageCaption} plugin:
+
+```js
+import ImageCaption from '@ckeditor/ckeditor5-image/src/imagecaption';
+
+// ...
+
+ClassicEditor
+	.create( document.querySelector( '#editor' ), {
+		// Add ImageCaption to the plugin list.
+		plugins: [ Essentials, Paragraph, Bold, Italic, Image, InsertImage, ImageCaption ],
+
+		// ...
+	} )
+	// ...
+```
+
+This should be the result of the change:
+
+{@img assets/img/framework-quick-start-classic-editor-bonus.gif 640 Screencast of inserting a new image with a caption.}
+
+## Final code
+
+If you got lost at any point, this should be your final `app.js`:
+
+```js
+import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor';
+
+import Essentials from '@ckeditor/ckeditor5-essentials/src/essentials';
+import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
+import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';
+import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic';
+import Image from '@ckeditor/ckeditor5-image/src/image';
+import ImageCaption from '@ckeditor/ckeditor5-image/src/imagecaption';
+
+import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
+import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';
+
+import imageIcon from '@ckeditor/ckeditor5-core/theme/icons/image.svg';
+
+class InsertImage extends Plugin {
+	init() {
+		const editor = this.editor;
+
+		editor.ui.componentFactory.add( 'insertImage', locale => {
+			const view = new ButtonView( locale );
+
+			view.set( {
+				label: 'Insert image',
+				icon: imageIcon,
+				tooltip: true
+			} );
+
+			// Callback executed once the image is clicked.
+			view.on( 'execute', () => {
+				const imageUrl = prompt( 'Image URL' );
+
+				editor.model.change( writer => {
+					const imageElement = writer.createElement( 'image', {
+						src: imageUrl
+					} );
+
+					// Insert the image in the current selection location.
+					editor.model.insertContent( imageElement, editor.model.document.selection );
+				} );
+			} );
+
+			return view;
+		} );
+	}
+}
+
+ClassicEditor
+	.create( document.querySelector( '#editor' ), {
+		plugins: [ Essentials, Paragraph, Bold, Italic, Image, InsertImage, ImageCaption ],
+		toolbar: [ 'bold', 'italic', 'insertImage' ]
+	} )
+	.then( editor => {
+		console.log( 'Editor was initialized', editor );
+	} )
+	.catch( error => {
+		console.error( error.stack );
+	} );
+```
+
+## What's next?
+
+If you would like to read more tutorials check out the following one:
+
+* {@link framework/guides/tutorials/implementing-a-block-widget Implementing a block widget}
+* {@link framework/guides/tutorials/implementing-an-inline-widget Implementing an inline widget}
+
+If you are more into reading about CKEditor 5's architecture, check out the {@link framework/guides/architecture/intro Introduction to CKEditor 5 architecture}.

+ 96 - 0
docs/framework/guides/development-tools.md

@@ -0,0 +1,96 @@
+---
+category: framework-guides
+order: 40
+---
+
+# Development tools
+
+In this you will learn about developer tools that will help you develop and debug editor plugins and features.
+
+## CKEditor 5 inspector
+
+The official [editor instance inspector](https://github.com/ckeditor/ckeditor5-inspector) provides rich debugging tools for editor internals like {@link framework/guides/architecture/editing-engine#model model}, {@link framework/guides/architecture/editing-engine#view view}, and  {@link framework/guides/architecture/core-editor-architecture#commands commands}.
+
+It allows observing changes to the data structures and the selection live in editor instances which is particularly helpful when developing new editor features or getting to understand the existing ones.
+
+{@img assets/img/framework-development-tools-inspector.jpg Screenshot of a CKEditor 5 inspector attached to an editor instance.}
+
+### Importing the inspector
+
+You can import the inspector as an [`@ckeditor/ckeditor5-inspector`](https://www.npmjs.com/package/@ckeditor/ckeditor5-inspector) package into your project:
+
+```
+yarn add --dev @ckeditor/ckeditor5-inspector
+```
+
+and then either import it as a module:
+
+```js
+import CKEditorInspector from '@ckeditor/ckeditor5-inspector';
+```
+
+or as a plain `<script>` tag in the HTML of your application:
+
+```html
+<script src="../node_modules/@ckeditor/ckeditor5-inspector/build/inspector.js"></script>
+```
+
+### Enabling the inspector
+
+Attach the inspector to the editor instance when {@link builds/guides/integration/basic-api#creating-an-editor created} using the `CKEditorInspector.attach()` method:
+
+```js
+ClassicEditor
+	.create( ... )
+	.then( editor => {
+		CKEditorInspector.attach( editor );
+	} )
+	.catch( error => {
+		console.error( error );
+	} );
+```
+
+The inspector will show up at the bottom of the screen. Click the button below the editor to see the inspector in action:
+
+{@snippet framework/development-tools/inspector}
+
+### Inspecting multiple editors
+
+You can inspect multiple editor instances at a time by calling `CKEditorInspector.attach()` for each one of them. Then you can switch the inspector context to inspect different editors.
+
+You can specify the name of the editor when attaching to make working with multiple instances easier:
+
+```js
+// Inspecting two editor instances at the same time.
+CKEditorInspector.attach( 'header-editor' editor );
+CKEditorInspector.attach( 'body-editor' editor );
+```
+
+The editor switcher is displayed in the upper–right corner of the inspector.
+
+## Testing helpers
+
+The `getData()` and `setData()` functions exposed by {@link module:engine/dev-utils/model model dev utils} and {@link module:engine/dev-utils/view view dev utils} are useful development helpers.
+
+They allow "stringifying" {@link framework/guides/architecture/editing-engine#model model} and {@link framework/guides/architecture/editing-engine#view view} structures, selections, ranges and positions as well as loading them from string. They are often use when writing tests.
+
+<info-box>
+	Both tools are designed for prototyping, debugging, and testing purposes. Do not use them in production-grade code.
+</info-box>
+
+For instance, to take a peek at the editor model, you could use the {@link module:engine/dev-utils/model#static-function-getData `getData()`} helper:
+
+```js
+import { getData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
+
+// ...
+
+ClassicEditor
+	.create( '<p>Hello <b>world</b>!</p>' )
+	.then( editor => {
+		// '<paragraph>[]Hello <$text bold="true">world</$text>!</paragraph>'
+		console.log( getData( editor.model ) );
+	} );
+```
+
+See the helper documentation to learn more about useful options.

+ 6 - 278
docs/framework/guides/quick-start.md

@@ -5,7 +5,7 @@ order: 20
 
 # Quick start
 
-This guide will show you how to initialize the editor from source and how to create a simple plugin.
+This guide will show you how to initialize the editor from source.
 
 ## How to install the framework?
 
@@ -96,6 +96,8 @@ module.exports = {
 };
 ```
 
+## Creating an editor
+
 You can now install some of the CKEditor 5 Framework packages which will allow you to initialize a simple editor. You can start with the {@link examples/builds/classic-editor classic editor} with a small set of features.
 
 ```bash
@@ -191,6 +193,8 @@ bundle.js.map  2.39 MiB    main  [emitted]  main
     + 491 hidden modules
 ```
 
+## Running the editor
+
 Finally, it is time to create an HTML page:
 
 ```html
@@ -214,284 +218,8 @@ Open this page in your browser and you should see the editor up and running. Mak
 
 {@img assets/img/framework-quick-start-classic-editor.png 976 Screenshot of a classic editor with bold and italic features.}
 
-## Creating a simple plugin
-
-After you initilized the editor from source, you are ready to create your first CKEditor 5 plugin.
-
-CKEditor plugins need to implement the {@link module:core/plugin~PluginInterface}. The easiest way to do that is to inherit from the {@link module:core/plugin~Plugin base `Plugin` class}, however, you can also write simple constructor functions. This guide uses the former method.
-
-The plugin that you will write will use a part of the {@link features/image image feature} and will add a simple UI to it &mdash; an "Insert image" button that will open a prompt window asking for the image URL when clicked. Submitting the URL will result in inserting the image into the content and selecting it.
-
-### Step 1. Installing dependencies
-
-Start from installing necessary dependencies:
-
-* The [`@ckeditor/ckeditor5-image`](https://www.npmjs.com/package/@ckeditor/ckeditor5-image) package that contains the image feature (on which the plugin will rely).
-* The [`@ckeditor/ckeditor5-core`](https://www.npmjs.com/package/@ckeditor/ckeditor5-core) package which contains the {@link module:core/plugin~Plugin} and {@link module:core/command~Command} classes.
-* The [`@ckeditor/ckeditor5-ui`](https://www.npmjs.com/package/@ckeditor/ckeditor5-ui) package which contains the UI library and framework.
-
-```bash
-npm install --save @ckeditor/ckeditor5-image \
-	@ckeditor/ckeditor5-core \
-	@ckeditor/ckeditor5-ui
-```
-
-<info-box>
-	Most of the time, you will also want to install the [`@ckeditor/ckeditor5-engine`](https://www.npmjs.com/package/@ckeditor/ckeditor5-engine) package (it contains the {@link framework/guides/architecture/editing-engine editing engine}). It was omitted in this guide because it is unnecessary for a simple plugin like this one.
-</info-box>
-
-Now, open the `app.js` file and start adding code there. Usually, when implementing more complex features you will want to split the code into multiple files (modules). However, to make this guide simpler the entire code will be kept in `app.js`.
-
-First thing to do will be to load the core of the image feature:
-
-```js
-import Image from '@ckeditor/ckeditor5-image/src/image';
-
-// ...
-
-ClassicEditor
-	.create( document.querySelector( '#editor' ), {
-		// Add Image to the plugin list.
-		plugins: [ Essentials, Paragraph, Bold, Italic, Image ],
-
-		// ...
-	} )
-	// ...
-```
-
-Save the file and run webpack. Refresh the page in your browser (**remember about the cache**) and... you should not see any changes. This is correct! The core of the image feature does not come with any UI, nor have you added any image to the initial HTML. Change this now:
-
-```html
-<div id="editor">
-	<p>Simple image:</p>
-
-	<figure class="image">
-		<img src="https://via.placeholder.com/1000x300/02c7cd/fff?text=Placeholder%20image" alt="CKEditor 5 rocks!">
-	</figure>
-</div>
-```
-
-{@img assets/img/framework-quick-start-classic-editor-with-image.png 837 Screenshot of a classic editor with bold, italic and image features.}
-
-<info-box>
-	Running webpack with the `-w` option will start it in the watch mode. This means that webpack will watch your files for changes and rebuild the application every time you save them.
-</info-box>
-
-### Step 2. Creating a plugin
-
-You can now start implementing your new plugin. Create the `InsertImage` plugin:
-
-```js
-import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
-
-class InsertImage extends Plugin {
-	init() {
-		console.log( 'InsertImage was initialized' );
-	}
-}
-```
-
-And add your new plugin to the `config.plugins` array. After rebuilding the application and refreshing the page you should see "InsertImage was initialized" logged to the console.
-
-<info-box hint>
-	It was said that your `InsertImage` plugin relies on the image feature represented here by the `Image` plugin. You could add the `Image` plugin as a {@link module:core/plugin~PluginInterface#requires dependency} of the `InsertImage` plugin. This would make the editor initialize `Image` automatically before initializing `InsertImage`, so you would be able to remove `Image` from `config.plugins`.
-
-	However, this means that your plugin would be coupled with the `Image` plugin. This is unnecessary &mdash; they do not need to know about each other. And while it does not change anything in this simple example, it is a good practice to keep plugins as decoupled as possible.
-</info-box>
-
-### Step 3. Registering a button
-
-Create a button now:
-
-```js
-// This SVG file import will be handled by webpack's raw-text loader.
-// This means that imageIcon will hold the source SVG.
-import imageIcon from '@ckeditor/ckeditor5-core/theme/icons/image.svg';
-
-import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';
-
-class InsertImage extends Plugin {
-	init() {
-		const editor = this.editor;
-
-		editor.ui.componentFactory.add( 'insertImage', locale => {
-			const view = new ButtonView( locale );
-
-			view.set( {
-				label: 'Insert image',
-				icon: imageIcon,
-				tooltip: true
-			} );
-
-			// Callback executed once the image is clicked.
-			view.on( 'execute', () => {
-				const imageURL = prompt( 'Image URL' );
-			} );
-
-			return view;
-		} );
-	}
-}
-```
-
-And add `insertImage` to `config.toolbar`:
-
-```js
-ClassicEditor
-	.create( document.querySelector( '#editor' ), {
-		// ...
-
-		toolbar: [ 'bold', 'italic', 'insertImage' ]
-	} )
-	// ...
-```
-
-Rebuild the application and refresh the page. You should see a new button in the toolbar. Clicking the button should open a prompt window asking you for the image URL.
-
-### Step 4. Inserting a new image
-
-Now, expand the button's `#execute` event listener, so it will actually insert a new image into the content:
-
-```js
-class InsertImage extends Plugin {
-	init() {
-		const editor = this.editor;
-
-		editor.ui.componentFactory.add( 'insertImage', locale => {
-			const view = new ButtonView( locale );
-
-			view.set( {
-				label: 'Insert image',
-				icon: imageIcon,
-				tooltip: true
-			} );
-
-			// Callback executed once the image is clicked.
-			view.on( 'execute', () => {
-				const imageUrl = prompt( 'Image URL' );
-
-				editor.model.change( writer => {
-					const imageElement = writer.createElement( 'image', {
-						src: imageUrl
-					} );
-
-					// Insert the image in the current selection location.
-					editor.model.insertContent( imageElement, editor.model.document.selection );
-				} );
-			} );
-
-			return view;
-		} );
-	}
-}
-```
-
-If you refresh the page, you should now be able to insert new images into the content:
-
-{@img assets/img/framework-quick-start-classic-editor-insert-image.gif 640 Screencast of inserting a new image.}
-
-The image is fully functional, you can undo inserting by pressing <kbd>Ctrl</kbd>+<kbd>Z</kbd> and the image is always inserted as a block element (the paragraph that contains the selection is automatically split). This is all handled by the CKEditor 5 engine.
-
-<info-box>
-	As you can see, by clicking the button you are inserting an `<image src="...">` element into the model. The image feature is represented in the model as `<image>`, while in the view (i.e. the virtual DOM) and in the real DOM it is rendered as `<figure class="image"><img src="..."></figure>`.
-
-	The `<image>` to `<figure><img></figure>` transformation is called "conversion" and it requires a separate guide. However, as you can see in this example, it is a powerful mechanism because it allows non-1:1 mappings.
-</info-box>
-
-Congratulations! You have just created your first CKEditor 5 plugin!
-
-### Bonus. Enabling image captions
-
-Thanks to the fact that all plugins operate on the model and on the view and know as little about themselves as possible, you can easily enable image captions by simply loading the {@link module:image/imagecaption~ImageCaption} plugin:
-
-```js
-import ImageCaption from '@ckeditor/ckeditor5-image/src/imagecaption';
-
-// ...
-
-ClassicEditor
-	.create( document.querySelector( '#editor' ), {
-		// Add ImageCaption to the plugin list.
-		plugins: [ Essentials, Paragraph, Bold, Italic, Image, InsertImage, ImageCaption ],
-
-		// ...
-	} )
-	// ...
-```
-
-This should be the result of the change:
-
-{@img assets/img/framework-quick-start-classic-editor-bonus.gif 640 Screencast of inserting a new image with a caption.}
-
-### Final code
-
-If you got lost at any point, this should be your final `app.js`:
-
-```js
-import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor';
-
-import Essentials from '@ckeditor/ckeditor5-essentials/src/essentials';
-import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
-import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';
-import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic';
-import Image from '@ckeditor/ckeditor5-image/src/image';
-import ImageCaption from '@ckeditor/ckeditor5-image/src/imagecaption';
-
-import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
-import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';
-
-import imageIcon from '@ckeditor/ckeditor5-core/theme/icons/image.svg';
-
-class InsertImage extends Plugin {
-	init() {
-		const editor = this.editor;
-
-		editor.ui.componentFactory.add( 'insertImage', locale => {
-			const view = new ButtonView( locale );
-
-			view.set( {
-				label: 'Insert image',
-				icon: imageIcon,
-				tooltip: true
-			} );
-
-			// Callback executed once the image is clicked.
-			view.on( 'execute', () => {
-				const imageUrl = prompt( 'Image URL' );
-
-				editor.model.change( writer => {
-					const imageElement = writer.createElement( 'image', {
-						src: imageUrl
-					} );
-
-					// Insert the image in the current selection location.
-					editor.model.insertContent( imageElement, editor.model.document.selection );
-				} );
-			} );
-
-			return view;
-		} );
-	}
-}
-
-ClassicEditor
-	.create( document.querySelector( '#editor' ), {
-		plugins: [ Essentials, Paragraph, Bold, Italic, Image, InsertImage, ImageCaption ],
-		toolbar: [ 'bold', 'italic', 'insertImage' ]
-	} )
-	.then( editor => {
-		console.log( 'Editor was initialized', editor );
-	} )
-	.catch( error => {
-		console.error( error.stack );
-	} );
-```
-
 ## What's next?
 
-If you would like to read more tutorials check out the following one:
-
-* {@link framework/guides/tutorials/implementing-a-block-widget Implementing a block widget}
-* {@link framework/guides/tutorials/implementing-an-inline-widget Implementing an inline widget}
+If you finished this guide, you should definitely check out the {@link framework/guides/creating-simple-plugin "Creating a simple plugin"} guide that will teach you some basics of developing features in the CKEditor 5 ecosystem.
 
 If you are more into reading about CKEditor 5's architecture, check out the {@link framework/guides/architecture/intro Introduction to CKEditor 5 architecture}.