From d208227455ea07aec97d2e11d74a64c942480fce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Remiszewski?= Date: Tue, 31 Jan 2023 08:06:18 +0100 Subject: [PATCH 1/4] Rewrite skeditor5-ckfinder to typescript. --- .gitignore | 1 + packages/ckeditor5-ckfinder/package.json | 10 +- packages/ckeditor5-ckfinder/src/ckfinder.js | 119 ---------------- packages/ckeditor5-ckfinder/src/ckfinder.ts | 132 ++++++++++++++++++ ...{ckfindercommand.js => ckfindercommand.ts} | 36 ++--- ...{ckfinderediting.js => ckfinderediting.ts} | 20 ++- .../src/{ckfinderui.js => ckfinderui.ts} | 8 +- .../src/{index.js => index.ts} | 0 .../tests/ckfindercommand.js | 2 +- packages/ckeditor5-ckfinder/tsconfig.json | 7 + .../ckeditor5-ckfinder/tsconfig.release.json | 10 ++ 11 files changed, 193 insertions(+), 152 deletions(-) delete mode 100644 packages/ckeditor5-ckfinder/src/ckfinder.js create mode 100644 packages/ckeditor5-ckfinder/src/ckfinder.ts rename packages/ckeditor5-ckfinder/src/{ckfindercommand.js => ckfindercommand.ts} (83%) rename packages/ckeditor5-ckfinder/src/{ckfinderediting.js => ckfinderediting.ts} (79%) rename packages/ckeditor5-ckfinder/src/{ckfinderui.js => ckfinderui.ts} (89%) rename packages/ckeditor5-ckfinder/src/{index.js => index.ts} (100%) create mode 100644 packages/ckeditor5-ckfinder/tsconfig.json create mode 100644 packages/ckeditor5-ckfinder/tsconfig.release.json diff --git a/.gitignore b/.gitignore index 706dacc356d..a76abb4c250 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,7 @@ packages/ckeditor5-autoformat/src/**/*.js packages/ckeditor5-autosave/src/**/*.js packages/ckeditor5-basic-styles/src/**/*.js packages/ckeditor5-block-quote/src/**/*.js +packages/ckeditor5-ckfinder/src/**/*.js packages/ckeditor5-clipboard/src/**/*.js packages/ckeditor5-code-block/src/**/*.js packages/ckeditor5-core/src/**/*.js diff --git a/packages/ckeditor5-ckfinder/package.json b/packages/ckeditor5-ckfinder/package.json index 66c1afc1f6a..e082dfc26db 100644 --- a/packages/ckeditor5-ckfinder/package.json +++ b/packages/ckeditor5-ckfinder/package.json @@ -10,7 +10,7 @@ "ckeditor5-plugin", "ckeditor5-dll" ], - "main": "src/index.js", + "main": "src/index.ts", "dependencies": { "ckeditor5": "^36.0.0" }, @@ -27,6 +27,7 @@ "@ckeditor/ckeditor5-theme-lark": "^36.0.0", "@ckeditor/ckeditor5-ui": "^36.0.0", "@ckeditor/ckeditor5-utils": "^36.0.0", + "typescript": "^4.8.4", "webpack": "^5.58.1", "webpack-cli": "^4.9.0" }, @@ -45,13 +46,16 @@ }, "files": [ "lang", - "src", + "src/**/*.js", + "src/**/*.d.ts", "theme", "build", "ckeditor5-metadata.json", "CHANGELOG.md" ], "scripts": { - "dll:build": "webpack" + "dll:build": "webpack", + "build": "tsc -p ./tsconfig.release.json", + "postversion": "npm run build" } } diff --git a/packages/ckeditor5-ckfinder/src/ckfinder.js b/packages/ckeditor5-ckfinder/src/ckfinder.js deleted file mode 100644 index 7c67aa65e8d..00000000000 --- a/packages/ckeditor5-ckfinder/src/ckfinder.js +++ /dev/null @@ -1,119 +0,0 @@ -/** - * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved. - * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license - */ - -/** - * @module ckfinder/ckfinder - */ - -import { Plugin } from 'ckeditor5/src/core'; - -import CKFinderUI from './ckfinderui'; -import CKFinderEditing from './ckfinderediting'; - -/** - * The CKFinder feature, a bridge between the CKEditor 5 WYSIWYG editor and the - * [CKFinder](https://ckeditor.com/ckfinder) file manager and uploader. - * - * This is a "glue" plugin which enables: - * - * * {@link module:ckfinder/ckfinderediting~CKFinderEditing}, - * * {@link module:ckfinder/ckfinderui~CKFinderUI}, - * * {@link module:adapter-ckfinder/uploadadapter~CKFinderUploadAdapter}. - * - * See the {@glink features/images/image-upload/ckfinder "CKFinder integration" guide} to learn how to configure - * and use this feature. - * - * Check out the {@glink features/images/image-upload/image-upload comprehensive "Image upload" guide} to learn about - * other ways to upload images into CKEditor 5. - * - * @extends module:core/plugin~Plugin - */ -export default class CKFinder extends Plugin { - /** - * @inheritDoc - */ - static get pluginName() { - return 'CKFinder'; - } - - /** - * @inheritDoc - */ - static get requires() { - return [ 'Link', 'CKFinderUploadAdapter', CKFinderEditing, CKFinderUI ]; - } -} - -/** - * The configuration of the {@link module:ckfinder/ckfinder~CKFinder CKFinder feature}. - * - * Read more in {@link module:ckfinder/ckfinder~CKFinderConfig}. - * - * @member {module:ckfinder/ckfinder~CKFinderConfig} module:core/editor/editorconfig~EditorConfig#ckfinder - */ - -/** - * The configuration of the {@link module:ckfinder/ckfinder~CKFinder CKFinder feature} - * and its {@link module:adapter-ckfinder/uploadadapter~CKFinderUploadAdapter upload adapter}. - * - * ClassicEditor - * .create( editorElement, { - * ckfinder: { - * options: { - * resourceType: 'Images' - * } - * } - * } ) - * .then( ... ) - * .catch( ... ); - * - * See {@link module:core/editor/editorconfig~EditorConfig all editor options}. - * - * @interface CKFinderConfig - */ - -/** - * The configuration options passed to the CKFinder file manager instance. - * - * Check the file manager [documentation](https://ckeditor.com/docs/ckfinder/ckfinder3/#!/api/CKFinder.Config-cfg-language) - * for the complete list of options. - * - * @member {Object} module:ckfinder/ckfinder~CKFinderConfig#options - */ - -/** - * The type of the CKFinder opener method. - * - * Supported types are: - * - * * `'modal'` – Opens CKFinder in a modal, - * * `'popup'` – Opens CKFinder in a new "pop-up" window. - * - * Defaults to `'modal'`. - * - * @member {String} module:ckfinder/ckfinder~CKFinderConfig#openerMethod - */ - -/** - * The path (URL) to the connector which handles the file upload in CKFinder file manager. - * When specified, it enables the automatic upload of resources such as images inserted into the content. - * - * For instance, to use CKFinder's - * [quick upload](https://ckeditor.com/docs/ckfinder/ckfinder3-php/commands.html#command_quick_upload) - * command, your can use the following (or similar) path: - * - * ClassicEditor - * .create( editorElement, { - * ckfinder: { - * uploadUrl: '/ckfinder/core/connector/php/connector.php?command=QuickUpload&type=Files&responseType=json' - * } - * } ) - * .then( ... ) - * .catch( ... ); - * - * Used by the {@link module:adapter-ckfinder/uploadadapter~CKFinderUploadAdapter upload adapter}. - * - * @member {String} module:ckfinder/ckfinder~CKFinderConfig#uploadUrl - */ diff --git a/packages/ckeditor5-ckfinder/src/ckfinder.ts b/packages/ckeditor5-ckfinder/src/ckfinder.ts new file mode 100644 index 00000000000..38271ce462d --- /dev/null +++ b/packages/ckeditor5-ckfinder/src/ckfinder.ts @@ -0,0 +1,132 @@ +/** + * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license + */ + +/** + * @module ckfinder/ckfinder + */ + +import { Plugin, type PluginDependencies } from 'ckeditor5/src/core'; + +import CKFinderUI from './ckfinderui'; +import CKFinderEditing from './ckfinderediting'; + +/** + * The CKFinder feature, a bridge between the CKEditor 5 WYSIWYG editor and the + * [CKFinder](https://ckeditor.com/ckfinder) file manager and uploader. + * + * This is a "glue" plugin which enables: + * + * * {@link module:ckfinder/ckfinderediting~CKFinderEditing}, + * * {@link module:ckfinder/ckfinderui~CKFinderUI}, + * * {@link module:adapter-ckfinder/uploadadapter~CKFinderUploadAdapter}. + * + * See the {@glink features/images/image-upload/ckfinder "CKFinder integration" guide} to learn how to configure + * and use this feature. + * + * Check out the {@glink features/images/image-upload/image-upload comprehensive "Image upload" guide} to learn about + * other ways to upload images into CKEditor 5. + */ +export default class CKFinder extends Plugin { + /** + * @inheritDoc + */ + public static get pluginName(): 'CKFinder' { + return 'CKFinder'; + } + + /** + * @inheritDoc + */ + public static get requires(): PluginDependencies { + return [ 'Link', 'CKFinderUploadAdapter', CKFinderEditing, CKFinderUI ]; + } +} + +declare module '@ckeditor/ckeditor5-core' { + interface PluginsMap { + [ CKFinder.pluginName ]: CKFinder; + } + + interface EditorConfig { + + /** + * The configuration of the {@link module:ckfinder/ckfinder~CKFinder CKFinder feature}. + * + * Read more in {@link module:ckfinder/ckfinder~CKFinderConfig}. + */ + ckfinder?: CKFinderConfig; + } +} + +/** + * The configuration of the {@link module:ckfinder/ckfinder~CKFinder CKFinder feature} + * and its {@link module:adapter-ckfinder/uploadadapter~CKFinderUploadAdapter upload adapter}. + * + * ``` + * ClassicEditor + * .create( editorElement, { + * ckfinder: { + * options: { + * resourceType: 'Images' + * } + * } + * } ) + * .then( ... ) + * .catch( ... ); + * ``` + * + * See {@link module:core/editor/editorconfig~EditorConfig all editor options}. + */ +interface CKFinderConfig { + + /** + * The configuration options passed to the CKFinder file manager instance. + * + * Check the file manager [documentation](https://ckeditor.com/docs/ckfinder/ckfinder3/#!/api/CKFinder.Config-cfg-language) + * for the complete list of options. + */ + options: CKFinderOptions; + + /** + * The type of the CKFinder opener method. + * + * Supported types are: + * + * * `'modal'` – Opens CKFinder in a modal, + * * `'popup'` – Opens CKFinder in a new "pop-up" window. + * + * Defaults to `'modal'`. + */ + openerMethod: string; + + /** + * The path (URL) to the connector which handles the file upload in CKFinder file manager. + * When specified, it enables the automatic upload of resources such as images inserted into the content. + * + * For instance, to use CKFinder's + * [quick upload](https://ckeditor.com/docs/ckfinder/ckfinder3-php/commands.html#command_quick_upload) + * command, your can use the following (or similar) path: + * + * ```ts + * ClassicEditor + * .create( editorElement, { + * ckfinder: { + * uploadUrl: '/ckfinder/core/connector/php/connector.php?command=QuickUpload&type=Files&responseType=json' + * } + * } ) + * .then( ... ) + * .catch( ... ); + * ``` + * + * Used by the {@link module:adapter-ckfinder/uploadadapter~CKFinderUploadAdapter upload adapter}. + */ + uploadUrl: string; +} + +interface CKFinderOptions extends Record { + chooseFiles?: boolean; + onInit?: ( finder: any ) => void; + language?: string; +} diff --git a/packages/ckeditor5-ckfinder/src/ckfindercommand.js b/packages/ckeditor5-ckfinder/src/ckfindercommand.ts similarity index 83% rename from packages/ckeditor5-ckfinder/src/ckfindercommand.js rename to packages/ckeditor5-ckfinder/src/ckfindercommand.ts index 85626160cd2..550d6490c02 100644 --- a/packages/ckeditor5-ckfinder/src/ckfindercommand.js +++ b/packages/ckeditor5-ckfinder/src/ckfindercommand.ts @@ -9,32 +9,32 @@ * @module ckfinder/ckfindercommand */ -import { Command } from 'ckeditor5/src/core'; +import { Command, type Editor } from 'ckeditor5/src/core'; import { CKEditorError } from 'ckeditor5/src/utils'; /** * The CKFinder command. It is used by the {@link module:ckfinder/ckfinderediting~CKFinderEditing CKFinder editing feature} * to open the CKFinder file manager to insert an image or a link to a file into the editor content. * - * editor.execute( 'ckfinder' ); + * ```ts + * editor.execute( 'ckfinder' ); + * ``` * * **Note:** This command uses other features to perform tasks: * - To insert images the {@link module:image/image/insertimagecommand~InsertImageCommand 'insertImage'} command * from the {@link module:image/image~Image Image feature}. * - To insert links to files the {@link module:link/linkcommand~LinkCommand 'link'} command * from the {@link module:link/link~Link Link feature}. - * - * @extends module:core/command~Command */ export default class CKFinderCommand extends Command { /** * @inheritDoc */ - constructor( editor ) { + constructor( editor: Editor ) { super( editor ); // The CKFinder command does not affect data by itself. - this._affectsData = false; + this.affectsData = false; // Remove default document listener to lower its priority. this.stopListening( this.editor.model.document, 'change' ); @@ -46,9 +46,9 @@ export default class CKFinderCommand extends Command { /** * @inheritDoc */ - refresh() { - const imageCommand = this.editor.commands.get( 'insertImage' ); - const linkCommand = this.editor.commands.get( 'link' ); + public override refresh(): void { + const imageCommand = this.editor.commands.get( 'insertImage' )!; + const linkCommand = this.editor.commands.get( 'link' )!; // The CKFinder command is enabled when one of image or link command is enabled. this.isEnabled = imageCommand.isEnabled || linkCommand.isEnabled; @@ -57,7 +57,7 @@ export default class CKFinderCommand extends Command { /** * @inheritDoc */ - execute() { + public override execute(): void { const editor = this.editor; const openerMethod = this.editor.config.get( 'ckfinder.openerMethod' ) || 'modal'; @@ -76,7 +76,7 @@ export default class CKFinderCommand extends Command { options.chooseFiles = true; // Cache the user-defined onInit method - const originalOnInit = options.onInit; + const originalOnInit = options.onInit as Function | undefined; // Pass the lang code to the CKFinder if not defined by user. if ( !options.language ) { @@ -90,12 +90,12 @@ export default class CKFinderCommand extends Command { originalOnInit( finder ); } - finder.on( 'files:choose', evt => { + finder.on( 'files:choose', ( evt: any ) => { const files = evt.data.files.toArray(); // Insert links - const links = files.filter( file => !file.isImage() ); - const images = files.filter( file => file.isImage() ); + const links = files.filter( ( file: any ) => !file.isImage() ); + const images = files.filter( ( file: any ) => file.isImage() ); for ( const linkFile of links ) { editor.execute( 'link', linkFile.getUrl() ); @@ -114,7 +114,7 @@ export default class CKFinderCommand extends Command { } } ); - finder.on( 'file:choose:resizedImage', evt => { + finder.on( 'file:choose:resizedImage', ( evt: any ) => { const resizedUrl = evt.data.resizedUrl; if ( !resizedUrl ) { @@ -133,12 +133,12 @@ export default class CKFinderCommand extends Command { } ); }; - window.CKFinder[ openerMethod ]( options ); + ( window as any ).CKFinder[ openerMethod ]( options ); } } -function insertImages( editor, urls ) { - const imageCommand = editor.commands.get( 'insertImage' ); +function insertImages( editor: Editor, urls: Array ): void { + const imageCommand = editor.commands.get( 'insertImage' )!; // Check if inserting an image is actually possible - it might be possible to only insert a link. if ( !imageCommand.isEnabled ) { diff --git a/packages/ckeditor5-ckfinder/src/ckfinderediting.js b/packages/ckeditor5-ckfinder/src/ckfinderediting.ts similarity index 79% rename from packages/ckeditor5-ckfinder/src/ckfinderediting.js rename to packages/ckeditor5-ckfinder/src/ckfinderediting.ts index c63f7867d67..17e0ca8782c 100644 --- a/packages/ckeditor5-ckfinder/src/ckfinderediting.js +++ b/packages/ckeditor5-ckfinder/src/ckfinderediting.ts @@ -7,7 +7,7 @@ * @module ckfinder/ckfinderediting */ -import { Plugin } from 'ckeditor5/src/core'; +import { Plugin, type PluginDependencies } from 'ckeditor5/src/core'; import { Notification } from 'ckeditor5/src/ui'; import { CKEditorError } from 'ckeditor5/src/utils'; @@ -15,28 +15,26 @@ import CKFinderCommand from './ckfindercommand'; /** * The CKFinder editing feature. It introduces the {@link module:ckfinder/ckfindercommand~CKFinderCommand CKFinder command}. - * - * @extends module:core/plugin~Plugin */ export default class CKFinderEditing extends Plugin { /** * @inheritDoc */ - static get pluginName() { + public static get pluginName(): 'CKFinderEditing' { return 'CKFinderEditing'; } /** * @inheritDoc */ - static get requires() { + public static get requires(): PluginDependencies { return [ Notification, 'LinkEditing' ]; } /** * @inheritDoc */ - init() { + public init(): void { const editor = this.editor; if ( !editor.plugins.has( 'ImageBlockEditing' ) && !editor.plugins.has( 'ImageInlineEditing' ) ) { @@ -58,3 +56,13 @@ export default class CKFinderEditing extends Plugin { editor.commands.add( 'ckfinder', new CKFinderCommand( editor ) ); } } + +declare module '@ckeditor/ckeditor5-core' { + interface PluginsMap { + [ CKFinderEditing.pluginName ]: CKFinderEditing; + } + + interface CommandsMap { + ckfinder: CKFinderCommand; + } +} diff --git a/packages/ckeditor5-ckfinder/src/ckfinderui.js b/packages/ckeditor5-ckfinder/src/ckfinderui.ts similarity index 89% rename from packages/ckeditor5-ckfinder/src/ckfinderui.js rename to packages/ckeditor5-ckfinder/src/ckfinderui.ts index d9932393b72..18b98e19c19 100644 --- a/packages/ckeditor5-ckfinder/src/ckfinderui.js +++ b/packages/ckeditor5-ckfinder/src/ckfinderui.ts @@ -14,27 +14,25 @@ import browseFilesIcon from '../theme/icons/browse-files.svg'; /** * The CKFinder UI plugin. It introduces the `'ckfinder'` toolbar button. - * - * @extends module:core/plugin~Plugin */ export default class CKFinderUI extends Plugin { /** * @inheritDoc */ - static get pluginName() { + public static get pluginName(): 'CKFinderUI' { return 'CKFinderUI'; } /** * @inheritDoc */ - init() { + public init(): void { const editor = this.editor; const componentFactory = editor.ui.componentFactory; const t = editor.t; componentFactory.add( 'ckfinder', locale => { - const command = editor.commands.get( 'ckfinder' ); + const command = editor.commands.get( 'ckfinder' )!; const button = new ButtonView( locale ); diff --git a/packages/ckeditor5-ckfinder/src/index.js b/packages/ckeditor5-ckfinder/src/index.ts similarity index 100% rename from packages/ckeditor5-ckfinder/src/index.js rename to packages/ckeditor5-ckfinder/src/index.ts diff --git a/packages/ckeditor5-ckfinder/tests/ckfindercommand.js b/packages/ckeditor5-ckfinder/tests/ckfindercommand.js index 7e52c6efa32..a627f1d035c 100644 --- a/packages/ckeditor5-ckfinder/tests/ckfindercommand.js +++ b/packages/ckeditor5-ckfinder/tests/ckfindercommand.js @@ -10,7 +10,7 @@ import { getData as getModelData, setData as setModelData } from '@ckeditor/cked import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils'; import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph'; import ImageBlockEditing from '@ckeditor/ckeditor5-image/src/image/imageblockediting'; -import ImageUploadEditing from '@ckeditor/ckeditor5-image/src/imageupload/imageuploadediting'; +import { ImageUploadEditing } from '@ckeditor/ckeditor5-image'; import LinkEditing from '@ckeditor/ckeditor5-link/src/linkediting'; import Notification from '@ckeditor/ckeditor5-ui/src/notification/notification'; import ClipboardPipeline from '@ckeditor/ckeditor5-clipboard/src/clipboardpipeline'; diff --git a/packages/ckeditor5-ckfinder/tsconfig.json b/packages/ckeditor5-ckfinder/tsconfig.json new file mode 100644 index 00000000000..9d4c891939c --- /dev/null +++ b/packages/ckeditor5-ckfinder/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "ckeditor5/tsconfig.json", + "include": [ + "src", + "../../typings" + ] +} diff --git a/packages/ckeditor5-ckfinder/tsconfig.release.json b/packages/ckeditor5-ckfinder/tsconfig.release.json new file mode 100644 index 00000000000..6d2d43909f9 --- /dev/null +++ b/packages/ckeditor5-ckfinder/tsconfig.release.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.release.json", + "include": [ + "./src/", + "../../typings/" + ], + "exclude": [ + "./tests/" + ] +} From 7fb84cb540b03564ebcbcc594ccbc1b172fbacd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Remiszewski?= Date: Tue, 31 Jan 2023 08:43:38 +0100 Subject: [PATCH 2/4] Make CKFinderConfig fields optional. --- packages/ckeditor5-ckfinder/src/ckfinder.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/ckeditor5-ckfinder/src/ckfinder.ts b/packages/ckeditor5-ckfinder/src/ckfinder.ts index 38271ce462d..bba8634a69c 100644 --- a/packages/ckeditor5-ckfinder/src/ckfinder.ts +++ b/packages/ckeditor5-ckfinder/src/ckfinder.ts @@ -87,7 +87,7 @@ interface CKFinderConfig { * Check the file manager [documentation](https://ckeditor.com/docs/ckfinder/ckfinder3/#!/api/CKFinder.Config-cfg-language) * for the complete list of options. */ - options: CKFinderOptions; + options?: CKFinderOptions; /** * The type of the CKFinder opener method. @@ -99,7 +99,7 @@ interface CKFinderConfig { * * Defaults to `'modal'`. */ - openerMethod: string; + openerMethod?: string; /** * The path (URL) to the connector which handles the file upload in CKFinder file manager. @@ -122,7 +122,7 @@ interface CKFinderConfig { * * Used by the {@link module:adapter-ckfinder/uploadadapter~CKFinderUploadAdapter upload adapter}. */ - uploadUrl: string; + uploadUrl?: string; } interface CKFinderOptions extends Record { From 8ccdbe159977f3f3f59417a664d9af4ebe151e66 Mon Sep 17 00:00:00 2001 From: Arkadiusz Filipczak Date: Wed, 1 Feb 2023 15:56:03 +0100 Subject: [PATCH 3/4] TS rewrite (ckfinder): misc. changes. --- packages/ckeditor5-ckfinder/src/ckfinder.ts | 81 ----------------- .../ckeditor5-ckfinder/src/ckfindercommand.ts | 7 +- .../ckeditor5-ckfinder/src/ckfinderconfig.ts | 91 +++++++++++++++++++ packages/ckeditor5-ckfinder/src/ckfinderui.ts | 4 +- packages/ckeditor5-ckfinder/src/index.ts | 1 + 5 files changed, 100 insertions(+), 84 deletions(-) create mode 100644 packages/ckeditor5-ckfinder/src/ckfinderconfig.ts diff --git a/packages/ckeditor5-ckfinder/src/ckfinder.ts b/packages/ckeditor5-ckfinder/src/ckfinder.ts index bba8634a69c..78f65fffb14 100644 --- a/packages/ckeditor5-ckfinder/src/ckfinder.ts +++ b/packages/ckeditor5-ckfinder/src/ckfinder.ts @@ -48,85 +48,4 @@ declare module '@ckeditor/ckeditor5-core' { interface PluginsMap { [ CKFinder.pluginName ]: CKFinder; } - - interface EditorConfig { - - /** - * The configuration of the {@link module:ckfinder/ckfinder~CKFinder CKFinder feature}. - * - * Read more in {@link module:ckfinder/ckfinder~CKFinderConfig}. - */ - ckfinder?: CKFinderConfig; - } -} - -/** - * The configuration of the {@link module:ckfinder/ckfinder~CKFinder CKFinder feature} - * and its {@link module:adapter-ckfinder/uploadadapter~CKFinderUploadAdapter upload adapter}. - * - * ``` - * ClassicEditor - * .create( editorElement, { - * ckfinder: { - * options: { - * resourceType: 'Images' - * } - * } - * } ) - * .then( ... ) - * .catch( ... ); - * ``` - * - * See {@link module:core/editor/editorconfig~EditorConfig all editor options}. - */ -interface CKFinderConfig { - - /** - * The configuration options passed to the CKFinder file manager instance. - * - * Check the file manager [documentation](https://ckeditor.com/docs/ckfinder/ckfinder3/#!/api/CKFinder.Config-cfg-language) - * for the complete list of options. - */ - options?: CKFinderOptions; - - /** - * The type of the CKFinder opener method. - * - * Supported types are: - * - * * `'modal'` – Opens CKFinder in a modal, - * * `'popup'` – Opens CKFinder in a new "pop-up" window. - * - * Defaults to `'modal'`. - */ - openerMethod?: string; - - /** - * The path (URL) to the connector which handles the file upload in CKFinder file manager. - * When specified, it enables the automatic upload of resources such as images inserted into the content. - * - * For instance, to use CKFinder's - * [quick upload](https://ckeditor.com/docs/ckfinder/ckfinder3-php/commands.html#command_quick_upload) - * command, your can use the following (or similar) path: - * - * ```ts - * ClassicEditor - * .create( editorElement, { - * ckfinder: { - * uploadUrl: '/ckfinder/core/connector/php/connector.php?command=QuickUpload&type=Files&responseType=json' - * } - * } ) - * .then( ... ) - * .catch( ... ); - * ``` - * - * Used by the {@link module:adapter-ckfinder/uploadadapter~CKFinderUploadAdapter upload adapter}. - */ - uploadUrl?: string; -} - -interface CKFinderOptions extends Record { - chooseFiles?: boolean; - onInit?: ( finder: any ) => void; - language?: string; } diff --git a/packages/ckeditor5-ckfinder/src/ckfindercommand.ts b/packages/ckeditor5-ckfinder/src/ckfindercommand.ts index 550d6490c02..ed54670ac35 100644 --- a/packages/ckeditor5-ckfinder/src/ckfindercommand.ts +++ b/packages/ckeditor5-ckfinder/src/ckfindercommand.ts @@ -11,6 +11,9 @@ import { Command, type Editor } from 'ckeditor5/src/core'; import { CKEditorError } from 'ckeditor5/src/utils'; +import type { Notification } from 'ckeditor5/src/ui'; + +import './ckfinderconfig'; /** * The CKFinder command. It is used by the {@link module:ckfinder/ckfinderediting~CKFinderEditing CKFinder editing feature} @@ -76,7 +79,7 @@ export default class CKFinderCommand extends Command { options.chooseFiles = true; // Cache the user-defined onInit method - const originalOnInit = options.onInit as Function | undefined; + const originalOnInit = options.onInit; // Pass the lang code to the CKFinder if not defined by user. if ( !options.language ) { @@ -142,7 +145,7 @@ function insertImages( editor: Editor, urls: Array ): void { // Check if inserting an image is actually possible - it might be possible to only insert a link. if ( !imageCommand.isEnabled ) { - const notification = editor.plugins.get( 'Notification' ); + const notification: Notification = editor.plugins.get( 'Notification' ); const t = editor.locale.t; notification.showWarning( t( 'Could not insert image at the current position.' ), { diff --git a/packages/ckeditor5-ckfinder/src/ckfinderconfig.ts b/packages/ckeditor5-ckfinder/src/ckfinderconfig.ts new file mode 100644 index 00000000000..fa0c225369d --- /dev/null +++ b/packages/ckeditor5-ckfinder/src/ckfinderconfig.ts @@ -0,0 +1,91 @@ +/** + * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license + */ + +/** + * @module ckfinder/ckfinder + */ + +/** + * The configuration of the {@link module:ckfinder/ckfinder~CKFinder CKFinder feature} + * and its {@link module:adapter-ckfinder/uploadadapter~CKFinderUploadAdapter upload adapter}. + * + * ``` + * ClassicEditor + * .create( editorElement, { + * ckfinder: { + * options: { + * resourceType: 'Images' + * } + * } + * } ) + * .then( ... ) + * .catch( ... ); + * ``` + * + * See {@link module:core/editor/editorconfig~EditorConfig all editor options}. + */ +export interface CKFinderConfig { + + /** + * The configuration options passed to the CKFinder file manager instance. + * + * Check the file manager [documentation](https://ckeditor.com/docs/ckfinder/ckfinder3/#!/api/CKFinder.Config-cfg-language) + * for the complete list of options. + */ + options?: CKFinderOptions; + + /** + * The type of the CKFinder opener method. + * + * Supported types are: + * + * * `'modal'` – Opens CKFinder in a modal, + * * `'popup'` – Opens CKFinder in a new "pop-up" window. + * + * Defaults to `'modal'`. + */ + openerMethod?: 'modal' | 'popup'; + + /** + * The path (URL) to the connector which handles the file upload in CKFinder file manager. + * When specified, it enables the automatic upload of resources such as images inserted into the content. + * + * For instance, to use CKFinder's + * [quick upload](https://ckeditor.com/docs/ckfinder/ckfinder3-php/commands.html#command_quick_upload) + * command, your can use the following (or similar) path: + * + * ```ts + * ClassicEditor + * .create( editorElement, { + * ckfinder: { + * uploadUrl: '/ckfinder/core/connector/php/connector.php?command=QuickUpload&type=Files&responseType=json' + * } + * } ) + * .then( ... ) + * .catch( ... ); + * ``` + * + * Used by the {@link module:adapter-ckfinder/uploadadapter~CKFinderUploadAdapter upload adapter}. + */ + uploadUrl?: string; +} + +export interface CKFinderOptions extends Record { + chooseFiles?: boolean; + onInit?: ( finder: any ) => void; + language?: string; +} + +declare module '@ckeditor/ckeditor5-core' { + interface EditorConfig { + + /** + * The configuration of the {@link module:ckfinder/ckfinder~CKFinder CKFinder feature}. + * + * Read more in {@link module:ckfinder/ckfinder~CKFinderConfig}. + */ + ckfinder?: CKFinderConfig; + } +} diff --git a/packages/ckeditor5-ckfinder/src/ckfinderui.ts b/packages/ckeditor5-ckfinder/src/ckfinderui.ts index 18b98e19c19..9b9980f1b18 100644 --- a/packages/ckeditor5-ckfinder/src/ckfinderui.ts +++ b/packages/ckeditor5-ckfinder/src/ckfinderui.ts @@ -10,6 +10,8 @@ import { Plugin } from 'ckeditor5/src/core'; import { ButtonView } from 'ckeditor5/src/ui'; +import type CKFinderCommand from './ckfindercommand'; + import browseFilesIcon from '../theme/icons/browse-files.svg'; /** @@ -32,7 +34,7 @@ export default class CKFinderUI extends Plugin { const t = editor.t; componentFactory.add( 'ckfinder', locale => { - const command = editor.commands.get( 'ckfinder' )!; + const command: CKFinderCommand = editor.commands.get( 'ckfinder' )!; const button = new ButtonView( locale ); diff --git a/packages/ckeditor5-ckfinder/src/index.ts b/packages/ckeditor5-ckfinder/src/index.ts index d79e48b105d..9422992a027 100644 --- a/packages/ckeditor5-ckfinder/src/index.ts +++ b/packages/ckeditor5-ckfinder/src/index.ts @@ -10,3 +10,4 @@ export { default as CKFinder } from './ckfinder'; export { default as CKFinderEditing } from './ckfinderediting'; export { default as CKFinderUI } from './ckfinderui'; +export type { CKFinderConfig } from './ckfinderconfig'; From 834a6f96bf65f167148aea59c863b37ac3c5760a Mon Sep 17 00:00:00 2001 From: Arkadiusz Filipczak Date: Wed, 1 Feb 2023 15:57:33 +0100 Subject: [PATCH 4/4] Added ckeditor5-ckfinder/_src. --- packages/ckeditor5-ckfinder/_src/ckfinder.js | 119 +++++++++++++ .../_src/ckfindercommand.js | 157 ++++++++++++++++++ .../_src/ckfinderediting.js | 60 +++++++ .../ckeditor5-ckfinder/_src/ckfinderui.js | 57 +++++++ packages/ckeditor5-ckfinder/_src/index.js | 12 ++ 5 files changed, 405 insertions(+) create mode 100644 packages/ckeditor5-ckfinder/_src/ckfinder.js create mode 100644 packages/ckeditor5-ckfinder/_src/ckfindercommand.js create mode 100644 packages/ckeditor5-ckfinder/_src/ckfinderediting.js create mode 100644 packages/ckeditor5-ckfinder/_src/ckfinderui.js create mode 100644 packages/ckeditor5-ckfinder/_src/index.js diff --git a/packages/ckeditor5-ckfinder/_src/ckfinder.js b/packages/ckeditor5-ckfinder/_src/ckfinder.js new file mode 100644 index 00000000000..7c67aa65e8d --- /dev/null +++ b/packages/ckeditor5-ckfinder/_src/ckfinder.js @@ -0,0 +1,119 @@ +/** + * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license + */ + +/** + * @module ckfinder/ckfinder + */ + +import { Plugin } from 'ckeditor5/src/core'; + +import CKFinderUI from './ckfinderui'; +import CKFinderEditing from './ckfinderediting'; + +/** + * The CKFinder feature, a bridge between the CKEditor 5 WYSIWYG editor and the + * [CKFinder](https://ckeditor.com/ckfinder) file manager and uploader. + * + * This is a "glue" plugin which enables: + * + * * {@link module:ckfinder/ckfinderediting~CKFinderEditing}, + * * {@link module:ckfinder/ckfinderui~CKFinderUI}, + * * {@link module:adapter-ckfinder/uploadadapter~CKFinderUploadAdapter}. + * + * See the {@glink features/images/image-upload/ckfinder "CKFinder integration" guide} to learn how to configure + * and use this feature. + * + * Check out the {@glink features/images/image-upload/image-upload comprehensive "Image upload" guide} to learn about + * other ways to upload images into CKEditor 5. + * + * @extends module:core/plugin~Plugin + */ +export default class CKFinder extends Plugin { + /** + * @inheritDoc + */ + static get pluginName() { + return 'CKFinder'; + } + + /** + * @inheritDoc + */ + static get requires() { + return [ 'Link', 'CKFinderUploadAdapter', CKFinderEditing, CKFinderUI ]; + } +} + +/** + * The configuration of the {@link module:ckfinder/ckfinder~CKFinder CKFinder feature}. + * + * Read more in {@link module:ckfinder/ckfinder~CKFinderConfig}. + * + * @member {module:ckfinder/ckfinder~CKFinderConfig} module:core/editor/editorconfig~EditorConfig#ckfinder + */ + +/** + * The configuration of the {@link module:ckfinder/ckfinder~CKFinder CKFinder feature} + * and its {@link module:adapter-ckfinder/uploadadapter~CKFinderUploadAdapter upload adapter}. + * + * ClassicEditor + * .create( editorElement, { + * ckfinder: { + * options: { + * resourceType: 'Images' + * } + * } + * } ) + * .then( ... ) + * .catch( ... ); + * + * See {@link module:core/editor/editorconfig~EditorConfig all editor options}. + * + * @interface CKFinderConfig + */ + +/** + * The configuration options passed to the CKFinder file manager instance. + * + * Check the file manager [documentation](https://ckeditor.com/docs/ckfinder/ckfinder3/#!/api/CKFinder.Config-cfg-language) + * for the complete list of options. + * + * @member {Object} module:ckfinder/ckfinder~CKFinderConfig#options + */ + +/** + * The type of the CKFinder opener method. + * + * Supported types are: + * + * * `'modal'` – Opens CKFinder in a modal, + * * `'popup'` – Opens CKFinder in a new "pop-up" window. + * + * Defaults to `'modal'`. + * + * @member {String} module:ckfinder/ckfinder~CKFinderConfig#openerMethod + */ + +/** + * The path (URL) to the connector which handles the file upload in CKFinder file manager. + * When specified, it enables the automatic upload of resources such as images inserted into the content. + * + * For instance, to use CKFinder's + * [quick upload](https://ckeditor.com/docs/ckfinder/ckfinder3-php/commands.html#command_quick_upload) + * command, your can use the following (or similar) path: + * + * ClassicEditor + * .create( editorElement, { + * ckfinder: { + * uploadUrl: '/ckfinder/core/connector/php/connector.php?command=QuickUpload&type=Files&responseType=json' + * } + * } ) + * .then( ... ) + * .catch( ... ); + * + * Used by the {@link module:adapter-ckfinder/uploadadapter~CKFinderUploadAdapter upload adapter}. + * + * @member {String} module:ckfinder/ckfinder~CKFinderConfig#uploadUrl + */ diff --git a/packages/ckeditor5-ckfinder/_src/ckfindercommand.js b/packages/ckeditor5-ckfinder/_src/ckfindercommand.js new file mode 100644 index 00000000000..85626160cd2 --- /dev/null +++ b/packages/ckeditor5-ckfinder/_src/ckfindercommand.js @@ -0,0 +1,157 @@ +/** + * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license + */ + +/* global window */ + +/** + * @module ckfinder/ckfindercommand + */ + +import { Command } from 'ckeditor5/src/core'; +import { CKEditorError } from 'ckeditor5/src/utils'; + +/** + * The CKFinder command. It is used by the {@link module:ckfinder/ckfinderediting~CKFinderEditing CKFinder editing feature} + * to open the CKFinder file manager to insert an image or a link to a file into the editor content. + * + * editor.execute( 'ckfinder' ); + * + * **Note:** This command uses other features to perform tasks: + * - To insert images the {@link module:image/image/insertimagecommand~InsertImageCommand 'insertImage'} command + * from the {@link module:image/image~Image Image feature}. + * - To insert links to files the {@link module:link/linkcommand~LinkCommand 'link'} command + * from the {@link module:link/link~Link Link feature}. + * + * @extends module:core/command~Command + */ +export default class CKFinderCommand extends Command { + /** + * @inheritDoc + */ + constructor( editor ) { + super( editor ); + + // The CKFinder command does not affect data by itself. + this._affectsData = false; + + // Remove default document listener to lower its priority. + this.stopListening( this.editor.model.document, 'change' ); + + // Lower this command listener priority to be sure that refresh() will be called after link & image refresh. + this.listenTo( this.editor.model.document, 'change', () => this.refresh(), { priority: 'low' } ); + } + + /** + * @inheritDoc + */ + refresh() { + const imageCommand = this.editor.commands.get( 'insertImage' ); + const linkCommand = this.editor.commands.get( 'link' ); + + // The CKFinder command is enabled when one of image or link command is enabled. + this.isEnabled = imageCommand.isEnabled || linkCommand.isEnabled; + } + + /** + * @inheritDoc + */ + execute() { + const editor = this.editor; + + const openerMethod = this.editor.config.get( 'ckfinder.openerMethod' ) || 'modal'; + + if ( openerMethod != 'popup' && openerMethod != 'modal' ) { + /** + * The `ckfinder.openerMethod` must be one of: "popup" or "modal". + * + * @error ckfinder-unknown-openermethod + */ + throw new CKEditorError( 'ckfinder-unknown-openermethod', editor ); + } + + const options = this.editor.config.get( 'ckfinder.options' ) || {}; + + options.chooseFiles = true; + + // Cache the user-defined onInit method + const originalOnInit = options.onInit; + + // Pass the lang code to the CKFinder if not defined by user. + if ( !options.language ) { + options.language = editor.locale.uiLanguage; + } + + // The onInit method allows to extend CKFinder's behavior. It is used to attach event listeners to file choosing related events. + options.onInit = finder => { + // Call original options.onInit if it was defined by user. + if ( originalOnInit ) { + originalOnInit( finder ); + } + + finder.on( 'files:choose', evt => { + const files = evt.data.files.toArray(); + + // Insert links + const links = files.filter( file => !file.isImage() ); + const images = files.filter( file => file.isImage() ); + + for ( const linkFile of links ) { + editor.execute( 'link', linkFile.getUrl() ); + } + + const imagesUrls = []; + + for ( const image of images ) { + const url = image.getUrl(); + + imagesUrls.push( url ? url : finder.request( 'file:getProxyUrl', { file: image } ) ); + } + + if ( imagesUrls.length ) { + insertImages( editor, imagesUrls ); + } + } ); + + finder.on( 'file:choose:resizedImage', evt => { + const resizedUrl = evt.data.resizedUrl; + + if ( !resizedUrl ) { + const notification = editor.plugins.get( 'Notification' ); + const t = editor.locale.t; + + notification.showWarning( t( 'Could not obtain resized image URL.' ), { + title: t( 'Selecting resized image failed' ), + namespace: 'ckfinder' + } ); + + return; + } + + insertImages( editor, [ resizedUrl ] ); + } ); + }; + + window.CKFinder[ openerMethod ]( options ); + } +} + +function insertImages( editor, urls ) { + const imageCommand = editor.commands.get( 'insertImage' ); + + // Check if inserting an image is actually possible - it might be possible to only insert a link. + if ( !imageCommand.isEnabled ) { + const notification = editor.plugins.get( 'Notification' ); + const t = editor.locale.t; + + notification.showWarning( t( 'Could not insert image at the current position.' ), { + title: t( 'Inserting image failed' ), + namespace: 'ckfinder' + } ); + + return; + } + + editor.execute( 'insertImage', { source: urls } ); +} diff --git a/packages/ckeditor5-ckfinder/_src/ckfinderediting.js b/packages/ckeditor5-ckfinder/_src/ckfinderediting.js new file mode 100644 index 00000000000..c63f7867d67 --- /dev/null +++ b/packages/ckeditor5-ckfinder/_src/ckfinderediting.js @@ -0,0 +1,60 @@ +/** + * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license + */ + +/** + * @module ckfinder/ckfinderediting + */ + +import { Plugin } from 'ckeditor5/src/core'; +import { Notification } from 'ckeditor5/src/ui'; +import { CKEditorError } from 'ckeditor5/src/utils'; + +import CKFinderCommand from './ckfindercommand'; + +/** + * The CKFinder editing feature. It introduces the {@link module:ckfinder/ckfindercommand~CKFinderCommand CKFinder command}. + * + * @extends module:core/plugin~Plugin + */ +export default class CKFinderEditing extends Plugin { + /** + * @inheritDoc + */ + static get pluginName() { + return 'CKFinderEditing'; + } + + /** + * @inheritDoc + */ + static get requires() { + return [ Notification, 'LinkEditing' ]; + } + + /** + * @inheritDoc + */ + init() { + const editor = this.editor; + + if ( !editor.plugins.has( 'ImageBlockEditing' ) && !editor.plugins.has( 'ImageInlineEditing' ) ) { + /** + * CKFinder requires at least one plugin providing support for images loaded in the editor. Please + * make sure either: + * + * * {@link module:image/image~Image} (which loads both types of images), + * * or {@link module:image/imageblock~ImageBlock}, + * * or {@link module:image/imageinline~ImageInline}. + * + * is loaded in your editor configuration. + * + * @error ckfinder-missing-image-plugin + */ + throw new CKEditorError( 'ckfinder-missing-image-plugin', editor ); + } + + editor.commands.add( 'ckfinder', new CKFinderCommand( editor ) ); + } +} diff --git a/packages/ckeditor5-ckfinder/_src/ckfinderui.js b/packages/ckeditor5-ckfinder/_src/ckfinderui.js new file mode 100644 index 00000000000..d9932393b72 --- /dev/null +++ b/packages/ckeditor5-ckfinder/_src/ckfinderui.js @@ -0,0 +1,57 @@ +/** + * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license + */ + +/** + * @module ckfinder/ckfinderui + */ + +import { Plugin } from 'ckeditor5/src/core'; +import { ButtonView } from 'ckeditor5/src/ui'; + +import browseFilesIcon from '../theme/icons/browse-files.svg'; + +/** + * The CKFinder UI plugin. It introduces the `'ckfinder'` toolbar button. + * + * @extends module:core/plugin~Plugin + */ +export default class CKFinderUI extends Plugin { + /** + * @inheritDoc + */ + static get pluginName() { + return 'CKFinderUI'; + } + + /** + * @inheritDoc + */ + init() { + const editor = this.editor; + const componentFactory = editor.ui.componentFactory; + const t = editor.t; + + componentFactory.add( 'ckfinder', locale => { + const command = editor.commands.get( 'ckfinder' ); + + const button = new ButtonView( locale ); + + button.set( { + label: t( 'Insert image or file' ), + icon: browseFilesIcon, + tooltip: true + } ); + + button.bind( 'isEnabled' ).to( command ); + + button.on( 'execute', () => { + editor.execute( 'ckfinder' ); + editor.editing.view.focus(); + } ); + + return button; + } ); + } +} diff --git a/packages/ckeditor5-ckfinder/_src/index.js b/packages/ckeditor5-ckfinder/_src/index.js new file mode 100644 index 00000000000..d79e48b105d --- /dev/null +++ b/packages/ckeditor5-ckfinder/_src/index.js @@ -0,0 +1,12 @@ +/** + * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license + */ + +/** + * @module ckfinder + */ + +export { default as CKFinder } from './ckfinder'; +export { default as CKFinderEditing } from './ckfinderediting'; +export { default as CKFinderUI } from './ckfinderui';