@shenjipo/mention-editor 2.6.0 → 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -1
package/dist/index.d.mts
CHANGED
|
@@ -71,6 +71,11 @@ declare class MentionDeletePlugin {
|
|
|
71
71
|
constructor(editor: MEditor, onMentionDelete?: (item: MentionItem) => void);
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
declare class ShiftEnterPlugin {
|
|
75
|
+
readonly plugin: Plugin;
|
|
76
|
+
constructor(editor: MEditor, onEnter?: () => void);
|
|
77
|
+
}
|
|
78
|
+
|
|
74
79
|
interface MentionEditorOptions {
|
|
75
80
|
element: HTMLElement;
|
|
76
81
|
onChange: (text: string) => void;
|
|
@@ -78,11 +83,14 @@ interface MentionEditorOptions {
|
|
|
78
83
|
onFileInput?: (file: File) => void;
|
|
79
84
|
content?: string;
|
|
80
85
|
onMentionDelete?: (item: MentionItem) => void;
|
|
86
|
+
onEnter?: () => void;
|
|
87
|
+
lineBreak?: 'shift-enter' | 'enter';
|
|
81
88
|
}
|
|
82
89
|
declare class MEditor {
|
|
83
90
|
_tiptapEditor: Editor;
|
|
84
91
|
readonly suggestionMenus: SuggestionMenuProseMirrorPlugin;
|
|
85
92
|
readonly mentionDeletePlugin: MentionDeletePlugin;
|
|
93
|
+
readonly shiftEnterPlugin: ShiftEnterPlugin;
|
|
86
94
|
constructor(options: MentionEditorOptions);
|
|
87
95
|
dispatch(tr: Transaction): void;
|
|
88
96
|
inserMentionBlock(item: MentionItem): void;
|
package/dist/index.d.ts
CHANGED
|
@@ -71,6 +71,11 @@ declare class MentionDeletePlugin {
|
|
|
71
71
|
constructor(editor: MEditor, onMentionDelete?: (item: MentionItem) => void);
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
declare class ShiftEnterPlugin {
|
|
75
|
+
readonly plugin: Plugin;
|
|
76
|
+
constructor(editor: MEditor, onEnter?: () => void);
|
|
77
|
+
}
|
|
78
|
+
|
|
74
79
|
interface MentionEditorOptions {
|
|
75
80
|
element: HTMLElement;
|
|
76
81
|
onChange: (text: string) => void;
|
|
@@ -78,11 +83,14 @@ interface MentionEditorOptions {
|
|
|
78
83
|
onFileInput?: (file: File) => void;
|
|
79
84
|
content?: string;
|
|
80
85
|
onMentionDelete?: (item: MentionItem) => void;
|
|
86
|
+
onEnter?: () => void;
|
|
87
|
+
lineBreak?: 'shift-enter' | 'enter';
|
|
81
88
|
}
|
|
82
89
|
declare class MEditor {
|
|
83
90
|
_tiptapEditor: Editor;
|
|
84
91
|
readonly suggestionMenus: SuggestionMenuProseMirrorPlugin;
|
|
85
92
|
readonly mentionDeletePlugin: MentionDeletePlugin;
|
|
93
|
+
readonly shiftEnterPlugin: ShiftEnterPlugin;
|
|
86
94
|
constructor(options: MentionEditorOptions);
|
|
87
95
|
dispatch(tr: Transaction): void;
|
|
88
96
|
inserMentionBlock(item: MentionItem): void;
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var
|
|
1
|
+
var U=Object.create;var h=Object.defineProperty;var A=Object.getOwnPropertyDescriptor;var H=Object.getOwnPropertyNames;var V=Object.getPrototypeOf,$=Object.prototype.hasOwnProperty;var z=(r,t,e)=>t in r?h(r,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):r[t]=e;var j=(r,t)=>{for(var e in t)h(r,e,{get:t[e],enumerable:!0})},k=(r,t,e,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of H(t))!$.call(r,n)&&n!==e&&h(r,n,{get:()=>t[n],enumerable:!(i=A(t,n))||i.enumerable});return r};var c=(r,t,e)=>(e=r!=null?U(V(r)):{},k(t||!r||!r.__esModule?h(e,"default",{value:r,enumerable:!0}):e,r)),G=r=>k(h({},"__esModule",{value:!0}),r);var s=(r,t,e)=>z(r,typeof t!="symbol"?t+"":t,e);var X={};j(X,{MEditor:()=>f,default:()=>J});module.exports=G(X);var x=require("@tiptap/core");var w=c(require("@tiptap/extension-document")),I=c(require("@tiptap/extension-paragraph")),v=c(require("@tiptap/extension-text")),_=c(require("@tiptap/extension-hard-break")),N=[w.default,I.default,v.default,_.default];var Q=c(require("@tiptap/extension-history")),R=c(require("@tiptap/extension-placeholder"));var F=require("@tiptap/core"),q=require("prosemirror-state"),B=F.Extension.create({name:"imageInput",addOptions(){return{onFileInput:void 0}},addProseMirrorPlugins(){let r=async t=>{var e,i;(i=(e=this.options).onFileInput)==null||i.call(e,t)};return[new q.Plugin({props:{handlePaste:(t,e)=>{var n;let i=(n=e.clipboardData)==null?void 0:n.items;if(!i)return!1;for(let o of i){if(o.kind!=="file")continue;let l=o.getAsFile();if(l)return r(l),!0}return!1},handleDrop:(t,e)=>{var n;let i=(n=e.dataTransfer)==null?void 0:n.files;return!i||i.length===0?!1:(r(i[0]),!0)}}})]}});var D=require("@tiptap/core"),E=require("prosemirror-state"),p=require("prosemirror-view");var m=class{constructor(){s(this,"callbacks",{})}on(t,e){return this.callbacks[t]||(this.callbacks[t]=[]),this.callbacks[t].push(e),()=>this.off(t,e)}emit(t,...e){let i=this.callbacks[t];i&&i.forEach(n=>n.apply(this,e))}off(t,e){let i=this.callbacks[t];i&&(e?this.callbacks[t]=i.filter(n=>n!==e):delete this.callbacks[t])}removeAllListeners(){this.callbacks={}}};var g=new E.PluginKey("SuggestionMenuPlugin"),W=(0,D.findParentNode)(r=>r.type.name==="blockContainer"),C=class{constructor(t,e){this.editor=t;s(this,"pluginState");s(this,"state");s(this,"emitUpdate");s(this,"rootEl");s(this,"closeMenu",()=>{this.editor.dispatch(this.editor._tiptapEditor.view.state.tr.setMeta(g,null))});s(this,"clearQuery",()=>{this.pluginState!==void 0&&this.editor._tiptapEditor.chain().focus().deleteRange({from:this.pluginState.queryStartPos-(this.pluginState.deleteTriggerCharacter?this.pluginState.triggerCharacter.length:0),to:this.editor._tiptapEditor.state.selection.from}).run()});s(this,"insertMention",t=>{this.editor._tiptapEditor.chain().focus().insertContent({type:"mention",attrs:t}).insertContent(" ").run()});this.pluginState=void 0,this.emitUpdate=i=>{var n;if(!this.state)throw new Error("Attempting to update uninitialized suggestions menu");e(i,{...this.state,ignoreQueryLength:(n=this.pluginState)==null?void 0:n.ignoreQueryLength})},setTimeout(()=>{this.rootEl=this.editor._tiptapEditor.view.root})}update(t,e){var d;let i=g.getState(e),n=g.getState(t.state),o=i===void 0&&n!==void 0,l=i!==void 0&&n===void 0;if(!o&&!(i!==void 0&&n!==void 0)&&!l)return;if(this.pluginState=l?i:n,l||!this.editor.isEditable){this.state.show=!1,this.emitUpdate(this.pluginState.triggerCharacter);return}let a=(d=this.rootEl)==null?void 0:d.querySelector(`[data-decoration-id="${this.pluginState.decorationId}"]`);this.editor.isEditable&&a&&(this.state={show:!0,referencePos:a.getBoundingClientRect(),query:this.pluginState.query},this.emitUpdate(this.pluginState.triggerCharacter))}destroy(){}getReplaceRange(){if(!this.pluginState)return null;let t=this.pluginState.queryStartPos-(this.pluginState.deleteTriggerCharacter?this.pluginState.triggerCharacter.length:0),e=this.editor._tiptapEditor.state.selection.from;return{from:t,to:e}}},y=class extends m{constructor(e){super();s(this,"view");s(this,"plugin");s(this,"triggerCharacters",[]);s(this,"addTriggerCharacter",e=>{this.triggerCharacters.push(e)});s(this,"removeTriggerCharacter",e=>{this.triggerCharacters=this.triggerCharacters.filter(i=>i!==e)});s(this,"closeMenu",()=>this.view.closeMenu());s(this,"clearQuery",()=>this.view.clearQuery());s(this,"insertMention",e=>this.view.insertMention(e));let i=this.triggerCharacters;this.plugin=new E.Plugin({key:g,view:()=>(this.view=new C(e,(n,o)=>{this.emit(`update ${n}`,o)}),this.view),state:{init(){},apply(n,o,l,u){var T;let a=n.getMeta(g);if(typeof a=="object"&&a!==null&&o===void 0)return{triggerCharacter:a.triggerCharacter,deleteTriggerCharacter:a.deleteTriggerCharacter!==!1,queryStartPos:((T=n.selection)==null?void 0:T.from)||u.selection.from,query:"",decorationId:`id_${Math.floor(Math.random()*4294967295)}`,ignoreQueryLength:a==null?void 0:a.ignoreQueryLength};if(o===void 0)return o;if(u.selection.from!==u.selection.to||a===null||n.getMeta("focus")||n.getMeta("blur")||n.getMeta("pointer")||o.triggerCharacter!==void 0&&u.selection.from<o.queryStartPos)return;let d={...o};return d.query=u.doc.textBetween(o.queryStartPos,u.selection.from),d}},props:{handleTextInput(n,o,l,u){let a=this.getState(n.state);return i.includes(u)&&a===void 0?(n.dispatch(n.state.tr.insertText(u).scrollIntoView().setMeta(g,{triggerCharacter:u})),!0):!1},decorations(n){let o=this.getState(n);if(o===void 0)return null;if(!o.deleteTriggerCharacter){let l=W(n.selection);if(l)return p.DecorationSet.create(n.doc,[p.Decoration.node(l.pos,l.pos+l.node.nodeSize,{nodeName:"span",class:"bn-suggestion-decorator","data-decoration-id":o.decorationId})])}return p.DecorationSet.create(n.doc,[p.Decoration.inline(o.queryStartPos-o.triggerCharacter.length,o.queryStartPos,{nodeName:"span",class:"bn-suggestion-decorator","data-decoration-id":o.decorationId})])}}})}onUpdate(e,i){return this.triggerCharacters.includes(e)||this.addTriggerCharacter(e),this.on(`update ${e}`,i)}get shown(){var e,i;return((i=(e=this.view)==null?void 0:e.state)==null?void 0:i.show)||!1}};var K=require("@tiptap/core"),L=K.Node.create({name:"mention",inline:!0,group:"inline",atom:!0,selectable:!1,addAttributes(){return{id:{default:null},label:{default:null}}},parseHTML(){return[{tag:'span[data-type="mention"]'}]},renderHTML({node:r}){return["span",{class:"mention","data-type":"mention","data-id":r.attrs.id,"data-label":r.attrs.label,contenteditable:"false"},r.attrs.label]},renderText({node:r}){return""}});function O(r,t){r._tiptapEditor.chain().insertContent({type:"mention",attrs:{id:t.id,label:t.label}}).run()}var S=require("prosemirror-state");var b=class{constructor(t,e){s(this,"plugin");this.plugin=new S.Plugin({key:new S.PluginKey("mention-delete"),appendTransaction(i,n,o){if(!i.some(a=>a.docChanged))return null;let l=new Map,u=new Set;n.doc.descendants(a=>{a.type.name==="mention"&&a.attrs.id&&l.set(a.attrs.id,a.attrs)}),o.doc.descendants(a=>{a.type.name==="mention"&&a.attrs.id&&u.add(a.attrs.id)});for(let[a,d]of l.entries())u.has(a)||e==null||e({id:d.id,label:d.label})}})}};var P=require("prosemirror-state");var M=class{constructor(t,e){s(this,"plugin");this.plugin=new P.Plugin({key:new P.PluginKey("shift-enter"),props:{handleKeyDown(i,n){if(n.key!=="Enter")return!1;if(n.shiftKey){n.preventDefault();let{state:o,dispatch:l}=i,{hard_break:u}=o.schema.nodes;return u?(l(o.tr.replaceSelectionWith(u.create()).scrollIntoView()),!0):!1}return t.suggestionMenus.shown?!1:e?(e(),!0):!1}}})}};var f=class{constructor(t){s(this,"_tiptapEditor");s(this,"suggestionMenus");s(this,"mentionDeletePlugin");s(this,"shiftEnterPlugin");this.suggestionMenus=new y(this),this.mentionDeletePlugin=new b(this,t.onMentionDelete),t.lineBreak==="shift-enter"&&(this.shiftEnterPlugin=new M(this,t.onEnter));let e=x.Extension.create({name:"MEditorUIExtension",addProseMirrorPlugins:()=>{let i=[this.suggestionMenus.plugin,this.mentionDeletePlugin.plugin];return this.shiftEnterPlugin&&i.unshift(this.shiftEnterPlugin.plugin),i}});this._tiptapEditor=new x.Editor({element:t.element,content:t.content||"",extensions:[...N,Q.default.configure({depth:100,newGroupDelay:500}),L,R.default.configure({placeholder:t.placeholder||"\u8BF7\u8F93\u5165...",emptyEditorClass:"is-editor-empty"}),B.configure({onFileInput:t.onFileInput}),e],onUpdate:({editor:i})=>{t.onChange(i.getText())}})}dispatch(t){this._tiptapEditor.view.dispatch(t)}inserMentionBlock(t){O(this,t)}get isEditable(){return this._tiptapEditor.isEditable===void 0?!0:this._tiptapEditor.isEditable}get domElement(){return this._tiptapEditor.view.dom}clear(){this._tiptapEditor.commands.clearContent(!0),this._tiptapEditor.commands.focus()}getAllMentionBlocks(){let t=[];return this._tiptapEditor.state.doc.descendants((i,n)=>{var o,l;i.type.name==="mention"&&t.push({id:(o=i.attrs.id)!=null?o:null,label:(l=i.attrs.label)!=null?l:null})}),t}};var J=f;0&&(module.exports={MEditor});
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/editor.ts","../src/schema/base.ts","../src/extensions/FileInput/FileInput.ts","../src/extensions/SuggestionMenu/SuggestionPlugin.ts","../src/utils/EventEmitter.ts","../src/blocks/MentionBlock.ts","../src/api/InsertMentionBlock.ts","../src/extensions/MentionDeletePlugin/MentionDeletePlugin.ts"],"sourcesContent":["import MEditor from \"./editor\";\n\nexport * from \"./extensions/SuggestionMenu/types\"\nexport * from \"./extensions/FileInput/types\"\n\nexport { MEditor }\nexport default MEditor","import { Editor, Extension } from '@tiptap/core'\nimport { baseExtensions } from './schema/base'\nimport History from '@tiptap/extension-history'\nimport Placeholder from '@tiptap/extension-placeholder'\nimport { FileInputExtension } from './extensions/FileInput/FileInput'\nimport { Transaction } from 'prosemirror-state'\nimport { SuggestionMenuProseMirrorPlugin } from './extensions/SuggestionMenu/SuggestionPlugin'\nimport { MentionBlock } from './blocks/MentionBlock'\nimport { type MentionItem } from './extensions/SuggestionMenu/types'\nimport { InsertMentionBlock } from './api/InsertMentionBlock'\nimport { MentionDeletePlugin } from './extensions/MentionDeletePlugin/MentionDeletePlugin'\n\nexport interface MentionEditorOptions {\n element: HTMLElement\n onChange: (text: string) => void\n placeholder?: string\n onFileInput?: (file: File) => void\n content?: string\n onMentionDelete?: (item: MentionItem) => void\n}\n\n\nexport default class MEditor {\n _tiptapEditor: Editor\n public readonly suggestionMenus: SuggestionMenuProseMirrorPlugin\n public readonly mentionDeletePlugin: MentionDeletePlugin\n\n constructor(options: MentionEditorOptions) {\n this.suggestionMenus = new SuggestionMenuProseMirrorPlugin(this)\n this.mentionDeletePlugin = new MentionDeletePlugin(this, options.onMentionDelete)\n\n const MEditorUIExtension = Extension.create({\n name: 'MEditorUIExtension',\n addProseMirrorPlugins: () => {\n return [\n this.suggestionMenus.plugin,\n this.mentionDeletePlugin.plugin,\n ]\n },\n })\n\n this._tiptapEditor = new Editor({\n element: options.element,\n content: options.content || '',\n extensions: [\n ...baseExtensions,\n History.configure({\n depth: 100,\n newGroupDelay: 500,\n }),\n MentionBlock,\n Placeholder.configure({\n placeholder: options.placeholder || '请输入...',\n emptyEditorClass: 'is-editor-empty'\n }),\n FileInputExtension.configure({\n onFileInput: options.onFileInput,\n }),\n MEditorUIExtension,\n ],\n onUpdate: ({ editor }) => {\n options.onChange(editor.getText())\n }\n })\n }\n\n\n dispatch(tr: Transaction) {\n this._tiptapEditor.view.dispatch(tr)\n }\n\n public inserMentionBlock(item: MentionItem) {\n InsertMentionBlock(this, item)\n // this._tiptapEditor\n // .chain()\n // .focus()\n // .insertContent({\n // type: 'mention',\n // attrs: item\n // })\n // .insertContent(' ')\n // .run()\n }\n\n public get isEditable(): boolean {\n return this._tiptapEditor.isEditable === undefined ? true : this._tiptapEditor.isEditable\n }\n\n public get domElement() {\n return this._tiptapEditor.view.dom as HTMLDivElement\n }\n\n public clear() {\n this._tiptapEditor.commands.clearContent(true)\n this._tiptapEditor.commands.focus()\n }\n\n public getAllMentionBlocks(): Array<MentionItem> {\n const mentions: Array<MentionItem> = []\n\n const doc = this._tiptapEditor.state.doc\n\n doc.descendants((node, pos) => {\n if (node.type.name === 'mention') {\n mentions.push({\n id: node.attrs.id ?? null,\n label: node.attrs.label ?? null,\n })\n }\n })\n\n return mentions\n }\n}\n","import Document from '@tiptap/extension-document'\nimport Paragraph from '@tiptap/extension-paragraph'\nimport Text from '@tiptap/extension-text'\n\nexport const baseExtensions = [\n Document,\n Paragraph,\n Text,\n]\n","import { Extension } from '@tiptap/core'\nimport { Plugin } from 'prosemirror-state'\nimport { FileInputOptions } from './types'\n\nexport const FileInputExtension = Extension.create<FileInputOptions>({\n name: 'imageInput',\n\n addOptions() {\n return {\n onFileInput: undefined,\n }\n },\n\n addProseMirrorPlugins() {\n const handleFile = async (file: File) => {\n this.options.onFileInput?.(file)\n }\n\n return [\n new Plugin({\n props: {\n handlePaste: (_, event) => {\n const items = event.clipboardData?.items\n if (!items) return false\n\n for (const item of items) {\n if (item.kind !== 'file') continue\n const file = item.getAsFile()\n if (!file) continue\n\n handleFile(file)\n return true\n }\n\n return false\n },\n\n handleDrop: (_, event) => {\n const files = event.dataTransfer?.files\n if (!files || files.length === 0) return false\n\n handleFile(files[0])\n return true\n },\n },\n }),\n ]\n },\n})\n","import { findParentNode } from '@tiptap/core'\nimport { EditorState, Plugin, PluginKey } from 'prosemirror-state'\nimport { Decoration, DecorationSet, EditorView } from 'prosemirror-view'\nimport MEditor from '../../editor'\nimport { EventEmitter } from '../../utils/EventEmitter'\nimport { SuggestionMenuState, MentionItem } from './types'\n\ntype SuggestionPluginState =\n | {\n triggerCharacter: string\n deleteTriggerCharacter: boolean\n queryStartPos: number\n query: string\n decorationId: string\n ignoreQueryLength?: boolean\n }\n | undefined\n\nexport const suggestionMenuPluginKey = new PluginKey('SuggestionMenuPlugin')\nconst findBlock = findParentNode(node => node.type.name === 'blockContainer')\n\nclass SuggestionMenuView {\n pluginState: SuggestionPluginState\n public state?: SuggestionMenuState\n public emitUpdate: (triggerCharacter: string) => void\n private rootEl?: Document | ShadowRoot\n\n constructor(\n private readonly editor: MEditor,\n emitUpdate: (menuName: string, state: SuggestionMenuState) => void\n ) {\n this.pluginState = undefined\n\n this.emitUpdate = (menuName: string) => {\n if (!this.state) {\n throw new Error('Attempting to update uninitialized suggestions menu')\n }\n emitUpdate(menuName, {\n ...this.state,\n ignoreQueryLength: this.pluginState?.ignoreQueryLength,\n })\n }\n setTimeout(() => {\n this.rootEl = this.editor._tiptapEditor.view.root\n })\n\n }\n\n update(view: EditorView, prevState: EditorState) {\n\n const prev: SuggestionPluginState = suggestionMenuPluginKey.getState(prevState)\n const next: SuggestionPluginState = suggestionMenuPluginKey.getState(view.state)\n\n \n const started = prev === undefined && next !== undefined\n const stopped = prev !== undefined && next === undefined\n const changed = prev !== undefined && next !== undefined\n\n \n if (!started && !changed && !stopped) {\n return\n }\n\n this.pluginState = stopped ? prev : next\n\n if (stopped || !this.editor.isEditable) {\n\n this.state!.show = false\n this.emitUpdate(this.pluginState!.triggerCharacter)\n\n return\n }\n\n const decorationNode = this.rootEl?.querySelector(`[data-decoration-id=\"${this.pluginState!.decorationId}\"]`)\n\n if (this.editor.isEditable && decorationNode) {\n\n this.state = {\n show: true,\n referencePos: decorationNode.getBoundingClientRect(),\n query: this.pluginState!.query,\n }\n\n this.emitUpdate(this.pluginState!.triggerCharacter!)\n }\n }\n\n destroy() {\n\n }\n\n closeMenu = () => {\n this.editor.dispatch(this.editor._tiptapEditor.view.state.tr.setMeta(suggestionMenuPluginKey, null))\n }\n\n clearQuery = () => {\n if (this.pluginState === undefined) {\n return\n }\n\n this.editor._tiptapEditor\n .chain()\n .focus()\n .deleteRange({\n from:\n this.pluginState.queryStartPos! -\n (this.pluginState.deleteTriggerCharacter ? this.pluginState.triggerCharacter!.length : 0),\n to: this.editor._tiptapEditor.state.selection.from,\n })\n .run()\n }\n\n insertMention = (item: MentionItem) => {\n this.editor._tiptapEditor\n .chain()\n .focus()\n .insertContent({\n type: 'mention',\n attrs: item\n })\n .insertContent(' ')\n .run()\n }\n\n getReplaceRange() {\n if (!this.pluginState) return null\n\n const from = this.pluginState.queryStartPos -\n (this.pluginState.deleteTriggerCharacter ? this.pluginState.triggerCharacter.length : 0)\n\n const to = this.editor._tiptapEditor.state.selection.from\n\n return { from, to }\n }\n\n}\n\nexport class SuggestionMenuProseMirrorPlugin extends EventEmitter<any> {\n public view: SuggestionMenuView\n public readonly plugin: Plugin\n private triggerCharacters: string[] = []\n\n constructor(editor: MEditor) {\n super()\n const triggerCharacters = this.triggerCharacters\n\n this.plugin = new Plugin({\n key: suggestionMenuPluginKey,\n view: () => {\n this.view = new SuggestionMenuView(editor, (triggerCharacter, state) => {\n this.emit(`update ${triggerCharacter}`, state)\n })\n return this.view\n },\n state: {\n init(): SuggestionPluginState {\n return undefined\n },\n apply(transaction, prev, _oldState, newState): SuggestionPluginState {\n const suggestionPluginTransactionMeta: {\n triggerCharacter: string\n deleteTriggerCharacter?: boolean\n ignoreQueryLength?: boolean\n } | null = transaction.getMeta(suggestionMenuPluginKey)\n\n\n if (\n typeof suggestionPluginTransactionMeta === 'object' &&\n suggestionPluginTransactionMeta !== null &&\n prev === undefined\n ) {\n return {\n triggerCharacter: suggestionPluginTransactionMeta.triggerCharacter,\n deleteTriggerCharacter: suggestionPluginTransactionMeta.deleteTriggerCharacter !== false,\n queryStartPos: transaction.selection?.from || newState.selection.from,\n query: '',\n decorationId: `id_${Math.floor(Math.random() * 0xffffffff)}`,\n ignoreQueryLength: suggestionPluginTransactionMeta?.ignoreQueryLength,\n }\n }\n\n\n if (prev === undefined) {\n return prev\n }\n\n\n if (\n newState.selection.from !== newState.selection.to ||\n suggestionPluginTransactionMeta === null ||\n transaction.getMeta('focus') ||\n transaction.getMeta('blur') ||\n transaction.getMeta('pointer') ||\n (prev.triggerCharacter !== undefined && newState.selection.from < prev.queryStartPos!)\n ) {\n\n return undefined\n }\n\n const next = { ...prev }\n\n\n next.query = newState.doc.textBetween(prev.queryStartPos!, newState.selection.from)\n\n return next\n }\n },\n\n props: {\n // 当用户输入一个 trigger 字符,且当前没有 suggestion 激活时:\n // 插件拦截这次输入,自己插入字符,并通过 transaction meta 通知 state 打开 suggestion 菜单;\n // 其余情况下,完全不干预编辑器行为。\n handleTextInput(view, _from, _to, text) {\n\n const suggestionPluginState: SuggestionPluginState = (this as Plugin).getState(view.state)\n\n if (triggerCharacters.includes(text) && suggestionPluginState === undefined) {\n view.dispatch(\n view.state.tr.insertText(text).scrollIntoView().setMeta(suggestionMenuPluginKey, {\n triggerCharacter: text,\n })\n )\n\n return true\n }\n return false\n },\n\n decorations(state) {\n const suggestionPluginState: SuggestionPluginState = (this as Plugin).getState(state)\n\n if (suggestionPluginState === undefined) {\n return null\n }\n\n \n if (!suggestionPluginState.deleteTriggerCharacter) {\n const blockNode = findBlock(state.selection)\n if (blockNode) {\n return DecorationSet.create(state.doc, [\n Decoration.node(blockNode.pos, blockNode.pos + blockNode.node.nodeSize, {\n nodeName: 'span',\n class: 'bn-suggestion-decorator',\n 'data-decoration-id': suggestionPluginState.decorationId,\n }),\n ])\n }\n }\n \n return DecorationSet.create(state.doc, [\n Decoration.inline(\n suggestionPluginState.queryStartPos! - suggestionPluginState.triggerCharacter!.length,\n suggestionPluginState.queryStartPos!,\n {\n nodeName: 'span',\n class: 'bn-suggestion-decorator',\n 'data-decoration-id': suggestionPluginState.decorationId,\n }\n ),\n ])\n },\n }\n })\n }\n\n public onUpdate(triggerCharacter: string, callback: (state: SuggestionMenuState) => void) {\n if (!this.triggerCharacters.includes(triggerCharacter)) {\n this.addTriggerCharacter(triggerCharacter)\n }\n \n return this.on(`update ${triggerCharacter}`, callback)\n }\n\n addTriggerCharacter = (triggerCharacter: string) => {\n this.triggerCharacters.push(triggerCharacter)\n }\n\n \n removeTriggerCharacter = (triggerCharacter: string) => {\n this.triggerCharacters = this.triggerCharacters.filter(c => c !== triggerCharacter)\n }\n\n closeMenu = () => this.view!.closeMenu()\n\n clearQuery = () => this.view!.clearQuery()\n\n insertMention = (item: MentionItem) => this.view!.insertMention(item)\n\n public get shown() {\n return this.view?.state?.show || false\n }\n\n}\n","type StringKeyOf<T> = Extract<keyof T, string>\ntype CallbackType<T extends Record<string, any>, EventName extends StringKeyOf<T>> = T[EventName] extends any[]\n ? T[EventName]\n : [T[EventName]]\ntype CallbackFunction<T extends Record<string, any>, EventName extends StringKeyOf<T>> = (...props: CallbackType<T, EventName>) => any\n\nexport class EventEmitter<T extends Record<string, any>> {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n private callbacks: { [key: string]: Function[] } = {}\n\n public on<EventName extends StringKeyOf<T>>(event: EventName, fn: CallbackFunction<T, EventName>) {\n if (!this.callbacks[event]) {\n this.callbacks[event] = []\n }\n\n this.callbacks[event].push(fn)\n\n return () => this.off(event, fn)\n }\n\n protected emit<EventName extends StringKeyOf<T>>(event: EventName, ...args: CallbackType<T, EventName>) {\n const callbacks = this.callbacks[event]\n\n if (callbacks) {\n callbacks.forEach(callback => callback.apply(this, args))\n }\n }\n\n public off<EventName extends StringKeyOf<T>>(event: EventName, fn?: CallbackFunction<T, EventName>) {\n const callbacks = this.callbacks[event]\n\n if (callbacks) {\n if (fn) {\n this.callbacks[event] = callbacks.filter(callback => callback !== fn)\n } else {\n delete this.callbacks[event]\n }\n }\n }\n\n protected removeAllListeners(): void {\n this.callbacks = {}\n }\n}\n","import { Node } from '@tiptap/core'\n\nexport const MentionBlock = Node.create({\n name: 'mention',\n inline: true,\n group: 'inline',\n atom: true,\n selectable: false,\n\n addAttributes() {\n return {\n id: { default: null },\n label: { default: null },\n }\n },\n\n parseHTML() {\n return [\n {\n tag: 'span[data-type=\"mention\"]',\n },\n ]\n },\n\n renderHTML({ node }) {\n return [\n 'span',\n {\n class: 'mention',\n 'data-type': 'mention',\n 'data-id': node.attrs.id,\n 'data-label': node.attrs.label,\n contenteditable: 'false', // 非编辑\n },\n node.attrs.label,\n ]\n },\n\n // 新增:确保mention节点可以正确序列化/反序列化\n renderText({ node }) {\n return ''\n },\n})\n\n\n","import { Selection } from 'prosemirror-state'\nimport MEditor from '../editor'\n\nexport function InsertMentionBlock(\n editor: MEditor,\n item: { id: string; label: string }\n) {\n\n editor._tiptapEditor.chain().insertContent({\n type: 'mention',\n attrs: {\n id: item.id,\n label: item.label,\n }\n }).run() \n\n}\n\n","import { Plugin, PluginKey } from 'prosemirror-state'\nimport MEditor from '../../editor'\nimport { MentionItem } from '../SuggestionMenu/types'\n\nexport class MentionDeletePlugin {\n public readonly plugin: Plugin\n\n constructor(editor: MEditor, onMentionDelete?: (item: MentionItem) => void) {\n this.plugin = new Plugin({\n key: new PluginKey('mention-delete'),\n\n appendTransaction(transactions, oldState, newState) {\n if (!transactions.some(tr => tr.docChanged)) {\n return null\n }\n\n const oldMentions = new Map<string, any>()\n const newMentionIds = new Set<string>()\n\n oldState.doc.descendants(node => {\n if (node.type.name === 'mention' && node.attrs.id) {\n oldMentions.set(node.attrs.id, node.attrs)\n }\n })\n\n newState.doc.descendants(node => {\n if (node.type.name === 'mention' && node.attrs.id) {\n newMentionIds.add(node.attrs.id)\n }\n })\n\n for (const [id, attrs] of oldMentions.entries()) {\n if (!newMentionIds.has(id)) {\n onMentionDelete?.({\n id: attrs.id,\n label: attrs.label,\n })\n }\n }\n },\n })\n }\n} \n"],"mappings":"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","names":["index_exports","__export","MEditor","index_default","__toCommonJS","import_core","import_extension_document","import_extension_paragraph","import_extension_text","baseExtensions","Document","Paragraph","Text","import_extension_history","import_extension_placeholder","import_core","import_prosemirror_state","FileInputExtension","handleFile","file","_a","_b","_","event","items","item","files","import_core","import_prosemirror_state","import_prosemirror_view","EventEmitter","__publicField","event","fn","args","callbacks","callback","suggestionMenuPluginKey","findBlock","node","SuggestionMenuView","editor","emitUpdate","__publicField","item","menuName","_a","view","prevState","prev","next","started","stopped","decorationNode","from","to","SuggestionMenuProseMirrorPlugin","EventEmitter","triggerCharacter","c","triggerCharacters","state","transaction","_oldState","newState","suggestionPluginTransactionMeta","_from","_to","text","suggestionPluginState","blockNode","callback","_b","import_core","MentionBlock","node","InsertMentionBlock","editor","item","import_prosemirror_state","MentionDeletePlugin","editor","onMentionDelete","__publicField","transactions","oldState","newState","tr","oldMentions","newMentionIds","node","id","attrs","MEditor","options","__publicField","SuggestionMenuProseMirrorPlugin","MentionDeletePlugin","MEditorUIExtension","baseExtensions","History","MentionBlock","Placeholder","FileInputExtension","editor","tr","item","InsertMentionBlock","mentions","node","pos","_a","_b","index_default","MEditor"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/editor.ts","../src/schema/base.ts","../src/extensions/FileInput/FileInput.ts","../src/extensions/SuggestionMenu/SuggestionPlugin.ts","../src/utils/EventEmitter.ts","../src/blocks/MentionBlock.ts","../src/api/InsertMentionBlock.ts","../src/extensions/MentionDeletePlugin/MentionDeletePlugin.ts","../src/extensions/ShiftEnterPlugin/ShiftEnterPlugin.ts"],"sourcesContent":["import MEditor from \"./editor\";\n\nexport * from \"./extensions/SuggestionMenu/types\"\nexport * from \"./extensions/FileInput/types\"\n\nexport { MEditor }\nexport default MEditor","import { Editor, Extension } from '@tiptap/core'\nimport { baseExtensions } from './schema/base'\nimport History from '@tiptap/extension-history'\nimport Placeholder from '@tiptap/extension-placeholder'\nimport { FileInputExtension } from './extensions/FileInput/FileInput'\nimport { Transaction } from 'prosemirror-state'\nimport { SuggestionMenuProseMirrorPlugin } from './extensions/SuggestionMenu/SuggestionPlugin'\nimport { MentionBlock } from './blocks/MentionBlock'\nimport { type MentionItem } from './extensions/SuggestionMenu/types'\nimport { InsertMentionBlock } from './api/InsertMentionBlock'\nimport { MentionDeletePlugin } from './extensions/MentionDeletePlugin/MentionDeletePlugin'\nimport { ShiftEnterPlugin } from './extensions/ShiftEnterPlugin/ShiftEnterPlugin'\n\nexport interface MentionEditorOptions {\n element: HTMLElement\n onChange: (text: string) => void\n placeholder?: string\n onFileInput?: (file: File) => void\n content?: string\n onMentionDelete?: (item: MentionItem) => void\n onEnter?: () => void\n lineBreak?: 'shift-enter' | 'enter'\n}\n\n\nexport default class MEditor {\n _tiptapEditor: Editor\n public readonly suggestionMenus: SuggestionMenuProseMirrorPlugin\n public readonly mentionDeletePlugin: MentionDeletePlugin\n public readonly shiftEnterPlugin: ShiftEnterPlugin\n\n constructor(options: MentionEditorOptions) {\n this.suggestionMenus = new SuggestionMenuProseMirrorPlugin(this)\n this.mentionDeletePlugin = new MentionDeletePlugin(this, options.onMentionDelete)\n\n if (options.lineBreak === 'shift-enter') {\n this.shiftEnterPlugin = new ShiftEnterPlugin(this, options.onEnter)\n }\n\n const MEditorUIExtension = Extension.create({\n name: 'MEditorUIExtension',\n addProseMirrorPlugins: () => {\n const plugins = [\n this.suggestionMenus.plugin,\n this.mentionDeletePlugin.plugin\n ]\n\n if (this.shiftEnterPlugin) {\n plugins.unshift(this.shiftEnterPlugin.plugin)\n }\n return plugins\n },\n })\n\n this._tiptapEditor = new Editor({\n element: options.element,\n content: options.content || '',\n extensions: [\n ...baseExtensions,\n History.configure({\n depth: 100,\n newGroupDelay: 500,\n }),\n MentionBlock,\n Placeholder.configure({\n placeholder: options.placeholder || '请输入...',\n emptyEditorClass: 'is-editor-empty'\n }),\n FileInputExtension.configure({\n onFileInput: options.onFileInput,\n }),\n MEditorUIExtension,\n ],\n onUpdate: ({ editor }) => {\n options.onChange(editor.getText())\n }\n })\n }\n\n\n dispatch(tr: Transaction) {\n this._tiptapEditor.view.dispatch(tr)\n }\n\n public inserMentionBlock(item: MentionItem) {\n InsertMentionBlock(this, item)\n // this._tiptapEditor\n // .chain()\n // .focus()\n // .insertContent({\n // type: 'mention',\n // attrs: item\n // })\n // .insertContent(' ')\n // .run()\n }\n\n public get isEditable(): boolean {\n return this._tiptapEditor.isEditable === undefined ? true : this._tiptapEditor.isEditable\n }\n\n public get domElement() {\n return this._tiptapEditor.view.dom as HTMLDivElement\n }\n\n public clear() {\n this._tiptapEditor.commands.clearContent(true)\n this._tiptapEditor.commands.focus()\n }\n\n public getAllMentionBlocks(): Array<MentionItem> {\n const mentions: Array<MentionItem> = []\n\n const doc = this._tiptapEditor.state.doc\n\n doc.descendants((node, pos) => {\n if (node.type.name === 'mention') {\n mentions.push({\n id: node.attrs.id ?? null,\n label: node.attrs.label ?? null,\n })\n }\n })\n\n return mentions\n }\n}\n","import Document from '@tiptap/extension-document'\nimport Paragraph from '@tiptap/extension-paragraph'\nimport Text from '@tiptap/extension-text'\nimport HardBreak from '@tiptap/extension-hard-break'\n\nexport const baseExtensions = [\n Document,\n Paragraph,\n Text,\n HardBreak,\n]\n","import { Extension } from '@tiptap/core'\nimport { Plugin } from 'prosemirror-state'\nimport { FileInputOptions } from './types'\n\nexport const FileInputExtension = Extension.create<FileInputOptions>({\n name: 'imageInput',\n\n addOptions() {\n return {\n onFileInput: undefined,\n }\n },\n\n addProseMirrorPlugins() {\n const handleFile = async (file: File) => {\n this.options.onFileInput?.(file)\n }\n\n return [\n new Plugin({\n props: {\n handlePaste: (_, event) => {\n const items = event.clipboardData?.items\n if (!items) return false\n\n for (const item of items) {\n if (item.kind !== 'file') continue\n const file = item.getAsFile()\n if (!file) continue\n\n handleFile(file)\n return true\n }\n\n return false\n },\n\n handleDrop: (_, event) => {\n const files = event.dataTransfer?.files\n if (!files || files.length === 0) return false\n\n handleFile(files[0])\n return true\n },\n },\n }),\n ]\n },\n})\n","import { findParentNode } from '@tiptap/core'\nimport { EditorState, Plugin, PluginKey } from 'prosemirror-state'\nimport { Decoration, DecorationSet, EditorView } from 'prosemirror-view'\nimport MEditor from '../../editor'\nimport { EventEmitter } from '../../utils/EventEmitter'\nimport { SuggestionMenuState, MentionItem } from './types'\n\ntype SuggestionPluginState =\n | {\n triggerCharacter: string\n deleteTriggerCharacter: boolean\n queryStartPos: number\n query: string\n decorationId: string\n ignoreQueryLength?: boolean\n }\n | undefined\n\nexport const suggestionMenuPluginKey = new PluginKey('SuggestionMenuPlugin')\nconst findBlock = findParentNode(node => node.type.name === 'blockContainer')\n\nclass SuggestionMenuView {\n pluginState: SuggestionPluginState\n public state?: SuggestionMenuState\n public emitUpdate: (triggerCharacter: string) => void\n private rootEl?: Document | ShadowRoot\n\n constructor(\n private readonly editor: MEditor,\n emitUpdate: (menuName: string, state: SuggestionMenuState) => void\n ) {\n this.pluginState = undefined\n\n this.emitUpdate = (menuName: string) => {\n if (!this.state) {\n throw new Error('Attempting to update uninitialized suggestions menu')\n }\n emitUpdate(menuName, {\n ...this.state,\n ignoreQueryLength: this.pluginState?.ignoreQueryLength,\n })\n }\n setTimeout(() => {\n this.rootEl = this.editor._tiptapEditor.view.root\n })\n\n }\n\n update(view: EditorView, prevState: EditorState) {\n\n const prev: SuggestionPluginState = suggestionMenuPluginKey.getState(prevState)\n const next: SuggestionPluginState = suggestionMenuPluginKey.getState(view.state)\n\n \n const started = prev === undefined && next !== undefined\n const stopped = prev !== undefined && next === undefined\n const changed = prev !== undefined && next !== undefined\n\n \n if (!started && !changed && !stopped) {\n return\n }\n\n this.pluginState = stopped ? prev : next\n\n if (stopped || !this.editor.isEditable) {\n\n this.state!.show = false\n this.emitUpdate(this.pluginState!.triggerCharacter)\n\n return\n }\n\n const decorationNode = this.rootEl?.querySelector(`[data-decoration-id=\"${this.pluginState!.decorationId}\"]`)\n\n if (this.editor.isEditable && decorationNode) {\n\n this.state = {\n show: true,\n referencePos: decorationNode.getBoundingClientRect(),\n query: this.pluginState!.query,\n }\n\n this.emitUpdate(this.pluginState!.triggerCharacter!)\n }\n }\n\n destroy() {\n\n }\n\n closeMenu = () => {\n this.editor.dispatch(this.editor._tiptapEditor.view.state.tr.setMeta(suggestionMenuPluginKey, null))\n }\n\n clearQuery = () => {\n if (this.pluginState === undefined) {\n return\n }\n\n this.editor._tiptapEditor\n .chain()\n .focus()\n .deleteRange({\n from:\n this.pluginState.queryStartPos! -\n (this.pluginState.deleteTriggerCharacter ? this.pluginState.triggerCharacter!.length : 0),\n to: this.editor._tiptapEditor.state.selection.from,\n })\n .run()\n }\n\n insertMention = (item: MentionItem) => {\n this.editor._tiptapEditor\n .chain()\n .focus()\n .insertContent({\n type: 'mention',\n attrs: item\n })\n .insertContent(' ')\n .run()\n }\n\n getReplaceRange() {\n if (!this.pluginState) return null\n\n const from = this.pluginState.queryStartPos -\n (this.pluginState.deleteTriggerCharacter ? this.pluginState.triggerCharacter.length : 0)\n\n const to = this.editor._tiptapEditor.state.selection.from\n\n return { from, to }\n }\n\n}\n\nexport class SuggestionMenuProseMirrorPlugin extends EventEmitter<any> {\n public view: SuggestionMenuView\n public readonly plugin: Plugin\n private triggerCharacters: string[] = []\n\n constructor(editor: MEditor) {\n super()\n const triggerCharacters = this.triggerCharacters\n\n this.plugin = new Plugin({\n key: suggestionMenuPluginKey,\n view: () => {\n this.view = new SuggestionMenuView(editor, (triggerCharacter, state) => {\n this.emit(`update ${triggerCharacter}`, state)\n })\n return this.view\n },\n state: {\n init(): SuggestionPluginState {\n return undefined\n },\n apply(transaction, prev, _oldState, newState): SuggestionPluginState {\n const suggestionPluginTransactionMeta: {\n triggerCharacter: string\n deleteTriggerCharacter?: boolean\n ignoreQueryLength?: boolean\n } | null = transaction.getMeta(suggestionMenuPluginKey)\n\n\n if (\n typeof suggestionPluginTransactionMeta === 'object' &&\n suggestionPluginTransactionMeta !== null &&\n prev === undefined\n ) {\n return {\n triggerCharacter: suggestionPluginTransactionMeta.triggerCharacter,\n deleteTriggerCharacter: suggestionPluginTransactionMeta.deleteTriggerCharacter !== false,\n queryStartPos: transaction.selection?.from || newState.selection.from,\n query: '',\n decorationId: `id_${Math.floor(Math.random() * 0xffffffff)}`,\n ignoreQueryLength: suggestionPluginTransactionMeta?.ignoreQueryLength,\n }\n }\n\n\n if (prev === undefined) {\n return prev\n }\n\n\n if (\n newState.selection.from !== newState.selection.to ||\n suggestionPluginTransactionMeta === null ||\n transaction.getMeta('focus') ||\n transaction.getMeta('blur') ||\n transaction.getMeta('pointer') ||\n (prev.triggerCharacter !== undefined && newState.selection.from < prev.queryStartPos!)\n ) {\n\n return undefined\n }\n\n const next = { ...prev }\n\n\n next.query = newState.doc.textBetween(prev.queryStartPos!, newState.selection.from)\n\n return next\n }\n },\n\n props: {\n // 当用户输入一个 trigger 字符,且当前没有 suggestion 激活时:\n // 插件拦截这次输入,自己插入字符,并通过 transaction meta 通知 state 打开 suggestion 菜单;\n // 其余情况下,完全不干预编辑器行为。\n handleTextInput(view, _from, _to, text) {\n\n const suggestionPluginState: SuggestionPluginState = (this as Plugin).getState(view.state)\n\n if (triggerCharacters.includes(text) && suggestionPluginState === undefined) {\n view.dispatch(\n view.state.tr.insertText(text).scrollIntoView().setMeta(suggestionMenuPluginKey, {\n triggerCharacter: text,\n })\n )\n\n return true\n }\n return false\n },\n\n decorations(state) {\n const suggestionPluginState: SuggestionPluginState = (this as Plugin).getState(state)\n\n if (suggestionPluginState === undefined) {\n return null\n }\n\n \n if (!suggestionPluginState.deleteTriggerCharacter) {\n const blockNode = findBlock(state.selection)\n if (blockNode) {\n return DecorationSet.create(state.doc, [\n Decoration.node(blockNode.pos, blockNode.pos + blockNode.node.nodeSize, {\n nodeName: 'span',\n class: 'bn-suggestion-decorator',\n 'data-decoration-id': suggestionPluginState.decorationId,\n }),\n ])\n }\n }\n \n return DecorationSet.create(state.doc, [\n Decoration.inline(\n suggestionPluginState.queryStartPos! - suggestionPluginState.triggerCharacter!.length,\n suggestionPluginState.queryStartPos!,\n {\n nodeName: 'span',\n class: 'bn-suggestion-decorator',\n 'data-decoration-id': suggestionPluginState.decorationId,\n }\n ),\n ])\n },\n }\n })\n }\n\n public onUpdate(triggerCharacter: string, callback: (state: SuggestionMenuState) => void) {\n if (!this.triggerCharacters.includes(triggerCharacter)) {\n this.addTriggerCharacter(triggerCharacter)\n }\n \n return this.on(`update ${triggerCharacter}`, callback)\n }\n\n addTriggerCharacter = (triggerCharacter: string) => {\n this.triggerCharacters.push(triggerCharacter)\n }\n\n \n removeTriggerCharacter = (triggerCharacter: string) => {\n this.triggerCharacters = this.triggerCharacters.filter(c => c !== triggerCharacter)\n }\n\n closeMenu = () => this.view!.closeMenu()\n\n clearQuery = () => this.view!.clearQuery()\n\n insertMention = (item: MentionItem) => this.view!.insertMention(item)\n\n public get shown() {\n return this.view?.state?.show || false\n }\n\n}\n","type StringKeyOf<T> = Extract<keyof T, string>\ntype CallbackType<T extends Record<string, any>, EventName extends StringKeyOf<T>> = T[EventName] extends any[]\n ? T[EventName]\n : [T[EventName]]\ntype CallbackFunction<T extends Record<string, any>, EventName extends StringKeyOf<T>> = (...props: CallbackType<T, EventName>) => any\n\nexport class EventEmitter<T extends Record<string, any>> {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n private callbacks: { [key: string]: Function[] } = {}\n\n public on<EventName extends StringKeyOf<T>>(event: EventName, fn: CallbackFunction<T, EventName>) {\n if (!this.callbacks[event]) {\n this.callbacks[event] = []\n }\n\n this.callbacks[event].push(fn)\n\n return () => this.off(event, fn)\n }\n\n protected emit<EventName extends StringKeyOf<T>>(event: EventName, ...args: CallbackType<T, EventName>) {\n const callbacks = this.callbacks[event]\n\n if (callbacks) {\n callbacks.forEach(callback => callback.apply(this, args))\n }\n }\n\n public off<EventName extends StringKeyOf<T>>(event: EventName, fn?: CallbackFunction<T, EventName>) {\n const callbacks = this.callbacks[event]\n\n if (callbacks) {\n if (fn) {\n this.callbacks[event] = callbacks.filter(callback => callback !== fn)\n } else {\n delete this.callbacks[event]\n }\n }\n }\n\n protected removeAllListeners(): void {\n this.callbacks = {}\n }\n}\n","import { Node } from '@tiptap/core'\n\nexport const MentionBlock = Node.create({\n name: 'mention',\n inline: true,\n group: 'inline',\n atom: true,\n selectable: false,\n\n addAttributes() {\n return {\n id: { default: null },\n label: { default: null },\n }\n },\n\n parseHTML() {\n return [\n {\n tag: 'span[data-type=\"mention\"]',\n },\n ]\n },\n\n renderHTML({ node }) {\n return [\n 'span',\n {\n class: 'mention',\n 'data-type': 'mention',\n 'data-id': node.attrs.id,\n 'data-label': node.attrs.label,\n contenteditable: 'false', // 非编辑\n },\n node.attrs.label,\n ]\n },\n\n // 新增:确保mention节点可以正确序列化/反序列化\n renderText({ node }) {\n return ''\n },\n})\n\n\n","import { Selection } from 'prosemirror-state'\nimport MEditor from '../editor'\n\nexport function InsertMentionBlock(\n editor: MEditor,\n item: { id: string; label: string }\n) {\n\n editor._tiptapEditor.chain().insertContent({\n type: 'mention',\n attrs: {\n id: item.id,\n label: item.label,\n }\n }).run() \n\n}\n\n","import { Plugin, PluginKey } from 'prosemirror-state'\nimport MEditor from '../../editor'\nimport { MentionItem } from '../SuggestionMenu/types'\n\nexport class MentionDeletePlugin {\n public readonly plugin: Plugin\n\n constructor(editor: MEditor, onMentionDelete?: (item: MentionItem) => void) {\n this.plugin = new Plugin({\n key: new PluginKey('mention-delete'),\n\n appendTransaction(transactions, oldState, newState) {\n if (!transactions.some(tr => tr.docChanged)) {\n return null\n }\n\n const oldMentions = new Map<string, any>()\n const newMentionIds = new Set<string>()\n\n oldState.doc.descendants(node => {\n if (node.type.name === 'mention' && node.attrs.id) {\n oldMentions.set(node.attrs.id, node.attrs)\n }\n })\n\n newState.doc.descendants(node => {\n if (node.type.name === 'mention' && node.attrs.id) {\n newMentionIds.add(node.attrs.id)\n }\n })\n\n for (const [id, attrs] of oldMentions.entries()) {\n if (!newMentionIds.has(id)) {\n onMentionDelete?.({\n id: attrs.id,\n label: attrs.label,\n })\n }\n }\n },\n })\n }\n} \n","import { Plugin, PluginKey } from 'prosemirror-state'\nimport MEditor from '../../editor'\n\nexport class ShiftEnterPlugin {\n public readonly plugin: Plugin\n\n constructor(editor: MEditor, onEnter?: () => void) {\n this.plugin = new Plugin({\n key: new PluginKey('shift-enter'),\n\n props: {\n handleKeyDown(view, event) {\n // 只处理 Enter\n if (event.key !== 'Enter') {\n return false\n }\n\n // Shift + Enter:插入换行\n if (event.shiftKey) {\n event.preventDefault()\n\n const { state, dispatch } = view\n const { hard_break } = state.schema.nodes\n \n if (!hard_break) {\n return false\n }\n\n dispatch(state.tr.replaceSelectionWith(hard_break.create()).scrollIntoView())\n\n return true\n }\n\n // 普通 Enter 如果 suggestion 菜单打开,让 suggestionPlugin 处理\n if (editor.suggestionMenus.shown) {\n return false\n }\n\n if (onEnter) {\n onEnter()\n return true\n }\n return false\n },\n },\n\n })\n }\n}"],"mappings":"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","names":["index_exports","__export","MEditor","index_default","__toCommonJS","import_core","import_extension_document","import_extension_paragraph","import_extension_text","import_extension_hard_break","baseExtensions","Document","Paragraph","Text","HardBreak","import_extension_history","import_extension_placeholder","import_core","import_prosemirror_state","FileInputExtension","handleFile","file","_a","_b","_","event","items","item","files","import_core","import_prosemirror_state","import_prosemirror_view","EventEmitter","__publicField","event","fn","args","callbacks","callback","suggestionMenuPluginKey","findBlock","node","SuggestionMenuView","editor","emitUpdate","__publicField","item","menuName","_a","view","prevState","prev","next","started","stopped","decorationNode","from","to","SuggestionMenuProseMirrorPlugin","EventEmitter","triggerCharacter","c","triggerCharacters","state","transaction","_oldState","newState","suggestionPluginTransactionMeta","_from","_to","text","suggestionPluginState","blockNode","callback","_b","import_core","MentionBlock","node","InsertMentionBlock","editor","item","import_prosemirror_state","MentionDeletePlugin","editor","onMentionDelete","__publicField","transactions","oldState","newState","tr","oldMentions","newMentionIds","node","id","attrs","import_prosemirror_state","ShiftEnterPlugin","editor","onEnter","__publicField","view","event","state","dispatch","hard_break","MEditor","options","__publicField","SuggestionMenuProseMirrorPlugin","MentionDeletePlugin","ShiftEnterPlugin","MEditorUIExtension","plugins","baseExtensions","History","MentionBlock","Placeholder","FileInputExtension","editor","tr","item","InsertMentionBlock","mentions","node","pos","_a","_b","index_default","MEditor"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var T=Object.defineProperty;var
|
|
1
|
+
var T=Object.defineProperty;var k=(a,t,e)=>t in a?T(a,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):a[t]=e;var o=(a,t,e)=>k(a,typeof t!="symbol"?t+"":t,e);import{Editor as A,Extension as H}from"@tiptap/core";import w from"@tiptap/extension-document";import I from"@tiptap/extension-paragraph";import v from"@tiptap/extension-text";import _ from"@tiptap/extension-hard-break";var b=[w,I,v,_];import V from"@tiptap/extension-history";import $ from"@tiptap/extension-placeholder";import{Extension as N}from"@tiptap/core";import{Plugin as F}from"prosemirror-state";var S=N.create({name:"imageInput",addOptions(){return{onFileInput:void 0}},addProseMirrorPlugins(){let a=async t=>{var e,i;(i=(e=this.options).onFileInput)==null||i.call(e,t)};return[new F({props:{handlePaste:(t,e)=>{var n;let i=(n=e.clipboardData)==null?void 0:n.items;if(!i)return!1;for(let r of i){if(r.kind!=="file")continue;let l=r.getAsFile();if(l)return a(l),!0}return!1},handleDrop:(t,e)=>{var n;let i=(n=e.dataTransfer)==null?void 0:n.files;return!i||i.length===0?!1:(a(i[0]),!0)}}})]}});import{findParentNode as q}from"@tiptap/core";import{Plugin as B,PluginKey as D}from"prosemirror-state";import{Decoration as M,DecorationSet as P}from"prosemirror-view";var p=class{constructor(){o(this,"callbacks",{})}on(t,e){return this.callbacks[t]||(this.callbacks[t]=[]),this.callbacks[t].push(e),()=>this.off(t,e)}emit(t,...e){let i=this.callbacks[t];i&&i.forEach(n=>n.apply(this,e))}off(t,e){let i=this.callbacks[t];i&&(e?this.callbacks[t]=i.filter(n=>n!==e):delete this.callbacks[t])}removeAllListeners(){this.callbacks={}}};var c=new D("SuggestionMenuPlugin"),K=q(a=>a.type.name==="blockContainer"),y=class{constructor(t,e){this.editor=t;o(this,"pluginState");o(this,"state");o(this,"emitUpdate");o(this,"rootEl");o(this,"closeMenu",()=>{this.editor.dispatch(this.editor._tiptapEditor.view.state.tr.setMeta(c,null))});o(this,"clearQuery",()=>{this.pluginState!==void 0&&this.editor._tiptapEditor.chain().focus().deleteRange({from:this.pluginState.queryStartPos-(this.pluginState.deleteTriggerCharacter?this.pluginState.triggerCharacter.length:0),to:this.editor._tiptapEditor.state.selection.from}).run()});o(this,"insertMention",t=>{this.editor._tiptapEditor.chain().focus().insertContent({type:"mention",attrs:t}).insertContent(" ").run()});this.pluginState=void 0,this.emitUpdate=i=>{var n;if(!this.state)throw new Error("Attempting to update uninitialized suggestions menu");e(i,{...this.state,ignoreQueryLength:(n=this.pluginState)==null?void 0:n.ignoreQueryLength})},setTimeout(()=>{this.rootEl=this.editor._tiptapEditor.view.root})}update(t,e){var d;let i=c.getState(e),n=c.getState(t.state),r=i===void 0&&n!==void 0,l=i!==void 0&&n===void 0;if(!r&&!(i!==void 0&&n!==void 0)&&!l)return;if(this.pluginState=l?i:n,l||!this.editor.isEditable){this.state.show=!1,this.emitUpdate(this.pluginState.triggerCharacter);return}let s=(d=this.rootEl)==null?void 0:d.querySelector(`[data-decoration-id="${this.pluginState.decorationId}"]`);this.editor.isEditable&&s&&(this.state={show:!0,referencePos:s.getBoundingClientRect(),query:this.pluginState.query},this.emitUpdate(this.pluginState.triggerCharacter))}destroy(){}getReplaceRange(){if(!this.pluginState)return null;let t=this.pluginState.queryStartPos-(this.pluginState.deleteTriggerCharacter?this.pluginState.triggerCharacter.length:0),e=this.editor._tiptapEditor.state.selection.from;return{from:t,to:e}}},f=class extends p{constructor(e){super();o(this,"view");o(this,"plugin");o(this,"triggerCharacters",[]);o(this,"addTriggerCharacter",e=>{this.triggerCharacters.push(e)});o(this,"removeTriggerCharacter",e=>{this.triggerCharacters=this.triggerCharacters.filter(i=>i!==e)});o(this,"closeMenu",()=>this.view.closeMenu());o(this,"clearQuery",()=>this.view.clearQuery());o(this,"insertMention",e=>this.view.insertMention(e));let i=this.triggerCharacters;this.plugin=new B({key:c,view:()=>(this.view=new y(e,(n,r)=>{this.emit(`update ${n}`,r)}),this.view),state:{init(){},apply(n,r,l,u){var E;let s=n.getMeta(c);if(typeof s=="object"&&s!==null&&r===void 0)return{triggerCharacter:s.triggerCharacter,deleteTriggerCharacter:s.deleteTriggerCharacter!==!1,queryStartPos:((E=n.selection)==null?void 0:E.from)||u.selection.from,query:"",decorationId:`id_${Math.floor(Math.random()*4294967295)}`,ignoreQueryLength:s==null?void 0:s.ignoreQueryLength};if(r===void 0)return r;if(u.selection.from!==u.selection.to||s===null||n.getMeta("focus")||n.getMeta("blur")||n.getMeta("pointer")||r.triggerCharacter!==void 0&&u.selection.from<r.queryStartPos)return;let d={...r};return d.query=u.doc.textBetween(r.queryStartPos,u.selection.from),d}},props:{handleTextInput(n,r,l,u){let s=this.getState(n.state);return i.includes(u)&&s===void 0?(n.dispatch(n.state.tr.insertText(u).scrollIntoView().setMeta(c,{triggerCharacter:u})),!0):!1},decorations(n){let r=this.getState(n);if(r===void 0)return null;if(!r.deleteTriggerCharacter){let l=K(n.selection);if(l)return P.create(n.doc,[M.node(l.pos,l.pos+l.node.nodeSize,{nodeName:"span",class:"bn-suggestion-decorator","data-decoration-id":r.decorationId})])}return P.create(n.doc,[M.inline(r.queryStartPos-r.triggerCharacter.length,r.queryStartPos,{nodeName:"span",class:"bn-suggestion-decorator","data-decoration-id":r.decorationId})])}}})}onUpdate(e,i){return this.triggerCharacters.includes(e)||this.addTriggerCharacter(e),this.on(`update ${e}`,i)}get shown(){var e,i;return((i=(e=this.view)==null?void 0:e.state)==null?void 0:i.show)||!1}};import{Node as L}from"@tiptap/core";var x=L.create({name:"mention",inline:!0,group:"inline",atom:!0,selectable:!1,addAttributes(){return{id:{default:null},label:{default:null}}},parseHTML(){return[{tag:'span[data-type="mention"]'}]},renderHTML({node:a}){return["span",{class:"mention","data-type":"mention","data-id":a.attrs.id,"data-label":a.attrs.label,contenteditable:"false"},a.attrs.label]},renderText({node:a}){return""}});function C(a,t){a._tiptapEditor.chain().insertContent({type:"mention",attrs:{id:t.id,label:t.label}}).run()}import{Plugin as O,PluginKey as Q}from"prosemirror-state";var h=class{constructor(t,e){o(this,"plugin");this.plugin=new O({key:new Q("mention-delete"),appendTransaction(i,n,r){if(!i.some(s=>s.docChanged))return null;let l=new Map,u=new Set;n.doc.descendants(s=>{s.type.name==="mention"&&s.attrs.id&&l.set(s.attrs.id,s.attrs)}),r.doc.descendants(s=>{s.type.name==="mention"&&s.attrs.id&&u.add(s.attrs.id)});for(let[s,d]of l.entries())u.has(s)||e==null||e({id:d.id,label:d.label})}})}};import{Plugin as R,PluginKey as U}from"prosemirror-state";var m=class{constructor(t,e){o(this,"plugin");this.plugin=new R({key:new U("shift-enter"),props:{handleKeyDown(i,n){if(n.key!=="Enter")return!1;if(n.shiftKey){n.preventDefault();let{state:r,dispatch:l}=i,{hard_break:u}=r.schema.nodes;return u?(l(r.tr.replaceSelectionWith(u.create()).scrollIntoView()),!0):!1}return t.suggestionMenus.shown?!1:e?(e(),!0):!1}}})}};var g=class{constructor(t){o(this,"_tiptapEditor");o(this,"suggestionMenus");o(this,"mentionDeletePlugin");o(this,"shiftEnterPlugin");this.suggestionMenus=new f(this),this.mentionDeletePlugin=new h(this,t.onMentionDelete),t.lineBreak==="shift-enter"&&(this.shiftEnterPlugin=new m(this,t.onEnter));let e=H.create({name:"MEditorUIExtension",addProseMirrorPlugins:()=>{let i=[this.suggestionMenus.plugin,this.mentionDeletePlugin.plugin];return this.shiftEnterPlugin&&i.unshift(this.shiftEnterPlugin.plugin),i}});this._tiptapEditor=new A({element:t.element,content:t.content||"",extensions:[...b,V.configure({depth:100,newGroupDelay:500}),x,$.configure({placeholder:t.placeholder||"\u8BF7\u8F93\u5165...",emptyEditorClass:"is-editor-empty"}),S.configure({onFileInput:t.onFileInput}),e],onUpdate:({editor:i})=>{t.onChange(i.getText())}})}dispatch(t){this._tiptapEditor.view.dispatch(t)}inserMentionBlock(t){C(this,t)}get isEditable(){return this._tiptapEditor.isEditable===void 0?!0:this._tiptapEditor.isEditable}get domElement(){return this._tiptapEditor.view.dom}clear(){this._tiptapEditor.commands.clearContent(!0),this._tiptapEditor.commands.focus()}getAllMentionBlocks(){let t=[];return this._tiptapEditor.state.doc.descendants((i,n)=>{var r,l;i.type.name==="mention"&&t.push({id:(r=i.attrs.id)!=null?r:null,label:(l=i.attrs.label)!=null?l:null})}),t}};var qt=g;export{g as MEditor,qt as default};
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/editor.ts","../src/schema/base.ts","../src/extensions/FileInput/FileInput.ts","../src/extensions/SuggestionMenu/SuggestionPlugin.ts","../src/utils/EventEmitter.ts","../src/blocks/MentionBlock.ts","../src/api/InsertMentionBlock.ts","../src/extensions/MentionDeletePlugin/MentionDeletePlugin.ts","../src/index.ts"],"sourcesContent":["import { Editor, Extension } from '@tiptap/core'\nimport { baseExtensions } from './schema/base'\nimport History from '@tiptap/extension-history'\nimport Placeholder from '@tiptap/extension-placeholder'\nimport { FileInputExtension } from './extensions/FileInput/FileInput'\nimport { Transaction } from 'prosemirror-state'\nimport { SuggestionMenuProseMirrorPlugin } from './extensions/SuggestionMenu/SuggestionPlugin'\nimport { MentionBlock } from './blocks/MentionBlock'\nimport { type MentionItem } from './extensions/SuggestionMenu/types'\nimport { InsertMentionBlock } from './api/InsertMentionBlock'\nimport { MentionDeletePlugin } from './extensions/MentionDeletePlugin/MentionDeletePlugin'\n\nexport interface MentionEditorOptions {\n element: HTMLElement\n onChange: (text: string) => void\n placeholder?: string\n onFileInput?: (file: File) => void\n content?: string\n onMentionDelete?: (item: MentionItem) => void\n}\n\n\nexport default class MEditor {\n _tiptapEditor: Editor\n public readonly suggestionMenus: SuggestionMenuProseMirrorPlugin\n public readonly mentionDeletePlugin: MentionDeletePlugin\n\n constructor(options: MentionEditorOptions) {\n this.suggestionMenus = new SuggestionMenuProseMirrorPlugin(this)\n this.mentionDeletePlugin = new MentionDeletePlugin(this, options.onMentionDelete)\n\n const MEditorUIExtension = Extension.create({\n name: 'MEditorUIExtension',\n addProseMirrorPlugins: () => {\n return [\n this.suggestionMenus.plugin,\n this.mentionDeletePlugin.plugin,\n ]\n },\n })\n\n this._tiptapEditor = new Editor({\n element: options.element,\n content: options.content || '',\n extensions: [\n ...baseExtensions,\n History.configure({\n depth: 100,\n newGroupDelay: 500,\n }),\n MentionBlock,\n Placeholder.configure({\n placeholder: options.placeholder || '请输入...',\n emptyEditorClass: 'is-editor-empty'\n }),\n FileInputExtension.configure({\n onFileInput: options.onFileInput,\n }),\n MEditorUIExtension,\n ],\n onUpdate: ({ editor }) => {\n options.onChange(editor.getText())\n }\n })\n }\n\n\n dispatch(tr: Transaction) {\n this._tiptapEditor.view.dispatch(tr)\n }\n\n public inserMentionBlock(item: MentionItem) {\n InsertMentionBlock(this, item)\n // this._tiptapEditor\n // .chain()\n // .focus()\n // .insertContent({\n // type: 'mention',\n // attrs: item\n // })\n // .insertContent(' ')\n // .run()\n }\n\n public get isEditable(): boolean {\n return this._tiptapEditor.isEditable === undefined ? true : this._tiptapEditor.isEditable\n }\n\n public get domElement() {\n return this._tiptapEditor.view.dom as HTMLDivElement\n }\n\n public clear() {\n this._tiptapEditor.commands.clearContent(true)\n this._tiptapEditor.commands.focus()\n }\n\n public getAllMentionBlocks(): Array<MentionItem> {\n const mentions: Array<MentionItem> = []\n\n const doc = this._tiptapEditor.state.doc\n\n doc.descendants((node, pos) => {\n if (node.type.name === 'mention') {\n mentions.push({\n id: node.attrs.id ?? null,\n label: node.attrs.label ?? null,\n })\n }\n })\n\n return mentions\n }\n}\n","import Document from '@tiptap/extension-document'\nimport Paragraph from '@tiptap/extension-paragraph'\nimport Text from '@tiptap/extension-text'\n\nexport const baseExtensions = [\n Document,\n Paragraph,\n Text,\n]\n","import { Extension } from '@tiptap/core'\nimport { Plugin } from 'prosemirror-state'\nimport { FileInputOptions } from './types'\n\nexport const FileInputExtension = Extension.create<FileInputOptions>({\n name: 'imageInput',\n\n addOptions() {\n return {\n onFileInput: undefined,\n }\n },\n\n addProseMirrorPlugins() {\n const handleFile = async (file: File) => {\n this.options.onFileInput?.(file)\n }\n\n return [\n new Plugin({\n props: {\n handlePaste: (_, event) => {\n const items = event.clipboardData?.items\n if (!items) return false\n\n for (const item of items) {\n if (item.kind !== 'file') continue\n const file = item.getAsFile()\n if (!file) continue\n\n handleFile(file)\n return true\n }\n\n return false\n },\n\n handleDrop: (_, event) => {\n const files = event.dataTransfer?.files\n if (!files || files.length === 0) return false\n\n handleFile(files[0])\n return true\n },\n },\n }),\n ]\n },\n})\n","import { findParentNode } from '@tiptap/core'\nimport { EditorState, Plugin, PluginKey } from 'prosemirror-state'\nimport { Decoration, DecorationSet, EditorView } from 'prosemirror-view'\nimport MEditor from '../../editor'\nimport { EventEmitter } from '../../utils/EventEmitter'\nimport { SuggestionMenuState, MentionItem } from './types'\n\ntype SuggestionPluginState =\n | {\n triggerCharacter: string\n deleteTriggerCharacter: boolean\n queryStartPos: number\n query: string\n decorationId: string\n ignoreQueryLength?: boolean\n }\n | undefined\n\nexport const suggestionMenuPluginKey = new PluginKey('SuggestionMenuPlugin')\nconst findBlock = findParentNode(node => node.type.name === 'blockContainer')\n\nclass SuggestionMenuView {\n pluginState: SuggestionPluginState\n public state?: SuggestionMenuState\n public emitUpdate: (triggerCharacter: string) => void\n private rootEl?: Document | ShadowRoot\n\n constructor(\n private readonly editor: MEditor,\n emitUpdate: (menuName: string, state: SuggestionMenuState) => void\n ) {\n this.pluginState = undefined\n\n this.emitUpdate = (menuName: string) => {\n if (!this.state) {\n throw new Error('Attempting to update uninitialized suggestions menu')\n }\n emitUpdate(menuName, {\n ...this.state,\n ignoreQueryLength: this.pluginState?.ignoreQueryLength,\n })\n }\n setTimeout(() => {\n this.rootEl = this.editor._tiptapEditor.view.root\n })\n\n }\n\n update(view: EditorView, prevState: EditorState) {\n\n const prev: SuggestionPluginState = suggestionMenuPluginKey.getState(prevState)\n const next: SuggestionPluginState = suggestionMenuPluginKey.getState(view.state)\n\n \n const started = prev === undefined && next !== undefined\n const stopped = prev !== undefined && next === undefined\n const changed = prev !== undefined && next !== undefined\n\n \n if (!started && !changed && !stopped) {\n return\n }\n\n this.pluginState = stopped ? prev : next\n\n if (stopped || !this.editor.isEditable) {\n\n this.state!.show = false\n this.emitUpdate(this.pluginState!.triggerCharacter)\n\n return\n }\n\n const decorationNode = this.rootEl?.querySelector(`[data-decoration-id=\"${this.pluginState!.decorationId}\"]`)\n\n if (this.editor.isEditable && decorationNode) {\n\n this.state = {\n show: true,\n referencePos: decorationNode.getBoundingClientRect(),\n query: this.pluginState!.query,\n }\n\n this.emitUpdate(this.pluginState!.triggerCharacter!)\n }\n }\n\n destroy() {\n\n }\n\n closeMenu = () => {\n this.editor.dispatch(this.editor._tiptapEditor.view.state.tr.setMeta(suggestionMenuPluginKey, null))\n }\n\n clearQuery = () => {\n if (this.pluginState === undefined) {\n return\n }\n\n this.editor._tiptapEditor\n .chain()\n .focus()\n .deleteRange({\n from:\n this.pluginState.queryStartPos! -\n (this.pluginState.deleteTriggerCharacter ? this.pluginState.triggerCharacter!.length : 0),\n to: this.editor._tiptapEditor.state.selection.from,\n })\n .run()\n }\n\n insertMention = (item: MentionItem) => {\n this.editor._tiptapEditor\n .chain()\n .focus()\n .insertContent({\n type: 'mention',\n attrs: item\n })\n .insertContent(' ')\n .run()\n }\n\n getReplaceRange() {\n if (!this.pluginState) return null\n\n const from = this.pluginState.queryStartPos -\n (this.pluginState.deleteTriggerCharacter ? this.pluginState.triggerCharacter.length : 0)\n\n const to = this.editor._tiptapEditor.state.selection.from\n\n return { from, to }\n }\n\n}\n\nexport class SuggestionMenuProseMirrorPlugin extends EventEmitter<any> {\n public view: SuggestionMenuView\n public readonly plugin: Plugin\n private triggerCharacters: string[] = []\n\n constructor(editor: MEditor) {\n super()\n const triggerCharacters = this.triggerCharacters\n\n this.plugin = new Plugin({\n key: suggestionMenuPluginKey,\n view: () => {\n this.view = new SuggestionMenuView(editor, (triggerCharacter, state) => {\n this.emit(`update ${triggerCharacter}`, state)\n })\n return this.view\n },\n state: {\n init(): SuggestionPluginState {\n return undefined\n },\n apply(transaction, prev, _oldState, newState): SuggestionPluginState {\n const suggestionPluginTransactionMeta: {\n triggerCharacter: string\n deleteTriggerCharacter?: boolean\n ignoreQueryLength?: boolean\n } | null = transaction.getMeta(suggestionMenuPluginKey)\n\n\n if (\n typeof suggestionPluginTransactionMeta === 'object' &&\n suggestionPluginTransactionMeta !== null &&\n prev === undefined\n ) {\n return {\n triggerCharacter: suggestionPluginTransactionMeta.triggerCharacter,\n deleteTriggerCharacter: suggestionPluginTransactionMeta.deleteTriggerCharacter !== false,\n queryStartPos: transaction.selection?.from || newState.selection.from,\n query: '',\n decorationId: `id_${Math.floor(Math.random() * 0xffffffff)}`,\n ignoreQueryLength: suggestionPluginTransactionMeta?.ignoreQueryLength,\n }\n }\n\n\n if (prev === undefined) {\n return prev\n }\n\n\n if (\n newState.selection.from !== newState.selection.to ||\n suggestionPluginTransactionMeta === null ||\n transaction.getMeta('focus') ||\n transaction.getMeta('blur') ||\n transaction.getMeta('pointer') ||\n (prev.triggerCharacter !== undefined && newState.selection.from < prev.queryStartPos!)\n ) {\n\n return undefined\n }\n\n const next = { ...prev }\n\n\n next.query = newState.doc.textBetween(prev.queryStartPos!, newState.selection.from)\n\n return next\n }\n },\n\n props: {\n // 当用户输入一个 trigger 字符,且当前没有 suggestion 激活时:\n // 插件拦截这次输入,自己插入字符,并通过 transaction meta 通知 state 打开 suggestion 菜单;\n // 其余情况下,完全不干预编辑器行为。\n handleTextInput(view, _from, _to, text) {\n\n const suggestionPluginState: SuggestionPluginState = (this as Plugin).getState(view.state)\n\n if (triggerCharacters.includes(text) && suggestionPluginState === undefined) {\n view.dispatch(\n view.state.tr.insertText(text).scrollIntoView().setMeta(suggestionMenuPluginKey, {\n triggerCharacter: text,\n })\n )\n\n return true\n }\n return false\n },\n\n decorations(state) {\n const suggestionPluginState: SuggestionPluginState = (this as Plugin).getState(state)\n\n if (suggestionPluginState === undefined) {\n return null\n }\n\n \n if (!suggestionPluginState.deleteTriggerCharacter) {\n const blockNode = findBlock(state.selection)\n if (blockNode) {\n return DecorationSet.create(state.doc, [\n Decoration.node(blockNode.pos, blockNode.pos + blockNode.node.nodeSize, {\n nodeName: 'span',\n class: 'bn-suggestion-decorator',\n 'data-decoration-id': suggestionPluginState.decorationId,\n }),\n ])\n }\n }\n \n return DecorationSet.create(state.doc, [\n Decoration.inline(\n suggestionPluginState.queryStartPos! - suggestionPluginState.triggerCharacter!.length,\n suggestionPluginState.queryStartPos!,\n {\n nodeName: 'span',\n class: 'bn-suggestion-decorator',\n 'data-decoration-id': suggestionPluginState.decorationId,\n }\n ),\n ])\n },\n }\n })\n }\n\n public onUpdate(triggerCharacter: string, callback: (state: SuggestionMenuState) => void) {\n if (!this.triggerCharacters.includes(triggerCharacter)) {\n this.addTriggerCharacter(triggerCharacter)\n }\n \n return this.on(`update ${triggerCharacter}`, callback)\n }\n\n addTriggerCharacter = (triggerCharacter: string) => {\n this.triggerCharacters.push(triggerCharacter)\n }\n\n \n removeTriggerCharacter = (triggerCharacter: string) => {\n this.triggerCharacters = this.triggerCharacters.filter(c => c !== triggerCharacter)\n }\n\n closeMenu = () => this.view!.closeMenu()\n\n clearQuery = () => this.view!.clearQuery()\n\n insertMention = (item: MentionItem) => this.view!.insertMention(item)\n\n public get shown() {\n return this.view?.state?.show || false\n }\n\n}\n","type StringKeyOf<T> = Extract<keyof T, string>\ntype CallbackType<T extends Record<string, any>, EventName extends StringKeyOf<T>> = T[EventName] extends any[]\n ? T[EventName]\n : [T[EventName]]\ntype CallbackFunction<T extends Record<string, any>, EventName extends StringKeyOf<T>> = (...props: CallbackType<T, EventName>) => any\n\nexport class EventEmitter<T extends Record<string, any>> {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n private callbacks: { [key: string]: Function[] } = {}\n\n public on<EventName extends StringKeyOf<T>>(event: EventName, fn: CallbackFunction<T, EventName>) {\n if (!this.callbacks[event]) {\n this.callbacks[event] = []\n }\n\n this.callbacks[event].push(fn)\n\n return () => this.off(event, fn)\n }\n\n protected emit<EventName extends StringKeyOf<T>>(event: EventName, ...args: CallbackType<T, EventName>) {\n const callbacks = this.callbacks[event]\n\n if (callbacks) {\n callbacks.forEach(callback => callback.apply(this, args))\n }\n }\n\n public off<EventName extends StringKeyOf<T>>(event: EventName, fn?: CallbackFunction<T, EventName>) {\n const callbacks = this.callbacks[event]\n\n if (callbacks) {\n if (fn) {\n this.callbacks[event] = callbacks.filter(callback => callback !== fn)\n } else {\n delete this.callbacks[event]\n }\n }\n }\n\n protected removeAllListeners(): void {\n this.callbacks = {}\n }\n}\n","import { Node } from '@tiptap/core'\n\nexport const MentionBlock = Node.create({\n name: 'mention',\n inline: true,\n group: 'inline',\n atom: true,\n selectable: false,\n\n addAttributes() {\n return {\n id: { default: null },\n label: { default: null },\n }\n },\n\n parseHTML() {\n return [\n {\n tag: 'span[data-type=\"mention\"]',\n },\n ]\n },\n\n renderHTML({ node }) {\n return [\n 'span',\n {\n class: 'mention',\n 'data-type': 'mention',\n 'data-id': node.attrs.id,\n 'data-label': node.attrs.label,\n contenteditable: 'false', // 非编辑\n },\n node.attrs.label,\n ]\n },\n\n // 新增:确保mention节点可以正确序列化/反序列化\n renderText({ node }) {\n return ''\n },\n})\n\n\n","import { Selection } from 'prosemirror-state'\nimport MEditor from '../editor'\n\nexport function InsertMentionBlock(\n editor: MEditor,\n item: { id: string; label: string }\n) {\n\n editor._tiptapEditor.chain().insertContent({\n type: 'mention',\n attrs: {\n id: item.id,\n label: item.label,\n }\n }).run() \n\n}\n\n","import { Plugin, PluginKey } from 'prosemirror-state'\nimport MEditor from '../../editor'\nimport { MentionItem } from '../SuggestionMenu/types'\n\nexport class MentionDeletePlugin {\n public readonly plugin: Plugin\n\n constructor(editor: MEditor, onMentionDelete?: (item: MentionItem) => void) {\n this.plugin = new Plugin({\n key: new PluginKey('mention-delete'),\n\n appendTransaction(transactions, oldState, newState) {\n if (!transactions.some(tr => tr.docChanged)) {\n return null\n }\n\n const oldMentions = new Map<string, any>()\n const newMentionIds = new Set<string>()\n\n oldState.doc.descendants(node => {\n if (node.type.name === 'mention' && node.attrs.id) {\n oldMentions.set(node.attrs.id, node.attrs)\n }\n })\n\n newState.doc.descendants(node => {\n if (node.type.name === 'mention' && node.attrs.id) {\n newMentionIds.add(node.attrs.id)\n }\n })\n\n for (const [id, attrs] of oldMentions.entries()) {\n if (!newMentionIds.has(id)) {\n onMentionDelete?.({\n id: attrs.id,\n label: attrs.label,\n })\n }\n }\n },\n })\n }\n} \n","import MEditor from \"./editor\";\n\nexport * from \"./extensions/SuggestionMenu/types\"\nexport * from \"./extensions/FileInput/types\"\n\nexport { MEditor }\nexport default MEditor"],"mappings":"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","names":["Editor","Extension","Document","Paragraph","Text","baseExtensions","History","Placeholder","Extension","Plugin","FileInputExtension","handleFile","file","_a","_b","_","event","items","item","files","findParentNode","Plugin","PluginKey","Decoration","DecorationSet","EventEmitter","__publicField","event","fn","args","callbacks","callback","suggestionMenuPluginKey","PluginKey","findBlock","findParentNode","node","SuggestionMenuView","editor","emitUpdate","__publicField","item","menuName","_a","view","prevState","prev","next","started","stopped","decorationNode","from","to","SuggestionMenuProseMirrorPlugin","EventEmitter","triggerCharacter","c","triggerCharacters","Plugin","state","transaction","_oldState","newState","suggestionPluginTransactionMeta","_from","_to","text","suggestionPluginState","blockNode","DecorationSet","Decoration","callback","_b","Node","MentionBlock","node","InsertMentionBlock","editor","item","Plugin","PluginKey","MentionDeletePlugin","editor","onMentionDelete","__publicField","Plugin","PluginKey","transactions","oldState","newState","tr","oldMentions","newMentionIds","node","id","attrs","MEditor","options","__publicField","SuggestionMenuProseMirrorPlugin","MentionDeletePlugin","MEditorUIExtension","Extension","Editor","baseExtensions","History","MentionBlock","Placeholder","FileInputExtension","editor","tr","item","InsertMentionBlock","mentions","node","pos","_a","_b","index_default","MEditor"]}
|
|
1
|
+
{"version":3,"sources":["../src/editor.ts","../src/schema/base.ts","../src/extensions/FileInput/FileInput.ts","../src/extensions/SuggestionMenu/SuggestionPlugin.ts","../src/utils/EventEmitter.ts","../src/blocks/MentionBlock.ts","../src/api/InsertMentionBlock.ts","../src/extensions/MentionDeletePlugin/MentionDeletePlugin.ts","../src/extensions/ShiftEnterPlugin/ShiftEnterPlugin.ts","../src/index.ts"],"sourcesContent":["import { Editor, Extension } from '@tiptap/core'\nimport { baseExtensions } from './schema/base'\nimport History from '@tiptap/extension-history'\nimport Placeholder from '@tiptap/extension-placeholder'\nimport { FileInputExtension } from './extensions/FileInput/FileInput'\nimport { Transaction } from 'prosemirror-state'\nimport { SuggestionMenuProseMirrorPlugin } from './extensions/SuggestionMenu/SuggestionPlugin'\nimport { MentionBlock } from './blocks/MentionBlock'\nimport { type MentionItem } from './extensions/SuggestionMenu/types'\nimport { InsertMentionBlock } from './api/InsertMentionBlock'\nimport { MentionDeletePlugin } from './extensions/MentionDeletePlugin/MentionDeletePlugin'\nimport { ShiftEnterPlugin } from './extensions/ShiftEnterPlugin/ShiftEnterPlugin'\n\nexport interface MentionEditorOptions {\n element: HTMLElement\n onChange: (text: string) => void\n placeholder?: string\n onFileInput?: (file: File) => void\n content?: string\n onMentionDelete?: (item: MentionItem) => void\n onEnter?: () => void\n lineBreak?: 'shift-enter' | 'enter'\n}\n\n\nexport default class MEditor {\n _tiptapEditor: Editor\n public readonly suggestionMenus: SuggestionMenuProseMirrorPlugin\n public readonly mentionDeletePlugin: MentionDeletePlugin\n public readonly shiftEnterPlugin: ShiftEnterPlugin\n\n constructor(options: MentionEditorOptions) {\n this.suggestionMenus = new SuggestionMenuProseMirrorPlugin(this)\n this.mentionDeletePlugin = new MentionDeletePlugin(this, options.onMentionDelete)\n\n if (options.lineBreak === 'shift-enter') {\n this.shiftEnterPlugin = new ShiftEnterPlugin(this, options.onEnter)\n }\n\n const MEditorUIExtension = Extension.create({\n name: 'MEditorUIExtension',\n addProseMirrorPlugins: () => {\n const plugins = [\n this.suggestionMenus.plugin,\n this.mentionDeletePlugin.plugin\n ]\n\n if (this.shiftEnterPlugin) {\n plugins.unshift(this.shiftEnterPlugin.plugin)\n }\n return plugins\n },\n })\n\n this._tiptapEditor = new Editor({\n element: options.element,\n content: options.content || '',\n extensions: [\n ...baseExtensions,\n History.configure({\n depth: 100,\n newGroupDelay: 500,\n }),\n MentionBlock,\n Placeholder.configure({\n placeholder: options.placeholder || '请输入...',\n emptyEditorClass: 'is-editor-empty'\n }),\n FileInputExtension.configure({\n onFileInput: options.onFileInput,\n }),\n MEditorUIExtension,\n ],\n onUpdate: ({ editor }) => {\n options.onChange(editor.getText())\n }\n })\n }\n\n\n dispatch(tr: Transaction) {\n this._tiptapEditor.view.dispatch(tr)\n }\n\n public inserMentionBlock(item: MentionItem) {\n InsertMentionBlock(this, item)\n // this._tiptapEditor\n // .chain()\n // .focus()\n // .insertContent({\n // type: 'mention',\n // attrs: item\n // })\n // .insertContent(' ')\n // .run()\n }\n\n public get isEditable(): boolean {\n return this._tiptapEditor.isEditable === undefined ? true : this._tiptapEditor.isEditable\n }\n\n public get domElement() {\n return this._tiptapEditor.view.dom as HTMLDivElement\n }\n\n public clear() {\n this._tiptapEditor.commands.clearContent(true)\n this._tiptapEditor.commands.focus()\n }\n\n public getAllMentionBlocks(): Array<MentionItem> {\n const mentions: Array<MentionItem> = []\n\n const doc = this._tiptapEditor.state.doc\n\n doc.descendants((node, pos) => {\n if (node.type.name === 'mention') {\n mentions.push({\n id: node.attrs.id ?? null,\n label: node.attrs.label ?? null,\n })\n }\n })\n\n return mentions\n }\n}\n","import Document from '@tiptap/extension-document'\nimport Paragraph from '@tiptap/extension-paragraph'\nimport Text from '@tiptap/extension-text'\nimport HardBreak from '@tiptap/extension-hard-break'\n\nexport const baseExtensions = [\n Document,\n Paragraph,\n Text,\n HardBreak,\n]\n","import { Extension } from '@tiptap/core'\nimport { Plugin } from 'prosemirror-state'\nimport { FileInputOptions } from './types'\n\nexport const FileInputExtension = Extension.create<FileInputOptions>({\n name: 'imageInput',\n\n addOptions() {\n return {\n onFileInput: undefined,\n }\n },\n\n addProseMirrorPlugins() {\n const handleFile = async (file: File) => {\n this.options.onFileInput?.(file)\n }\n\n return [\n new Plugin({\n props: {\n handlePaste: (_, event) => {\n const items = event.clipboardData?.items\n if (!items) return false\n\n for (const item of items) {\n if (item.kind !== 'file') continue\n const file = item.getAsFile()\n if (!file) continue\n\n handleFile(file)\n return true\n }\n\n return false\n },\n\n handleDrop: (_, event) => {\n const files = event.dataTransfer?.files\n if (!files || files.length === 0) return false\n\n handleFile(files[0])\n return true\n },\n },\n }),\n ]\n },\n})\n","import { findParentNode } from '@tiptap/core'\nimport { EditorState, Plugin, PluginKey } from 'prosemirror-state'\nimport { Decoration, DecorationSet, EditorView } from 'prosemirror-view'\nimport MEditor from '../../editor'\nimport { EventEmitter } from '../../utils/EventEmitter'\nimport { SuggestionMenuState, MentionItem } from './types'\n\ntype SuggestionPluginState =\n | {\n triggerCharacter: string\n deleteTriggerCharacter: boolean\n queryStartPos: number\n query: string\n decorationId: string\n ignoreQueryLength?: boolean\n }\n | undefined\n\nexport const suggestionMenuPluginKey = new PluginKey('SuggestionMenuPlugin')\nconst findBlock = findParentNode(node => node.type.name === 'blockContainer')\n\nclass SuggestionMenuView {\n pluginState: SuggestionPluginState\n public state?: SuggestionMenuState\n public emitUpdate: (triggerCharacter: string) => void\n private rootEl?: Document | ShadowRoot\n\n constructor(\n private readonly editor: MEditor,\n emitUpdate: (menuName: string, state: SuggestionMenuState) => void\n ) {\n this.pluginState = undefined\n\n this.emitUpdate = (menuName: string) => {\n if (!this.state) {\n throw new Error('Attempting to update uninitialized suggestions menu')\n }\n emitUpdate(menuName, {\n ...this.state,\n ignoreQueryLength: this.pluginState?.ignoreQueryLength,\n })\n }\n setTimeout(() => {\n this.rootEl = this.editor._tiptapEditor.view.root\n })\n\n }\n\n update(view: EditorView, prevState: EditorState) {\n\n const prev: SuggestionPluginState = suggestionMenuPluginKey.getState(prevState)\n const next: SuggestionPluginState = suggestionMenuPluginKey.getState(view.state)\n\n \n const started = prev === undefined && next !== undefined\n const stopped = prev !== undefined && next === undefined\n const changed = prev !== undefined && next !== undefined\n\n \n if (!started && !changed && !stopped) {\n return\n }\n\n this.pluginState = stopped ? prev : next\n\n if (stopped || !this.editor.isEditable) {\n\n this.state!.show = false\n this.emitUpdate(this.pluginState!.triggerCharacter)\n\n return\n }\n\n const decorationNode = this.rootEl?.querySelector(`[data-decoration-id=\"${this.pluginState!.decorationId}\"]`)\n\n if (this.editor.isEditable && decorationNode) {\n\n this.state = {\n show: true,\n referencePos: decorationNode.getBoundingClientRect(),\n query: this.pluginState!.query,\n }\n\n this.emitUpdate(this.pluginState!.triggerCharacter!)\n }\n }\n\n destroy() {\n\n }\n\n closeMenu = () => {\n this.editor.dispatch(this.editor._tiptapEditor.view.state.tr.setMeta(suggestionMenuPluginKey, null))\n }\n\n clearQuery = () => {\n if (this.pluginState === undefined) {\n return\n }\n\n this.editor._tiptapEditor\n .chain()\n .focus()\n .deleteRange({\n from:\n this.pluginState.queryStartPos! -\n (this.pluginState.deleteTriggerCharacter ? this.pluginState.triggerCharacter!.length : 0),\n to: this.editor._tiptapEditor.state.selection.from,\n })\n .run()\n }\n\n insertMention = (item: MentionItem) => {\n this.editor._tiptapEditor\n .chain()\n .focus()\n .insertContent({\n type: 'mention',\n attrs: item\n })\n .insertContent(' ')\n .run()\n }\n\n getReplaceRange() {\n if (!this.pluginState) return null\n\n const from = this.pluginState.queryStartPos -\n (this.pluginState.deleteTriggerCharacter ? this.pluginState.triggerCharacter.length : 0)\n\n const to = this.editor._tiptapEditor.state.selection.from\n\n return { from, to }\n }\n\n}\n\nexport class SuggestionMenuProseMirrorPlugin extends EventEmitter<any> {\n public view: SuggestionMenuView\n public readonly plugin: Plugin\n private triggerCharacters: string[] = []\n\n constructor(editor: MEditor) {\n super()\n const triggerCharacters = this.triggerCharacters\n\n this.plugin = new Plugin({\n key: suggestionMenuPluginKey,\n view: () => {\n this.view = new SuggestionMenuView(editor, (triggerCharacter, state) => {\n this.emit(`update ${triggerCharacter}`, state)\n })\n return this.view\n },\n state: {\n init(): SuggestionPluginState {\n return undefined\n },\n apply(transaction, prev, _oldState, newState): SuggestionPluginState {\n const suggestionPluginTransactionMeta: {\n triggerCharacter: string\n deleteTriggerCharacter?: boolean\n ignoreQueryLength?: boolean\n } | null = transaction.getMeta(suggestionMenuPluginKey)\n\n\n if (\n typeof suggestionPluginTransactionMeta === 'object' &&\n suggestionPluginTransactionMeta !== null &&\n prev === undefined\n ) {\n return {\n triggerCharacter: suggestionPluginTransactionMeta.triggerCharacter,\n deleteTriggerCharacter: suggestionPluginTransactionMeta.deleteTriggerCharacter !== false,\n queryStartPos: transaction.selection?.from || newState.selection.from,\n query: '',\n decorationId: `id_${Math.floor(Math.random() * 0xffffffff)}`,\n ignoreQueryLength: suggestionPluginTransactionMeta?.ignoreQueryLength,\n }\n }\n\n\n if (prev === undefined) {\n return prev\n }\n\n\n if (\n newState.selection.from !== newState.selection.to ||\n suggestionPluginTransactionMeta === null ||\n transaction.getMeta('focus') ||\n transaction.getMeta('blur') ||\n transaction.getMeta('pointer') ||\n (prev.triggerCharacter !== undefined && newState.selection.from < prev.queryStartPos!)\n ) {\n\n return undefined\n }\n\n const next = { ...prev }\n\n\n next.query = newState.doc.textBetween(prev.queryStartPos!, newState.selection.from)\n\n return next\n }\n },\n\n props: {\n // 当用户输入一个 trigger 字符,且当前没有 suggestion 激活时:\n // 插件拦截这次输入,自己插入字符,并通过 transaction meta 通知 state 打开 suggestion 菜单;\n // 其余情况下,完全不干预编辑器行为。\n handleTextInput(view, _from, _to, text) {\n\n const suggestionPluginState: SuggestionPluginState = (this as Plugin).getState(view.state)\n\n if (triggerCharacters.includes(text) && suggestionPluginState === undefined) {\n view.dispatch(\n view.state.tr.insertText(text).scrollIntoView().setMeta(suggestionMenuPluginKey, {\n triggerCharacter: text,\n })\n )\n\n return true\n }\n return false\n },\n\n decorations(state) {\n const suggestionPluginState: SuggestionPluginState = (this as Plugin).getState(state)\n\n if (suggestionPluginState === undefined) {\n return null\n }\n\n \n if (!suggestionPluginState.deleteTriggerCharacter) {\n const blockNode = findBlock(state.selection)\n if (blockNode) {\n return DecorationSet.create(state.doc, [\n Decoration.node(blockNode.pos, blockNode.pos + blockNode.node.nodeSize, {\n nodeName: 'span',\n class: 'bn-suggestion-decorator',\n 'data-decoration-id': suggestionPluginState.decorationId,\n }),\n ])\n }\n }\n \n return DecorationSet.create(state.doc, [\n Decoration.inline(\n suggestionPluginState.queryStartPos! - suggestionPluginState.triggerCharacter!.length,\n suggestionPluginState.queryStartPos!,\n {\n nodeName: 'span',\n class: 'bn-suggestion-decorator',\n 'data-decoration-id': suggestionPluginState.decorationId,\n }\n ),\n ])\n },\n }\n })\n }\n\n public onUpdate(triggerCharacter: string, callback: (state: SuggestionMenuState) => void) {\n if (!this.triggerCharacters.includes(triggerCharacter)) {\n this.addTriggerCharacter(triggerCharacter)\n }\n \n return this.on(`update ${triggerCharacter}`, callback)\n }\n\n addTriggerCharacter = (triggerCharacter: string) => {\n this.triggerCharacters.push(triggerCharacter)\n }\n\n \n removeTriggerCharacter = (triggerCharacter: string) => {\n this.triggerCharacters = this.triggerCharacters.filter(c => c !== triggerCharacter)\n }\n\n closeMenu = () => this.view!.closeMenu()\n\n clearQuery = () => this.view!.clearQuery()\n\n insertMention = (item: MentionItem) => this.view!.insertMention(item)\n\n public get shown() {\n return this.view?.state?.show || false\n }\n\n}\n","type StringKeyOf<T> = Extract<keyof T, string>\ntype CallbackType<T extends Record<string, any>, EventName extends StringKeyOf<T>> = T[EventName] extends any[]\n ? T[EventName]\n : [T[EventName]]\ntype CallbackFunction<T extends Record<string, any>, EventName extends StringKeyOf<T>> = (...props: CallbackType<T, EventName>) => any\n\nexport class EventEmitter<T extends Record<string, any>> {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n private callbacks: { [key: string]: Function[] } = {}\n\n public on<EventName extends StringKeyOf<T>>(event: EventName, fn: CallbackFunction<T, EventName>) {\n if (!this.callbacks[event]) {\n this.callbacks[event] = []\n }\n\n this.callbacks[event].push(fn)\n\n return () => this.off(event, fn)\n }\n\n protected emit<EventName extends StringKeyOf<T>>(event: EventName, ...args: CallbackType<T, EventName>) {\n const callbacks = this.callbacks[event]\n\n if (callbacks) {\n callbacks.forEach(callback => callback.apply(this, args))\n }\n }\n\n public off<EventName extends StringKeyOf<T>>(event: EventName, fn?: CallbackFunction<T, EventName>) {\n const callbacks = this.callbacks[event]\n\n if (callbacks) {\n if (fn) {\n this.callbacks[event] = callbacks.filter(callback => callback !== fn)\n } else {\n delete this.callbacks[event]\n }\n }\n }\n\n protected removeAllListeners(): void {\n this.callbacks = {}\n }\n}\n","import { Node } from '@tiptap/core'\n\nexport const MentionBlock = Node.create({\n name: 'mention',\n inline: true,\n group: 'inline',\n atom: true,\n selectable: false,\n\n addAttributes() {\n return {\n id: { default: null },\n label: { default: null },\n }\n },\n\n parseHTML() {\n return [\n {\n tag: 'span[data-type=\"mention\"]',\n },\n ]\n },\n\n renderHTML({ node }) {\n return [\n 'span',\n {\n class: 'mention',\n 'data-type': 'mention',\n 'data-id': node.attrs.id,\n 'data-label': node.attrs.label,\n contenteditable: 'false', // 非编辑\n },\n node.attrs.label,\n ]\n },\n\n // 新增:确保mention节点可以正确序列化/反序列化\n renderText({ node }) {\n return ''\n },\n})\n\n\n","import { Selection } from 'prosemirror-state'\nimport MEditor from '../editor'\n\nexport function InsertMentionBlock(\n editor: MEditor,\n item: { id: string; label: string }\n) {\n\n editor._tiptapEditor.chain().insertContent({\n type: 'mention',\n attrs: {\n id: item.id,\n label: item.label,\n }\n }).run() \n\n}\n\n","import { Plugin, PluginKey } from 'prosemirror-state'\nimport MEditor from '../../editor'\nimport { MentionItem } from '../SuggestionMenu/types'\n\nexport class MentionDeletePlugin {\n public readonly plugin: Plugin\n\n constructor(editor: MEditor, onMentionDelete?: (item: MentionItem) => void) {\n this.plugin = new Plugin({\n key: new PluginKey('mention-delete'),\n\n appendTransaction(transactions, oldState, newState) {\n if (!transactions.some(tr => tr.docChanged)) {\n return null\n }\n\n const oldMentions = new Map<string, any>()\n const newMentionIds = new Set<string>()\n\n oldState.doc.descendants(node => {\n if (node.type.name === 'mention' && node.attrs.id) {\n oldMentions.set(node.attrs.id, node.attrs)\n }\n })\n\n newState.doc.descendants(node => {\n if (node.type.name === 'mention' && node.attrs.id) {\n newMentionIds.add(node.attrs.id)\n }\n })\n\n for (const [id, attrs] of oldMentions.entries()) {\n if (!newMentionIds.has(id)) {\n onMentionDelete?.({\n id: attrs.id,\n label: attrs.label,\n })\n }\n }\n },\n })\n }\n} \n","import { Plugin, PluginKey } from 'prosemirror-state'\nimport MEditor from '../../editor'\n\nexport class ShiftEnterPlugin {\n public readonly plugin: Plugin\n\n constructor(editor: MEditor, onEnter?: () => void) {\n this.plugin = new Plugin({\n key: new PluginKey('shift-enter'),\n\n props: {\n handleKeyDown(view, event) {\n // 只处理 Enter\n if (event.key !== 'Enter') {\n return false\n }\n\n // Shift + Enter:插入换行\n if (event.shiftKey) {\n event.preventDefault()\n\n const { state, dispatch } = view\n const { hard_break } = state.schema.nodes\n \n if (!hard_break) {\n return false\n }\n\n dispatch(state.tr.replaceSelectionWith(hard_break.create()).scrollIntoView())\n\n return true\n }\n\n // 普通 Enter 如果 suggestion 菜单打开,让 suggestionPlugin 处理\n if (editor.suggestionMenus.shown) {\n return false\n }\n\n if (onEnter) {\n onEnter()\n return true\n }\n return false\n },\n },\n\n })\n }\n}","import MEditor from \"./editor\";\n\nexport * from \"./extensions/SuggestionMenu/types\"\nexport * from \"./extensions/FileInput/types\"\n\nexport { MEditor }\nexport default MEditor"],"mappings":"oKAAA,OAAS,UAAAA,EAAQ,aAAAC,MAAiB,eCAlC,OAAOC,MAAc,6BACrB,OAAOC,MAAe,8BACtB,OAAOC,MAAU,yBACjB,OAAOC,MAAe,+BAEf,IAAMC,EAAiB,CAC1BJ,EACAC,EACAC,EACAC,CACJ,EDRA,OAAOE,MAAa,4BACpB,OAAOC,MAAiB,gCEHxB,OAAS,aAAAC,MAAiB,eAC1B,OAAS,UAAAC,MAAc,oBAGhB,IAAMC,EAAqBF,EAAU,OAAyB,CACjE,KAAM,aAEN,YAAa,CACT,MAAO,CACH,YAAa,MACjB,CACJ,EAEA,uBAAwB,CACpB,IAAMG,EAAa,MAAOC,GAAe,CAdjD,IAAAC,EAAAC,GAeYA,GAAAD,EAAA,KAAK,SAAQ,cAAb,MAAAC,EAAA,KAAAD,EAA2BD,EAC/B,EAEA,MAAO,CACH,IAAIH,EAAO,CACP,MAAO,CACH,YAAa,CAACM,EAAGC,IAAU,CArB/C,IAAAH,EAsBwB,IAAMI,GAAQJ,EAAAG,EAAM,gBAAN,YAAAH,EAAqB,MACnC,GAAI,CAACI,EAAO,MAAO,GAEnB,QAAWC,KAAQD,EAAO,CACtB,GAAIC,EAAK,OAAS,OAAQ,SAC1B,IAAMN,EAAOM,EAAK,UAAU,EAC5B,GAAKN,EAEL,OAAAD,EAAWC,CAAI,EACR,EACX,CAEA,MAAO,EACX,EAEA,WAAY,CAACG,EAAGC,IAAU,CArC9C,IAAAH,EAsCwB,IAAMM,GAAQN,EAAAG,EAAM,eAAN,YAAAH,EAAoB,MAClC,MAAI,CAACM,GAASA,EAAM,SAAW,EAAU,IAEzCR,EAAWQ,EAAM,CAAC,CAAC,EACZ,GACX,CACJ,CACJ,CAAC,CACL,CACJ,CACJ,CAAC,EChDD,OAAS,kBAAAC,MAAsB,eAC/B,OAAsB,UAAAC,EAAQ,aAAAC,MAAiB,oBAC/C,OAAS,cAAAC,EAAY,iBAAAC,MAAiC,mBCI/C,IAAMC,EAAN,KAAkD,CAAlD,cAEHC,EAAA,KAAQ,YAA2C,CAAC,GAE7C,GAAqCC,EAAkBC,EAAoC,CAC9F,OAAK,KAAK,UAAUD,CAAK,IACrB,KAAK,UAAUA,CAAK,EAAI,CAAC,GAG7B,KAAK,UAAUA,CAAK,EAAE,KAAKC,CAAE,EAEtB,IAAM,KAAK,IAAID,EAAOC,CAAE,CACnC,CAEU,KAAuCD,KAAqBE,EAAkC,CACpG,IAAMC,EAAY,KAAK,UAAUH,CAAK,EAElCG,GACAA,EAAU,QAAQC,GAAYA,EAAS,MAAM,KAAMF,CAAI,CAAC,CAEhE,CAEO,IAAsCF,EAAkBC,EAAqC,CAChG,IAAME,EAAY,KAAK,UAAUH,CAAK,EAElCG,IACIF,EACA,KAAK,UAAUD,CAAK,EAAIG,EAAU,OAAOC,GAAYA,IAAaH,CAAE,EAEpE,OAAO,KAAK,UAAUD,CAAK,EAGvC,CAEU,oBAA2B,CACjC,KAAK,UAAY,CAAC,CACtB,CACJ,EDzBO,IAAMK,EAA0B,IAAIC,EAAU,sBAAsB,EACrEC,EAAYC,EAAeC,GAAQA,EAAK,KAAK,OAAS,gBAAgB,EAEtEC,EAAN,KAAyB,CAMrB,YACqBC,EACjBC,EACF,CAFmB,YAAAD,EANrBE,EAAA,oBACAA,EAAA,KAAO,SACPA,EAAA,KAAO,cACPA,EAAA,KAAQ,UAkERA,EAAA,iBAAY,IAAM,CACd,KAAK,OAAO,SAAS,KAAK,OAAO,cAAc,KAAK,MAAM,GAAG,QAAQR,EAAyB,IAAI,CAAC,CACvG,GAEAQ,EAAA,kBAAa,IAAM,CACX,KAAK,cAAgB,QAIzB,KAAK,OAAO,cACP,MAAM,EACN,MAAM,EACN,YAAY,CACT,KACI,KAAK,YAAY,eAChB,KAAK,YAAY,uBAAyB,KAAK,YAAY,iBAAkB,OAAS,GAC3F,GAAI,KAAK,OAAO,cAAc,MAAM,UAAU,IAClD,CAAC,EACA,IAAI,CACb,GAEAA,EAAA,qBAAiBC,GAAsB,CACnC,KAAK,OAAO,cACP,MAAM,EACN,MAAM,EACN,cAAc,CACX,KAAM,UACN,MAAOA,CACX,CAAC,EACA,cAAc,GAAG,EACjB,IAAI,CACb,GA3FI,KAAK,YAAc,OAEnB,KAAK,WAAcC,GAAqB,CAjChD,IAAAC,EAkCY,GAAI,CAAC,KAAK,MACN,MAAM,IAAI,MAAM,qDAAqD,EAEzEJ,EAAWG,EAAU,CACjB,GAAG,KAAK,MACR,mBAAmBC,EAAA,KAAK,cAAL,YAAAA,EAAkB,iBACzC,CAAC,CACL,EACA,WAAW,IAAM,CACb,KAAK,OAAS,KAAK,OAAO,cAAc,KAAK,IACjD,CAAC,CAEL,CAEA,OAAOC,EAAkBC,EAAwB,CAhDrD,IAAAF,EAkDQ,IAAMG,EAA8Bd,EAAwB,SAASa,CAAS,EACxEE,EAA8Bf,EAAwB,SAASY,EAAK,KAAK,EAGzEI,EAAUF,IAAS,QAAaC,IAAS,OACzCE,EAAUH,IAAS,QAAaC,IAAS,OAI/C,GAAI,CAACC,GAAW,EAHAF,IAAS,QAAaC,IAAS,SAGnB,CAACE,EACzB,OAKJ,GAFA,KAAK,YAAcA,EAAUH,EAAOC,EAEhCE,GAAW,CAAC,KAAK,OAAO,WAAY,CAEpC,KAAK,MAAO,KAAO,GACnB,KAAK,WAAW,KAAK,YAAa,gBAAgB,EAElD,MACJ,CAEA,IAAMC,GAAiBP,EAAA,KAAK,SAAL,YAAAA,EAAa,cAAc,wBAAwB,KAAK,YAAa,YAAY,MAEpG,KAAK,OAAO,YAAcO,IAE1B,KAAK,MAAQ,CACT,KAAM,GACN,aAAcA,EAAe,sBAAsB,EACnD,MAAO,KAAK,YAAa,KAC7B,EAEA,KAAK,WAAW,KAAK,YAAa,gBAAiB,EAE3D,CAEA,SAAU,CAEV,CAmCA,iBAAkB,CACd,GAAI,CAAC,KAAK,YAAa,OAAO,KAE9B,IAAMC,EAAO,KAAK,YAAY,eACzB,KAAK,YAAY,uBAAyB,KAAK,YAAY,iBAAiB,OAAS,GAEpFC,EAAK,KAAK,OAAO,cAAc,MAAM,UAAU,KAErD,MAAO,CAAE,KAAAD,EAAM,GAAAC,CAAG,CACtB,CAEJ,EAEaC,EAAN,cAA8CC,CAAkB,CAKnE,YAAYhB,EAAiB,CACzB,MAAM,EALVE,EAAA,KAAO,QACPA,EAAA,KAAgB,UAChBA,EAAA,KAAQ,oBAA8B,CAAC,GAqIvCA,EAAA,2BAAuBe,GAA6B,CAChD,KAAK,kBAAkB,KAAKA,CAAgB,CAChD,GAGAf,EAAA,8BAA0Be,GAA6B,CACnD,KAAK,kBAAoB,KAAK,kBAAkB,OAAOC,GAAKA,IAAMD,CAAgB,CACtF,GAEAf,EAAA,iBAAY,IAAM,KAAK,KAAM,UAAU,GAEvCA,EAAA,kBAAa,IAAM,KAAK,KAAM,WAAW,GAEzCA,EAAA,qBAAiBC,GAAsB,KAAK,KAAM,cAAcA,CAAI,GA9IhE,IAAMgB,EAAoB,KAAK,kBAE/B,KAAK,OAAS,IAAIC,EAAO,CACrB,IAAK1B,EACL,KAAM,KACF,KAAK,KAAO,IAAIK,EAAmBC,EAAQ,CAACiB,EAAkBI,IAAU,CACpE,KAAK,KAAK,UAAUJ,CAAgB,GAAII,CAAK,CACjD,CAAC,EACM,KAAK,MAEhB,MAAO,CACH,MAA8B,CAE9B,EACA,MAAMC,EAAad,EAAMe,EAAWC,EAAiC,CA9JrF,IAAAnB,EA+JoB,IAAMoB,EAIKH,EAAY,QAAQ5B,CAAuB,EAGtD,GACI,OAAO+B,GAAoC,UAC3CA,IAAoC,MACpCjB,IAAS,OAET,MAAO,CACH,iBAAkBiB,EAAgC,iBAClD,uBAAwBA,EAAgC,yBAA2B,GACnF,gBAAepB,EAAAiB,EAAY,YAAZ,YAAAjB,EAAuB,OAAQmB,EAAS,UAAU,KACjE,MAAO,GACP,aAAc,MAAM,KAAK,MAAM,KAAK,OAAO,EAAI,UAAU,CAAC,GAC1D,kBAAmBC,GAAA,YAAAA,EAAiC,iBACxD,EAIJ,GAAIjB,IAAS,OACT,OAAOA,EAIX,GACIgB,EAAS,UAAU,OAASA,EAAS,UAAU,IAC/CC,IAAoC,MACpCH,EAAY,QAAQ,OAAO,GAC3BA,EAAY,QAAQ,MAAM,GAC1BA,EAAY,QAAQ,SAAS,GAC5Bd,EAAK,mBAAqB,QAAagB,EAAS,UAAU,KAAOhB,EAAK,cAGvE,OAGJ,IAAMC,EAAO,CAAE,GAAGD,CAAK,EAGvB,OAAAC,EAAK,MAAQe,EAAS,IAAI,YAAYhB,EAAK,cAAgBgB,EAAS,UAAU,IAAI,EAE3Ef,CACX,CACJ,EAEA,MAAO,CAIH,gBAAgBH,EAAMoB,EAAOC,EAAKC,EAAM,CAEpC,IAAMC,EAAgD,KAAgB,SAASvB,EAAK,KAAK,EAEzF,OAAIa,EAAkB,SAASS,CAAI,GAAKC,IAA0B,QAC9DvB,EAAK,SACDA,EAAK,MAAM,GAAG,WAAWsB,CAAI,EAAE,eAAe,EAAE,QAAQlC,EAAyB,CAC7E,iBAAkBkC,CACtB,CAAC,CACL,EAEO,IAEJ,EACX,EAEA,YAAYP,EAAO,CACf,IAAMQ,EAAgD,KAAgB,SAASR,CAAK,EAEpF,GAAIQ,IAA0B,OAC1B,OAAO,KAIX,GAAI,CAACA,EAAsB,uBAAwB,CAC/C,IAAMC,EAAYlC,EAAUyB,EAAM,SAAS,EAC3C,GAAIS,EACA,OAAOC,EAAc,OAAOV,EAAM,IAAK,CACnCW,EAAW,KAAKF,EAAU,IAAKA,EAAU,IAAMA,EAAU,KAAK,SAAU,CACpE,SAAU,OACV,MAAO,0BACP,qBAAsBD,EAAsB,YAChD,CAAC,CACL,CAAC,CAET,CAEA,OAAOE,EAAc,OAAOV,EAAM,IAAK,CACnCW,EAAW,OACPH,EAAsB,cAAiBA,EAAsB,iBAAkB,OAC/EA,EAAsB,cACtB,CACI,SAAU,OACV,MAAO,0BACP,qBAAsBA,EAAsB,YAChD,CACJ,CACJ,CAAC,CACL,CACJ,CACJ,CAAC,CACL,CAEO,SAASZ,EAA0BgB,EAAgD,CACtF,OAAK,KAAK,kBAAkB,SAAShB,CAAgB,GACjD,KAAK,oBAAoBA,CAAgB,EAGtC,KAAK,GAAG,UAAUA,CAAgB,GAAIgB,CAAQ,CACzD,CAiBA,IAAW,OAAQ,CAhSvB,IAAA5B,EAAA6B,EAiSQ,QAAOA,GAAA7B,EAAA,KAAK,OAAL,YAAAA,EAAW,QAAX,YAAA6B,EAAkB,OAAQ,EACrC,CAEJ,EEpSA,OAAS,QAAAC,MAAY,eAEd,IAAMC,EAAeD,EAAK,OAAO,CACpC,KAAM,UACN,OAAQ,GACR,MAAO,SACP,KAAM,GACN,WAAY,GAEZ,eAAgB,CACZ,MAAO,CACH,GAAI,CAAE,QAAS,IAAK,EACpB,MAAO,CAAE,QAAS,IAAK,CAC3B,CACJ,EAEA,WAAY,CACR,MAAO,CACH,CACI,IAAK,2BACT,CACJ,CACJ,EAEA,WAAW,CAAE,KAAAE,CAAK,EAAG,CACjB,MAAO,CACH,OACA,CACI,MAAO,UACP,YAAa,UACb,UAAWA,EAAK,MAAM,GACtB,aAAcA,EAAK,MAAM,MACzB,gBAAiB,OACrB,EACAA,EAAK,MAAM,KACf,CACJ,EAGA,WAAW,CAAE,KAAAA,CAAK,EAAG,CACjB,MAAO,EACX,CACJ,CAAC,ECvCM,SAASC,EACZC,EACAC,EACF,CAEED,EAAO,cAAc,MAAM,EAAE,cAAc,CACvC,KAAM,UACN,MAAO,CACH,GAAIC,EAAK,GACT,MAAOA,EAAK,KAChB,CACJ,CAAC,EAAE,IAAI,CAEX,CChBA,OAAS,UAAAC,EAAQ,aAAAC,MAAiB,oBAI3B,IAAMC,EAAN,KAA0B,CAG7B,YAAYC,EAAiBC,EAA+C,CAF5EC,EAAA,KAAgB,UAGZ,KAAK,OAAS,IAAIC,EAAO,CACrB,IAAK,IAAIC,EAAU,gBAAgB,EAEnC,kBAAkBC,EAAcC,EAAUC,EAAU,CAChD,GAAI,CAACF,EAAa,KAAKG,GAAMA,EAAG,UAAU,EACtC,OAAO,KAGX,IAAMC,EAAc,IAAI,IAClBC,EAAgB,IAAI,IAE1BJ,EAAS,IAAI,YAAYK,GAAQ,CACzBA,EAAK,KAAK,OAAS,WAAaA,EAAK,MAAM,IAC3CF,EAAY,IAAIE,EAAK,MAAM,GAAIA,EAAK,KAAK,CAEjD,CAAC,EAEDJ,EAAS,IAAI,YAAYI,GAAQ,CACzBA,EAAK,KAAK,OAAS,WAAaA,EAAK,MAAM,IAC3CD,EAAc,IAAIC,EAAK,MAAM,EAAE,CAEvC,CAAC,EAED,OAAW,CAACC,EAAIC,CAAK,IAAKJ,EAAY,QAAQ,EACrCC,EAAc,IAAIE,CAAE,GACrBX,GAAA,MAAAA,EAAkB,CACd,GAAIY,EAAM,GACV,MAAOA,EAAM,KACjB,EAGZ,CACJ,CAAC,CACL,CACJ,EC1CA,OAAS,UAAAC,EAAQ,aAAAC,MAAiB,oBAG3B,IAAMC,EAAN,KAAuB,CAG1B,YAAYC,EAAiBC,EAAsB,CAFnDC,EAAA,KAAgB,UAGZ,KAAK,OAAS,IAAIC,EAAO,CACrB,IAAK,IAAIC,EAAU,aAAa,EAEhC,MAAO,CACH,cAAcC,EAAMC,EAAO,CAEvB,GAAIA,EAAM,MAAQ,QACd,MAAO,GAIX,GAAIA,EAAM,SAAU,CAChBA,EAAM,eAAe,EAErB,GAAM,CAAE,MAAAC,EAAO,SAAAC,CAAS,EAAIH,EACtB,CAAE,WAAAI,CAAW,EAAIF,EAAM,OAAO,MAEpC,OAAKE,GAILD,EAASD,EAAM,GAAG,qBAAqBE,EAAW,OAAO,CAAC,EAAE,eAAe,CAAC,EAErE,IALI,EAMf,CAGA,OAAIT,EAAO,gBAAgB,MAChB,GAGPC,GACAA,EAAQ,EACD,IAEJ,EACX,CACJ,CAEJ,CAAC,CACL,CACJ,ERvBA,IAAqBS,EAArB,KAA6B,CAMzB,YAAYC,EAA+B,CAL3CC,EAAA,sBACAA,EAAA,KAAgB,mBAChBA,EAAA,KAAgB,uBAChBA,EAAA,KAAgB,oBAGZ,KAAK,gBAAkB,IAAIC,EAAgC,IAAI,EAC/D,KAAK,oBAAsB,IAAIC,EAAoB,KAAMH,EAAQ,eAAe,EAE5EA,EAAQ,YAAc,gBACtB,KAAK,iBAAmB,IAAII,EAAiB,KAAMJ,EAAQ,OAAO,GAGtE,IAAMK,EAAqBC,EAAU,OAAO,CACxC,KAAM,qBACN,sBAAuB,IAAM,CACzB,IAAMC,EAAU,CACZ,KAAK,gBAAgB,OACrB,KAAK,oBAAoB,MAC7B,EAEA,OAAI,KAAK,kBACLA,EAAQ,QAAQ,KAAK,iBAAiB,MAAM,EAEzCA,CACX,CACJ,CAAC,EAED,KAAK,cAAgB,IAAIC,EAAO,CAC5B,QAASR,EAAQ,QACjB,QAASA,EAAQ,SAAW,GAC5B,WAAY,CACR,GAAGS,EACHC,EAAQ,UAAU,CACd,MAAO,IACP,cAAe,GACnB,CAAC,EACDC,EACAC,EAAY,UAAU,CAClB,YAAaZ,EAAQ,aAAe,wBACpC,iBAAkB,iBACtB,CAAC,EACDa,EAAmB,UAAU,CACzB,YAAab,EAAQ,WACzB,CAAC,EACDK,CACJ,EACA,SAAU,CAAC,CAAE,OAAAS,CAAO,IAAM,CACtBd,EAAQ,SAASc,EAAO,QAAQ,CAAC,CACrC,CACJ,CAAC,CACL,CAGA,SAASC,EAAiB,CACtB,KAAK,cAAc,KAAK,SAASA,CAAE,CACvC,CAEO,kBAAkBC,EAAmB,CACxCC,EAAmB,KAAMD,CAAI,CAUjC,CAEA,IAAW,YAAsB,CAC7B,OAAO,KAAK,cAAc,aAAe,OAAY,GAAO,KAAK,cAAc,UACnF,CAEA,IAAW,YAAa,CACpB,OAAO,KAAK,cAAc,KAAK,GACnC,CAEO,OAAQ,CACX,KAAK,cAAc,SAAS,aAAa,EAAI,EAC7C,KAAK,cAAc,SAAS,MAAM,CACtC,CAEO,qBAA0C,CAC7C,IAAME,EAA+B,CAAC,EAItC,OAFY,KAAK,cAAc,MAAM,IAEjC,YAAY,CAACC,EAAMC,IAAQ,CAnHvC,IAAAC,EAAAC,EAoHgBH,EAAK,KAAK,OAAS,WACnBD,EAAS,KAAK,CACV,IAAIG,EAAAF,EAAK,MAAM,KAAX,KAAAE,EAAiB,KACrB,OAAOC,EAAAH,EAAK,MAAM,QAAX,KAAAG,EAAoB,IAC/B,CAAC,CAET,CAAC,EAEMJ,CACX,CACJ,ESxHA,IAAOK,GAAQC","names":["Editor","Extension","Document","Paragraph","Text","HardBreak","baseExtensions","History","Placeholder","Extension","Plugin","FileInputExtension","handleFile","file","_a","_b","_","event","items","item","files","findParentNode","Plugin","PluginKey","Decoration","DecorationSet","EventEmitter","__publicField","event","fn","args","callbacks","callback","suggestionMenuPluginKey","PluginKey","findBlock","findParentNode","node","SuggestionMenuView","editor","emitUpdate","__publicField","item","menuName","_a","view","prevState","prev","next","started","stopped","decorationNode","from","to","SuggestionMenuProseMirrorPlugin","EventEmitter","triggerCharacter","c","triggerCharacters","Plugin","state","transaction","_oldState","newState","suggestionPluginTransactionMeta","_from","_to","text","suggestionPluginState","blockNode","DecorationSet","Decoration","callback","_b","Node","MentionBlock","node","InsertMentionBlock","editor","item","Plugin","PluginKey","MentionDeletePlugin","editor","onMentionDelete","__publicField","Plugin","PluginKey","transactions","oldState","newState","tr","oldMentions","newMentionIds","node","id","attrs","Plugin","PluginKey","ShiftEnterPlugin","editor","onEnter","__publicField","Plugin","PluginKey","view","event","state","dispatch","hard_break","MEditor","options","__publicField","SuggestionMenuProseMirrorPlugin","MentionDeletePlugin","ShiftEnterPlugin","MEditorUIExtension","Extension","plugins","Editor","baseExtensions","History","MentionBlock","Placeholder","FileInputExtension","editor","tr","item","InsertMentionBlock","mentions","node","pos","_a","_b","index_default","MEditor"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shenjipo/mention-editor",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"module": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"@tiptap/extension-paragraph": "2.7.1",
|
|
27
27
|
"@tiptap/extension-placeholder": "2.7.1",
|
|
28
28
|
"@tiptap/extension-text": "2.7.1",
|
|
29
|
+
"@tiptap/extension-hard-break": "2.7.1",
|
|
29
30
|
"prosemirror-model": "^1.21.0",
|
|
30
31
|
"prosemirror-state": "^1.4.3",
|
|
31
32
|
"prosemirror-view": "^1.33.7"
|