Skip to content

Commit

Permalink
Merge pull request #13360 from ckeditor/ck/13006-rewrite-ckfinder-to-…
Browse files Browse the repository at this point in the history
…typescript

Other (ckfinder): Rewrite ckeditor5-ckfinder to TypeScript. Closes #13006.
  • Loading branch information
arkflpc authored Feb 1, 2023
2 parents 653d6c2 + 834a6f9 commit fa105ac
Show file tree
Hide file tree
Showing 16 changed files with 466 additions and 4 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ packages/ckeditor5-autosave/src/**/*.js
packages/ckeditor5-basic-styles/src/**/*.js
packages/ckeditor5-block-quote/src/**/*.js
packages/ckeditor5-ckbox/src/**/*.js
packages/ckeditor5-ckfinder/src/**/*.js
packages/ckeditor5-clipboard/src/**/*.js
packages/ckeditor5-cloud-services/src/**/*.js
packages/ckeditor5-code-block/src/**/*.js
Expand Down
File renamed without changes.
File renamed without changes.
10 changes: 7 additions & 3 deletions packages/ckeditor5-ckfinder/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"ckeditor5-plugin",
"ckeditor5-dll"
],
"main": "src/index.js",
"main": "src/index.ts",
"dependencies": {
"ckeditor5": "^36.0.0"
},
Expand All @@ -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"
},
Expand All @@ -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"
}
}
51 changes: 51 additions & 0 deletions packages/ckeditor5-ckfinder/src/ckfinder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* @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;
}
}
160 changes: 160 additions & 0 deletions packages/ckeditor5-ckfinder/src/ckfindercommand.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/**
* @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, 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}
* to open the CKFinder file manager to insert an image or a link to a file into the editor content.
*
* ```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}.
*/
export default class CKFinderCommand extends Command {
/**
* @inheritDoc
*/
constructor( editor: 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
*/
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;
}

/**
* @inheritDoc
*/
public override execute(): void {
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: any ) => {
const files = evt.data.files.toArray();

// Insert links
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() );
}

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: any ) => {
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 as any ).CKFinder[ openerMethod ]( options );
}
}

function insertImages( editor: Editor, urls: Array<string> ): 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 ) {
const notification: 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 } );
}
91 changes: 91 additions & 0 deletions packages/ckeditor5-ckfinder/src/ckfinderconfig.ts
Original file line number Diff line number Diff line change
@@ -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'` &ndash; Opens CKFinder in a modal,
* * `'popup'` &ndash; 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<string, unknown> {
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;
}
}
Loading

0 comments on commit fa105ac

Please sign in to comment.