@shenjipo/mention-editor 2.5.0 → 2.6.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 CHANGED
@@ -76,7 +76,8 @@ interface MentionEditorOptions {
76
76
  onChange: (text: string) => void;
77
77
  placeholder?: string;
78
78
  onFileInput?: (file: File) => void;
79
- onMentionDelete: (item: MentionItem) => void;
79
+ content?: string;
80
+ onMentionDelete?: (item: MentionItem) => void;
80
81
  }
81
82
  declare class MEditor {
82
83
  _tiptapEditor: Editor;
package/dist/index.d.ts CHANGED
@@ -76,7 +76,8 @@ interface MentionEditorOptions {
76
76
  onChange: (text: string) => void;
77
77
  placeholder?: string;
78
78
  onFileInput?: (file: File) => void;
79
- onMentionDelete: (item: MentionItem) => void;
79
+ content?: string;
80
+ onMentionDelete?: (item: MentionItem) => void;
80
81
  }
81
82
  declare class MEditor {
82
83
  _tiptapEditor: Editor;
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- var K=Object.create;var m=Object.defineProperty;var Q=Object.getOwnPropertyDescriptor;var R=Object.getOwnPropertyNames;var U=Object.getPrototypeOf,A=Object.prototype.hasOwnProperty;var H=(r,t,e)=>t in r?m(r,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):r[t]=e;var $=(r,t)=>{for(var e in t)m(r,e,{get:t[e],enumerable:!0})},T=(r,t,e,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of R(t))!A.call(r,i)&&i!==e&&m(r,i,{get:()=>t[i],enumerable:!(n=Q(t,i))||n.enumerable});return r};var h=(r,t,e)=>(e=r!=null?K(U(r)):{},T(t||!r||!r.__esModule?m(e,"default",{value:r,enumerable:!0}):e,r)),V=r=>T(m({},"__esModule",{value:!0}),r);var s=(r,t,e)=>H(r,typeof t!="symbol"?t+"":t,e);var G={};$(G,{MEditor:()=>p,default:()=>j});module.exports=V(G);var M=require("@tiptap/core");var x=h(require("@tiptap/extension-document")),I=h(require("@tiptap/extension-paragraph")),k=h(require("@tiptap/extension-text")),v=[x.default,I.default,k.default];var D=h(require("@tiptap/extension-history")),B=h(require("@tiptap/extension-placeholder"));var w=require("@tiptap/core"),N=require("prosemirror-state"),_=w.Extension.create({name:"imageInput",addOptions(){return{onFileInput:void 0}},addProseMirrorPlugins(){let r=async t=>{var e,n;(n=(e=this.options).onFileInput)==null||n.call(e,t)};return[new N.Plugin({props:{handlePaste:(t,e)=>{var i;let n=(i=e.clipboardData)==null?void 0:i.items;if(!n)return!1;for(let o of n){if(o.kind!=="file")continue;let l=o.getAsFile();if(l)return r(l),!0}return!1},handleDrop:(t,e)=>{var i;let n=(i=e.dataTransfer)==null?void 0:i.files;return!n||n.length===0?!1:(r(n[0]),!0)}}})]}});var F=require("@tiptap/core"),E=require("prosemirror-state"),g=require("prosemirror-view");var f=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 n=this.callbacks[t];n&&n.forEach(i=>i.apply(this,e))}off(t,e){let n=this.callbacks[t];n&&(e?this.callbacks[t]=n.filter(i=>i!==e):delete this.callbacks[t])}removeAllListeners(){this.callbacks={}}};var c=new E.PluginKey("SuggestionMenuPlugin"),z=(0,F.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(c,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=n=>{var i;if(!this.state)throw new Error("Attempting to update uninitialized suggestions menu");e(n,{...this.state,ignoreQueryLength:(i=this.pluginState)==null?void 0:i.ignoreQueryLength})},setTimeout(()=>{this.rootEl=this.editor._tiptapEditor.view.root})}update(t,e){var u;let n=c.getState(e),i=c.getState(t.state),o=n===void 0&&i!==void 0,l=n!==void 0&&i===void 0;if(!o&&!(n!==void 0&&i!==void 0)&&!l)return;if(this.pluginState=l?n:i,l||!this.editor.isEditable){this.state.show=!1,this.emitUpdate(this.pluginState.triggerCharacter);return}let a=(u=this.rootEl)==null?void 0:u.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 f{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(n=>n!==e)});s(this,"closeMenu",()=>this.view.closeMenu());s(this,"clearQuery",()=>this.view.clearQuery());s(this,"insertMention",e=>this.view.insertMention(e));let n=this.triggerCharacters;this.plugin=new E.Plugin({key:c,view:()=>(this.view=new C(e,(i,o)=>{this.emit(`update ${i}`,o)}),this.view),state:{init(){},apply(i,o,l,d){var P;let a=i.getMeta(c);if(typeof a=="object"&&a!==null&&o===void 0)return{triggerCharacter:a.triggerCharacter,deleteTriggerCharacter:a.deleteTriggerCharacter!==!1,queryStartPos:((P=i.selection)==null?void 0:P.from)||d.selection.from,query:"",decorationId:`id_${Math.floor(Math.random()*4294967295)}`,ignoreQueryLength:a==null?void 0:a.ignoreQueryLength};if(o===void 0)return o;if(d.selection.from!==d.selection.to||a===null||i.getMeta("focus")||i.getMeta("blur")||i.getMeta("pointer")||o.triggerCharacter!==void 0&&d.selection.from<o.queryStartPos)return;let u={...o};return u.query=d.doc.textBetween(o.queryStartPos,d.selection.from),u}},props:{handleTextInput(i,o,l,d){let a=this.getState(i.state);return n.includes(d)&&a===void 0?(i.dispatch(i.state.tr.insertText(d).scrollIntoView().setMeta(c,{triggerCharacter:d})),!0):!1},decorations(i){let o=this.getState(i);if(o===void 0)return null;if(!o.deleteTriggerCharacter){let l=z(i.selection);if(l)return g.DecorationSet.create(i.doc,[g.Decoration.node(l.pos,l.pos+l.node.nodeSize,{nodeName:"span",class:"bn-suggestion-decorator","data-decoration-id":o.decorationId})])}return g.DecorationSet.create(i.doc,[g.Decoration.inline(o.queryStartPos-o.triggerCharacter.length,o.queryStartPos,{nodeName:"span",class:"bn-suggestion-decorator","data-decoration-id":o.decorationId})])}}})}onUpdate(e,n){return this.triggerCharacters.includes(e)||this.addTriggerCharacter(e),this.on(`update ${e}`,n)}get shown(){var e,n;return((n=(e=this.view)==null?void 0:e.state)==null?void 0:n.show)||!1}};var q=require("@tiptap/core"),L=q.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(n,i,o){if(!n.some(a=>a.docChanged))return null;let l=new Map,d=new Set;i.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&&d.add(a.attrs.id)});for(let[a,u]of l.entries())d.has(a)||e==null||e({id:u.id,label:u.label})}})}};var p=class{constructor(t){s(this,"_tiptapEditor");s(this,"suggestionMenus");s(this,"mentionDeletePlugin");this.suggestionMenus=new y(this),this.mentionDeletePlugin=new b(this,t.onMentionDelete);let e=M.Extension.create({name:"MEditorUIExtension",addProseMirrorPlugins:()=>[this.suggestionMenus.plugin,this.mentionDeletePlugin.plugin]});this._tiptapEditor=new M.Editor({element:t.element,extensions:[...v,D.default.configure({depth:100,newGroupDelay:500}),L,B.default.configure({placeholder:t.placeholder||"\u8BF7\u8F93\u5165...",emptyEditorClass:"is-editor-empty"}),_.configure({onFileInput:t.onFileInput}),e],onUpdate:({editor:n})=>{t.onChange(n.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((n,i)=>{var o,l;n.type.name==="mention"&&t.push({id:(o=n.attrs.id)!=null?o:null,label:(l=n.attrs.label)!=null?l:null})}),t}};var j=p;0&&(module.exports={MEditor});
1
+ var K=Object.create;var m=Object.defineProperty;var Q=Object.getOwnPropertyDescriptor;var R=Object.getOwnPropertyNames;var U=Object.getPrototypeOf,A=Object.prototype.hasOwnProperty;var H=(r,t,e)=>t in r?m(r,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):r[t]=e;var $=(r,t)=>{for(var e in t)m(r,e,{get:t[e],enumerable:!0})},T=(r,t,e,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of R(t))!A.call(r,i)&&i!==e&&m(r,i,{get:()=>t[i],enumerable:!(n=Q(t,i))||n.enumerable});return r};var h=(r,t,e)=>(e=r!=null?K(U(r)):{},T(t||!r||!r.__esModule?m(e,"default",{value:r,enumerable:!0}):e,r)),V=r=>T(m({},"__esModule",{value:!0}),r);var s=(r,t,e)=>H(r,typeof t!="symbol"?t+"":t,e);var G={};$(G,{MEditor:()=>p,default:()=>j});module.exports=V(G);var M=require("@tiptap/core");var x=h(require("@tiptap/extension-document")),I=h(require("@tiptap/extension-paragraph")),k=h(require("@tiptap/extension-text")),v=[x.default,I.default,k.default];var D=h(require("@tiptap/extension-history")),B=h(require("@tiptap/extension-placeholder"));var w=require("@tiptap/core"),N=require("prosemirror-state"),_=w.Extension.create({name:"imageInput",addOptions(){return{onFileInput:void 0}},addProseMirrorPlugins(){let r=async t=>{var e,n;(n=(e=this.options).onFileInput)==null||n.call(e,t)};return[new N.Plugin({props:{handlePaste:(t,e)=>{var i;let n=(i=e.clipboardData)==null?void 0:i.items;if(!n)return!1;for(let o of n){if(o.kind!=="file")continue;let l=o.getAsFile();if(l)return r(l),!0}return!1},handleDrop:(t,e)=>{var i;let n=(i=e.dataTransfer)==null?void 0:i.files;return!n||n.length===0?!1:(r(n[0]),!0)}}})]}});var F=require("@tiptap/core"),E=require("prosemirror-state"),g=require("prosemirror-view");var f=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 n=this.callbacks[t];n&&n.forEach(i=>i.apply(this,e))}off(t,e){let n=this.callbacks[t];n&&(e?this.callbacks[t]=n.filter(i=>i!==e):delete this.callbacks[t])}removeAllListeners(){this.callbacks={}}};var c=new E.PluginKey("SuggestionMenuPlugin"),z=(0,F.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(c,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=n=>{var i;if(!this.state)throw new Error("Attempting to update uninitialized suggestions menu");e(n,{...this.state,ignoreQueryLength:(i=this.pluginState)==null?void 0:i.ignoreQueryLength})},setTimeout(()=>{this.rootEl=this.editor._tiptapEditor.view.root})}update(t,e){var u;let n=c.getState(e),i=c.getState(t.state),o=n===void 0&&i!==void 0,l=n!==void 0&&i===void 0;if(!o&&!(n!==void 0&&i!==void 0)&&!l)return;if(this.pluginState=l?n:i,l||!this.editor.isEditable){this.state.show=!1,this.emitUpdate(this.pluginState.triggerCharacter);return}let a=(u=this.rootEl)==null?void 0:u.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 f{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(n=>n!==e)});s(this,"closeMenu",()=>this.view.closeMenu());s(this,"clearQuery",()=>this.view.clearQuery());s(this,"insertMention",e=>this.view.insertMention(e));let n=this.triggerCharacters;this.plugin=new E.Plugin({key:c,view:()=>(this.view=new C(e,(i,o)=>{this.emit(`update ${i}`,o)}),this.view),state:{init(){},apply(i,o,l,d){var P;let a=i.getMeta(c);if(typeof a=="object"&&a!==null&&o===void 0)return{triggerCharacter:a.triggerCharacter,deleteTriggerCharacter:a.deleteTriggerCharacter!==!1,queryStartPos:((P=i.selection)==null?void 0:P.from)||d.selection.from,query:"",decorationId:`id_${Math.floor(Math.random()*4294967295)}`,ignoreQueryLength:a==null?void 0:a.ignoreQueryLength};if(o===void 0)return o;if(d.selection.from!==d.selection.to||a===null||i.getMeta("focus")||i.getMeta("blur")||i.getMeta("pointer")||o.triggerCharacter!==void 0&&d.selection.from<o.queryStartPos)return;let u={...o};return u.query=d.doc.textBetween(o.queryStartPos,d.selection.from),u}},props:{handleTextInput(i,o,l,d){let a=this.getState(i.state);return n.includes(d)&&a===void 0?(i.dispatch(i.state.tr.insertText(d).scrollIntoView().setMeta(c,{triggerCharacter:d})),!0):!1},decorations(i){let o=this.getState(i);if(o===void 0)return null;if(!o.deleteTriggerCharacter){let l=z(i.selection);if(l)return g.DecorationSet.create(i.doc,[g.Decoration.node(l.pos,l.pos+l.node.nodeSize,{nodeName:"span",class:"bn-suggestion-decorator","data-decoration-id":o.decorationId})])}return g.DecorationSet.create(i.doc,[g.Decoration.inline(o.queryStartPos-o.triggerCharacter.length,o.queryStartPos,{nodeName:"span",class:"bn-suggestion-decorator","data-decoration-id":o.decorationId})])}}})}onUpdate(e,n){return this.triggerCharacters.includes(e)||this.addTriggerCharacter(e),this.on(`update ${e}`,n)}get shown(){var e,n;return((n=(e=this.view)==null?void 0:e.state)==null?void 0:n.show)||!1}};var q=require("@tiptap/core"),L=q.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(n,i,o){if(!n.some(a=>a.docChanged))return null;let l=new Map,d=new Set;i.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&&d.add(a.attrs.id)});for(let[a,u]of l.entries())d.has(a)||e==null||e({id:u.id,label:u.label})}})}};var p=class{constructor(t){s(this,"_tiptapEditor");s(this,"suggestionMenus");s(this,"mentionDeletePlugin");this.suggestionMenus=new y(this),this.mentionDeletePlugin=new b(this,t.onMentionDelete);let e=M.Extension.create({name:"MEditorUIExtension",addProseMirrorPlugins:()=>[this.suggestionMenus.plugin,this.mentionDeletePlugin.plugin]});this._tiptapEditor=new M.Editor({element:t.element,content:t.content||"",extensions:[...v,D.default.configure({depth:100,newGroupDelay:500}),L,B.default.configure({placeholder:t.placeholder||"\u8BF7\u8F93\u5165...",emptyEditorClass:"is-editor-empty"}),_.configure({onFileInput:t.onFileInput}),e],onUpdate:({editor:n})=>{t.onChange(n.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((n,i)=>{var o,l;n.type.name==="mention"&&t.push({id:(o=n.attrs.id)!=null?o:null,label:(l=n.attrs.label)!=null?l:null})}),t}};var j=p;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 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 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"],"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"]}
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- var T=Object.defineProperty;var x=(s,t,e)=>t in s?T(s,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):s[t]=e;var a=(s,t,e)=>x(s,typeof t!="symbol"?t+"":t,e);import{Editor as K,Extension as Q}from"@tiptap/core";import I from"@tiptap/extension-document";import k from"@tiptap/extension-paragraph";import v from"@tiptap/extension-text";var E=[I,k,v];import R from"@tiptap/extension-history";import U from"@tiptap/extension-placeholder";import{Extension as w}from"@tiptap/core";import{Plugin as N}from"prosemirror-state";var b=w.create({name:"imageInput",addOptions(){return{onFileInput:void 0}},addProseMirrorPlugins(){let s=async t=>{var e,i;(i=(e=this.options).onFileInput)==null||i.call(e,t)};return[new N({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 s(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:(s(i[0]),!0)}}})]}});import{findParentNode as _}from"@tiptap/core";import{Plugin as F,PluginKey as q}from"prosemirror-state";import{Decoration as S,DecorationSet as M}from"prosemirror-view";var p=class{constructor(){a(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 q("SuggestionMenuPlugin"),L=_(s=>s.type.name==="blockContainer"),f=class{constructor(t,e){this.editor=t;a(this,"pluginState");a(this,"state");a(this,"emitUpdate");a(this,"rootEl");a(this,"closeMenu",()=>{this.editor.dispatch(this.editor._tiptapEditor.view.state.tr.setMeta(c,null))});a(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()});a(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 u;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 o=(u=this.rootEl)==null?void 0:u.querySelector(`[data-decoration-id="${this.pluginState.decorationId}"]`);this.editor.isEditable&&o&&(this.state={show:!0,referencePos:o.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}}},m=class extends p{constructor(e){super();a(this,"view");a(this,"plugin");a(this,"triggerCharacters",[]);a(this,"addTriggerCharacter",e=>{this.triggerCharacters.push(e)});a(this,"removeTriggerCharacter",e=>{this.triggerCharacters=this.triggerCharacters.filter(i=>i!==e)});a(this,"closeMenu",()=>this.view.closeMenu());a(this,"clearQuery",()=>this.view.clearQuery());a(this,"insertMention",e=>this.view.insertMention(e));let i=this.triggerCharacters;this.plugin=new F({key:c,view:()=>(this.view=new f(e,(n,r)=>{this.emit(`update ${n}`,r)}),this.view),state:{init(){},apply(n,r,l,d){var y;let o=n.getMeta(c);if(typeof o=="object"&&o!==null&&r===void 0)return{triggerCharacter:o.triggerCharacter,deleteTriggerCharacter:o.deleteTriggerCharacter!==!1,queryStartPos:((y=n.selection)==null?void 0:y.from)||d.selection.from,query:"",decorationId:`id_${Math.floor(Math.random()*4294967295)}`,ignoreQueryLength:o==null?void 0:o.ignoreQueryLength};if(r===void 0)return r;if(d.selection.from!==d.selection.to||o===null||n.getMeta("focus")||n.getMeta("blur")||n.getMeta("pointer")||r.triggerCharacter!==void 0&&d.selection.from<r.queryStartPos)return;let u={...r};return u.query=d.doc.textBetween(r.queryStartPos,d.selection.from),u}},props:{handleTextInput(n,r,l,d){let o=this.getState(n.state);return i.includes(d)&&o===void 0?(n.dispatch(n.state.tr.insertText(d).scrollIntoView().setMeta(c,{triggerCharacter:d})),!0):!1},decorations(n){let r=this.getState(n);if(r===void 0)return null;if(!r.deleteTriggerCharacter){let l=L(n.selection);if(l)return M.create(n.doc,[S.node(l.pos,l.pos+l.node.nodeSize,{nodeName:"span",class:"bn-suggestion-decorator","data-decoration-id":r.decorationId})])}return M.create(n.doc,[S.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 O}from"@tiptap/core";var C=O.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:s}){return["span",{class:"mention","data-type":"mention","data-id":s.attrs.id,"data-label":s.attrs.label,contenteditable:"false"},s.attrs.label]},renderText({node:s}){return""}});function P(s,t){s._tiptapEditor.chain().insertContent({type:"mention",attrs:{id:t.id,label:t.label}}).run()}import{Plugin as D,PluginKey as B}from"prosemirror-state";var h=class{constructor(t,e){a(this,"plugin");this.plugin=new D({key:new B("mention-delete"),appendTransaction(i,n,r){if(!i.some(o=>o.docChanged))return null;let l=new Map,d=new Set;n.doc.descendants(o=>{o.type.name==="mention"&&o.attrs.id&&l.set(o.attrs.id,o.attrs)}),r.doc.descendants(o=>{o.type.name==="mention"&&o.attrs.id&&d.add(o.attrs.id)});for(let[o,u]of l.entries())d.has(o)||e==null||e({id:u.id,label:u.label})}})}};var g=class{constructor(t){a(this,"_tiptapEditor");a(this,"suggestionMenus");a(this,"mentionDeletePlugin");this.suggestionMenus=new m(this),this.mentionDeletePlugin=new h(this,t.onMentionDelete);let e=Q.create({name:"MEditorUIExtension",addProseMirrorPlugins:()=>[this.suggestionMenus.plugin,this.mentionDeletePlugin.plugin]});this._tiptapEditor=new K({element:t.element,extensions:[...E,R.configure({depth:100,newGroupDelay:500}),C,U.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){P(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 Tt=g;export{g as MEditor,Tt as default};
1
+ var T=Object.defineProperty;var x=(s,t,e)=>t in s?T(s,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):s[t]=e;var a=(s,t,e)=>x(s,typeof t!="symbol"?t+"":t,e);import{Editor as K,Extension as Q}from"@tiptap/core";import I from"@tiptap/extension-document";import k from"@tiptap/extension-paragraph";import v from"@tiptap/extension-text";var E=[I,k,v];import R from"@tiptap/extension-history";import U from"@tiptap/extension-placeholder";import{Extension as w}from"@tiptap/core";import{Plugin as N}from"prosemirror-state";var b=w.create({name:"imageInput",addOptions(){return{onFileInput:void 0}},addProseMirrorPlugins(){let s=async t=>{var e,i;(i=(e=this.options).onFileInput)==null||i.call(e,t)};return[new N({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 s(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:(s(i[0]),!0)}}})]}});import{findParentNode as _}from"@tiptap/core";import{Plugin as F,PluginKey as q}from"prosemirror-state";import{Decoration as S,DecorationSet as M}from"prosemirror-view";var p=class{constructor(){a(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 q("SuggestionMenuPlugin"),L=_(s=>s.type.name==="blockContainer"),f=class{constructor(t,e){this.editor=t;a(this,"pluginState");a(this,"state");a(this,"emitUpdate");a(this,"rootEl");a(this,"closeMenu",()=>{this.editor.dispatch(this.editor._tiptapEditor.view.state.tr.setMeta(c,null))});a(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()});a(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 u;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 o=(u=this.rootEl)==null?void 0:u.querySelector(`[data-decoration-id="${this.pluginState.decorationId}"]`);this.editor.isEditable&&o&&(this.state={show:!0,referencePos:o.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}}},m=class extends p{constructor(e){super();a(this,"view");a(this,"plugin");a(this,"triggerCharacters",[]);a(this,"addTriggerCharacter",e=>{this.triggerCharacters.push(e)});a(this,"removeTriggerCharacter",e=>{this.triggerCharacters=this.triggerCharacters.filter(i=>i!==e)});a(this,"closeMenu",()=>this.view.closeMenu());a(this,"clearQuery",()=>this.view.clearQuery());a(this,"insertMention",e=>this.view.insertMention(e));let i=this.triggerCharacters;this.plugin=new F({key:c,view:()=>(this.view=new f(e,(n,r)=>{this.emit(`update ${n}`,r)}),this.view),state:{init(){},apply(n,r,l,d){var y;let o=n.getMeta(c);if(typeof o=="object"&&o!==null&&r===void 0)return{triggerCharacter:o.triggerCharacter,deleteTriggerCharacter:o.deleteTriggerCharacter!==!1,queryStartPos:((y=n.selection)==null?void 0:y.from)||d.selection.from,query:"",decorationId:`id_${Math.floor(Math.random()*4294967295)}`,ignoreQueryLength:o==null?void 0:o.ignoreQueryLength};if(r===void 0)return r;if(d.selection.from!==d.selection.to||o===null||n.getMeta("focus")||n.getMeta("blur")||n.getMeta("pointer")||r.triggerCharacter!==void 0&&d.selection.from<r.queryStartPos)return;let u={...r};return u.query=d.doc.textBetween(r.queryStartPos,d.selection.from),u}},props:{handleTextInput(n,r,l,d){let o=this.getState(n.state);return i.includes(d)&&o===void 0?(n.dispatch(n.state.tr.insertText(d).scrollIntoView().setMeta(c,{triggerCharacter:d})),!0):!1},decorations(n){let r=this.getState(n);if(r===void 0)return null;if(!r.deleteTriggerCharacter){let l=L(n.selection);if(l)return M.create(n.doc,[S.node(l.pos,l.pos+l.node.nodeSize,{nodeName:"span",class:"bn-suggestion-decorator","data-decoration-id":r.decorationId})])}return M.create(n.doc,[S.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 O}from"@tiptap/core";var C=O.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:s}){return["span",{class:"mention","data-type":"mention","data-id":s.attrs.id,"data-label":s.attrs.label,contenteditable:"false"},s.attrs.label]},renderText({node:s}){return""}});function P(s,t){s._tiptapEditor.chain().insertContent({type:"mention",attrs:{id:t.id,label:t.label}}).run()}import{Plugin as D,PluginKey as B}from"prosemirror-state";var h=class{constructor(t,e){a(this,"plugin");this.plugin=new D({key:new B("mention-delete"),appendTransaction(i,n,r){if(!i.some(o=>o.docChanged))return null;let l=new Map,d=new Set;n.doc.descendants(o=>{o.type.name==="mention"&&o.attrs.id&&l.set(o.attrs.id,o.attrs)}),r.doc.descendants(o=>{o.type.name==="mention"&&o.attrs.id&&d.add(o.attrs.id)});for(let[o,u]of l.entries())d.has(o)||e==null||e({id:u.id,label:u.label})}})}};var g=class{constructor(t){a(this,"_tiptapEditor");a(this,"suggestionMenus");a(this,"mentionDeletePlugin");this.suggestionMenus=new m(this),this.mentionDeletePlugin=new h(this,t.onMentionDelete);let e=Q.create({name:"MEditorUIExtension",addProseMirrorPlugins:()=>[this.suggestionMenus.plugin,this.mentionDeletePlugin.plugin]});this._tiptapEditor=new K({element:t.element,content:t.content||"",extensions:[...E,R.configure({depth:100,newGroupDelay:500}),C,U.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){P(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 Tt=g;export{g as MEditor,Tt as default};
2
2
  //# sourceMappingURL=index.mjs.map
@@ -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 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 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/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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shenjipo/mention-editor",
3
- "version": "2.5.0",
3
+ "version": "2.6.0",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.js",
6
6
  "types": "dist/index.d.ts",