From d167357db9a4647e10e691419f0ebd6101c423cd Mon Sep 17 00:00:00 2001 From: jinwoo-lee Date: Thu, 4 Aug 2022 13:57:45 +0900 Subject: [PATCH 1/2] feat: add plugin interface (editorCore instance, keymap) --- apps/editor/src/editorCore.ts | 11 +++++----- apps/editor/src/helper/plugin.ts | 36 +++++++++++++++++++++++--------- apps/editor/types/editor.d.ts | 19 +++++++++++++++++ 3 files changed, 51 insertions(+), 15 deletions(-) diff --git a/apps/editor/src/editorCore.ts b/apps/editor/src/editorCore.ts index 2b025790fa..62b7279d97 100644 --- a/apps/editor/src/editorCore.ts +++ b/apps/editor/src/editorCore.ts @@ -183,11 +183,12 @@ class ToastUIEditorCore { const linkAttributes = sanitizeLinkAttribute(this.options.linkAttributes); - this.pluginInfo = getPluginInfo( - this.options.plugins, - this.eventEmitter, - this.options.usageStatistics - ); + this.pluginInfo = getPluginInfo({ + plugins: this.options.plugins, + eventEmitter: this.eventEmitter, + usageStatistics: this.options.usageStatistics, + editorInstance: this, + }); const { toHTMLRenderers, toMarkdownRenderers, diff --git a/apps/editor/src/helper/plugin.ts b/apps/editor/src/helper/plugin.ts index 11e5f6b38e..14d9bd6751 100644 --- a/apps/editor/src/helper/plugin.ts +++ b/apps/editor/src/helper/plugin.ts @@ -2,21 +2,34 @@ import isArray from 'tui-code-snippet/type/isArray'; import { Plugin, PluginKey, Selection, TextSelection } from 'prosemirror-state'; import { inputRules, InputRule, undoInputRule } from 'prosemirror-inputrules'; import { Decoration, DecorationSet } from 'prosemirror-view'; +import { keymap } from 'prosemirror-keymap'; import { Fragment } from 'prosemirror-model'; import i18n from '@/i18n/i18n'; import { deepMergedCopy } from '@/utils/common'; -import { EditorPlugin } from '@t/editor'; -import { Emitter } from '@t/event'; +import { EditorPluginInfo, EditorPluginsInfo } from '@t/editor'; import { PluginInfoResult } from '@t/plugin'; import { mixinTableOffsetMapPrototype } from '@/wysiwyg/helper/tableOffsetMap'; -function execPlugin(plugin: EditorPlugin, eventEmitter: Emitter, usageStatistics: boolean) { +function execPlugin(pluginInfo: EditorPluginInfo) { + const { plugin, eventEmitter, usageStatistics, editorInstance } = pluginInfo; + const pmState = { Plugin, PluginKey, Selection, TextSelection }; const pmView = { Decoration, DecorationSet }; const pmModel = { Fragment }; const pmRules = { InputRule, inputRules, undoInputRule }; - const context = { eventEmitter, usageStatistics, pmState, pmView, pmModel, pmRules, i18n }; + const pmKeymap = { keymap }; + const context = { + eventEmitter, + usageStatistics, + editorInstance, + pmState, + pmView, + pmModel, + pmRules, + pmKeymap, + i18n, + }; if (isArray(plugin)) { const [pluginFn, options = {}] = plugin; @@ -27,16 +40,19 @@ function execPlugin(plugin: EditorPlugin, eventEmitter: Emitter, usageStatistics return plugin(context); } -export function getPluginInfo( - plugins: EditorPlugin[], - eventEmitter: Emitter, - usageStatistics: boolean -) { +export function getPluginInfo(pluginsInfo: EditorPluginsInfo) { + const { plugins, eventEmitter, usageStatistics, editorInstance } = pluginsInfo; + eventEmitter.listen('mixinTableOffsetMapPrototype', mixinTableOffsetMapPrototype); return (plugins ?? []).reduce( (acc, plugin) => { - const pluginInfoResult = execPlugin(plugin, eventEmitter, usageStatistics); + const pluginInfoResult = execPlugin({ + plugin, + eventEmitter, + usageStatistics, + editorInstance, + }); if (!pluginInfoResult) { throw new Error('The return value of the executed plugin is empty.'); diff --git a/apps/editor/types/editor.d.ts b/apps/editor/types/editor.d.ts index 2c69bf3317..6ea051bb30 100644 --- a/apps/editor/types/editor.d.ts +++ b/apps/editor/types/editor.d.ts @@ -2,6 +2,8 @@ import { Schema, NodeSpec, MarkSpec, Fragment } from 'prosemirror-model'; import { EditorView, Decoration, DecorationSet } from 'prosemirror-view'; import { EditorState, Plugin, PluginKey, Selection, TextSelection } from 'prosemirror-state'; import { undoInputRule, InputRule, inputRules } from 'prosemirror-inputrules'; +import { keymap } from 'prosemirror-keymap'; +import { Editor } from '@t/index'; import { HTMLConvertor, @@ -122,6 +124,7 @@ export interface PluginContext { eventEmitter: Emitter; usageStatistics?: boolean; i18n: I18n; + editorInstance: Editor; pmState: { Plugin: typeof Plugin; PluginKey: typeof PluginKey; @@ -135,10 +138,26 @@ export interface PluginContext { InputRule: typeof InputRule; undoInputRule: typeof undoInputRule; }; + pmKeymap: { + keymap: typeof keymap; + }; } export type PluginFn = (context: PluginContext, options?: any) => PluginInfo | null; export type EditorPlugin = PluginFn | [PluginFn, any]; +type ContextInfo = { + eventEmitter: Emitter; + usageStatistics: boolean; + editorInstance: ToastUIEditorCore; +}; + +export type EditorPluginInfo = ContextInfo & { + plugin: EditorPlugin; +}; + +export type EditorPluginsInfo = ContextInfo & { + plugins: EditorPlugin[]; +}; export interface EditorOptions { el: HTMLElement; From 4ec0968d2621a14e94d60e9be8cf5b37d042c188 Mon Sep 17 00:00:00 2001 From: jinwoo-lee Date: Fri, 5 Aug 2022 13:57:54 +0900 Subject: [PATCH 2/2] fix: type error (change type editorInstance to instance to handle viewer) --- apps/editor/src/editorCore.ts | 2 +- apps/editor/src/helper/plugin.ts | 8 ++++---- apps/editor/src/viewer.ts | 7 ++++++- apps/editor/types/editor.d.ts | 4 ++-- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/apps/editor/src/editorCore.ts b/apps/editor/src/editorCore.ts index 62b7279d97..cb2c7b9d50 100644 --- a/apps/editor/src/editorCore.ts +++ b/apps/editor/src/editorCore.ts @@ -187,7 +187,7 @@ class ToastUIEditorCore { plugins: this.options.plugins, eventEmitter: this.eventEmitter, usageStatistics: this.options.usageStatistics, - editorInstance: this, + instance: this, }); const { toHTMLRenderers, diff --git a/apps/editor/src/helper/plugin.ts b/apps/editor/src/helper/plugin.ts index 14d9bd6751..6c68287bc3 100644 --- a/apps/editor/src/helper/plugin.ts +++ b/apps/editor/src/helper/plugin.ts @@ -12,7 +12,7 @@ import { PluginInfoResult } from '@t/plugin'; import { mixinTableOffsetMapPrototype } from '@/wysiwyg/helper/tableOffsetMap'; function execPlugin(pluginInfo: EditorPluginInfo) { - const { plugin, eventEmitter, usageStatistics, editorInstance } = pluginInfo; + const { plugin, eventEmitter, usageStatistics, instance } = pluginInfo; const pmState = { Plugin, PluginKey, Selection, TextSelection }; const pmView = { Decoration, DecorationSet }; @@ -22,7 +22,7 @@ function execPlugin(pluginInfo: EditorPluginInfo) { const context = { eventEmitter, usageStatistics, - editorInstance, + instance, pmState, pmView, pmModel, @@ -41,7 +41,7 @@ function execPlugin(pluginInfo: EditorPluginInfo) { } export function getPluginInfo(pluginsInfo: EditorPluginsInfo) { - const { plugins, eventEmitter, usageStatistics, editorInstance } = pluginsInfo; + const { plugins, eventEmitter, usageStatistics, instance } = pluginsInfo; eventEmitter.listen('mixinTableOffsetMapPrototype', mixinTableOffsetMapPrototype); @@ -51,7 +51,7 @@ export function getPluginInfo(pluginsInfo: EditorPluginsInfo) { plugin, eventEmitter, usageStatistics, - editorInstance, + instance, }); if (!pluginInfoResult) { diff --git a/apps/editor/src/viewer.ts b/apps/editor/src/viewer.ts index c00f1d129a..9901bb1e59 100644 --- a/apps/editor/src/viewer.ts +++ b/apps/editor/src/viewer.ts @@ -73,7 +73,12 @@ class ToastUIEditorViewer { const linkAttributes = sanitizeLinkAttribute(this.options.linkAttributes); const { toHTMLRenderers, markdownParsers } = - getPluginInfo(this.options.plugins, this.eventEmitter, this.options.usageStatistics) || {}; + getPluginInfo({ + plugins: this.options.plugins, + eventEmitter: this.eventEmitter, + usageStatistics: this.options.usageStatistics, + instance: this, + }) || {}; const { customHTMLRenderer, extendedAutolinks, diff --git a/apps/editor/types/editor.d.ts b/apps/editor/types/editor.d.ts index 6ea051bb30..9c14b98574 100644 --- a/apps/editor/types/editor.d.ts +++ b/apps/editor/types/editor.d.ts @@ -124,7 +124,7 @@ export interface PluginContext { eventEmitter: Emitter; usageStatistics?: boolean; i18n: I18n; - editorInstance: Editor; + instance: Editor | Viewer; pmState: { Plugin: typeof Plugin; PluginKey: typeof PluginKey; @@ -148,7 +148,7 @@ export type EditorPlugin = PluginFn | [PluginFn, any]; type ContextInfo = { eventEmitter: Emitter; usageStatistics: boolean; - editorInstance: ToastUIEditorCore; + instance: Editor | Viewer; }; export type EditorPluginInfo = ContextInfo & {