@ckeditor/ckeditor5-mention 36.0.1 → 37.0.0-alpha.0
Sign up to get free protection for your applications and to get access to all the features.
- package/build/mention.js +1 -1
- package/package.json +22 -21
- package/src/index.d.ts +10 -0
- package/src/mention.d.ts +69 -0
- package/src/mention.js +1 -1
- package/src/mentioncommand.d.ts +76 -0
- package/src/mentioncommand.js +3 -3
- package/src/mentionconfig.d.ts +275 -0
- package/src/mentionconfig.js +5 -0
- package/src/mentionediting.d.ts +45 -0
- package/src/mentionui.d.ts +110 -0
- package/src/mentionui.js +16 -10
- package/src/ui/domwrapperview.d.ts +37 -0
- package/src/ui/domwrapperview.js +1 -1
- package/src/ui/mentionlistitemview.d.ts +15 -0
- package/src/ui/mentionsview.d.ts +60 -0
package/build/mention.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
1
|
/*!
|
2
2
|
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
3
3
|
* For licensing, see LICENSE.md.
|
4
|
-
*/(()=>{var e={677:(e,t,n)=>{"use strict";n.d(t,{Z:()=>r});var i=n(609),o=n.n(i)()((function(e){return e[1]}));o.push([e.id,":root{--ck-color-mention-background:rgba(153,0,48,.1);--ck-color-mention-text:#990030}.ck-content .mention{background:var(--ck-color-mention-background);color:var(--ck-color-mention-text)}",""]);const r=o},216:(e,t,n)=>{"use strict";n.d(t,{Z:()=>r});var i=n(609),o=n.n(i)()((function(e){return e[1]}));o.push([e.id,":root{--ck-mention-list-max-height:300px}.ck.ck-mentions{max-height:var(--ck-mention-list-max-height);overflow-x:hidden;overflow-y:auto;overscroll-behavior:contain}.ck.ck-mentions>.ck-list__item{flex-shrink:0;overflow:hidden}",""]);const r=o},609:e=>{"use strict";e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var n=e(t);return t[2]?"@media ".concat(t[2]," {").concat(n,"}"):n})).join("")},t.i=function(e,n,i){"string"==typeof e&&(e=[[null,e,""]]);var o={};if(i)for(var r=0;r<this.length;r++){var s=this[r][0];null!=s&&(o[s]=!0)}for(var a=0;a<e.length;a++){var c=[].concat(e[a]);i&&o[c[0]]||(n&&(c[2]?c[2]="".concat(n," and ").concat(c[2]):c[2]=n),t.push(c))}},t}},62:(e,t,n)=>{"use strict";var i,o=function(){return void 0===i&&(i=Boolean(window&&document&&document.all&&!window.atob)),i},r=function(){var e={};return function(t){if(void 0===e[t]){var n=document.querySelector(t);if(window.HTMLIFrameElement&&n instanceof window.HTMLIFrameElement)try{n=n.contentDocument.head}catch(e){n=null}e[t]=n}return e[t]}}(),s=[];function a(e){for(var t=-1,n=0;n<s.length;n++)if(s[n].identifier===e){t=n;break}return t}function c(e,t){for(var n={},i=[],o=0;o<e.length;o++){var r=e[o],c=t.base?r[0]+t.base:r[0],d=n[c]||0,l="".concat(c," ").concat(d);n[c]=d+1;var u=a(l),m={css:r[1],media:r[2],sourceMap:r[3]};-1!==u?(s[u].references++,s[u].updater(m)):s.push({identifier:l,updater:p(m,t),references:1}),i.push(l)}return i}function d(e){var t=document.createElement("style"),i=e.attributes||{};if(void 0===i.nonce){var o=n.nc;o&&(i.nonce=o)}if(Object.keys(i).forEach((function(e){t.setAttribute(e,i[e])})),"function"==typeof e.insert)e.insert(t);else{var s=r(e.insert||"head");if(!s)throw new Error("Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid.");s.appendChild(t)}return t}var l,u=(l=[],function(e,t){return l[e]=t,l.filter(Boolean).join("\n")});function m(e,t,n,i){var o=n?"":i.media?"@media ".concat(i.media," {").concat(i.css,"}"):i.css;if(e.styleSheet)e.styleSheet.cssText=u(t,o);else{var r=document.createTextNode(o),s=e.childNodes;s[t]&&e.removeChild(s[t]),s.length?e.insertBefore(r,s[t]):e.appendChild(r)}}function h(e,t,n){var i=n.css,o=n.media,r=n.sourceMap;if(o?e.setAttribute("media",o):e.removeAttribute("media"),r&&"undefined"!=typeof btoa&&(i+="\n/*# sourceMappingURL=data:application/json;base64,".concat(btoa(unescape(encodeURIComponent(JSON.stringify(r))))," */")),e.styleSheet)e.styleSheet.cssText=i;else{for(;e.firstChild;)e.removeChild(e.firstChild);e.appendChild(document.createTextNode(i))}}var f=null,g=0;function p(e,t){var n,i,o;if(t.singleton){var r=g++;n=f||(f=d(t)),i=m.bind(null,n,r,!1),o=m.bind(null,n,r,!0)}else n=d(t),i=h.bind(null,n,t),o=function(){!function(e){if(null===e.parentNode)return!1;e.parentNode.removeChild(e)}(n)};return i(e),function(t){if(t){if(t.css===e.css&&t.media===e.media&&t.sourceMap===e.sourceMap)return;i(e=t)}else o()}}e.exports=function(e,t){(t=t||{}).singleton||"boolean"==typeof t.singleton||(t.singleton=o());var n=c(e=e||[],t);return function(e){if(e=e||[],"[object Array]"===Object.prototype.toString.call(e)){for(var i=0;i<n.length;i++){var o=a(n[i]);s[o].references--}for(var r=c(e,t),d=0;d<n.length;d++){var l=a(n[d]);0===s[l].references&&(s[l].updater(),s.splice(l,1))}n=r}}}},704:(e,t,n)=>{e.exports=n(79)("./src/core.js")},181:(e,t,n)=>{e.exports=n(79)("./src/typing.js")},273:(e,t,n)=>{e.exports=n(79)("./src/ui.js")},209:(e,t,n)=>{e.exports=n(79)("./src/utils.js")},79:e=>{"use strict";e.exports=CKEditor5.dll}},t={};function n(i){var o=t[i];if(void 0!==o)return o.exports;var r=t[i]={id:i,exports:{}};return e[i](r,r.exports,n),r.exports}n.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return n.d(t,{a:t}),t},n.d=(e,t)=>{for(var i in t)n.o(t,i)&&!n.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:t[i]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),n.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.nc=void 0;var i={};(()=>{"use strict";n.r(i),n.d(i,{Mention:()=>he,MentionEditing:()=>r,MentionUI:()=>oe});var e=n(704),t=n(209);class o extends e.Command{refresh(){const e=this.editor.model,t=e.document;this.isEnabled=e.schema.checkAttributeInSelection(t.selection,"mention")}execute(e){const n=this.editor.model,i=n.document.selection,o="string"==typeof e.mention?{id:e.mention}:e.mention,r=o.id,a=e.range||i.getFirstRange(),c=e.text||r,d=s({_text:c,id:r},o);if(1!=e.marker.length)throw new t.CKEditorError("mentioncommand-incorrect-marker",this);if(r.charAt(0)!=e.marker)throw new t.CKEditorError("mentioncommand-incorrect-id",this);n.change((e=>{const o=(0,t.toMap)(i.getAttributes()),r=new Map(o.entries());r.set("mention",d),n.insertContent(e.createText(c,r),a),n.insertContent(e.createText(" ",o),a.start.getShiftedBy(c.length))}))}}class r extends e.Plugin{static get pluginName(){return"MentionEditing"}init(){const e=this.editor,t=e.model,n=t.document;t.schema.extend("$text",{allowAttributes:"mention"}),e.conversion.for("upcast").elementToAttribute({view:{name:"span",key:"data-mention",classes:"mention"},model:{key:"mention",value:e=>a(e)}}),e.conversion.for("downcast").attributeToElement({model:"mention",view:d}),e.conversion.for("downcast").add(c),n.registerPostFixer((e=>function(e,t,n){const i=t.differ.getChanges();let o=!1;for(const t of i){if("attribute"==t.type)continue;const i=t.position;if("$text"==t.name){const t=i.textNode&&i.textNode.nextSibling;o=u(i.textNode,e)||o,o=u(t,e)||o,o=u(i.nodeBefore,e)||o,o=u(i.nodeAfter,e)||o}if("$text"!=t.name&&"insert"==t.type){const t=i.nodeAfter;for(const n of e.createRangeIn(t).getItems())o=u(n,e)||o}if("insert"==t.type&&n.isInline(t.name)){const t=i.nodeAfter&&i.nodeAfter.nextSibling;o=u(i.nodeBefore,e)||o,o=u(t,e)||o}}return o}(e,n,t.schema))),n.registerPostFixer((e=>function(e,t){const n=t.differ.getChanges();let i=!1;for(const t of n)if("attribute"===t.type&&"mention"!=t.attributeKey){const n=t.range.start.nodeBefore,o=t.range.end.nodeAfter;for(const r of[n,o])l(r)&&r.getAttribute(t.attributeKey)!=t.attributeNewValue&&(e.setAttribute(t.attributeKey,t.attributeNewValue,r),i=!0)}return i}(e,n))),n.registerPostFixer((e=>function(e,t){const n=t.selection,i=n.focus;if(n.isCollapsed&&n.hasAttribute("mention")&&function(e){const t=e.isAtStart;return e.nodeBefore&&e.nodeBefore.is("$text")||t}(i))return e.removeSelectionAttribute("mention"),!0;return!1}(e,n))),e.commands.add("mention",new o(e))}}function s(e,n){return Object.assign({uid:(0,t.uid)()},e,n||{})}function a(e,t){const n=e.getAttribute("data-mention"),i=e.getChild(0);if(!i)return;return s({id:n,_text:i.data},t)}function c(e){e.on("attribute:mention",((e,t,n)=>{const i=t.attributeNewValue;if(!t.item.is("$textProxy")||!i)return;const o=t.range.start;(o.textNode||o.nodeAfter).data!=i._text&&n.consumable.consume(t.item,e.name)}),{priority:"highest"})}function d(e,{writer:t}){if(!e)return;const n={class:"mention","data-mention":e.id},i={id:e.uid,priority:20};return t.createAttributeElement("span",n,i)}function l(e){if(!e||!e.is("$text")&&!e.is("$textProxy")||!e.hasAttribute("mention"))return!1;return e.data!=e.getAttribute("mention")._text}function u(e,t){return!!l(e)&&(t.removeAttribute("mention",e),!0)}var m=n(273),h=n(181);const f=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)};const g="object"==typeof global&&global&&global.Object===Object&&global;var p="object"==typeof self&&self&&self.Object===Object&&self;const v=g||p||Function("return this")();const b=function(){return v.Date.now()};var w=/\s/;const x=function(e){for(var t=e.length;t--&&w.test(e.charAt(t)););return t};var y=/^\s+/;const k=function(e){return e?e.slice(0,x(e)+1).replace(y,""):e};const _=v.Symbol;var C=Object.prototype,A=C.hasOwnProperty,T=C.toString,I=_?_.toStringTag:void 0;const M=function(e){var t=A.call(e,I),n=e[I];try{e[I]=void 0;var i=!0}catch(e){}var o=T.call(e);return i&&(t?e[I]=n:delete e[I]),o};var R=Object.prototype.toString;const S=function(e){return R.call(e)};var V="[object Null]",E="[object Undefined]",j=_?_.toStringTag:void 0;const O=function(e){return null==e?void 0===e?E:V:j&&j in Object(e)?M(e):S(e)};const P=function(e){return null!=e&&"object"==typeof e};var N="[object Symbol]";const U=function(e){return"symbol"==typeof e||P(e)&&O(e)==N};var F=NaN,B=/^[-+]0x[0-9a-f]+$/i,$=/^0b[01]+$/i,q=/^0o[0-7]+$/i,L=parseInt;const D=function(e){if("number"==typeof e)return e;if(U(e))return F;if(f(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=f(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=k(e);var n=$.test(e);return n||q.test(e)?L(e.slice(2),n?2:8):B.test(e)?F:+e};var K="Expected a function",W=Math.max,Z=Math.min;const H=function(e,t,n){var i,o,r,s,a,c,d=0,l=!1,u=!1,m=!0;if("function"!=typeof e)throw new TypeError(K);function h(t){var n=i,r=o;return i=o=void 0,d=t,s=e.apply(r,n)}function g(e){var n=e-c;return void 0===c||n>=t||n<0||u&&e-d>=r}function p(){var e=b();if(g(e))return v(e);a=setTimeout(p,function(e){var n=t-(e-c);return u?Z(n,r-(e-d)):n}(e))}function v(e){return a=void 0,m&&i?h(e):(i=o=void 0,s)}function w(){var e=b(),n=g(e);if(i=arguments,o=this,c=e,n){if(void 0===a)return function(e){return d=e,a=setTimeout(p,t),l?h(e):s}(c);if(u)return clearTimeout(a),a=setTimeout(p,t),h(c)}return void 0===a&&(a=setTimeout(p,t)),s}return t=D(t)||0,f(n)&&(l=!!n.leading,r=(u="maxWait"in n)?W(D(n.maxWait)||0,t):r,m="trailing"in n?!!n.trailing:m),w.cancel=function(){void 0!==a&&clearTimeout(a),d=0,i=c=o=a=void 0},w.flush=function(){return void 0===a?s:v(b())},w};var J=n(62),z=n.n(J),G=n(216),Q={injectType:"singletonStyleTag",attributes:{"data-cke":!0},insert:"head",singleton:!0};z()(G.Z,Q);G.Z.locals;class X extends m.ListView{constructor(e){super(e),this.extendTemplate({attributes:{class:["ck-mentions"],tabindex:"-1"}})}selectFirst(){this.select(0)}selectNext(){const e=this.selected,t=this.items.getIndex(e);this.select(t+1)}selectPrevious(){const e=this.selected,t=this.items.getIndex(e);this.select(t-1)}select(e){let t=0;e>0&&e<this.items.length?t=e:e<0&&(t=this.items.length-1);const n=this.items.get(t);this.selected!==n&&(this.selected&&this.selected.removeHighlight(),n.highlight(),this.selected=n,this._isItemVisibleInScrolledArea(n)||(this.element.scrollTop=n.element.offsetTop))}executeSelected(){this.selected.fire("execute")}_isItemVisibleInScrolledArea(e){return new t.Rect(this.element).contains(new t.Rect(e.element))}}class Y extends m.View{constructor(e,t){super(e),this.template=!1,this.domElement=t,this.domElement.classList.add("ck-button"),this.set("isOn",!1),this.on("change:isOn",((e,t,n)=>{n?(this.domElement.classList.add("ck-on"),this.domElement.classList.remove("ck-off")):(this.domElement.classList.add("ck-off"),this.domElement.classList.remove("ck-on"))})),this.listenTo(this.domElement,"click",(()=>{this.fire("execute")}))}render(){super.render(),this.element=this.domElement}}class ee extends m.ListItemView{highlight(){this.children.first.isOn=!0}removeHighlight(){this.children.first.isOn=!1}}const te=3,ne=[t.keyCodes.arrowup,t.keyCodes.arrowdown,t.keyCodes.esc],ie=[t.keyCodes.enter,t.keyCodes.tab];class oe extends e.Plugin{static get pluginName(){return"MentionUI"}static get requires(){return[m.ContextualBalloon]}constructor(e){super(e),this._items=new t.Collection,this._mentionsView=this._createMentionView(),this._mentionsConfigurations=new Map,this._requestFeedDebounced=H(this._requestFeed,100),e.config.define("mention",{feeds:[]})}init(){const e=this.editor,n=e.config.get("mention.commitKeys")||ie,i=ne.concat(n);this._balloon=e.plugins.get(m.ContextualBalloon),e.editing.view.document.on("keydown",((e,o)=>{var r;r=o.keyCode,i.includes(r)&&this._isUIVisible&&(o.preventDefault(),e.stop(),o.keyCode==t.keyCodes.arrowdown&&this._mentionsView.selectNext(),o.keyCode==t.keyCodes.arrowup&&this._mentionsView.selectPrevious(),n.includes(o.keyCode)&&this._mentionsView.executeSelected(),o.keyCode==t.keyCodes.esc&&this._hideUIAndRemoveMarker())}),{priority:"highest"}),(0,m.clickOutsideHandler)({emitter:this._mentionsView,activator:()=>this._isUIVisible,contextElements:()=>[this._balloon.view.element],callback:()=>this._hideUIAndRemoveMarker()});const o=e.config.get("mention.feeds");for(const e of o){const n=e.feed,i=e.marker;if(!de(i))throw new t.CKEditorError("mentionconfig-incorrect-marker",null,{marker:i});const o={marker:i,feedCallback:"function"==typeof n?n.bind(this.editor):ce(n),itemRenderer:e.itemRenderer};this._mentionsConfigurations.set(i,o)}this._setupTextWatcher(o),this.listenTo(e,"change:isReadOnly",(()=>{this._hideUIAndRemoveMarker()})),this.on("requestFeed:response",((e,t)=>this._handleFeedResponse(t))),this.on("requestFeed:error",(()=>this._hideUIAndRemoveMarker()))}destroy(){super.destroy(),this._mentionsView.destroy()}get _isUIVisible(){return this._balloon.visibleView===this._mentionsView}_createMentionView(){const e=this.editor.locale,t=new X(e);return t.items.bindTo(this._items).using((n=>{const{item:i,marker:o}=n,r=this.editor.config.get("mention.dropdownLimit")||10;if(t.items.length>=r)return null;const s=new ee(e),a=this._renderItem(i,o);return a.delegate("execute").to(s),s.children.add(a),s.item=i,s.marker=o,s.on("execute",(()=>{t.fire("execute",{item:i,marker:o})})),s})),t.on("execute",((e,t)=>{const n=this.editor,i=n.model,o=t.item,r=t.marker,s=n.model.markers.get("mention"),a=i.createPositionAt(i.document.selection.focus),c=i.createPositionAt(s.getStart()),d=i.createRange(c,a);this._hideUIAndRemoveMarker(),n.execute("mention",{mention:o,text:o.text,marker:r,range:d}),n.editing.view.focus()})),t}_getItemRenderer(e){const{itemRenderer:t}=this._mentionsConfigurations.get(e);return t}_requestFeed(e,n){this._lastRequested=n;const{feedCallback:i}=this._mentionsConfigurations.get(e),o=i(n);o instanceof Promise?o.then((t=>{this._lastRequested==n?this.fire("requestFeed:response",{feed:t,marker:e,feedText:n}):this.fire("requestFeed:discarded",{feed:t,marker:e,feedText:n})})).catch((n=>{this.fire("requestFeed:error",{error:n}),(0,t.logWarning)("mention-feed-callback-error",{marker:e})})):this.fire("requestFeed:response",{feed:o,marker:e,feedText:n})}_setupTextWatcher(e){const t=this.editor,n=e.map((e=>({...e,pattern:ae(e.marker,e.minimumCharacters||0)}))),i=new h.TextWatcher(t.model,function(e){const t=t=>{const n=se(e,t);if(!n)return!1;let i=0;0!==n.position&&(i=n.position-1);const o=t.substring(i);return n.pattern.test(o)};return t}(n));i.on("matched",((e,i)=>{const o=se(n,i.text),r=t.model.document.selection.focus,s=t.model.createPositionAt(r.parent,o.position);if(function(e){const t=e.textNode&&e.textNode.hasAttribute("mention"),n=e.nodeBefore;return t||n&&n.is("$text")&&n.hasAttribute("mention")}(r)||function(e){const t=e.nodeAfter;return t&&t.is("$text")&&t.hasAttribute("mention")}(s))return void this._hideUIAndRemoveMarker();const a=function(e,t){let n=0;0!==e.position&&(n=e.position-1);const i=ae(e.marker,0),o=t.substring(n);return o.match(i)[2]}(o,i.text),c=o.marker.length+a.length,d=r.getShiftedBy(-c),l=r.getShiftedBy(-a.length),u=t.model.createRange(d,l);if(le(t)){const e=t.model.markers.get("mention");t.model.change((t=>{t.updateMarker(e,{range:u})}))}else t.model.change((e=>{e.addMarker("mention",{range:u,usingOperation:!1,affectsData:!1})}));this._requestFeedDebounced(o.marker,a)})),i.on("unmatched",(()=>{this._hideUIAndRemoveMarker()}));const o=t.commands.get("mention");return i.bind("isEnabled").to(o),i}_handleFeedResponse(e){const{feed:t,marker:n}=e;if(!le(this.editor))return;this._items.clear();for(const e of t){const t="object"!=typeof e?{id:e,text:e}:e;this._items.add({item:t,marker:n})}const i=this.editor.model.markers.get("mention");this._items.length?this._showOrUpdateUI(i):this._hideUIAndRemoveMarker()}_showOrUpdateUI(e){this._isUIVisible?this._balloon.updatePosition(this._getBalloonPanelPositionData(e,this._mentionsView.position)):this._balloon.add({view:this._mentionsView,position:this._getBalloonPanelPositionData(e,this._mentionsView.position),singleViewMode:!0}),this._mentionsView.position=this._balloon.view.position,this._mentionsView.selectFirst()}_hideUIAndRemoveMarker(){this._balloon.hasView(this._mentionsView)&&this._balloon.remove(this._mentionsView),le(this.editor)&&this.editor.model.change((e=>e.removeMarker("mention"))),this._mentionsView.position=void 0}_renderItem(e,t){const n=this.editor;let i,o=e.id;const r=this._getItemRenderer(t);if(r){const t=r(e);"string"!=typeof t?i=new Y(n.locale,t):o=t}if(!i){const e=new m.ButtonView(n.locale);e.label=o,e.withText=!0,i=e}return i}_getBalloonPanelPositionData(e,n){const i=this.editor,o=i.editing,r=o.view.domConverter,s=o.mapper;return{target:()=>{let n=e.getRange();"$graveyard"==n.start.root.rootName&&(n=i.model.document.selection.getFirstRange());const o=s.toViewRange(n);return t.Rect.getDomRangeRects(r.viewRangeToDom(o)).pop()},limiter:()=>{const e=this.editor.editing.view,t=e.document.selection.editableElement;return t?e.domConverter.mapViewToDom(t.root):null},positions:re(n)}}}function re(e){const t={caret_se:e=>({top:e.bottom+te,left:e.right,name:"caret_se",config:{withArrow:!1}}),caret_ne:(e,t)=>({top:e.top-t.height-te,left:e.right,name:"caret_ne",config:{withArrow:!1}}),caret_sw:(e,t)=>({top:e.bottom+te,left:e.right-t.width,name:"caret_sw",config:{withArrow:!1}}),caret_nw:(e,t)=>({top:e.top-t.height-te,left:e.right-t.width,name:"caret_nw",config:{withArrow:!1}})};return Object.prototype.hasOwnProperty.call(t,e)?[t[e]]:[t.caret_se,t.caret_sw,t.caret_ne,t.caret_nw]}function se(e,t){let n;for(const i of e){const e=t.lastIndexOf(i.marker);e>0&&!t.substring(e-1).match(i.pattern)||(!n||e>=n.position)&&(n={marker:i.marker,position:e,minimumCharacters:i.minimumCharacters,pattern:i.pattern})}return n}function ae(e,n){const i=0==n?"*":`{${n},}`,o=t.env.features.isRegExpUnicodePropertySupported?"\\p{Ps}\\p{Pi}\"'":"\\(\\[{\"'";return new RegExp(`(?:^|[ ${o}])([${e}])(.${i})$`,"u")}function ce(e){return t=>e.filter((e=>("string"==typeof e?e:String(e.id)).toLowerCase().includes(t.toLowerCase())))}function de(e){return e&&1==e.length}function le(e){return e.model.markers.has("mention")}var ue=n(677),me={injectType:"singletonStyleTag",attributes:{"data-cke":!0},insert:"head",singleton:!0};z()(ue.Z,me);ue.Z.locals;class he extends e.Plugin{toMentionAttribute(e,t){return a(e,t)}static get pluginName(){return"Mention"}static get requires(){return[r,oe]}}})(),(window.CKEditor5=window.CKEditor5||{}).mention=i})();
|
4
|
+
*/(()=>{var e={677:(e,t,n)=>{"use strict";n.d(t,{Z:()=>r});var i=n(609),o=n.n(i)()((function(e){return e[1]}));o.push([e.id,":root{--ck-color-mention-background:rgba(153,0,48,.1);--ck-color-mention-text:#990030}.ck-content .mention{background:var(--ck-color-mention-background);color:var(--ck-color-mention-text)}",""]);const r=o},216:(e,t,n)=>{"use strict";n.d(t,{Z:()=>r});var i=n(609),o=n.n(i)()((function(e){return e[1]}));o.push([e.id,":root{--ck-mention-list-max-height:300px}.ck.ck-mentions{max-height:var(--ck-mention-list-max-height);overflow-x:hidden;overflow-y:auto;overscroll-behavior:contain}.ck.ck-mentions>.ck-list__item{flex-shrink:0;overflow:hidden}",""]);const r=o},609:e=>{"use strict";e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var n=e(t);return t[2]?"@media ".concat(t[2]," {").concat(n,"}"):n})).join("")},t.i=function(e,n,i){"string"==typeof e&&(e=[[null,e,""]]);var o={};if(i)for(var r=0;r<this.length;r++){var s=this[r][0];null!=s&&(o[s]=!0)}for(var a=0;a<e.length;a++){var c=[].concat(e[a]);i&&o[c[0]]||(n&&(c[2]?c[2]="".concat(n," and ").concat(c[2]):c[2]=n),t.push(c))}},t}},62:(e,t,n)=>{"use strict";var i,o=function(){return void 0===i&&(i=Boolean(window&&document&&document.all&&!window.atob)),i},r=function(){var e={};return function(t){if(void 0===e[t]){var n=document.querySelector(t);if(window.HTMLIFrameElement&&n instanceof window.HTMLIFrameElement)try{n=n.contentDocument.head}catch(e){n=null}e[t]=n}return e[t]}}(),s=[];function a(e){for(var t=-1,n=0;n<s.length;n++)if(s[n].identifier===e){t=n;break}return t}function c(e,t){for(var n={},i=[],o=0;o<e.length;o++){var r=e[o],c=t.base?r[0]+t.base:r[0],d=n[c]||0,l="".concat(c," ").concat(d);n[c]=d+1;var u=a(l),m={css:r[1],media:r[2],sourceMap:r[3]};-1!==u?(s[u].references++,s[u].updater(m)):s.push({identifier:l,updater:p(m,t),references:1}),i.push(l)}return i}function d(e){var t=document.createElement("style"),i=e.attributes||{};if(void 0===i.nonce){var o=n.nc;o&&(i.nonce=o)}if(Object.keys(i).forEach((function(e){t.setAttribute(e,i[e])})),"function"==typeof e.insert)e.insert(t);else{var s=r(e.insert||"head");if(!s)throw new Error("Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid.");s.appendChild(t)}return t}var l,u=(l=[],function(e,t){return l[e]=t,l.filter(Boolean).join("\n")});function m(e,t,n,i){var o=n?"":i.media?"@media ".concat(i.media," {").concat(i.css,"}"):i.css;if(e.styleSheet)e.styleSheet.cssText=u(t,o);else{var r=document.createTextNode(o),s=e.childNodes;s[t]&&e.removeChild(s[t]),s.length?e.insertBefore(r,s[t]):e.appendChild(r)}}function h(e,t,n){var i=n.css,o=n.media,r=n.sourceMap;if(o?e.setAttribute("media",o):e.removeAttribute("media"),r&&"undefined"!=typeof btoa&&(i+="\n/*# sourceMappingURL=data:application/json;base64,".concat(btoa(unescape(encodeURIComponent(JSON.stringify(r))))," */")),e.styleSheet)e.styleSheet.cssText=i;else{for(;e.firstChild;)e.removeChild(e.firstChild);e.appendChild(document.createTextNode(i))}}var f=null,g=0;function p(e,t){var n,i,o;if(t.singleton){var r=g++;n=f||(f=d(t)),i=m.bind(null,n,r,!1),o=m.bind(null,n,r,!0)}else n=d(t),i=h.bind(null,n,t),o=function(){!function(e){if(null===e.parentNode)return!1;e.parentNode.removeChild(e)}(n)};return i(e),function(t){if(t){if(t.css===e.css&&t.media===e.media&&t.sourceMap===e.sourceMap)return;i(e=t)}else o()}}e.exports=function(e,t){(t=t||{}).singleton||"boolean"==typeof t.singleton||(t.singleton=o());var n=c(e=e||[],t);return function(e){if(e=e||[],"[object Array]"===Object.prototype.toString.call(e)){for(var i=0;i<n.length;i++){var o=a(n[i]);s[o].references--}for(var r=c(e,t),d=0;d<n.length;d++){var l=a(n[d]);0===s[l].references&&(s[l].updater(),s.splice(l,1))}n=r}}}},704:(e,t,n)=>{e.exports=n(79)("./src/core.js")},181:(e,t,n)=>{e.exports=n(79)("./src/typing.js")},273:(e,t,n)=>{e.exports=n(79)("./src/ui.js")},209:(e,t,n)=>{e.exports=n(79)("./src/utils.js")},79:e=>{"use strict";e.exports=CKEditor5.dll}},t={};function n(i){var o=t[i];if(void 0!==o)return o.exports;var r=t[i]={id:i,exports:{}};return e[i](r,r.exports,n),r.exports}n.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return n.d(t,{a:t}),t},n.d=(e,t)=>{for(var i in t)n.o(t,i)&&!n.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:t[i]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),n.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.nc=void 0;var i={};(()=>{"use strict";n.r(i),n.d(i,{Mention:()=>he,MentionEditing:()=>r,MentionUI:()=>oe});var e=n(704),t=n(209);class o extends e.Command{refresh(){const e=this.editor.model,t=e.document;this.isEnabled=e.schema.checkAttributeInSelection(t.selection,"mention")}execute(e){const n=this.editor.model,i=n.document.selection,o="string"==typeof e.mention?{id:e.mention}:e.mention,r=o.id,a=e.range||i.getFirstRange(),c=e.text||r,d=s({_text:c,id:r},o);if(1!=e.marker.length)throw new t.CKEditorError("mentioncommand-incorrect-marker",this);if(r.charAt(0)!=e.marker)throw new t.CKEditorError("mentioncommand-incorrect-id",this);n.change((e=>{const o=(0,t.toMap)(i.getAttributes()),r=new Map(o.entries());r.set("mention",d),n.insertContent(e.createText(c,r),a),n.insertContent(e.createText(" ",o),a.start.getShiftedBy(c.length))}))}}class r extends e.Plugin{static get pluginName(){return"MentionEditing"}init(){const e=this.editor,t=e.model,n=t.document;t.schema.extend("$text",{allowAttributes:"mention"}),e.conversion.for("upcast").elementToAttribute({view:{name:"span",key:"data-mention",classes:"mention"},model:{key:"mention",value:e=>a(e)}}),e.conversion.for("downcast").attributeToElement({model:"mention",view:d}),e.conversion.for("downcast").add(c),n.registerPostFixer((e=>function(e,t,n){const i=t.differ.getChanges();let o=!1;for(const t of i){if("attribute"==t.type)continue;const i=t.position;if("$text"==t.name){const t=i.textNode&&i.textNode.nextSibling;o=u(i.textNode,e)||o,o=u(t,e)||o,o=u(i.nodeBefore,e)||o,o=u(i.nodeAfter,e)||o}if("$text"!=t.name&&"insert"==t.type){const t=i.nodeAfter;for(const n of e.createRangeIn(t).getItems())o=u(n,e)||o}if("insert"==t.type&&n.isInline(t.name)){const t=i.nodeAfter&&i.nodeAfter.nextSibling;o=u(i.nodeBefore,e)||o,o=u(t,e)||o}}return o}(e,n,t.schema))),n.registerPostFixer((e=>function(e,t){const n=t.differ.getChanges();let i=!1;for(const t of n)if("attribute"===t.type&&"mention"!=t.attributeKey){const n=t.range.start.nodeBefore,o=t.range.end.nodeAfter;for(const r of[n,o])l(r)&&r.getAttribute(t.attributeKey)!=t.attributeNewValue&&(e.setAttribute(t.attributeKey,t.attributeNewValue,r),i=!0)}return i}(e,n))),n.registerPostFixer((e=>function(e,t){const n=t.selection,i=n.focus;if(n.isCollapsed&&n.hasAttribute("mention")&&function(e){const t=e.isAtStart;return e.nodeBefore&&e.nodeBefore.is("$text")||t}(i))return e.removeSelectionAttribute("mention"),!0;return!1}(e,n))),e.commands.add("mention",new o(e))}}function s(e,n){return Object.assign({uid:(0,t.uid)()},e,n||{})}function a(e,t){const n=e.getAttribute("data-mention"),i=e.getChild(0);if(!i)return;return s({id:n,_text:i.data},t)}function c(e){e.on("attribute:mention",((e,t,n)=>{const i=t.attributeNewValue;if(!t.item.is("$textProxy")||!i)return;const o=t.range.start;(o.textNode||o.nodeAfter).data!=i._text&&n.consumable.consume(t.item,e.name)}),{priority:"highest"})}function d(e,{writer:t}){if(!e)return;const n={class:"mention","data-mention":e.id},i={id:e.uid,priority:20};return t.createAttributeElement("span",n,i)}function l(e){if(!e||!e.is("$text")&&!e.is("$textProxy")||!e.hasAttribute("mention"))return!1;return e.data!=e.getAttribute("mention")._text}function u(e,t){return!!l(e)&&(t.removeAttribute("mention",e),!0)}var m=n(273),h=n(181);const f=function(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)};const g="object"==typeof global&&global&&global.Object===Object&&global;var p="object"==typeof self&&self&&self.Object===Object&&self;const v=g||p||Function("return this")();const b=function(){return v.Date.now()};var w=/\s/;const x=function(e){for(var t=e.length;t--&&w.test(e.charAt(t)););return t};var y=/^\s+/;const _=function(e){return e?e.slice(0,x(e)+1).replace(y,""):e};const k=v.Symbol;var C=Object.prototype,A=C.hasOwnProperty,T=C.toString,I=k?k.toStringTag:void 0;const M=function(e){var t=A.call(e,I),n=e[I];try{e[I]=void 0;var i=!0}catch(e){}var o=T.call(e);return i&&(t?e[I]=n:delete e[I]),o};var R=Object.prototype.toString;const S=function(e){return R.call(e)};var V="[object Null]",E="[object Undefined]",j=k?k.toStringTag:void 0;const O=function(e){return null==e?void 0===e?E:V:j&&j in Object(e)?M(e):S(e)};const P=function(e){return null!=e&&"object"==typeof e};var N="[object Symbol]";const U=function(e){return"symbol"==typeof e||P(e)&&O(e)==N};var F=NaN,B=/^[-+]0x[0-9a-f]+$/i,$=/^0b[01]+$/i,L=/^0o[0-7]+$/i,q=parseInt;const D=function(e){if("number"==typeof e)return e;if(U(e))return F;if(f(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=f(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=_(e);var n=$.test(e);return n||L.test(e)?q(e.slice(2),n?2:8):B.test(e)?F:+e};var K="Expected a function",W=Math.max,Z=Math.min;const H=function(e,t,n){var i,o,r,s,a,c,d=0,l=!1,u=!1,m=!0;if("function"!=typeof e)throw new TypeError(K);function h(t){var n=i,r=o;return i=o=void 0,d=t,s=e.apply(r,n)}function g(e){var n=e-c;return void 0===c||n>=t||n<0||u&&e-d>=r}function p(){var e=b();if(g(e))return v(e);a=setTimeout(p,function(e){var n=t-(e-c);return u?Z(n,r-(e-d)):n}(e))}function v(e){return a=void 0,m&&i?h(e):(i=o=void 0,s)}function w(){var e=b(),n=g(e);if(i=arguments,o=this,c=e,n){if(void 0===a)return function(e){return d=e,a=setTimeout(p,t),l?h(e):s}(c);if(u)return clearTimeout(a),a=setTimeout(p,t),h(c)}return void 0===a&&(a=setTimeout(p,t)),s}return t=D(t)||0,f(n)&&(l=!!n.leading,r=(u="maxWait"in n)?W(D(n.maxWait)||0,t):r,m="trailing"in n?!!n.trailing:m),w.cancel=function(){void 0!==a&&clearTimeout(a),d=0,i=c=o=a=void 0},w.flush=function(){return void 0===a?s:v(b())},w};var J=n(62),z=n.n(J),G=n(216),Q={injectType:"singletonStyleTag",attributes:{"data-cke":!0},insert:"head",singleton:!0};z()(G.Z,Q);G.Z.locals;class X extends m.ListView{constructor(e){super(e),this.extendTemplate({attributes:{class:["ck-mentions"],tabindex:"-1"}})}selectFirst(){this.select(0)}selectNext(){const e=this.selected,t=this.items.getIndex(e);this.select(t+1)}selectPrevious(){const e=this.selected,t=this.items.getIndex(e);this.select(t-1)}select(e){let t=0;e>0&&e<this.items.length?t=e:e<0&&(t=this.items.length-1);const n=this.items.get(t);this.selected!==n&&(this.selected&&this.selected.removeHighlight(),n.highlight(),this.selected=n,this._isItemVisibleInScrolledArea(n)||(this.element.scrollTop=n.element.offsetTop))}executeSelected(){this.selected.fire("execute")}_isItemVisibleInScrolledArea(e){return new t.Rect(this.element).contains(new t.Rect(e.element))}}class Y extends m.View{constructor(e,t){super(e),this.template=void 0,this.domElement=t,this.domElement.classList.add("ck-button"),this.set("isOn",!1),this.on("change:isOn",((e,t,n)=>{n?(this.domElement.classList.add("ck-on"),this.domElement.classList.remove("ck-off")):(this.domElement.classList.add("ck-off"),this.domElement.classList.remove("ck-on"))})),this.listenTo(this.domElement,"click",(()=>{this.fire("execute")}))}render(){super.render(),this.element=this.domElement}}class ee extends m.ListItemView{highlight(){this.children.first.isOn=!0}removeHighlight(){this.children.first.isOn=!1}}const te=3,ne=[t.keyCodes.arrowup,t.keyCodes.arrowdown,t.keyCodes.esc],ie=[t.keyCodes.enter,t.keyCodes.tab];class oe extends e.Plugin{static get pluginName(){return"MentionUI"}static get requires(){return[m.ContextualBalloon]}constructor(e){super(e),this._items=new t.Collection,this._mentionsView=this._createMentionView(),this._mentionsConfigurations=new Map,this._requestFeedDebounced=H(this._requestFeed,100),e.config.define("mention",{feeds:[]})}init(){const e=this.editor,n=e.config.get("mention.commitKeys")||ie,i=ne.concat(n);this._balloon=e.plugins.get(m.ContextualBalloon),e.editing.view.document.on("keydown",((e,o)=>{var r;r=o.keyCode,i.includes(r)&&this._isUIVisible&&(o.preventDefault(),e.stop(),o.keyCode==t.keyCodes.arrowdown&&this._mentionsView.selectNext(),o.keyCode==t.keyCodes.arrowup&&this._mentionsView.selectPrevious(),n.includes(o.keyCode)&&this._mentionsView.executeSelected(),o.keyCode==t.keyCodes.esc&&this._hideUIAndRemoveMarker())}),{priority:"highest"}),(0,m.clickOutsideHandler)({emitter:this._mentionsView,activator:()=>this._isUIVisible,contextElements:()=>[this._balloon.view.element],callback:()=>this._hideUIAndRemoveMarker()});const o=e.config.get("mention.feeds");for(const e of o){const{feed:n,marker:i,dropdownLimit:o}=e;if(!de(i))throw new t.CKEditorError("mentionconfig-incorrect-marker",null,{marker:i});const r={marker:i,feedCallback:"function"==typeof n?n.bind(this.editor):ce(n),itemRenderer:e.itemRenderer,dropdownLimit:o};this._mentionsConfigurations.set(i,r)}this._setupTextWatcher(o),this.listenTo(e,"change:isReadOnly",(()=>{this._hideUIAndRemoveMarker()})),this.on("requestFeed:response",((e,t)=>this._handleFeedResponse(t))),this.on("requestFeed:error",(()=>this._hideUIAndRemoveMarker()))}destroy(){super.destroy(),this._mentionsView.destroy()}get _isUIVisible(){return this._balloon.visibleView===this._mentionsView}_createMentionView(){const e=this.editor.locale,t=new X(e);return t.items.bindTo(this._items).using((n=>{const{item:i,marker:o}=n,{dropdownLimit:r}=this._mentionsConfigurations.get(o),s=r||this.editor.config.get("mention.dropdownLimit")||10;if(t.items.length>=s)return null;const a=new ee(e),c=this._renderItem(i,o);return c.delegate("execute").to(a),a.children.add(c),a.item=i,a.marker=o,a.on("execute",(()=>{t.fire("execute",{item:i,marker:o})})),a})),t.on("execute",((e,t)=>{const n=this.editor,i=n.model,o=t.item,r=t.marker,s=n.model.markers.get("mention"),a=i.createPositionAt(i.document.selection.focus),c=i.createPositionAt(s.getStart()),d=i.createRange(c,a);this._hideUIAndRemoveMarker(),n.execute("mention",{mention:o,text:o.text,marker:r,range:d}),n.editing.view.focus()})),t}_getItemRenderer(e){const{itemRenderer:t}=this._mentionsConfigurations.get(e);return t}_requestFeed(e,n){this._lastRequested=n;const{feedCallback:i}=this._mentionsConfigurations.get(e),o=i(n);o instanceof Promise?o.then((t=>{this._lastRequested==n?this.fire("requestFeed:response",{feed:t,marker:e,feedText:n}):this.fire("requestFeed:discarded",{feed:t,marker:e,feedText:n})})).catch((n=>{this.fire("requestFeed:error",{error:n}),(0,t.logWarning)("mention-feed-callback-error",{marker:e})})):this.fire("requestFeed:response",{feed:o,marker:e,feedText:n})}_setupTextWatcher(e){const t=this.editor,n=e.map((e=>({...e,pattern:ae(e.marker,e.minimumCharacters||0)}))),i=new h.TextWatcher(t.model,function(e){const t=t=>{const n=se(e,t);if(!n)return!1;let i=0;0!==n.position&&(i=n.position-1);const o=t.substring(i);return n.pattern.test(o)};return t}(n));i.on("matched",((e,i)=>{const o=se(n,i.text),r=t.model.document.selection.focus,s=t.model.createPositionAt(r.parent,o.position);if(function(e){const t=e.textNode&&e.textNode.hasAttribute("mention"),n=e.nodeBefore;return t||n&&n.is("$text")&&n.hasAttribute("mention")}(r)||function(e){const t=e.nodeAfter;return t&&t.is("$text")&&t.hasAttribute("mention")}(s))return void this._hideUIAndRemoveMarker();const a=function(e,t){let n=0;0!==e.position&&(n=e.position-1);const i=ae(e.marker,0),o=t.substring(n);return o.match(i)[2]}(o,i.text),c=o.marker.length+a.length,d=r.getShiftedBy(-c),l=r.getShiftedBy(-a.length),u=t.model.createRange(d,l);if(le(t)){const e=t.model.markers.get("mention");t.model.change((t=>{t.updateMarker(e,{range:u})}))}else t.model.change((e=>{e.addMarker("mention",{range:u,usingOperation:!1,affectsData:!1})}));this._requestFeedDebounced(o.marker,a)})),i.on("unmatched",(()=>{this._hideUIAndRemoveMarker()}));const o=t.commands.get("mention");return i.bind("isEnabled").to(o),i}_handleFeedResponse(e){const{feed:t,marker:n}=e;if(!le(this.editor))return;this._items.clear();for(const e of t){const t="object"!=typeof e?{id:e,text:e}:e;this._items.add({item:t,marker:n})}const i=this.editor.model.markers.get("mention");this._items.length?this._showOrUpdateUI(i):this._hideUIAndRemoveMarker()}_showOrUpdateUI(e){this._isUIVisible?this._balloon.updatePosition(this._getBalloonPanelPositionData(e,this._mentionsView.position)):this._balloon.add({view:this._mentionsView,position:this._getBalloonPanelPositionData(e,this._mentionsView.position),singleViewMode:!0}),this._mentionsView.position=this._balloon.view.position,this._mentionsView.selectFirst()}_hideUIAndRemoveMarker(){this._balloon.hasView(this._mentionsView)&&this._balloon.remove(this._mentionsView),le(this.editor)&&this.editor.model.change((e=>e.removeMarker("mention"))),this._mentionsView.position=void 0}_renderItem(e,t){const n=this.editor;let i,o=e.id;const r=this._getItemRenderer(t);if(r){const t=r(e);"string"!=typeof t?i=new Y(n.locale,t):o=t}if(!i){const e=new m.ButtonView(n.locale);e.label=o,e.withText=!0,i=e}return i}_getBalloonPanelPositionData(e,n){const i=this.editor,o=i.editing,r=o.view.domConverter,s=o.mapper;return{target:()=>{let n=e.getRange();"$graveyard"==n.start.root.rootName&&(n=i.model.document.selection.getFirstRange());const o=s.toViewRange(n);return t.Rect.getDomRangeRects(r.viewRangeToDom(o)).pop()},limiter:()=>{const e=this.editor.editing.view,t=e.document.selection.editableElement;return t?e.domConverter.mapViewToDom(t.root):null},positions:re(n,i.locale.uiLanguageDirection)}}}function re(e,t){const n={caret_se:e=>({top:e.bottom+te,left:e.right,name:"caret_se",config:{withArrow:!1}}),caret_ne:(e,t)=>({top:e.top-t.height-te,left:e.right,name:"caret_ne",config:{withArrow:!1}}),caret_sw:(e,t)=>({top:e.bottom+te,left:e.right-t.width,name:"caret_sw",config:{withArrow:!1}}),caret_nw:(e,t)=>({top:e.top-t.height-te,left:e.right-t.width,name:"caret_nw",config:{withArrow:!1}})};return Object.prototype.hasOwnProperty.call(n,e)?[n[e]]:"rtl"!==t?[n.caret_se,n.caret_sw,n.caret_ne,n.caret_nw]:[n.caret_sw,n.caret_se,n.caret_nw,n.caret_ne]}function se(e,t){let n;for(const i of e){const e=t.lastIndexOf(i.marker);e>0&&!t.substring(e-1).match(i.pattern)||(!n||e>=n.position)&&(n={marker:i.marker,position:e,minimumCharacters:i.minimumCharacters,pattern:i.pattern})}return n}function ae(e,n){const i=0==n?"*":`{${n},}`,o=t.env.features.isRegExpUnicodePropertySupported?"\\p{Ps}\\p{Pi}\"'":"\\(\\[{\"'";return new RegExp(`(?:^|[ ${o}])([${e}])(.${i})$`,"u")}function ce(e){return t=>e.filter((e=>("string"==typeof e?e:String(e.id)).toLowerCase().includes(t.toLowerCase())))}function de(e){return e&&1==e.length}function le(e){return e.model.markers.has("mention")}var ue=n(677),me={injectType:"singletonStyleTag",attributes:{"data-cke":!0},insert:"head",singleton:!0};z()(ue.Z,me);ue.Z.locals;class he extends e.Plugin{toMentionAttribute(e,t){return a(e,t)}static get pluginName(){return"Mention"}static get requires(){return[r,oe]}}})(),(window.CKEditor5=window.CKEditor5||{}).mention=i})();
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@ckeditor/ckeditor5-mention",
|
3
|
-
"version": "
|
3
|
+
"version": "37.0.0-alpha.0",
|
4
4
|
"description": "Mention feature for CKEditor 5.",
|
5
5
|
"keywords": [
|
6
6
|
"ckeditor",
|
@@ -12,28 +12,28 @@
|
|
12
12
|
],
|
13
13
|
"main": "src/index.js",
|
14
14
|
"dependencies": {
|
15
|
-
"ckeditor5": "^
|
15
|
+
"ckeditor5": "^37.0.0-alpha.0",
|
16
16
|
"lodash-es": "^4.17.15"
|
17
17
|
},
|
18
18
|
"devDependencies": {
|
19
|
-
"@ckeditor/ckeditor5-basic-styles": "^
|
20
|
-
"@ckeditor/ckeditor5-block-quote": "^
|
21
|
-
"@ckeditor/ckeditor5-clipboard": "^
|
22
|
-
"@ckeditor/ckeditor5-cloud-services": "^
|
23
|
-
"@ckeditor/ckeditor5-core": "^
|
24
|
-
"@ckeditor/ckeditor5-dev-utils": "^
|
25
|
-
"@ckeditor/ckeditor5-editor-classic": "^
|
26
|
-
"@ckeditor/ckeditor5-engine": "^
|
27
|
-
"@ckeditor/ckeditor5-font": "^
|
28
|
-
"@ckeditor/ckeditor5-link": "^
|
29
|
-
"@ckeditor/ckeditor5-paragraph": "^
|
30
|
-
"@ckeditor/ckeditor5-table": "^
|
31
|
-
"@ckeditor/ckeditor5-theme-lark": "^
|
32
|
-
"@ckeditor/ckeditor5-typing": "^
|
33
|
-
"@ckeditor/ckeditor5-ui": "^
|
34
|
-
"@ckeditor/ckeditor5-undo": "^
|
35
|
-
"@ckeditor/ckeditor5-utils": "^
|
36
|
-
"@ckeditor/ckeditor5-widget": "^
|
19
|
+
"@ckeditor/ckeditor5-basic-styles": "^37.0.0-alpha.0",
|
20
|
+
"@ckeditor/ckeditor5-block-quote": "^37.0.0-alpha.0",
|
21
|
+
"@ckeditor/ckeditor5-clipboard": "^37.0.0-alpha.0",
|
22
|
+
"@ckeditor/ckeditor5-cloud-services": "^37.0.0-alpha.0",
|
23
|
+
"@ckeditor/ckeditor5-core": "^37.0.0-alpha.0",
|
24
|
+
"@ckeditor/ckeditor5-dev-utils": "^34.0.0",
|
25
|
+
"@ckeditor/ckeditor5-editor-classic": "^37.0.0-alpha.0",
|
26
|
+
"@ckeditor/ckeditor5-engine": "^37.0.0-alpha.0",
|
27
|
+
"@ckeditor/ckeditor5-font": "^37.0.0-alpha.0",
|
28
|
+
"@ckeditor/ckeditor5-link": "^37.0.0-alpha.0",
|
29
|
+
"@ckeditor/ckeditor5-paragraph": "^37.0.0-alpha.0",
|
30
|
+
"@ckeditor/ckeditor5-table": "^37.0.0-alpha.0",
|
31
|
+
"@ckeditor/ckeditor5-theme-lark": "^37.0.0-alpha.0",
|
32
|
+
"@ckeditor/ckeditor5-typing": "^37.0.0-alpha.0",
|
33
|
+
"@ckeditor/ckeditor5-ui": "^37.0.0-alpha.0",
|
34
|
+
"@ckeditor/ckeditor5-undo": "^37.0.0-alpha.0",
|
35
|
+
"@ckeditor/ckeditor5-utils": "^37.0.0-alpha.0",
|
36
|
+
"@ckeditor/ckeditor5-widget": "^37.0.0-alpha.0",
|
37
37
|
"lodash": "^4.17.15",
|
38
38
|
"typescript": "^4.8.4",
|
39
39
|
"webpack": "^5.58.1",
|
@@ -65,5 +65,6 @@
|
|
65
65
|
"dll:build": "webpack",
|
66
66
|
"build": "tsc -p ./tsconfig.release.json",
|
67
67
|
"postversion": "npm run build"
|
68
|
-
}
|
68
|
+
},
|
69
|
+
"types": "src/index.d.ts"
|
69
70
|
}
|
package/src/index.d.ts
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
/**
|
2
|
+
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
3
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4
|
+
*/
|
5
|
+
/**
|
6
|
+
* @module mention
|
7
|
+
*/
|
8
|
+
export { default as Mention } from './mention';
|
9
|
+
export { default as MentionEditing } from './mentionediting';
|
10
|
+
export { default as MentionUI } from './mentionui';
|
package/src/mention.d.ts
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
/**
|
2
|
+
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
3
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4
|
+
*/
|
5
|
+
/**
|
6
|
+
* @module mention/mention
|
7
|
+
*/
|
8
|
+
import { Plugin, type PluginDependencies } from 'ckeditor5/src/core';
|
9
|
+
import type { Element } from 'ckeditor5/src/engine';
|
10
|
+
import '../theme/mention.css';
|
11
|
+
/**
|
12
|
+
* The mention plugin.
|
13
|
+
*
|
14
|
+
* For a detailed overview, check the {@glink features/mentions Mention feature} guide.
|
15
|
+
*/
|
16
|
+
export default class Mention extends Plugin {
|
17
|
+
/**
|
18
|
+
* Creates a mention attribute value from the provided view element and optional data.
|
19
|
+
*
|
20
|
+
* ```ts
|
21
|
+
* editor.plugins.get( 'Mention' ).toMentionAttribute( viewElement, { userId: '1234' } );
|
22
|
+
*
|
23
|
+
* // For a view element: <span data-mention="@joe">@John Doe</span>
|
24
|
+
* // it will return:
|
25
|
+
* // { id: '@joe', userId: '1234', uid: '7a7bc7...', _text: '@John Doe' }
|
26
|
+
* ```
|
27
|
+
*
|
28
|
+
* @param viewElement
|
29
|
+
* @param data Additional data to be stored in the mention attribute.
|
30
|
+
*/
|
31
|
+
toMentionAttribute(viewElement: Element, data?: MentionAttribute): MentionAttribute | undefined;
|
32
|
+
/**
|
33
|
+
* @inheritDoc
|
34
|
+
*/
|
35
|
+
static get pluginName(): 'Mention';
|
36
|
+
/**
|
37
|
+
* @inheritDoc
|
38
|
+
*/
|
39
|
+
static get requires(): PluginDependencies;
|
40
|
+
}
|
41
|
+
/**
|
42
|
+
* Represents a mention in the model.
|
43
|
+
*
|
44
|
+
* See {@link module:mention/mention~Mention#toMentionAttribute `Mention#toMentionAttribute()`}.
|
45
|
+
*/
|
46
|
+
export type MentionAttribute = {
|
47
|
+
/**
|
48
|
+
* The ID of a mention. It identifies the mention item in the mention feed. There can be multiple mentions
|
49
|
+
* in the document with the same ID (e.g. the same hashtag being mentioned).
|
50
|
+
*/
|
51
|
+
id: string;
|
52
|
+
/**
|
53
|
+
* A unique ID of this mention instance. Should be passed as an `option.id` when using
|
54
|
+
* {@link module:engine/view/downcastwriter~DowncastWriter#createAttributeElement writer.createAttributeElement()}.
|
55
|
+
*/
|
56
|
+
uid?: string;
|
57
|
+
/**
|
58
|
+
* Helper property that stores the text of the inserted mention. Used for detecting a broken mention
|
59
|
+
* in the editing area.
|
60
|
+
*
|
61
|
+
* @internal
|
62
|
+
*/
|
63
|
+
_text?: string;
|
64
|
+
};
|
65
|
+
declare module '@ckeditor/ckeditor5-core' {
|
66
|
+
interface PluginsMap {
|
67
|
+
[Mention.pluginName]: Mention;
|
68
|
+
}
|
69
|
+
}
|
package/src/mention.js
CHANGED
@@ -12,7 +12,7 @@ import '../theme/mention.css';
|
|
12
12
|
/**
|
13
13
|
* The mention plugin.
|
14
14
|
*
|
15
|
-
* For a detailed overview, check the {@glink features/mentions Mention feature
|
15
|
+
* For a detailed overview, check the {@glink features/mentions Mention feature} guide.
|
16
16
|
*/
|
17
17
|
export default class Mention extends Plugin {
|
18
18
|
/**
|
@@ -0,0 +1,76 @@
|
|
1
|
+
/**
|
2
|
+
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
3
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4
|
+
*/
|
5
|
+
/**
|
6
|
+
* @module mention/mentioncommand
|
7
|
+
*/
|
8
|
+
import { Command } from 'ckeditor5/src/core';
|
9
|
+
import type { Range } from 'ckeditor5/src/engine';
|
10
|
+
import type { MentionAttribute } from './mention';
|
11
|
+
/**
|
12
|
+
* The mention command.
|
13
|
+
*
|
14
|
+
* The command is registered by {@link module:mention/mentionediting~MentionEditing} as `'mention'`.
|
15
|
+
*
|
16
|
+
* To insert a mention into a range, execute the command and specify a mention object with a range to replace:
|
17
|
+
*
|
18
|
+
* ```ts
|
19
|
+
* const focus = editor.model.document.selection.focus;
|
20
|
+
*
|
21
|
+
* // It will replace one character before the selection focus with the '#1234' text
|
22
|
+
* // with the mention attribute filled with passed attributes.
|
23
|
+
* editor.execute( 'mention', {
|
24
|
+
* marker: '#',
|
25
|
+
* mention: {
|
26
|
+
* id: '#1234',
|
27
|
+
* name: 'Foo',
|
28
|
+
* title: 'Big Foo'
|
29
|
+
* },
|
30
|
+
* range: editor.model.createRange( focus.getShiftedBy( -1 ), focus )
|
31
|
+
* } );
|
32
|
+
*
|
33
|
+
* // It will replace one character before the selection focus with the 'The "Big Foo"' text
|
34
|
+
* // with the mention attribute filled with passed attributes.
|
35
|
+
* editor.execute( 'mention', {
|
36
|
+
* marker: '#',
|
37
|
+
* mention: {
|
38
|
+
* id: '#1234',
|
39
|
+
* name: 'Foo',
|
40
|
+
* title: 'Big Foo'
|
41
|
+
* },
|
42
|
+
* text: 'The "Big Foo"',
|
43
|
+
* range: editor.model.createRange( focus.getShiftedBy( -1 ), focus )
|
44
|
+
* } );
|
45
|
+
* ```
|
46
|
+
*/
|
47
|
+
export default class MentionCommand extends Command {
|
48
|
+
/**
|
49
|
+
* @inheritDoc
|
50
|
+
*/
|
51
|
+
refresh(): void;
|
52
|
+
/**
|
53
|
+
* Executes the command.
|
54
|
+
*
|
55
|
+
* @param options Options for the executed command.
|
56
|
+
* @param options.mention The mention object to insert. When a string is passed, it will be used to create a plain
|
57
|
+
* object with the name attribute that equals the passed string.
|
58
|
+
* @param options.marker The marker character (e.g. `'@'`).
|
59
|
+
* @param options.text The text of the inserted mention. Defaults to the full mention string composed from `marker` and
|
60
|
+
* `mention` string or `mention.id` if an object is passed.
|
61
|
+
* @param options.range The range to replace.
|
62
|
+
* Note that the replaced range might be shorter than the inserted text with the mention attribute.
|
63
|
+
* @fires execute
|
64
|
+
*/
|
65
|
+
execute(options: {
|
66
|
+
mention: string | MentionAttribute;
|
67
|
+
marker: string;
|
68
|
+
text?: string;
|
69
|
+
range?: Range;
|
70
|
+
}): void;
|
71
|
+
}
|
72
|
+
declare module '@ckeditor/ckeditor5-core' {
|
73
|
+
interface CommandsMap {
|
74
|
+
mention: MentionCommand;
|
75
|
+
}
|
76
|
+
}
|
package/src/mentioncommand.js
CHANGED
@@ -13,7 +13,7 @@ import { _addMentionAttributes } from './mentionediting';
|
|
13
13
|
*
|
14
14
|
* The command is registered by {@link module:mention/mentionediting~MentionEditing} as `'mention'`.
|
15
15
|
*
|
16
|
-
* To insert a mention
|
16
|
+
* To insert a mention into a range, execute the command and specify a mention object with a range to replace:
|
17
17
|
*
|
18
18
|
* ```ts
|
19
19
|
* const focus = editor.model.document.selection.focus;
|
@@ -83,7 +83,7 @@ export default class MentionCommand extends Command {
|
|
83
83
|
*
|
84
84
|
* Incorrect markers: `'@@'`, `'[@'`.
|
85
85
|
*
|
86
|
-
* See {@link module:mention/
|
86
|
+
* See {@link module:mention/mentionconfig~MentionConfig}.
|
87
87
|
*
|
88
88
|
* @error mentioncommand-incorrect-marker
|
89
89
|
*/
|
@@ -115,7 +115,7 @@ export default class MentionCommand extends Command {
|
|
115
115
|
* ]
|
116
116
|
* ```
|
117
117
|
*
|
118
|
-
* See {@link module:mention/
|
118
|
+
* See {@link module:mention/mentionconfig~MentionConfig}.
|
119
119
|
*
|
120
120
|
* @error mentioncommand-incorrect-id
|
121
121
|
*/
|
@@ -0,0 +1,275 @@
|
|
1
|
+
/**
|
2
|
+
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
3
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4
|
+
*/
|
5
|
+
/**
|
6
|
+
* @module mention/mentionconfig
|
7
|
+
*/
|
8
|
+
/**
|
9
|
+
* The configuration of the mention feature.
|
10
|
+
*
|
11
|
+
* Read more about {@glink features/mentions#configuration configuring the mention feature}.
|
12
|
+
*
|
13
|
+
* ```ts
|
14
|
+
* ClassicEditor
|
15
|
+
* .create( editorElement, {
|
16
|
+
* mention: ... // Mention feature options.
|
17
|
+
* } )
|
18
|
+
* .then( ... )
|
19
|
+
* .catch( ... );
|
20
|
+
* ```
|
21
|
+
*
|
22
|
+
* See {@link module:core/editor/editorconfig~EditorConfig all editor options}.
|
23
|
+
*/
|
24
|
+
export interface MentionConfig {
|
25
|
+
/**
|
26
|
+
* The list of mention feeds supported by the editor.
|
27
|
+
*
|
28
|
+
* ```ts
|
29
|
+
* ClassicEditor
|
30
|
+
* .create( editorElement, {
|
31
|
+
* plugins: [ Mention, ... ],
|
32
|
+
* mention: {
|
33
|
+
* feeds: [
|
34
|
+
* {
|
35
|
+
* marker: '@',
|
36
|
+
* feed: [ '@Barney', '@Lily', '@Marshall', '@Robin', '@Ted' ]
|
37
|
+
* },
|
38
|
+
* ...
|
39
|
+
* ]
|
40
|
+
* }
|
41
|
+
* } )
|
42
|
+
* .then( ... )
|
43
|
+
* .catch( ... );
|
44
|
+
* ```
|
45
|
+
*
|
46
|
+
* You can provide many mention feeds but they must use different `marker`s.
|
47
|
+
* For example, you can use `'@'` to autocomplete people and `'#'` to autocomplete tags.
|
48
|
+
*/
|
49
|
+
feeds: Array<MentionFeed>;
|
50
|
+
/**
|
51
|
+
* The configuration of the custom commit keys supported by the editor.
|
52
|
+
*
|
53
|
+
* ```ts
|
54
|
+
* ClassicEditor
|
55
|
+
* .create( editorElement, {
|
56
|
+
* plugins: [ Mention, ... ],
|
57
|
+
* mention: {
|
58
|
+
* // [ Enter, Space ]
|
59
|
+
* commitKeys: [ 13, 32 ]
|
60
|
+
* feeds: [
|
61
|
+
* { ... }
|
62
|
+
* ...
|
63
|
+
* ]
|
64
|
+
* }
|
65
|
+
* } )
|
66
|
+
* .then( ... )
|
67
|
+
* .catch( ... );
|
68
|
+
* ```
|
69
|
+
*
|
70
|
+
* Custom commit keys configuration allows you to customize how users will confirm the selection of mentions from the dropdown list.
|
71
|
+
* You can add as many mention commit keys as you need. For instance, in the snippet above new mentions will be committed by pressing
|
72
|
+
* either <kbd>Enter</kbd> or <kbd>Space</kbd> (13 and 32 key codes respectively).
|
73
|
+
*
|
74
|
+
* @default [ 13, 9 ] // [ Enter, Tab ]
|
75
|
+
*/
|
76
|
+
commitKeys?: Array<number>;
|
77
|
+
/**
|
78
|
+
* The configuration of the custom number of visible mentions.
|
79
|
+
*
|
80
|
+
* Customizing the number of visible mentions allows you to specify how many available elements will the users be able to see
|
81
|
+
* in the dropdown list. You can specify any number you see fit. For example, in the snippets below you will find the
|
82
|
+
* dropdownLimit set to `20` and `Infinity` (the latter will result in showing all available mentions).
|
83
|
+
*
|
84
|
+
* ```ts
|
85
|
+
* ClassicEditor
|
86
|
+
* .create( editorElement, {
|
87
|
+
* plugins: [ Mention, ... ],
|
88
|
+
* mention: {
|
89
|
+
* dropdownLimit: 20,
|
90
|
+
* feeds: [
|
91
|
+
* { ... }
|
92
|
+
* ...
|
93
|
+
* ]
|
94
|
+
* }
|
95
|
+
* } )
|
96
|
+
* .then( ... )
|
97
|
+
* .catch( ... );
|
98
|
+
*
|
99
|
+
* ClassicEditor
|
100
|
+
* .create( editorElement, {
|
101
|
+
* plugins: [ Mention, ... ],
|
102
|
+
* mention: {
|
103
|
+
* dropdownLimit: Infinity,
|
104
|
+
* feeds: [
|
105
|
+
* { ... }
|
106
|
+
* ...
|
107
|
+
* ]
|
108
|
+
* }
|
109
|
+
* } )
|
110
|
+
* .then( ... )
|
111
|
+
* .catch( ... );
|
112
|
+
* ```
|
113
|
+
*
|
114
|
+
* @default 10
|
115
|
+
*/
|
116
|
+
dropdownLimit?: number;
|
117
|
+
}
|
118
|
+
/**
|
119
|
+
* The mention feed descriptor. Used in {@link module:mention/mentionconfig~MentionConfig `config.mention`}.
|
120
|
+
*
|
121
|
+
* See {@link module:mention/mentionconfig~MentionConfig} to learn more.
|
122
|
+
*
|
123
|
+
* ```ts
|
124
|
+
* // Static configuration.
|
125
|
+
* const mentionFeedPeople = {
|
126
|
+
* marker: '@',
|
127
|
+
* feed: [ '@Alice', '@Bob', ... ],
|
128
|
+
* minimumCharacters: 2
|
129
|
+
* };
|
130
|
+
*
|
131
|
+
* // Simple synchronous callback.
|
132
|
+
* const mentionFeedTags = {
|
133
|
+
* marker: '#',
|
134
|
+
* feed: ( searchString: string ) => {
|
135
|
+
* return tags
|
136
|
+
* // Filter the tags list.
|
137
|
+
* .filter( tag => {
|
138
|
+
* return tag.toLowerCase().includes( queryText.toLowerCase() );
|
139
|
+
* } )
|
140
|
+
* }
|
141
|
+
* };
|
142
|
+
*
|
143
|
+
* const tags = [ 'wysiwyg', 'rte', 'rich-text-edior', 'collaboration', 'real-time', ... ];
|
144
|
+
*
|
145
|
+
* // Asynchronous callback.
|
146
|
+
* const mentionFeedPlaceholders = {
|
147
|
+
* marker: '$',
|
148
|
+
* feed: ( searchString: string ) => {
|
149
|
+
* return getMatchingPlaceholders( searchString );
|
150
|
+
* }
|
151
|
+
* };
|
152
|
+
*
|
153
|
+
* function getMatchingPlaceholders( searchString: string ) {
|
154
|
+
* return new Promise<Array<MentionFeedItem>>( resolve => {
|
155
|
+
* doSomeXHRQuery( result => {
|
156
|
+
* // console.log( result );
|
157
|
+
* // -> [ '$name', '$surname', '$postal', ... ]
|
158
|
+
*
|
159
|
+
* resolve( result );
|
160
|
+
* } );
|
161
|
+
* } );
|
162
|
+
* }
|
163
|
+
* ```
|
164
|
+
*/
|
165
|
+
export interface MentionFeed {
|
166
|
+
/**
|
167
|
+
* The character which triggers autocompletion for mention. It must be a single character.
|
168
|
+
*/
|
169
|
+
marker: string;
|
170
|
+
/**
|
171
|
+
* Autocomplete items. Provide an array for
|
172
|
+
* a static configuration (the mention feature will show matching items automatically) or a function which returns an array of
|
173
|
+
* matching items (directly, or via a promise). If a function is passed, it is executed in the context of the editor instance.
|
174
|
+
*/
|
175
|
+
feed: Array<MentionFeedItem> | FeedCallback;
|
176
|
+
/**
|
177
|
+
* Specifies after how many characters the autocomplete panel should be shown.
|
178
|
+
*
|
179
|
+
* @default 0
|
180
|
+
*/
|
181
|
+
minimumCharacters?: number;
|
182
|
+
/**
|
183
|
+
* A function that renders a {@link module:mention/mentionconfig~MentionFeedItem}
|
184
|
+
* to the autocomplete panel.
|
185
|
+
*/
|
186
|
+
itemRenderer?: ItemRenderer;
|
187
|
+
/**
|
188
|
+
* Specify how many available elements per feeds will the users be able to see in the dropdown list.
|
189
|
+
* If it not set, limit is inherited from {@link module:mention/mentionconfig~MentionConfig#dropdownLimit MentionConfig}.
|
190
|
+
*/
|
191
|
+
dropdownLimit?: number;
|
192
|
+
}
|
193
|
+
/**
|
194
|
+
* Function that renders an array of {@link module:mention/mentionconfig~MentionFeedItem} based on string input.
|
195
|
+
*/
|
196
|
+
export type FeedCallback = (searchString: string) => Array<MentionFeedItem> | Promise<Array<MentionFeedItem>>;
|
197
|
+
/**
|
198
|
+
* Function that takes renders a {@link module:mention/mentionconfig~MentionFeedItem} as HTMLElement.
|
199
|
+
*/
|
200
|
+
export type ItemRenderer = (item: MentionFeedItem) => HTMLElement;
|
201
|
+
/**
|
202
|
+
* The mention feed item. It may be defined as a string or a plain object.
|
203
|
+
*
|
204
|
+
* When defining a feed item as a plain object, the `id` property is obligatory. Additional properties
|
205
|
+
* can be used when customizing the mention feature bahavior
|
206
|
+
* (see {@glink features/mentions#customizing-the-autocomplete-list "Customizing the autocomplete list"}
|
207
|
+
* and {@glink features/mentions#customizing-the-output "Customizing the output"} sections).
|
208
|
+
*
|
209
|
+
* ```ts
|
210
|
+
* ClassicEditor
|
211
|
+
* .create( editorElement, {
|
212
|
+
* plugins: [ Mention, ... ],
|
213
|
+
* mention: {
|
214
|
+
* feeds: [
|
215
|
+
* // Feed items as objects.
|
216
|
+
* {
|
217
|
+
* marker: '@',
|
218
|
+
* feed: [
|
219
|
+
* {
|
220
|
+
* id: '@Barney',
|
221
|
+
* fullName: 'Barney Bloom'
|
222
|
+
* },
|
223
|
+
* {
|
224
|
+
* id: '@Lily',
|
225
|
+
* fullName: 'Lily Smith'
|
226
|
+
* },
|
227
|
+
* {
|
228
|
+
* id: '@Marshall',
|
229
|
+
* fullName: 'Marshall McDonald'
|
230
|
+
* },
|
231
|
+
* {
|
232
|
+
* id: '@Robin',
|
233
|
+
* fullName: 'Robin Hood'
|
234
|
+
* },
|
235
|
+
* {
|
236
|
+
* id: '@Ted',
|
237
|
+
* fullName: 'Ted Cruze'
|
238
|
+
* },
|
239
|
+
* // ...
|
240
|
+
* ]
|
241
|
+
* },
|
242
|
+
*
|
243
|
+
* // Feed items as plain strings.
|
244
|
+
* {
|
245
|
+
* marker: '#',
|
246
|
+
* feed: [ 'wysiwyg', 'rte', 'rich-text-edior', 'collaboration', 'real-time', ... ]
|
247
|
+
* },
|
248
|
+
* ]
|
249
|
+
* }
|
250
|
+
* } )
|
251
|
+
* .then( ... )
|
252
|
+
* .catch( ... );
|
253
|
+
* ```
|
254
|
+
*/
|
255
|
+
export type MentionFeedItem = string | MentionFeedObjectItem;
|
256
|
+
export type MentionFeedObjectItem = {
|
257
|
+
/**
|
258
|
+
* A unique ID of the mention. It must start with the marker character.
|
259
|
+
*/
|
260
|
+
id: string;
|
261
|
+
/**
|
262
|
+
* Text inserted into the editor when creating a mention.
|
263
|
+
*/
|
264
|
+
text: string;
|
265
|
+
};
|
266
|
+
declare module '@ckeditor/ckeditor5-core' {
|
267
|
+
interface EditorConfig {
|
268
|
+
/**
|
269
|
+
* The configuration of the {@link module:mention/mention~Mention} feature.
|
270
|
+
*
|
271
|
+
* Read more in {@link module:mention/mentionconfig~MentionConfig}.
|
272
|
+
*/
|
273
|
+
mention?: MentionConfig;
|
274
|
+
}
|
275
|
+
}
|
@@ -0,0 +1,45 @@
|
|
1
|
+
/**
|
2
|
+
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
3
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4
|
+
*/
|
5
|
+
/**
|
6
|
+
* @module mention/mentionediting
|
7
|
+
*/
|
8
|
+
import { Plugin } from 'ckeditor5/src/core';
|
9
|
+
import type { Element } from 'ckeditor5/src/engine';
|
10
|
+
import type { MentionAttribute } from './mention';
|
11
|
+
/**
|
12
|
+
* The mention editing feature.
|
13
|
+
*
|
14
|
+
* It introduces the {@link module:mention/mentioncommand~MentionCommand command} and the `mention`
|
15
|
+
* attribute in the {@link module:engine/model/model~Model model} which renders in the {@link module:engine/view/view view}
|
16
|
+
* as a `<span class="mention" data-mention="@mention">`.
|
17
|
+
*/
|
18
|
+
export default class MentionEditing extends Plugin {
|
19
|
+
/**
|
20
|
+
* @inheritDoc
|
21
|
+
*/
|
22
|
+
static get pluginName(): 'MentionEditing';
|
23
|
+
/**
|
24
|
+
* @inheritDoc
|
25
|
+
*/
|
26
|
+
init(): void;
|
27
|
+
}
|
28
|
+
/**
|
29
|
+
* @internal
|
30
|
+
*/
|
31
|
+
export declare function _addMentionAttributes(baseMentionData: MentionAttribute, data?: MentionAttribute): MentionAttribute;
|
32
|
+
/**
|
33
|
+
* Creates a mention attribute value from the provided view element and optional data.
|
34
|
+
*
|
35
|
+
* This function is exposed as
|
36
|
+
* {@link module:mention/mention~Mention#toMentionAttribute `editor.plugins.get( 'Mention' ).toMentionAttribute()`}.
|
37
|
+
*
|
38
|
+
* @internal
|
39
|
+
*/
|
40
|
+
export declare function _toMentionAttribute(viewElementOrMention: Element, data?: MentionAttribute): MentionAttribute | undefined;
|
41
|
+
declare module '@ckeditor/ckeditor5-core' {
|
42
|
+
interface PluginsMap {
|
43
|
+
[MentionEditing.pluginName]: MentionEditing;
|
44
|
+
}
|
45
|
+
}
|
@@ -0,0 +1,110 @@
|
|
1
|
+
/**
|
2
|
+
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
3
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4
|
+
*/
|
5
|
+
/**
|
6
|
+
* @module mention/mentionui
|
7
|
+
*/
|
8
|
+
import { Plugin, type Editor, type PluginDependencies } from 'ckeditor5/src/core';
|
9
|
+
/**
|
10
|
+
* The mention UI feature.
|
11
|
+
*/
|
12
|
+
export default class MentionUI extends Plugin {
|
13
|
+
/**
|
14
|
+
* The mention view.
|
15
|
+
*/
|
16
|
+
private readonly _mentionsView;
|
17
|
+
/**
|
18
|
+
* Stores mention feeds configurations.
|
19
|
+
*/
|
20
|
+
private _mentionsConfigurations;
|
21
|
+
/**
|
22
|
+
* The contextual balloon plugin instance.
|
23
|
+
*/
|
24
|
+
private _balloon;
|
25
|
+
private _items;
|
26
|
+
private _lastRequested?;
|
27
|
+
/**
|
28
|
+
* Debounced feed requester. It uses `lodash#debounce` method to delay function call.
|
29
|
+
*/
|
30
|
+
private _requestFeedDebounced;
|
31
|
+
/**
|
32
|
+
* @inheritDoc
|
33
|
+
*/
|
34
|
+
static get pluginName(): 'MentionUI';
|
35
|
+
/**
|
36
|
+
* @inheritDoc
|
37
|
+
*/
|
38
|
+
static get requires(): PluginDependencies;
|
39
|
+
/**
|
40
|
+
* @inheritDoc
|
41
|
+
*/
|
42
|
+
constructor(editor: Editor);
|
43
|
+
/**
|
44
|
+
* @inheritDoc
|
45
|
+
*/
|
46
|
+
init(): void;
|
47
|
+
/**
|
48
|
+
* @inheritDoc
|
49
|
+
*/
|
50
|
+
destroy(): void;
|
51
|
+
/**
|
52
|
+
* Returns true when {@link #_mentionsView} is in the {@link module:ui/panel/balloon/contextualballoon~ContextualBalloon} and it is
|
53
|
+
* currently visible.
|
54
|
+
*/
|
55
|
+
private get _isUIVisible();
|
56
|
+
/**
|
57
|
+
* Creates the {@link #_mentionsView}.
|
58
|
+
*/
|
59
|
+
private _createMentionView;
|
60
|
+
/**
|
61
|
+
* Returns item renderer for the marker.
|
62
|
+
*/
|
63
|
+
private _getItemRenderer;
|
64
|
+
/**
|
65
|
+
* Requests a feed from a configured callbacks.
|
66
|
+
*
|
67
|
+
* @fires response
|
68
|
+
* @fires discarded
|
69
|
+
* @fires error
|
70
|
+
*/
|
71
|
+
private _requestFeed;
|
72
|
+
/**
|
73
|
+
* Registers a text watcher for the marker.
|
74
|
+
*/
|
75
|
+
private _setupTextWatcher;
|
76
|
+
/**
|
77
|
+
* Handles the feed response event data.
|
78
|
+
*/
|
79
|
+
private _handleFeedResponse;
|
80
|
+
/**
|
81
|
+
* Shows the mentions balloon. If the panel is already visible, it will reposition it.
|
82
|
+
*/
|
83
|
+
private _showOrUpdateUI;
|
84
|
+
/**
|
85
|
+
* Hides the mentions balloon and removes the 'mention' marker from the markers collection.
|
86
|
+
*/
|
87
|
+
private _hideUIAndRemoveMarker;
|
88
|
+
/**
|
89
|
+
* Renders a single item in the autocomplete list.
|
90
|
+
*/
|
91
|
+
private _renderItem;
|
92
|
+
/**
|
93
|
+
* Creates a position options object used to position the balloon panel.
|
94
|
+
*
|
95
|
+
* @param mentionMarker
|
96
|
+
* @param preferredPosition The name of the last matched position name.
|
97
|
+
*/
|
98
|
+
private _getBalloonPanelPositionData;
|
99
|
+
}
|
100
|
+
/**
|
101
|
+
* Creates a RegExp pattern for the marker.
|
102
|
+
*
|
103
|
+
* Function has to be exported to achieve 100% code coverage.
|
104
|
+
*/
|
105
|
+
export declare function createRegExp(marker: string, minimumCharacters: number): RegExp;
|
106
|
+
declare module '@ckeditor/ckeditor5-core' {
|
107
|
+
interface PluginsMap {
|
108
|
+
[MentionUI.pluginName]: MentionUI;
|
109
|
+
}
|
110
|
+
}
|
package/src/mentionui.js
CHANGED
@@ -88,8 +88,7 @@ export default class MentionUI extends Plugin {
|
|
88
88
|
});
|
89
89
|
const feeds = editor.config.get('mention.feeds');
|
90
90
|
for (const mentionDescription of feeds) {
|
91
|
-
const feed = mentionDescription
|
92
|
-
const marker = mentionDescription.marker;
|
91
|
+
const { feed, marker, dropdownLimit } = mentionDescription;
|
93
92
|
if (!isValidMentionMarker(marker)) {
|
94
93
|
/**
|
95
94
|
* The marker must be a single character.
|
@@ -98,7 +97,7 @@ export default class MentionUI extends Plugin {
|
|
98
97
|
*
|
99
98
|
* Incorrect markers: `'$$'`, `'[@'`.
|
100
99
|
*
|
101
|
-
* See {@link module:mention/
|
100
|
+
* See {@link module:mention/mentionconfig~MentionConfig}.
|
102
101
|
*
|
103
102
|
* @error mentionconfig-incorrect-marker
|
104
103
|
* @param marker Configured marker
|
@@ -107,7 +106,7 @@ export default class MentionUI extends Plugin {
|
|
107
106
|
}
|
108
107
|
const feedCallback = typeof feed == 'function' ? feed.bind(this.editor) : createFeedCallback(feed);
|
109
108
|
const itemRenderer = mentionDescription.itemRenderer;
|
110
|
-
const definition = { marker, feedCallback, itemRenderer };
|
109
|
+
const definition = { marker, feedCallback, itemRenderer, dropdownLimit };
|
111
110
|
this._mentionsConfigurations.set(marker, definition);
|
112
111
|
}
|
113
112
|
this._setupTextWatcher(feeds);
|
@@ -146,8 +145,9 @@ export default class MentionUI extends Plugin {
|
|
146
145
|
const mentionsView = new MentionsView(locale);
|
147
146
|
mentionsView.items.bindTo(this._items).using(data => {
|
148
147
|
const { item, marker } = data;
|
148
|
+
const { dropdownLimit: markerDropdownLimit } = this._mentionsConfigurations.get(marker);
|
149
149
|
// Set to 10 by default for backwards compatibility. See: #10479
|
150
|
-
const dropdownLimit = this.editor.config.get('mention.dropdownLimit') || 10;
|
150
|
+
const dropdownLimit = markerDropdownLimit || this.editor.config.get('mention.dropdownLimit') || 10;
|
151
151
|
if (mentionsView.items.length >= dropdownLimit) {
|
152
152
|
return null;
|
153
153
|
}
|
@@ -281,7 +281,7 @@ export default class MentionUI extends Plugin {
|
|
281
281
|
});
|
282
282
|
}
|
283
283
|
this._requestFeedDebounced(markerDefinition.marker, feedText);
|
284
|
-
// @if CK_DEBUG_MENTION // console.groupEnd(
|
284
|
+
// @if CK_DEBUG_MENTION // console.groupEnd();
|
285
285
|
});
|
286
286
|
watcher.on('unmatched', () => {
|
287
287
|
this._hideUIAndRemoveMarker();
|
@@ -389,6 +389,7 @@ export default class MentionUI extends Plugin {
|
|
389
389
|
const editing = editor.editing;
|
390
390
|
const domConverter = editing.view.domConverter;
|
391
391
|
const mapper = editing.mapper;
|
392
|
+
const uiLanguageDirection = editor.locale.uiLanguageDirection;
|
392
393
|
return {
|
393
394
|
target: () => {
|
394
395
|
let modelRange = mentionMarker.getRange();
|
@@ -410,14 +411,14 @@ export default class MentionUI extends Plugin {
|
|
410
411
|
}
|
411
412
|
return null;
|
412
413
|
},
|
413
|
-
positions: getBalloonPanelPositions(preferredPosition)
|
414
|
+
positions: getBalloonPanelPositions(preferredPosition, uiLanguageDirection)
|
414
415
|
};
|
415
416
|
}
|
416
417
|
}
|
417
418
|
/**
|
418
419
|
* Returns the balloon positions data callbacks.
|
419
420
|
*/
|
420
|
-
function getBalloonPanelPositions(preferredPosition) {
|
421
|
+
function getBalloonPanelPositions(preferredPosition, uiLanguageDirection) {
|
421
422
|
const positions = {
|
422
423
|
// Positions the panel to the southeast of the caret rectangle.
|
423
424
|
'caret_se': (targetRect) => {
|
@@ -470,12 +471,17 @@ function getBalloonPanelPositions(preferredPosition) {
|
|
470
471
|
positions[preferredPosition]
|
471
472
|
];
|
472
473
|
}
|
473
|
-
// By default return all position callbacks.
|
474
|
-
return [
|
474
|
+
// By default, return all position callbacks ordered depending on the UI language direction.
|
475
|
+
return uiLanguageDirection !== 'rtl' ? [
|
475
476
|
positions.caret_se,
|
476
477
|
positions.caret_sw,
|
477
478
|
positions.caret_ne,
|
478
479
|
positions.caret_nw
|
480
|
+
] : [
|
481
|
+
positions.caret_sw,
|
482
|
+
positions.caret_se,
|
483
|
+
positions.caret_nw,
|
484
|
+
positions.caret_ne
|
479
485
|
];
|
480
486
|
}
|
481
487
|
/**
|
@@ -0,0 +1,37 @@
|
|
1
|
+
/**
|
2
|
+
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
3
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4
|
+
*/
|
5
|
+
/**
|
6
|
+
* @module mention/ui/domwrapperview
|
7
|
+
*/
|
8
|
+
import { View } from 'ckeditor5/src/ui';
|
9
|
+
import type { Locale } from 'ckeditor5/src/utils';
|
10
|
+
/**
|
11
|
+
* This class wraps DOM element as a CKEditor5 UI View.
|
12
|
+
*
|
13
|
+
* It allows to render any DOM element and use it in mentions list.
|
14
|
+
*/
|
15
|
+
export default class DomWrapperView extends View {
|
16
|
+
/**
|
17
|
+
* The DOM element for which wrapper was created.
|
18
|
+
*/
|
19
|
+
domElement: HTMLElement;
|
20
|
+
/**
|
21
|
+
* Controls whether the dom wrapper view is "on". This is in line with {@link module:ui/button/button~Button#isOn} property.
|
22
|
+
*
|
23
|
+
* @observable
|
24
|
+
* @default true
|
25
|
+
*/
|
26
|
+
isOn: boolean;
|
27
|
+
/**
|
28
|
+
* Creates an instance of {@link module:mention/ui/domwrapperview~DomWrapperView} class.
|
29
|
+
*
|
30
|
+
* Also see {@link #render}.
|
31
|
+
*/
|
32
|
+
constructor(locale: Locale, domElement: HTMLElement);
|
33
|
+
/**
|
34
|
+
* @inheritDoc
|
35
|
+
*/
|
36
|
+
render(): void;
|
37
|
+
}
|
package/src/ui/domwrapperview.js
CHANGED
@@ -20,7 +20,7 @@ export default class DomWrapperView extends View {
|
|
20
20
|
constructor(locale, domElement) {
|
21
21
|
super(locale);
|
22
22
|
// Disable template rendering on this view.
|
23
|
-
this.template =
|
23
|
+
this.template = undefined;
|
24
24
|
this.domElement = domElement;
|
25
25
|
// Render dom wrapper as a button.
|
26
26
|
this.domElement.classList.add('ck-button');
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/**
|
2
|
+
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
3
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4
|
+
*/
|
5
|
+
/**
|
6
|
+
* @module mention/ui/mentionlistitemview
|
7
|
+
*/
|
8
|
+
import { ListItemView } from 'ckeditor5/src/ui';
|
9
|
+
import type { MentionFeedItem } from '../mentionconfig';
|
10
|
+
export default class MentionListItemView extends ListItemView {
|
11
|
+
item: MentionFeedItem;
|
12
|
+
marker: string;
|
13
|
+
highlight(): void;
|
14
|
+
removeHighlight(): void;
|
15
|
+
}
|
@@ -0,0 +1,60 @@
|
|
1
|
+
/**
|
2
|
+
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
3
|
+
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
4
|
+
*/
|
5
|
+
/**
|
6
|
+
* @module mention/ui/mentionsview
|
7
|
+
*/
|
8
|
+
import { ListView } from 'ckeditor5/src/ui';
|
9
|
+
import { type Locale } from 'ckeditor5/src/utils';
|
10
|
+
import type MentionListItemView from './mentionlistitemview';
|
11
|
+
import '../../theme/mentionui.css';
|
12
|
+
/**
|
13
|
+
* The mention ui view.
|
14
|
+
*/
|
15
|
+
export default class MentionsView extends ListView {
|
16
|
+
selected: MentionListItemView | undefined;
|
17
|
+
position: string | undefined;
|
18
|
+
/**
|
19
|
+
* @inheritDoc
|
20
|
+
*/
|
21
|
+
constructor(locale: Locale);
|
22
|
+
/**
|
23
|
+
* {@link #select Selects} the first item.
|
24
|
+
*/
|
25
|
+
selectFirst(): void;
|
26
|
+
/**
|
27
|
+
* Selects next item to the currently {@link #select selected}.
|
28
|
+
*
|
29
|
+
* If the last item is already selected, it will select the first item.
|
30
|
+
*/
|
31
|
+
selectNext(): void;
|
32
|
+
/**
|
33
|
+
* Selects previous item to the currently {@link #select selected}.
|
34
|
+
*
|
35
|
+
* If the first item is already selected, it will select the last item.
|
36
|
+
*/
|
37
|
+
selectPrevious(): void;
|
38
|
+
/**
|
39
|
+
* Marks item at a given index as selected.
|
40
|
+
*
|
41
|
+
* Handles selection cycling when passed index is out of bounds:
|
42
|
+
* - if the index is lower than 0, it will select the last item,
|
43
|
+
* - if the index is higher than the last item index, it will select the first item.
|
44
|
+
*
|
45
|
+
* @param index Index of an item to be marked as selected.
|
46
|
+
*/
|
47
|
+
select(index: number): void;
|
48
|
+
/**
|
49
|
+
* Triggers the `execute` event on the {@link #select selected} item.
|
50
|
+
*/
|
51
|
+
executeSelected(): void;
|
52
|
+
/**
|
53
|
+
* Checks if an item is visible in the scrollable area.
|
54
|
+
*
|
55
|
+
* The item is considered visible when:
|
56
|
+
* - its top boundary is inside the scrollable rect
|
57
|
+
* - its bottom boundary is inside the scrollable rect (the whole item must be visible)
|
58
|
+
*/
|
59
|
+
private _isItemVisibleInScrolledArea;
|
60
|
+
}
|