Skip to content

Commit

Permalink
Merge pull request #8019 from ckeditor/i/7890
Browse files Browse the repository at this point in the history
Other (image): Introduced `ImageInsert` as a standalone plugin that contains `ImageUpload` functionality. Closes #7890.

Internal (image): Reverted the changes in `ImageUpload` plugin that introduced the "Insert image via URL" feature.

Fix (image): Aligned and fixed the styling for the split button in the `ImageInsert` dropdown. Closes #7986. Closes #7927.

Docs (image): Fixed the docs after plugins separation.

MAJOR BREAKING CHANGE (image): In order to use the "insert image via URL" feature you now need to load the `ImageInsert` plugin and use the `imageInsert` button instead of the `imageUpload` button that implemented that functionality previously previously.
  • Loading branch information
Reinmar committed Sep 11, 2020
2 parents ab7bce9 + 3abcbd1 commit 4671ed1
Show file tree
Hide file tree
Showing 23 changed files with 1,001 additions and 1,005 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
import ClassicEditor from '@ckeditor/ckeditor5-build-classic/src/ckeditor';

import ImageResize from '@ckeditor/ckeditor5-image/src/imageresize';
import ImageInsert from '@ckeditor/ckeditor5-image/src/imageinsert';
import LinkImage from '@ckeditor/ckeditor5-link/src/linkimage';

ClassicEditor.builtinPlugins.push( ImageResize );
ClassicEditor.builtinPlugins.push( ImageInsert );
ClassicEditor.builtinPlugins.push( LinkImage );

window.ClassicEditor = ClassicEditor;
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,15 @@

import { CS_CONFIG } from '@ckeditor/ckeditor5-cloud-services/tests/_utils/cloud-services-config.js';

const toolbarItems = [ ...ClassicEditor.defaultConfig.toolbar.items ];

toolbarItems.splice( toolbarItems.indexOf( 'imageUpload' ), 1, 'imageInsert' );

