From fa58055109259fe43e05ddd89b4472cc440dbdad Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sun, 4 May 2025 17:12:49 +0300 Subject: [PATCH] chore(ckeditor5-mermaid): port source code --- _regroup/ckeditor5-mermaid/package.json | 3 +- _regroup/ckeditor5-mermaid/src/index.js | 19 --- _regroup/ckeditor5-mermaid/src/mermaid.js | 27 ---- packages/ckeditor5-mermaid/package.json | 4 + .../ckeditor5-mermaid/src/augmentation.ts | 18 +++ .../src/commands/insertMermaidCommand.ts | 19 +-- .../src/commands/mermaidPreviewCommand.ts | 34 ++---- .../src/commands/mermaidSourceViewCommand.ts | 20 +-- .../src/commands/mermaidSplitViewCommand.ts | 18 +-- packages/ckeditor5-mermaid/src/index.ts | 12 +- packages/ckeditor5-mermaid/src/mermaid.ts | 38 ++---- .../ckeditor5-mermaid/src/mermaidediting.ts | 115 ++++++++---------- .../ckeditor5-mermaid/src/mermaidtoolbar.ts | 20 +-- .../ckeditor5-mermaid/src/mermaidui.ts | 33 ++--- .../ckeditor5-mermaid/src/utils.ts | 12 +- .../theme/icons/ckeditor.svg | 1 - .../ckeditor5-mermaid/theme/icons/info.svg | 0 .../ckeditor5-mermaid/theme/icons/insert.svg | 0 .../theme/icons/preview-mode.svg | 0 .../theme/icons/source-mode.svg | 0 .../theme/icons/split-mode.svg | 0 .../ckeditor5-mermaid/theme/mermaid.css | 0 pnpm-lock.yaml | 19 +++ 23 files changed, 167 insertions(+), 245 deletions(-) delete mode 100644 _regroup/ckeditor5-mermaid/src/index.js delete mode 100644 _regroup/ckeditor5-mermaid/src/mermaid.js rename _regroup/ckeditor5-mermaid/src/commands/insertMermaidCommand.js => packages/ckeditor5-mermaid/src/commands/insertMermaidCommand.ts (77%) rename _regroup/ckeditor5-mermaid/src/commands/mermaidPreviewCommand.js => packages/ckeditor5-mermaid/src/commands/mermaidPreviewCommand.ts (62%) rename _regroup/ckeditor5-mermaid/src/commands/mermaidSourceViewCommand.js => packages/ckeditor5-mermaid/src/commands/mermaidSourceViewCommand.ts (79%) rename _regroup/ckeditor5-mermaid/src/commands/mermaidSplitViewCommand.js => packages/ckeditor5-mermaid/src/commands/mermaidSplitViewCommand.ts (79%) rename _regroup/ckeditor5-mermaid/src/mermaidediting.js => packages/ckeditor5-mermaid/src/mermaidediting.ts (70%) rename _regroup/ckeditor5-mermaid/src/mermaidtoolbar.js => packages/ckeditor5-mermaid/src/mermaidtoolbar.ts (72%) rename _regroup/ckeditor5-mermaid/src/mermaidui.js => packages/ckeditor5-mermaid/src/mermaidui.ts (78%) rename _regroup/ckeditor5-mermaid/src/utils.js => packages/ckeditor5-mermaid/src/utils.ts (69%) delete mode 100644 packages/ckeditor5-mermaid/theme/icons/ckeditor.svg rename {_regroup => packages}/ckeditor5-mermaid/theme/icons/info.svg (100%) rename {_regroup => packages}/ckeditor5-mermaid/theme/icons/insert.svg (100%) rename {_regroup => packages}/ckeditor5-mermaid/theme/icons/preview-mode.svg (100%) rename {_regroup => packages}/ckeditor5-mermaid/theme/icons/source-mode.svg (100%) rename {_regroup => packages}/ckeditor5-mermaid/theme/icons/split-mode.svg (100%) rename {_regroup => packages}/ckeditor5-mermaid/theme/mermaid.css (100%) diff --git a/_regroup/ckeditor5-mermaid/package.json b/_regroup/ckeditor5-mermaid/package.json index c0785edae..2a0853fe0 100644 --- a/_regroup/ckeditor5-mermaid/package.json +++ b/_regroup/ckeditor5-mermaid/package.json @@ -30,8 +30,7 @@ "ckeditor5-metadata.json" ], "dependencies": { - "ckeditor5": "43.2.0", - "lodash-es": "^4.17.15" + "ckeditor5": "43.2.0" }, "devDependencies": { "@ckeditor/ckeditor5-dev-build-tools": "^42.0.0", diff --git a/_regroup/ckeditor5-mermaid/src/index.js b/_regroup/ckeditor5-mermaid/src/index.js deleted file mode 100644 index 6b37848d8..000000000 --- a/_regroup/ckeditor5-mermaid/src/index.js +++ /dev/null @@ -1,19 +0,0 @@ -/** - * @module mermaid - */ - -import infoIcon from './../theme/icons/info.svg'; -import insertMermaidIcon from './../theme/icons/insert.svg'; -import previewModeIcon from './../theme/icons/preview-mode.svg'; -import splitModeIcon from './../theme/icons/split-mode.svg'; -import sourceModeIcon from './../theme/icons/source-mode.svg'; - -export { default as Mermaid } from './mermaid.js'; - -export const icons = { - infoIcon, - insertMermaidIcon, - previewModeIcon, - splitModeIcon, - sourceModeIcon -}; diff --git a/_regroup/ckeditor5-mermaid/src/mermaid.js b/_regroup/ckeditor5-mermaid/src/mermaid.js deleted file mode 100644 index 0a8aec3b6..000000000 --- a/_regroup/ckeditor5-mermaid/src/mermaid.js +++ /dev/null @@ -1,27 +0,0 @@ -/** - * @module mermaid/mermaid - */ - -import { Plugin } from 'ckeditor5/src/core.js'; - -import MermaidEditing from './mermaidediting.js'; -import MermaidToolbar from './mermaidtoolbar.js'; -import MermaidUI from './mermaidui.js'; - -import '../theme/mermaid.css'; - -export default class Mermaid extends Plugin { - /** - * @inheritDoc - */ - static get requires() { - return [ MermaidEditing, MermaidToolbar, MermaidUI ]; - } - - /** - * @inheritDoc - */ - static get pluginName() { - return 'Mermaid'; - } -} diff --git a/packages/ckeditor5-mermaid/package.json b/packages/ckeditor5-mermaid/package.json index f2a164636..33582553d 100644 --- a/packages/ckeditor5-mermaid/package.json +++ b/packages/ckeditor5-mermaid/package.json @@ -85,5 +85,9 @@ "hooks": { "pre-commit": "lint-staged" } + }, + "dependencies": { + "@types/lodash-es": "4.17.12", + "lodash-es": "^4.17.21" } } diff --git a/packages/ckeditor5-mermaid/src/augmentation.ts b/packages/ckeditor5-mermaid/src/augmentation.ts index 0a41de8c7..29d4f5304 100644 --- a/packages/ckeditor5-mermaid/src/augmentation.ts +++ b/packages/ckeditor5-mermaid/src/augmentation.ts @@ -1,7 +1,25 @@ import type { Mermaid } from './index.js'; +import MermaidEditing from './mermaidediting.js'; +import MermaidToolbar from './mermaidtoolbar.js'; +import MermaidUI from './mermaidui.js'; declare module 'ckeditor5' { interface PluginsMap { [ Mermaid.pluginName ]: Mermaid; + [ MermaidEditing.pluginName ]: MermaidEditing; + [ MermaidToolbar.pluginName ]: MermaidToolbar; + [ MermaidUI.pluginName]: MermaidUI; } } + +declare global { + interface Mermaid { + init(config: MermaidConfig, element: HTMLElement): void; + } + + interface MermaidConfig { + + } + + var mermaid: Mermaid | null | undefined; +} diff --git a/_regroup/ckeditor5-mermaid/src/commands/insertMermaidCommand.js b/packages/ckeditor5-mermaid/src/commands/insertMermaidCommand.ts similarity index 77% rename from _regroup/ckeditor5-mermaid/src/commands/insertMermaidCommand.js rename to packages/ckeditor5-mermaid/src/commands/insertMermaidCommand.ts index 8fbf52a90..256f0a0b9 100644 --- a/_regroup/ckeditor5-mermaid/src/commands/insertMermaidCommand.js +++ b/packages/ckeditor5-mermaid/src/commands/insertMermaidCommand.ts @@ -1,8 +1,4 @@ -/** - * @module mermaid/insertmermaidcommand - */ - -import { Command } from 'ckeditor5/src/core.js'; +import { Command } from "ckeditor5"; const MOCK_MERMAID_MARKUP = `flowchart TB A --> B @@ -12,14 +8,10 @@ B --> C`; * The insert mermaid command. * * Allows to insert mermaid. - * - * @extends module:core/command~Command */ export default class InsertMermaidCommand extends Command { - /** - * @inheritDoc - */ - refresh() { + + override refresh() { const documentSelection = this.editor.model.document.selection; const selectedElement = documentSelection.getSelectedElement(); @@ -30,10 +22,7 @@ export default class InsertMermaidCommand extends Command { } } - /** - * @inheritDoc - */ - execute() { + override execute() { const editor = this.editor; const model = editor.model; let mermaidItem; diff --git a/_regroup/ckeditor5-mermaid/src/commands/mermaidPreviewCommand.js b/packages/ckeditor5-mermaid/src/commands/mermaidPreviewCommand.ts similarity index 62% rename from _regroup/ckeditor5-mermaid/src/commands/mermaidPreviewCommand.js rename to packages/ckeditor5-mermaid/src/commands/mermaidPreviewCommand.ts index 0fc0b15ec..793692246 100644 --- a/_regroup/ckeditor5-mermaid/src/commands/mermaidPreviewCommand.js +++ b/packages/ckeditor5-mermaid/src/commands/mermaidPreviewCommand.ts @@ -1,29 +1,22 @@ -/** - * @module mermaid/mermaidpreviewcommand - */ - import { Command } from 'ckeditor5/src/core.js'; import { checkIsOn } from '../utils.js'; +import { Element } from 'ckeditor5'; /** * The mermaid preview command. * * Allows to switch to a preview mode. - * - * @extends module:core/command~Command */ export default class MermaidPreviewCommand extends Command { - /** - * @inheritDoc - */ - refresh() { + + override refresh() { const editor = this.editor; const documentSelection = editor.model.document.selection; const selectedElement = documentSelection.getSelectedElement(); const isSelectedElementMermaid = selectedElement && selectedElement.name === 'mermaid'; - if ( isSelectedElementMermaid || documentSelection.getLastPosition().findAncestor( 'mermaid' ) ) { + if ( isSelectedElementMermaid || documentSelection.getLastPosition()?.findAncestor( 'mermaid' ) ) { this.isEnabled = !!selectedElement; } else { this.isEnabled = false; @@ -32,19 +25,18 @@ export default class MermaidPreviewCommand extends Command { this.value = checkIsOn( editor, 'preview' ); } - /** - * @inheritDoc - */ - execute() { + override execute() { const editor = this.editor; const model = editor.model; const documentSelection = this.editor.model.document.selection; - const mermaidItem = documentSelection.getSelectedElement() || documentSelection.getLastPosition().parent; + const mermaidItem = (documentSelection.getSelectedElement() || documentSelection.getLastPosition()?.parent) as Element; - model.change( writer => { - if ( mermaidItem.getAttribute( 'displayMode' ) !== 'preview' ) { - writer.setAttribute( 'displayMode', 'preview', mermaidItem ); - } - } ); + if (mermaidItem) { + model.change( writer => { + if ( mermaidItem.getAttribute( 'displayMode' ) !== 'preview' ) { + writer.setAttribute( 'displayMode', 'preview', mermaidItem ); + } + } ); + } } } diff --git a/_regroup/ckeditor5-mermaid/src/commands/mermaidSourceViewCommand.js b/packages/ckeditor5-mermaid/src/commands/mermaidSourceViewCommand.ts similarity index 79% rename from _regroup/ckeditor5-mermaid/src/commands/mermaidSourceViewCommand.js rename to packages/ckeditor5-mermaid/src/commands/mermaidSourceViewCommand.ts index 043490154..ed1f23dcd 100644 --- a/_regroup/ckeditor5-mermaid/src/commands/mermaidSourceViewCommand.js +++ b/packages/ckeditor5-mermaid/src/commands/mermaidSourceViewCommand.ts @@ -1,10 +1,7 @@ -/** - * @module mermaid/mermaidsourceviewcommand - */ - import { Command } from 'ckeditor5/src/core.js'; import { checkIsOn } from '../utils.js'; +import { Element } from 'ckeditor5'; /** * The mermaid source view command. @@ -14,16 +11,14 @@ import { checkIsOn } from '../utils.js'; * @extends module:core/command~Command */ export default class MermaidSourceViewCommand extends Command { - /** - * @inheritDoc - */ - refresh() { + + override refresh() { const editor = this.editor; const documentSelection = editor.model.document.selection; const selectedElement = documentSelection.getSelectedElement(); const isSelectedElementMermaid = selectedElement && selectedElement.name === 'mermaid'; - if ( isSelectedElementMermaid || documentSelection.getLastPosition().findAncestor( 'mermaid' ) ) { + if ( isSelectedElementMermaid || documentSelection.getLastPosition()?.findAncestor( 'mermaid' ) ) { this.isEnabled = !!selectedElement; } else { this.isEnabled = false; @@ -32,14 +27,11 @@ export default class MermaidSourceViewCommand extends Command { this.value = checkIsOn( editor, 'source' ); } - /** - * @inheritDoc - */ - execute() { + override execute() { const editor = this.editor; const model = editor.model; const documentSelection = this.editor.model.document.selection; - const mermaidItem = documentSelection.getSelectedElement() || documentSelection.getLastPosition().parent; + const mermaidItem = (documentSelection.getSelectedElement() || documentSelection.getLastPosition()?.parent) as Element; model.change( writer => { if ( mermaidItem.getAttribute( 'displayMode' ) !== 'source' ) { diff --git a/_regroup/ckeditor5-mermaid/src/commands/mermaidSplitViewCommand.js b/packages/ckeditor5-mermaid/src/commands/mermaidSplitViewCommand.ts similarity index 79% rename from _regroup/ckeditor5-mermaid/src/commands/mermaidSplitViewCommand.js rename to packages/ckeditor5-mermaid/src/commands/mermaidSplitViewCommand.ts index c5f77dd21..d7579a26a 100644 --- a/_regroup/ckeditor5-mermaid/src/commands/mermaidSplitViewCommand.js +++ b/packages/ckeditor5-mermaid/src/commands/mermaidSplitViewCommand.ts @@ -5,25 +5,22 @@ import { Command } from 'ckeditor5/src/core.js'; import { checkIsOn } from '../utils.js'; +import { Element } from 'ckeditor5'; /** * The mermaid split view command. * * Allows to switch to a split view mode. - * - * @extends module:core/command~Command */ export default class MermaidSplitViewCommand extends Command { - /** - * @inheritDoc - */ - refresh() { + + override refresh() { const editor = this.editor; const documentSelection = editor.model.document.selection; const selectedElement = documentSelection.getSelectedElement(); const isSelectedElementMermaid = selectedElement && selectedElement.name === 'mermaid'; - if ( isSelectedElementMermaid || documentSelection.getLastPosition().findAncestor( 'mermaid' ) ) { + if ( isSelectedElementMermaid || documentSelection.getLastPosition()?.findAncestor( 'mermaid' ) ) { this.isEnabled = !!selectedElement; } else { this.isEnabled = false; @@ -32,14 +29,11 @@ export default class MermaidSplitViewCommand extends Command { this.value = checkIsOn( editor, 'split' ); } - /** - * @inheritDoc - */ - execute() { + override execute() { const editor = this.editor; const model = editor.model; const documentSelection = this.editor.model.document.selection; - const mermaidItem = documentSelection.getSelectedElement() || documentSelection.getLastPosition().parent; + const mermaidItem = (documentSelection.getSelectedElement() || documentSelection.getLastPosition()?.parent) as Element; model.change( writer => { if ( mermaidItem.getAttribute( 'displayMode' ) !== 'split' ) { diff --git a/packages/ckeditor5-mermaid/src/index.ts b/packages/ckeditor5-mermaid/src/index.ts index 34fe7ca87..46c94ca0f 100644 --- a/packages/ckeditor5-mermaid/src/index.ts +++ b/packages/ckeditor5-mermaid/src/index.ts @@ -1,8 +1,16 @@ -import ckeditor from './../theme/icons/ckeditor.svg'; import './augmentation.js'; export { default as Mermaid } from './mermaid.js'; +import infoIcon from './../theme/icons/info.svg'; +import insertMermaidIcon from './../theme/icons/insert.svg'; +import previewModeIcon from './../theme/icons/preview-mode.svg'; +import splitModeIcon from './../theme/icons/split-mode.svg'; +import sourceModeIcon from './../theme/icons/source-mode.svg'; export const icons = { - ckeditor + infoIcon, + insertMermaidIcon, + previewModeIcon, + splitModeIcon, + sourceModeIcon }; diff --git a/packages/ckeditor5-mermaid/src/mermaid.ts b/packages/ckeditor5-mermaid/src/mermaid.ts index b345019b4..fa85b7806 100644 --- a/packages/ckeditor5-mermaid/src/mermaid.ts +++ b/packages/ckeditor5-mermaid/src/mermaid.ts @@ -1,39 +1,17 @@ import { Plugin, ButtonView } from 'ckeditor5'; -import ckeditor5Icon from '../theme/icons/ckeditor.svg'; +import MermaidEditing from './mermaidediting.js'; +import MermaidToolbar from './mermaidtoolbar.js'; +import MermaidUI from './mermaidui.js'; export default class Mermaid extends Plugin { + + static get requires() { + return [ MermaidEditing, MermaidToolbar, MermaidUI ]; + } + public static get pluginName() { return 'Mermaid' as const; } - public init(): void { - const editor = this.editor; - const t = editor.t; - const model = editor.model; - - // Register the "mermaid" button, so it can be displayed in the toolbar. - editor.ui.componentFactory.add( 'mermaid', locale => { - const view = new ButtonView( locale ); - - view.set( { - label: t( 'Mermaid' ), - icon: ckeditor5Icon, - tooltip: true - } ); - - // Insert a text into the editor after clicking the button. - this.listenTo( view, 'execute', () => { - model.change( writer => { - const textNode = writer.createText( 'Hello CKEditor 5!' ); - - model.insertContent( textNode ); - } ); - - editor.editing.view.focus(); - } ); - - return view; - } ); - } } diff --git a/_regroup/ckeditor5-mermaid/src/mermaidediting.js b/packages/ckeditor5-mermaid/src/mermaidediting.ts similarity index 70% rename from _regroup/ckeditor5-mermaid/src/mermaidediting.js rename to packages/ckeditor5-mermaid/src/mermaidediting.ts index 9e8fdd2e2..3ee30107d 100644 --- a/_regroup/ckeditor5-mermaid/src/mermaidediting.js +++ b/packages/ckeditor5-mermaid/src/mermaidediting.ts @@ -11,18 +11,30 @@ import MermaidPreviewCommand from './commands/mermaidPreviewCommand.js'; import MermaidSourceViewCommand from './commands/mermaidSourceViewCommand.js'; import MermaidSplitViewCommand from './commands/mermaidSplitViewCommand.js'; import InsertMermaidCommand from './commands/insertMermaidCommand.js'; +import { DowncastAttributeEvent, DowncastConversionApi, Element, EventInfo, Item, Node, UpcastConversionApi, UpcastConversionData, ViewElement, ViewNode, ViewText, ViewUIElement } from 'ckeditor5'; // Time in milliseconds. const DEBOUNCE_TIME = 300; /* global window */ +interface MermaidConfig { + lazyLoad?: () => Promise | Mermaid; + config: MermaidConfig; +} + +type DowncastConversionData = DowncastAttributeEvent["args"][0]; + export default class MermaidEditing extends Plugin { + + private _config!: MermaidConfig; + private mermaid?: Mermaid; + /** * @inheritDoc */ static get pluginName() { - return 'MermaidEditing'; + return 'MermaidEditing' as const; } /** @@ -31,7 +43,7 @@ export default class MermaidEditing extends Plugin { init() { this._registerCommands(); this._defineConverters(); - this._config = this.editor.config.get("mermaid"); + this._config = this.editor.config.get("mermaid") as MermaidConfig; } /** @@ -83,14 +95,7 @@ export default class MermaidEditing extends Plugin { } ); } - /** - * - * @private - * @param {*} evt - * @param {*} data - * @param {*} conversionApi - */ - _mermaidDataDowncast( evt, data, conversionApi ) { + _mermaidDataDowncast( evt: EventInfo, data: DowncastConversionData, conversionApi: DowncastConversionApi ) { const model = this.editor.model; const { writer, mapper } = conversionApi; @@ -98,31 +103,24 @@ export default class MermaidEditing extends Plugin { return; } - const targetViewPosition = mapper.toViewPosition( model.createPositionBefore( data.item ) ); + const targetViewPosition = mapper.toViewPosition( model.createPositionBefore( data.item as Item ) ); // For downcast we're using only language-mermaid class. We don't set class to `mermaid language-mermaid` as // multiple markdown converters that we have seen are using only `language-mermaid` class and not `mermaid` alone. const code = writer.createContainerElement( 'code', { class: 'language-mermaid' - } ); + } ) as unknown as ViewNode; const pre = writer.createContainerElement( 'pre', { spellcheck: 'false' - } ); - const sourceTextNode = writer.createText( data.item.getAttribute( 'source' ) ); + } ) as unknown as ViewNode; + const sourceTextNode = writer.createText( data.item.getAttribute( 'source' ) as string); - writer.insert( model.createPositionAt( code, 'end' ), sourceTextNode ); - writer.insert( model.createPositionAt( pre, 'end' ), code ); + writer.insert( mapper.toViewPosition(model.createPositionAt( code as unknown as Node, 'end' )), sourceTextNode ); + writer.insert( mapper.toViewPosition(model.createPositionAt( pre as unknown as Node, 'end' )), code ); writer.insert( targetViewPosition, pre ); - mapper.bindElements( data.item, code ); + mapper.bindElements( data.item as Element, code as ViewElement ); } - /** - * - * @private - * @param {*} evt - * @param {*} data - * @param {*} conversionApi - */ - _mermaidDowncast( evt, data, conversionApi ) { + _mermaidDowncast( evt: EventInfo, data: DowncastConversionData, conversionApi: DowncastConversionApi ) { const { writer, mapper, consumable } = conversionApi; const { editor } = this; const { model, t } = editor; @@ -132,7 +130,7 @@ export default class MermaidEditing extends Plugin { return; } - const targetViewPosition = mapper.toViewPosition( model.createPositionBefore( data.item ) ); + const targetViewPosition = mapper.toViewPosition( model.createPositionBefore( data.item as Item ) ); const wrapperAttributes = { class: [ 'ck-mermaid__wrapper' ] @@ -147,26 +145,26 @@ export default class MermaidEditing extends Plugin { const editingContainer = writer.createUIElement( 'textarea', textareaAttributes, createEditingTextarea ); const previewContainer = writer.createUIElement( 'div', { class: [ 'ck-mermaid__preview' ] }, createMermaidPreview ); - writer.insert( writer.createPositionAt( wrapper, 'start' ), previewContainer ); - writer.insert( writer.createPositionAt( wrapper, 'start' ), editingContainer ); + writer.insert( writer.createPositionAt( wrapper, 'before' ), previewContainer ); + writer.insert( writer.createPositionAt( wrapper, 'before' ), editingContainer ); writer.insert( targetViewPosition, wrapper ); - mapper.bindElements( data.item, wrapper ); + mapper.bindElements( data.item as Element, wrapper ); return toWidget( wrapper, writer, { - widgetLabel: t( 'Mermaid widget' ), + label: t( 'Mermaid widget' ), hasSelectionHandle: true } ); - function createEditingTextarea( domDocument ) { - const domElement = this.toDomElement( domDocument ); + function createEditingTextarea(this: ViewUIElement, domDocument: Document ) { + const domElement = this.toDomElement( domDocument ) as HTMLElement as HTMLInputElement; - domElement.value = data.item.getAttribute( 'source' ); + domElement.value = data.item.getAttribute( 'source' ) as string; const debouncedListener = debounce( event => { editor.model.change( writer => { - writer.setAttribute( 'source', event.target.value, data.item ); + writer.setAttribute( 'source', event.target.value, data.item as Node ); } ); }, DEBOUNCE_TIME ); @@ -179,16 +177,16 @@ export default class MermaidEditing extends Plugin { // Move the selection onto the mermaid widget if it's currently not selected. if ( selectedElement !== data.item ) { - model.change( writer => writer.setSelection( data.item, 'on' ) ); + model.change( writer => writer.setSelection( data.item as Node, 'on' ) ); } }, true ); return domElement; } - function createMermaidPreview( domDocument ) { + function createMermaidPreview(this: ViewUIElement, domDocument: Document ) { // Taking the text from the wrapper container element for now - const mermaidSource = data.item.getAttribute( 'source' ); + const mermaidSource = data.item.getAttribute( 'source' ) as string; const domElement = this.toDomElement( domDocument ); domElement.innerHTML = mermaidSource; @@ -202,31 +200,29 @@ export default class MermaidEditing extends Plugin { } } - /** - * - * @param {*} evt - * @param {*} data - * @param {*} conversionApi - * @returns - */ - _sourceAttributeDowncast( evt, data, conversionApi ) { + _sourceAttributeDowncast( evt: EventInfo, data: DowncastConversionData, conversionApi: DowncastConversionApi ) { // @todo: test whether the attribute was consumed. - const newSource = data.attributeNewValue; + const newSource = data.attributeNewValue as string; const domConverter = this.editor.editing.view.domConverter; if ( newSource ) { - const mermaidView = conversionApi.mapper.toViewElement( data.item ); + const mermaidView = conversionApi.mapper.toViewElement( data.item as Element ); + if (!mermaidView) { + return; + } - for ( const child of mermaidView.getChildren() ) { + for ( const _child of mermaidView.getChildren() ) { + const child = _child as ViewElement; if ( child.name === 'textarea' && child.hasClass( 'ck-mermaid__editing-view' ) ) { - const domEditingTextarea = domConverter.viewToDom( child, window.document ); + // Text & HTMLElement & Node & DocumentFragment + const domEditingTextarea = domConverter.viewToDom(child) as HTMLElement as HTMLInputElement; if ( domEditingTextarea.value != newSource ) { domEditingTextarea.value = newSource; } } else if ( child.name === 'div' && child.hasClass( 'ck-mermaid__preview' ) ) { // @todo: we could optimize this and not refresh mermaid if widget is in source mode. - const domPreviewWrapper = domConverter.viewToDom( child, window.document ); + const domPreviewWrapper = domConverter.viewToDom(child); if ( domPreviewWrapper ) { domPreviewWrapper.innerHTML = newSource; @@ -239,15 +235,8 @@ export default class MermaidEditing extends Plugin { } } - /** - * - * @private - * @param {*} evt - * @param {*} data - * @param {*} conversionApi - */ - _mermaidUpcast( evt, data, conversionApi ) { - const viewCodeElement = data.viewItem; + _mermaidUpcast( evt: EventInfo, data: UpcastConversionData, conversionApi: UpcastConversionApi ) { + const viewCodeElement = data.viewItem as ViewElement; const hasPreElementParent = !viewCodeElement.parent || !viewCodeElement.parent.is( 'element', 'pre' ); const hasCodeAncestors = data.modelCursor.findAncestor( 'code' ); const { consumable, writer } = conversionApi; @@ -261,7 +250,7 @@ export default class MermaidEditing extends Plugin { } const mermaidSource = Array.from( viewCodeElement.getChildren() ) .filter( item => item.is( '$text' ) ) - .map( item => item.data ) + .map( item => (item as ViewText).data ) .join( '' ); const mermaidElement = writer.createElement( 'mermaid', { @@ -282,14 +271,12 @@ export default class MermaidEditing extends Plugin { /** * Renders Mermaid in a given `domElement`. Expect this domElement to have mermaid * source set as text content. - * - * @param {HTMLElement} domElement */ - async _renderMermaid( domElement ) { + async _renderMermaid( domElement: HTMLElement ) { if (!window.mermaid && typeof this._config?.lazyLoad === "function") { this.mermaid = await this._config.lazyLoad(); } - this.mermaid.init( this._config.config, domElement ); + this.mermaid?.init( this._config.config, domElement ); } } diff --git a/_regroup/ckeditor5-mermaid/src/mermaidtoolbar.js b/packages/ckeditor5-mermaid/src/mermaidtoolbar.ts similarity index 72% rename from _regroup/ckeditor5-mermaid/src/mermaidtoolbar.js rename to packages/ckeditor5-mermaid/src/mermaidtoolbar.ts index dd7940743..514005966 100644 --- a/_regroup/ckeditor5-mermaid/src/mermaidtoolbar.js +++ b/packages/ckeditor5-mermaid/src/mermaidtoolbar.ts @@ -2,27 +2,19 @@ * @module mermaid/mermaidtoolbar */ -import { Plugin } from 'ckeditor5/src/core.js'; -import { WidgetToolbarRepository } from 'ckeditor5/src/widget.js'; +import { Plugin, ViewDocumentSelection, ViewElement, WidgetToolbarRepository } from "ckeditor5"; + export default class MermaidToolbar extends Plugin { - /** - * @inheritDoc - */ + static get requires() { return [ WidgetToolbarRepository ]; } - /** - * @inheritDoc - */ static get pluginName() { - return 'MermaidToolbar'; + return 'MermaidToolbar' as const; } - /** - * @inheritDoc - */ afterInit() { const editor = this.editor; const t = editor.t; @@ -40,8 +32,8 @@ export default class MermaidToolbar extends Plugin { } } -function getSelectedElement( selection ) { - const viewElement = selection.getSelectedElement(); +function getSelectedElement( selection: ViewDocumentSelection ) { + const viewElement = selection.getSelectedElement() as unknown as ViewElement; if ( viewElement && viewElement.hasClass( 'ck-mermaid__wrapper' ) ) { return viewElement; diff --git a/_regroup/ckeditor5-mermaid/src/mermaidui.js b/packages/ckeditor5-mermaid/src/mermaidui.ts similarity index 78% rename from _regroup/ckeditor5-mermaid/src/mermaidui.js rename to packages/ckeditor5-mermaid/src/mermaidui.ts index 419e46f44..e7109c0c0 100644 --- a/_regroup/ckeditor5-mermaid/src/mermaidui.js +++ b/packages/ckeditor5-mermaid/src/mermaidui.ts @@ -2,14 +2,13 @@ * @module mermaid/mermaidui */ -import { Plugin } from 'ckeditor5/src/core.js'; -import { ButtonView } from 'ckeditor5/src/ui.js'; - import insertMermaidIcon from '../theme/icons/insert.svg'; import previewModeIcon from '../theme/icons/preview-mode.svg'; import splitModeIcon from '../theme/icons/split-mode.svg'; import sourceModeIcon from '../theme/icons/source-mode.svg'; import infoIcon from '../theme/icons/info.svg'; +import { ButtonView, Editor, Element, Locale, Observable, Plugin } from 'ckeditor5'; +import InsertMermaidCommand from './commands/insertMermaidCommand.js'; /* global window, document */ @@ -18,7 +17,7 @@ export default class MermaidUI extends Plugin { * @inheritDoc */ static get pluginName() { - return 'MermaidUI'; + return 'MermaidUI' as const; } /** @@ -53,9 +52,12 @@ export default class MermaidUI extends Plugin { const t = editor.t; const view = editor.editing.view; - editor.ui.componentFactory.add( 'mermaid', locale => { + editor.ui.componentFactory.add( 'mermaid', (locale: Locale) => { const buttonView = new ButtonView( locale ); - const command = editor.commands.get( 'insertMermaidCommand' ); + const command = editor.commands.get( 'insertMermaidCommand' ) as InsertMermaidCommand; + if (!command) { + throw new Error("Missing command."); + } buttonView.set( { label: t( 'Insert Mermaid diagram' ), @@ -63,21 +65,21 @@ export default class MermaidUI extends Plugin { tooltip: true } ); - buttonView.bind( 'isOn', 'isEnabled' ).to( command, 'value', 'isEnabled' ); + buttonView.bind( 'isOn', 'isEnabled' ).to( command as (Observable & { value: boolean; } & { isEnabled: boolean; }), 'value', 'isEnabled' ); // Execute the command when the button is clicked. command.listenTo( buttonView, 'execute', () => { - const mermaidItem = editor.execute( 'insertMermaidCommand' ); + const mermaidItem = editor.execute( 'insertMermaidCommand' ) as Element; const mermaidItemViewElement = editor.editing.mapper.toViewElement( mermaidItem ); view.scrollToTheSelection(); view.focus(); if ( mermaidItemViewElement ) { - const mermaidItemDomElement = view.domConverter.viewToDom( mermaidItemViewElement, document ); + const mermaidItemDomElement = view.domConverter.viewToDom( mermaidItemViewElement ); if ( mermaidItemDomElement ) { - mermaidItemDomElement.querySelector( '.ck-mermaid__editing-view' ).focus(); + (mermaidItemDomElement.querySelector( '.ck-mermaid__editing-view' ) as HTMLElement)?.focus(); } } } ); @@ -117,17 +119,16 @@ export default class MermaidUI extends Plugin { * Adds the mermaid balloon toolbar button. * * @private - * @param {module:core/editor/editor~Editor} editor - * @param {String} name Name of the button. - * @param {String} label Label for the button. - * @param {String} icon The button icon. */ - _createToolbarButton( editor, name, label, icon ) { + _createToolbarButton( editor: Editor, name: string, label: string, icon: string ) { const t = editor.t; editor.ui.componentFactory.add( name, locale => { const buttonView = new ButtonView( locale ); const command = editor.commands.get( `${ name }Command` ); + if (!command) { + throw new Error("Missing command."); + } buttonView.set( { label: t( label ), @@ -135,7 +136,7 @@ export default class MermaidUI extends Plugin { tooltip: true } ); - buttonView.bind( 'isOn', 'isEnabled' ).to( command, 'value', 'isEnabled' ); + buttonView.bind( 'isOn', 'isEnabled' ).to( command as (Observable & { value: boolean; } & { isEnabled: boolean; }), 'value', 'isEnabled' ); // Execute the command when the button is clicked. command.listenTo( buttonView, 'execute', () => { diff --git a/_regroup/ckeditor5-mermaid/src/utils.js b/packages/ckeditor5-mermaid/src/utils.ts similarity index 69% rename from _regroup/ckeditor5-mermaid/src/utils.js rename to packages/ckeditor5-mermaid/src/utils.ts index 98ba6f879..184d0bdd0 100644 --- a/_regroup/ckeditor5-mermaid/src/utils.js +++ b/packages/ckeditor5-mermaid/src/utils.ts @@ -3,21 +3,17 @@ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ -/** - * @module mermaid/utils - */ +import { Editor } from "ckeditor5"; /** * Helper function for setting the `isOn` state of buttons. * * @private - * @param {module:core/editor/editor~Editor} editor - * @param {String} commandName Short name of the command. - * @returns {Boolean} + * @param commandName Short name of the command. */ -export function checkIsOn( editor, commandName ) { +export function checkIsOn( editor: Editor, commandName: string ) { const selection = editor.model.document.selection; - const mermaidItem = selection.getSelectedElement() || selection.getLastPosition().parent; + const mermaidItem = selection.getSelectedElement() || selection.getLastPosition()?.parent; if ( mermaidItem && mermaidItem.is( 'element', 'mermaid' ) && mermaidItem.getAttribute( 'displayMode' ) === commandName ) { return true; diff --git a/packages/ckeditor5-mermaid/theme/icons/ckeditor.svg b/packages/ckeditor5-mermaid/theme/icons/ckeditor.svg deleted file mode 100644 index 25436f4b8..000000000 --- a/packages/ckeditor5-mermaid/theme/icons/ckeditor.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/_regroup/ckeditor5-mermaid/theme/icons/info.svg b/packages/ckeditor5-mermaid/theme/icons/info.svg similarity index 100% rename from _regroup/ckeditor5-mermaid/theme/icons/info.svg rename to packages/ckeditor5-mermaid/theme/icons/info.svg diff --git a/_regroup/ckeditor5-mermaid/theme/icons/insert.svg b/packages/ckeditor5-mermaid/theme/icons/insert.svg similarity index 100% rename from _regroup/ckeditor5-mermaid/theme/icons/insert.svg rename to packages/ckeditor5-mermaid/theme/icons/insert.svg diff --git a/_regroup/ckeditor5-mermaid/theme/icons/preview-mode.svg b/packages/ckeditor5-mermaid/theme/icons/preview-mode.svg similarity index 100% rename from _regroup/ckeditor5-mermaid/theme/icons/preview-mode.svg rename to packages/ckeditor5-mermaid/theme/icons/preview-mode.svg diff --git a/_regroup/ckeditor5-mermaid/theme/icons/source-mode.svg b/packages/ckeditor5-mermaid/theme/icons/source-mode.svg similarity index 100% rename from _regroup/ckeditor5-mermaid/theme/icons/source-mode.svg rename to packages/ckeditor5-mermaid/theme/icons/source-mode.svg diff --git a/_regroup/ckeditor5-mermaid/theme/icons/split-mode.svg b/packages/ckeditor5-mermaid/theme/icons/split-mode.svg similarity index 100% rename from _regroup/ckeditor5-mermaid/theme/icons/split-mode.svg rename to packages/ckeditor5-mermaid/theme/icons/split-mode.svg diff --git a/_regroup/ckeditor5-mermaid/theme/mermaid.css b/packages/ckeditor5-mermaid/theme/mermaid.css similarity index 100% rename from _regroup/ckeditor5-mermaid/theme/mermaid.css rename to packages/ckeditor5-mermaid/theme/mermaid.css diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e53dbea28..9e5500b12 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -882,6 +882,13 @@ importers: version: 9.12.7(bufferutil@4.0.9)(utf-8-validate@6.0.5) packages/ckeditor5-mermaid: + dependencies: + '@types/lodash-es': + specifier: 4.17.12 + version: 4.17.12 + lodash-es: + specifier: ^4.17.21 + version: 4.17.21 devDependencies: '@ckeditor/ckeditor5-dev-build-tools': specifier: 43.0.1 @@ -4302,6 +4309,12 @@ packages: '@types/leaflet@1.9.17': resolution: {integrity: sha512-IJ4K6t7I3Fh5qXbQ1uwL3CFVbCi6haW9+53oLWgdKlLP7EaS21byWFJxxqOx9y8I0AP0actXSJLVMbyvxhkUTA==} + '@types/lodash-es@4.17.12': + resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==} + + '@types/lodash@4.17.16': + resolution: {integrity: sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==} + '@types/mdast@3.0.15': resolution: {integrity: sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==} @@ -18246,6 +18259,12 @@ snapshots: dependencies: '@types/geojson': 7946.0.16 + '@types/lodash-es@4.17.12': + dependencies: + '@types/lodash': 4.17.16 + + '@types/lodash@4.17.16': {} + '@types/mdast@3.0.15': dependencies: '@types/unist': 2.0.11