diff --git a/_regroup/ckeditor5-file-upload/package.json b/_regroup/ckeditor5-file-upload/package.json deleted file mode 100644 index 146106462..000000000 --- a/_regroup/ckeditor5-file-upload/package.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "name": "@ckeditor/ckeditor5-file-upload", - "version": "1.0.0", - "description": "File Upload for CKEditor5", - "main": "src/fileupload.js", - "keywords": [ "ckeditor5" ], - "dependencies": { - "@ckeditor/ckeditor5-core": "^38.0.1", - "@ckeditor/ckeditor5-upload": "^38.0.1", - "@ckeditor/ckeditor5-ui": "^38.0.1", - "@ckeditor/ckeditor5-clipboard": "^38.0.1", - "@ckeditor/ckeditor5-engine": "^38.0.1", - "@ckeditor/ckeditor5-utils": "^38.0.1", - "@ckeditor/ckeditor5-widget": "^38.0.1" - }, - "license": "GPL-3.0", - "devDependencies": {} -} diff --git a/_regroup/ckeditor5-file-upload/theme/icons/fileupload.svg b/packages/ckeditor5/src/icons/fileupload.svg similarity index 100% rename from _regroup/ckeditor5-file-upload/theme/icons/fileupload.svg rename to packages/ckeditor5/src/icons/fileupload.svg diff --git a/packages/ckeditor5/src/plugins.ts b/packages/ckeditor5/src/plugins.ts index 61c428d6a..c7b9c264d 100644 --- a/packages/ckeditor5/src/plugins.ts +++ b/packages/ckeditor5/src/plugins.ts @@ -12,6 +12,7 @@ import IndentBlockShortcutPlugin from "./plugins/indent_block_shortcut.js"; import MarkdownImportPlugin from "./plugins/markdownimport.js"; import MentionCustomization from "./plugins/mention_customization.js"; import IncludeNote from "./plugins/includenote.js"; +import Uploadfileplugin from "./plugins/file_upload/uploadfileplugin.js"; const TRILIUM_PLUGINS: typeof Plugin[] = [ CutToNotePlugin, @@ -25,7 +26,8 @@ const TRILIUM_PLUGINS: typeof Plugin[] = [ IndentBlockShortcutPlugin, MarkdownImportPlugin, MentionCustomization, - IncludeNote + IncludeNote, + Uploadfileplugin ]; export const COMMON_PLUGINS: typeof Plugin[] = [ @@ -70,7 +72,6 @@ export const COMMON_PLUGINS: typeof Plugin[] = [ IndentBlock, ParagraphButtonUI, HeadingButtonsUI, - //Uploadfileplugin TextTransformation, Font, FontColor, @@ -83,7 +84,6 @@ export const COMMON_PLUGINS: typeof Plugin[] = [ SpecialCharactersEssentials, FindAndReplace, Mention, - // IncludeNote, PageBreak, GeneralHtmlSupport, TextPartLanguage, diff --git a/_regroup/ckeditor5-file-upload/src/fileuploadcommand.js b/packages/ckeditor5/src/plugins/file_upload/fileuploadcommand.ts similarity index 74% rename from _regroup/ckeditor5-file-upload/src/fileuploadcommand.js rename to packages/ckeditor5/src/plugins/file_upload/fileuploadcommand.ts index e0eec148c..1d6b2981d 100644 --- a/_regroup/ckeditor5-file-upload/src/fileuploadcommand.js +++ b/packages/ckeditor5/src/plugins/file_upload/fileuploadcommand.ts @@ -1,5 +1,8 @@ -import { FileRepository } from 'ckeditor5/src/upload'; -import { Command } from 'ckeditor5/src/core'; +import { Command, FileRepository, Model, type NodeAttributes, type Writer } from "ckeditor5"; + +interface FileUploadOpts { + file: File[]; +} export default class FileUploadCommand extends Command { refresh() { @@ -13,7 +16,7 @@ export default class FileUploadCommand extends Command { * @param {Object} options Options for the executed command. * @param {File|Array.} options.file The file or an array of files to upload. */ - execute( options ) { + execute( options: FileUploadOpts ) { const editor = this.editor; const model = editor.model; @@ -30,12 +33,8 @@ export default class FileUploadCommand extends Command { /** * Handles uploading single file. - * - * @param {module:engine/model/writer~writer} writer - * @param {module:engine/model/model~Model} model - * @param {File} file */ -function uploadFile( writer, model, fileRepository, file ) { +function uploadFile( writer: Writer, model: Model, fileRepository: FileRepository, file: File ) { const loader = fileRepository.createLoader( file ); // Do not throw when upload adapter is not set. FileRepository will log an error anyway. @@ -46,7 +45,7 @@ function uploadFile( writer, model, fileRepository, file ) { insertFileLink( writer, model, { href: '', uploadId: loader.id }, file ); } -function insertFileLink( writer, model, attributes = {}, file ) { +function insertFileLink( writer: Writer, model: Model, attributes: NodeAttributes = {}, file: File ) { const placeholder = writer.createElement( 'reference', attributes ); model.insertContent( placeholder, model.document.selection ); writer.insertText( ' ', placeholder, 'after' ); diff --git a/_regroup/ckeditor5-file-upload/src/fileuploadediting.js b/packages/ckeditor5/src/plugins/file_upload/fileuploadediting.ts similarity index 81% rename from _regroup/ckeditor5-file-upload/src/fileuploadediting.js rename to packages/ckeditor5/src/plugins/file_upload/fileuploadediting.ts index ee1e0ae11..e8ae16172 100644 --- a/_regroup/ckeditor5-file-upload/src/fileuploadediting.js +++ b/packages/ckeditor5/src/plugins/file_upload/fileuploadediting.ts @@ -1,12 +1,8 @@ -import { Plugin } from 'ckeditor5/src/core'; -import { FileRepository } from 'ckeditor5/src/upload'; -import { Notification } from 'ckeditor5/src/ui'; -import { Clipboard } from 'ckeditor5/src/clipboard'; -import { UpcastWriter } from 'ckeditor5/src/engine'; - +import { Clipboard, FileRepository, Notification, Plugin, UpcastWriter, ViewElement, type Editor, type FileLoader, type Item, type Node, type ViewItem, type ViewRange } from 'ckeditor5'; import FileUploadCommand from './fileuploadcommand'; export default class FileUploadEditing extends Plugin { + static get requires() { return [ FileRepository, Notification, Clipboard ]; } @@ -46,14 +42,14 @@ export default class FileUploadEditing extends Plugin { editor.model.change( writer => { // Set selection to paste target. if ( data.targetRanges ) { - writer.setSelection( data.targetRanges.map( viewRange => editor.editing.mapper.toModelRange( viewRange ) ) ); + writer.setSelection( data.targetRanges.map( (viewRange: ViewRange) => editor.editing.mapper.toModelRange( viewRange ) ) ); } if ( files.length ) { evt.stop(); // Upload files after the selection has changed in order to ensure the command's state is refreshed. - editor.model.enqueueChange( 'default', () => { + editor.model.enqueueChange(() => { editor.execute( 'fileUpload', { file: files } ); } ); } @@ -62,15 +58,16 @@ export default class FileUploadEditing extends Plugin { this.listenTo( editor.plugins.get( Clipboard ), 'inputTransformation', ( evt, data ) => { const fetchableFiles = Array.from( editor.editing.view.createRangeIn( data.content ) ) - .filter( value => isLocalFile( value.item ) && !value.item.getAttribute( 'uploadProcessed' ) ) + .filter( value => isLocalFile( value.item ) && !(value.item as unknown as Node).getAttribute( 'uploadProcessed' ) ) .map( value => { - return { promise: fetchLocalFile( value.item ), fileElement: value.item }; + return { promise: fetchLocalFile( value.item ), fileElement: value as unknown as ViewElement }; } ); if ( !fetchableFiles.length ) { return; } + //@ts-expect-error Missing document. const writer = new UpcastWriter(); for ( const fetchableFile of fetchableFiles ) { @@ -101,7 +98,7 @@ export default class FileUploadEditing extends Plugin { const isInGraveyard = entry.position.root.rootName == '$graveyard'; for ( const file of getFileLinksFromChangeItem( editor, item ) ) { // Check if the file element still has upload id. - const uploadId = file.getAttribute( 'uploadId' ); + const uploadId = file.getAttribute( 'uploadId' ) as string | number; if ( !uploadId ) { continue; } @@ -127,14 +124,14 @@ export default class FileUploadEditing extends Plugin { } ); } - _readAndUpload( loader, fileElement ) { + _readAndUpload( loader: FileLoader, fileElement: Item ) { const editor = this.editor; const model = editor.model; const t = editor.locale.t; const fileRepository = editor.plugins.get( FileRepository ); const notification = editor.plugins.get( Notification ); - model.enqueueChange( 'transparent', writer => { + model.enqueueChange(writer => { writer.setAttribute( 'uploadStatus', 'reading', fileElement ); } ); @@ -142,14 +139,14 @@ export default class FileUploadEditing extends Plugin { .then( () => { const promise = loader.upload(); - model.enqueueChange( 'transparent', writer => { + model.enqueueChange(writer => { writer.setAttribute( 'uploadStatus', 'uploading', fileElement ); } ); return promise; } ) .then( data => { - model.enqueueChange( 'transparent', writer => { + model.enqueueChange(writer => { writer.setAttributes( { uploadStatus: 'complete', href: data.default }, fileElement ); } ); @@ -181,13 +178,13 @@ export default class FileUploadEditing extends Plugin { clean(); // Permanently remove file from insertion batch. - model.enqueueChange( 'transparent', writer => { + model.enqueueChange(writer => { writer.remove( fileElement ); } ); } ); function clean() { - model.enqueueChange( 'transparent', writer => { + model.enqueueChange(writer => { writer.removeAttribute( 'uploadId', fileElement ); writer.removeAttribute( 'uploadStatus', fileElement ); } ); @@ -197,16 +194,16 @@ export default class FileUploadEditing extends Plugin { } } -function fetchLocalFile( link ) { - return new Promise( ( resolve, reject ) => { - const href = link.getAttribute( 'href' ); +function fetchLocalFile( link: ViewItem ) { + return new Promise( ( resolve, reject ) => { + const href = (link as unknown as Node).getAttribute( 'href' ) as string; // Fetch works asynchronously and so does not block the browser UI when processing data. fetch( href ) .then( resource => resource.blob() ) .then( blob => { - const mimeType = getFileMimeType( blob, href ); - const ext = mimeType.replace( 'file/', '' ); + const mimeType = getFileMimeType( blob, href ) ?? ""; + const ext = mimeType?.replace( 'file/', '' ); const filename = `file.${ ext }`; const file = createFileFromBlob( blob, filename, mimeType ); @@ -216,7 +213,7 @@ function fetchLocalFile( link ) { } ); } -function isLocalFile( node ) { +function isLocalFile( node: ViewItem ) { if ( !node.is( 'element', 'a' ) || !node.getAttribute( 'href' ) ) { return false; } @@ -224,17 +221,17 @@ function isLocalFile( node ) { return node.getAttribute( 'href' ); } -function getFileMimeType( blob, src ) { +function getFileMimeType( blob: Blob, src: string ) { if ( blob.type ) { return blob.type; } else if ( src.match( /data:(image\/\w+);base64/ ) ) { - return src.match( /data:(image\/\w+);base64/ )[ 1 ].toLowerCase(); + return src.match( /data:(image\/\w+);base64/ )?.[ 1 ].toLowerCase(); } else { throw new Error( 'Could not retrieve mime type for file.' ); } } -function createFileFromBlob( blob, filename, mimeType ) { +function createFileFromBlob( blob: BlobPart, filename: string, mimeType: string ) { try { return new File( [ blob ], filename, { type: mimeType } ); } catch ( err ) { @@ -250,11 +247,11 @@ function createFileFromBlob( blob, filename, mimeType ) { // // @param {module:clipboard/datatransfer~DataTransfer} dataTransfer // @returns {Boolean} -export function isHtmlIncluded( dataTransfer ) { +export function isHtmlIncluded( dataTransfer: DataTransfer ) { return Array.from( dataTransfer.types ).includes( 'text/html' ) && dataTransfer.getData( 'text/html' ) !== ''; } -function getFileLinksFromChangeItem( editor, item ) { +function getFileLinksFromChangeItem( editor: Editor, item: Item ) { return Array.from( editor.model.createRangeOn( item ) ) .filter( value => value.item.hasAttribute( 'href' ) ) .map( value => value.item ); diff --git a/_regroup/ckeditor5-file-upload/theme/progressbarview.js b/packages/ckeditor5/src/plugins/file_upload/progressbarview.ts similarity index 73% rename from _regroup/ckeditor5-file-upload/theme/progressbarview.js rename to packages/ckeditor5/src/plugins/file_upload/progressbarview.ts index 38419626a..daa888751 100644 --- a/_regroup/ckeditor5-file-upload/theme/progressbarview.js +++ b/packages/ckeditor5/src/plugins/file_upload/progressbarview.ts @@ -1,13 +1,14 @@ -import View from "@ckeditor/ckeditor5-ui/src/view"; -import toUnit from '@ckeditor/ckeditor5-utils/src/dom/tounit'; -import ButtonView from "@ckeditor/ckeditor5-ui/src/button/buttonview"; - import cancelIcon from '@ckeditor/ckeditor5-core/theme/icons/cancel.svg'; +import { ButtonView, Locale, toUnit, View } from 'ckeditor5'; const toPx = toUnit('%'); export default class ProgressBarView extends View { - constructor(locale) { + private cancelButton: ButtonView; + width!: number; + customWidth!: number; + + constructor(locale: Locale) { super(locale); const bind = this.bindTemplate; @@ -40,6 +41,7 @@ export default class ProgressBarView extends View { 'ck-progress-bar', // Observable attributes control the state of the view in DOM. + //@ts-expect-error Type 'ListenerBinding' is not assignable to type 'TemplateSimpleValueSchema' bind.to('elementClass') ], style: { @@ -49,12 +51,13 @@ export default class ProgressBarView extends View { }); } - _createCancelButton(locale) { + _createCancelButton(locale: Locale) { const view = new ButtonView(locale); view.set({ icon: cancelIcon, tooltip: true, label: 'Cancel', + //@ts-expect-error Object literal may only specify known properties, and 'attributes' does not exist in type attributes: { class: ['ck', 'ck-button', 'ck-off', 'ck-button-cancel', 'ck-uploading-cancel'] } diff --git a/_regroup/ckeditor5-file-upload/uploadfileplugin.js b/packages/ckeditor5/src/plugins/file_upload/uploadfileplugin.ts similarity index 63% rename from _regroup/ckeditor5-file-upload/uploadfileplugin.js rename to packages/ckeditor5/src/plugins/file_upload/uploadfileplugin.ts index f4616b15d..0c9caf025 100644 --- a/_regroup/ckeditor5-file-upload/uploadfileplugin.js +++ b/packages/ckeditor5/src/plugins/file_upload/uploadfileplugin.ts @@ -1,5 +1,5 @@ -import { Plugin } from 'ckeditor5/src/core'; -import FileUploadEditing from './src/fileuploadediting'; +import { Plugin } from "ckeditor5"; +import FileUploadEditing from "./fileuploadediting"; export default class Uploadfileplugin extends Plugin { static get requires() { diff --git a/packages/ckeditor5/tsconfig.lib.json b/packages/ckeditor5/tsconfig.lib.json index db3c5b036..1d33066d6 100644 --- a/packages/ckeditor5/tsconfig.lib.json +++ b/packages/ckeditor5/tsconfig.lib.json @@ -9,7 +9,7 @@ "tsBuildInfoFile": "dist/tsconfig.lib.tsbuildinfo", "emitDeclarationOnly": true, "forceConsistentCasingInFileNames": true, - "lib": ["DOM", "ES2015"], + "lib": ["DOM", "ES2020"], "types": [ "vite/client", "jquery"