ClassicEditor
.create( document.querySelector( '#snippet-image-insert-via-url' ), {
removePlugins: [ 'ImageToolbar', 'ImageCaption', 'ImageStyle', 'ImageResize', 'LinkImage' ],
toolbar: {
items: toolbarItems,
viewportTopOffset: window.getViewportTopOffsetConfig()
},
image: {
Expand All @@ -24,7 +29,7 @@ ClassicEditor
cloudServices: CS_CONFIG
} )
.then( editor => {
window.imageViaUrl = editor;
window.editorInsertImageViaUrl = editor;
} )
.catch( err => {
console.error( err );
Expand Down
10 changes: 7 additions & 3 deletions packages/ckeditor5-image/docs/features/image.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ The [`@ckeditor/ckeditor5-image`](https://www.npmjs.com/package/@ckeditor/ckedit
* {@link module:image/imagestyle~ImageStyle} adds support for [image styles](#image-styles).
* {@link module:image/imagetextalternative~ImageTextAlternative} adds support for adding text alternative.
* {@link module:image/imageupload~ImageUpload} adds support for {@link features/image-upload uploading dropped or pasted images}.
* {@link module:image/imageinsert~ImageInsert} adds support for [inserting images via URL](#inserting-images-via-source-url) and other custom integrations.
* {@link module:image/imageresize~ImageResize} adds support for [resizing images](#resizing-images).
* {@link module:link/linkimage~LinkImage} adds support for [linking images](#linking-images).

Expand Down Expand Up @@ -86,12 +87,15 @@ See the {@link features/image-upload Image upload} guide.

Besides the ability to insert images by uploading them directly from your disk or via CKFinder, you can also configure CKEditor 5 to allow inserting images via source URL.

In order to enable this option, configure {@link module:image/imageupload~ImageUploadPanelConfig#items `image.upload.panel.items`} like below:
In order to enable this option, install the `ImageInsert` plugin and configure {@link module:image/imageupload~ImageUploadPanelConfig#items `image.upload.panel.items`} like below:

```js
import ImageInsert from '@ckeditor/ckeditor5-image/src/imageinsert';

ClassicEditor
.create( document.querySelector( '#editor' ), {
// ...
plugins: [ ... , ImageInsert ],
toolbar: [ ... , 'imageInsert' ],
image: {
// ...
upload: {
Expand All @@ -103,7 +107,7 @@ ClassicEditor
} )
```

This will extend the standalone **Insert image** button in the toolbar by adding a dropdown panel with the new feature. To open the panel and add the image URL, click the arrow next to the image button. Check the demo below to insert a new image via URL or update an existing image by selecting it, opening the dropdown panel and pasting a new URL.
This will add a new **Insert image** dropdown in the toolbar. To open the panel and add the image URL, click the arrow next to the image button. Check the demo below to insert a new image via URL or update an existing image by selecting it, opening the dropdown panel and pasting a new URL.

{@snippet features/image-insert-via-url}

Expand Down
98 changes: 98 additions & 0 deletions packages/ckeditor5-image/src/imageinsert.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/**
* @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/

/**
* @module image/imageinsert
*/

import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
import ImageUpload from './imageupload';
import ImageInsertUI from './imageinsert/imageinsertui';

/**
* The image insert plugin.
*
* For a detailed overview, check the {@glink features/image-upload/image-upload Image upload feature}
* and {@glink features/image#inserting-images-via-source-url Insert images via source URL} documentation.
*
* This plugin does not do anything directly, but it loads a set of specific plugins
* to enable image uploading or inserting via implemented integrations:
*
* * {@link module:image/imageupload~ImageUpload}
* * {@link module:image/imageinsert/imageinsertui~ImageInsertUI},
*
* @extends module:core/plugin~Plugin
*/
export default class ImageInsert extends Plugin {
/**
* @inheritDoc
*/
static get pluginName() {
return 'ImageInsert';
}

/**
* @inheritDoc
*/
static get requires() {
return [ ImageUpload, ImageInsertUI ];
}
}

/**
* Image insert panel view configuration.
* **NOTE:** Currently the panel settings are configurable through the `image.upload` property.
*
* @protected
* @member {module:image/imageupload~ImageUploadPanelConfig} module:image/imageupload~ImageUploadConfig#panel
*/

/**
* The configuration of the image insert dropdown panel view. Used by the image insert feature in the `@ckeditor/ckeditor5-image` package.
*
* ClassicEditor
* .create( editorElement, {
* image: {
* upload: {
* panel: ... // panel settings for "imageInsert" view goes here
* }
* }
* } )
* .then( ... )
* .catch( ... );
*
* See {@link module:core/editor/editorconfig~EditorConfig all editor options}.
*
* @protected
* @interface module:image/imageupload~ImageUploadPanelConfig
*/

/**
* The list of {@link module:image/imageinsert~ImageInsert} integrations.
*
* The option accepts string tokens.
* * for predefined integrations, we have two special strings: `insertImageViaUrl` and `openCKFinder`.
* The former adds the **Insert image via URL** feature, while the latter adds the built-in **CKFinder** integration.
* * for custom integrations, each string should be a name of the component registered in the
* {@link module:ui/componentfactory~ComponentFactory component factory}.
* If you have a plugin `PluginX` that registers `pluginXButton` component, then the integration token
* in that case should be `pluginXButton`.
*
* // Add `insertImageViaUrl`, `openCKFinder` and custom `pluginXButton` integrations.
* const imageUploadConfig = {
* upload: {
* panel: {
* items: [
* 'insertImageViaUrl',
* 'openCKFinder',
* 'pluginXButton'
* ]
* }
* }
* };
*
* @member {Array.<String>} module:image/imageupload~ImageUploadPanelConfig#items
* @default [ 'insertImageViaUrl' ]
*/
151 changes: 151 additions & 0 deletions packages/ckeditor5-image/src/imageinsert/imageinsertui.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/**
* @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/

/**
* @module image/imageinsert/imageinsertui
*/

import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
import ImageInsertPanelView from './ui/imageinsertpanelview';
import { prepareIntegrations } from './utils';

import { isImage } from '../image/utils';

/**
* The image insert dropdown plugin.
*
* For a detailed overview, check the {@glink features/image-upload/image-upload Image upload feature}
* and {@glink features/image#inserting-images-via-source-url Insert images via source URL} documentation.
*
* Adds the `'imageInsert'` dropdown to the {@link module:ui/componentfactory~ComponentFactory UI component factory}.
*
* @extends module:core/plugin~Plugin
*/
export default class ImageInsertUI extends Plugin {
/**
* @inheritDoc
*/
static get pluginName() {
return 'ImageInsertUI';
}

/**
* @inheritDoc
*/
init() {
const editor = this.editor;

editor.ui.componentFactory.add( 'imageInsert', locale => {
return this._createDropdownView( locale );
} );
}

/**
* Creates the dropdown view.
*
* @param {module:utils/locale~Locale} locale The localization services instance.
*
* @private
* @returns {module:ui/dropdown/dropdownview~DropdownView}
*/
_createDropdownView( locale ) {
const editor = this.editor;
const imageInsertView = new ImageInsertPanelView( locale, prepareIntegrations( editor ) );
const command = editor.commands.get( 'imageUpload' );

const dropdownView = imageInsertView.dropdownView;
const splitButtonView = dropdownView.buttonView;

splitButtonView.actionView = editor.ui.componentFactory.create( 'imageUpload' );
// After we replaced action button with `imageUpload` component,
// we have lost a proper styling and some minor visual quirks have appeared.
// Brining back original split button classes helps fix the button styling
// See https://github.com/ckeditor/ckeditor5/issues/7986.
splitButtonView.actionView.extendTemplate( {
attributes: {
class: 'ck ck-button ck-splitbutton__action'
}
} );

return this._setUpDropdown( dropdownView, imageInsertView, command );
}

/**
* Sets up the dropdown view.
*
* @param {module:ui/dropdown/dropdownview~DropdownView} dropdownView A dropdownView.
* @param {module:image/imageinsert/ui/imageinsertpanelview~ImageInsertPanelView} imageInsertView An imageInsertView.
* @param {module:core/command~Command} command An imageInsert command
*
* @private
* @returns {module:ui/dropdown/dropdownview~DropdownView}
*/
_setUpDropdown( dropdownView, imageInsertView, command ) {
const editor = this.editor;
const t = editor.t;
const insertButtonView = imageInsertView.insertButtonView;
const insertImageViaUrlForm = imageInsertView.getIntegration( 'insertImageViaUrl' );
const panelView = dropdownView.panelView;

dropdownView.bind( 'isEnabled' ).to( command );

// Defer the children injection to improve initial performance.
// See https://github.com/ckeditor/ckeditor5/pull/8019#discussion_r484069652.
dropdownView.buttonView.once( 'open', () => {
panelView.children.add( imageInsertView );
} );

dropdownView.on( 'change:isOpen', () => {
const selectedElement = editor.model.document.selection.getSelectedElement();

if ( dropdownView.isOpen ) {
imageInsertView.focus();

if ( isImage( selectedElement ) ) {
imageInsertView.imageURLInputValue = selectedElement.getAttribute( 'src' );
insertButtonView.label = t( 'Update' );
insertImageViaUrlForm.label = t( 'Update image URL' );
} else {
imageInsertView.imageURLInputValue = '';
insertButtonView.label = t( 'Insert' );
insertImageViaUrlForm.label = t( 'Insert image via URL' );
}
}
} );

imageInsertView.delegate( 'submit', 'cancel' ).to( dropdownView );
this.delegate( 'cancel' ).to( dropdownView );

dropdownView.on( 'submit', () => {
closePanel();
onSubmit();
} );

dropdownView.on( 'cancel', () => {
closePanel();
} );

function onSubmit() {
const selectedElement = editor.model.document.selection.getSelectedElement();

if ( isImage( selectedElement ) ) {
editor.model.change( writer => {
writer.setAttribute( 'src', imageInsertView.imageURLInputValue, selectedElement );
writer.removeAttribute( 'srcset', selectedElement );
writer.removeAttribute( 'sizes', selectedElement );
} );
} else {
editor.execute( 'imageInsert', { source: imageInsertView.imageURLInputValue } );
}
}

function closePanel() {
editor.editing.view.focus();
dropdownView.isOpen = false;
}

return dropdownView;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@
*/

/**
* @module image/imageupload/ui/imageuploadformrowview
* @module image/imageinsert/ui/imageinsertformrowview
*/

import View from '@ckeditor/ckeditor5-ui/src/view';

import '../../../theme/imageuploadformrowview.css';
import '../../../theme/imageinsertformrowview.css';

/**
* The class representing a single row in a complex form,
* used by {@link module:image/imageupload/ui/imageuploadpanelview~ImageUploadPanelView}.
* used by {@link module:image/imageinsert/ui/imageinsertpanelview~ImageInsertPanelView}.
*
* **Note**: For now this class is private. When more use cases appear (beyond `ckeditor5-table` and `ckeditor5-image`),
* it will become a component in `ckeditor5-ui`.
Expand Down
Loading

0 comments on commit 4671ed1

Please sign in to comment.