@ckeditor/ckeditor5-mention 36.0.1 → 37.0.0-alpha.1

Sign up to get free protection for your applications and to get access to all the features.
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": "36.0.1",
3
+ "version": "37.0.0-alpha.1",
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": "^36.0.1",
15
+ "ckeditor5": "^37.0.0-alpha.1",
16
16
  "lodash-es": "^4.17.15"
17
17
  },
18
18
  "devDependencies": {
19
- "@ckeditor/ckeditor5-basic-styles": "^36.0.1",
20
- "@ckeditor/ckeditor5-block-quote": "^36.0.1",
21
- "@ckeditor/ckeditor5-clipboard": "^36.0.1",
22
- "@ckeditor/ckeditor5-cloud-services": "^36.0.1",
23
- "@ckeditor/ckeditor5-core": "^36.0.1",
24
- "@ckeditor/ckeditor5-dev-utils": "^32.0.0",
25
- "@ckeditor/ckeditor5-editor-classic": "^36.0.1",
26
- "@ckeditor/ckeditor5-engine": "^36.0.1",
27
- "@ckeditor/ckeditor5-font": "^36.0.1",
28
- "@ckeditor/ckeditor5-link": "^36.0.1",
29
- "@ckeditor/ckeditor5-paragraph": "^36.0.1",
30
- "@ckeditor/ckeditor5-table": "^36.0.1",
31
- "@ckeditor/ckeditor5-theme-lark": "^36.0.1",
32
- "@ckeditor/ckeditor5-typing": "^36.0.1",
33
- "@ckeditor/ckeditor5-ui": "^36.0.1",
34
- "@ckeditor/ckeditor5-undo": "^36.0.1",
35
- "@ckeditor/ckeditor5-utils": "^36.0.1",
36
- "@ckeditor/ckeditor5-widget": "^36.0.1",
19
+ "@ckeditor/ckeditor5-basic-styles": "^37.0.0-alpha.1",
20
+ "@ckeditor/ckeditor5-block-quote": "^37.0.0-alpha.1",
21
+ "@ckeditor/ckeditor5-clipboard": "^37.0.0-alpha.1",
22
+ "@ckeditor/ckeditor5-cloud-services": "^37.0.0-alpha.1",
23
+ "@ckeditor/ckeditor5-core": "^37.0.0-alpha.1",
24
+ "@ckeditor/ckeditor5-dev-utils": "^35.0.0",
25
+ "@ckeditor/ckeditor5-editor-classic": "^37.0.0-alpha.1",
26
+ "@ckeditor/ckeditor5-engine": "^37.0.0-alpha.1",
27
+ "@ckeditor/ckeditor5-font": "^37.0.0-alpha.1",
28
+ "@ckeditor/ckeditor5-link": "^37.0.0-alpha.1",
29
+ "@ckeditor/ckeditor5-paragraph": "^37.0.0-alpha.1",
30
+ "@ckeditor/ckeditor5-table": "^37.0.0-alpha.1",
31
+ "@ckeditor/ckeditor5-theme-lark": "^37.0.0-alpha.1",
32
+ "@ckeditor/ckeditor5-typing": "^37.0.0-alpha.1",
33
+ "@ckeditor/ckeditor5-ui": "^37.0.0-alpha.1",
34
+ "@ckeditor/ckeditor5-undo": "^37.0.0-alpha.1",
35
+ "@ckeditor/ckeditor5-utils": "^37.0.0-alpha.1",
36
+ "@ckeditor/ckeditor5-widget": "^37.0.0-alpha.1",
37
37
  "lodash": "^4.17.15",
38
38
  "typescript": "^4.8.4",
39
39
  "webpack": "^5.58.1",
@@ -63,7 +63,8 @@
63
63
  ],
64
64
  "scripts": {
65
65
  "dll:build": "webpack",
66
- "build": "tsc -p ./tsconfig.release.json",
66
+ "build": "tsc -p ./tsconfig.json",
67
67
  "postversion": "npm run build"
68
- }
68
+ },
69
+ "types": "src/index.d.ts"
69
70
  }
@@ -0,0 +1,23 @@
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
+ import type { MentionConfig, Mention, MentionEditing, MentionUI, MentionCommand } from './index';
6
+ declare module '@ckeditor/ckeditor5-core' {
7
+ interface EditorConfig {
8
+ /**
9
+ * The configuration of the {@link module:mention/mention~Mention} feature.
10
+ *
11
+ * Read more in {@link module:mention/mentionconfig~MentionConfig}.
12
+ */
13
+ mention?: MentionConfig;
14
+ }
15
+ interface PluginsMap {
16
+ [Mention.pluginName]: Mention;
17
+ [MentionEditing.pluginName]: MentionEditing;
18
+ [MentionUI.pluginName]: MentionUI;
19
+ }
20
+ interface CommandsMap {
21
+ mention: MentionCommand;
22
+ }
23
+ }
@@ -0,0 +1,5 @@
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
+ export {};
package/src/index.d.ts ADDED
@@ -0,0 +1,13 @@
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';
11
+ export type { MentionConfig } from './mentionconfig';
12
+ export type { default as MentionCommand } from './mentioncommand';
13
+ import './augmentation';
package/src/index.js CHANGED
@@ -8,3 +8,4 @@
8
8
  export { default as Mention } from './mention';
9
9
  export { default as MentionEditing } from './mentionediting';
10
10
  export { default as MentionUI } from './mentionui';
11
+ import './augmentation';
@@ -0,0 +1,64 @@
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
+ };
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 documentation}.
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,71 @@
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
+ }
@@ -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 onto a range, execute the command and specify a mention object with a range to replace:
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/mention~MentionConfig}.
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/mention~MentionConfig}.
118
+ * See {@link module:mention/mentionconfig~MentionConfig}.
119
119
  *
120
120
  * @error mentioncommand-incorrect-id
121
121
  */
@@ -0,0 +1,265 @@
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~MentionFeedObjectItem} as HTMLElement.
199
+ */
200
+ export type ItemRenderer = (item: MentionFeedObjectItem) => HTMLElement | string;
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
+ };
@@ -0,0 +1,5 @@
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
+ export {};
@@ -0,0 +1,40 @@
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;
@@ -0,0 +1,101 @@
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
+ private _requestFeed;
68
+ /**
69
+ * Registers a text watcher for the marker.
70
+ */
71
+ private _setupTextWatcher;
72
+ /**
73
+ * Handles the feed response event data.
74
+ */
75
+ private _handleFeedResponse;
76
+ /**
77
+ * Shows the mentions balloon. If the panel is already visible, it will reposition it.
78
+ */
79
+ private _showOrUpdateUI;
80
+ /**
81
+ * Hides the mentions balloon and removes the 'mention' marker from the markers collection.
82
+ */
83
+ private _hideUIAndRemoveMarker;
84
+ /**
85
+ * Renders a single item in the autocomplete list.
86
+ */
87
+ private _renderItem;
88
+ /**
89
+ * Creates a position options object used to position the balloon panel.
90
+ *
91
+ * @param mentionMarker
92
+ * @param preferredPosition The name of the last matched position name.
93
+ */
94
+ private _getBalloonPanelPositionData;
95
+ }
96
+ /**
97
+ * Creates a RegExp pattern for the marker.
98
+ *
99
+ * Function has to be exported to achieve 100% code coverage.
100
+ */
101
+ export declare function createRegExp(marker: string, minimumCharacters: number): RegExp;
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.feed;
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/mention~MentionConfig}.
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
  }
@@ -195,10 +195,6 @@ export default class MentionUI extends Plugin {
195
195
  }
196
196
  /**
197
197
  * Requests a feed from a configured callbacks.
198
- *
199
- * @fires response
200
- * @fires discarded
201
- * @fires error
202
198
  */
203
199
  _requestFeed(marker, feedText) {
204
200
  // @if CK_DEBUG_MENTION // console.log( '%c[Feed]%c Requesting for', 'color: blue', 'color: black', `"${ feedText }"` );
@@ -281,7 +277,7 @@ export default class MentionUI extends Plugin {
281
277
  });
282
278
  }
283
279
  this._requestFeedDebounced(markerDefinition.marker, feedText);
284
- // @if CK_DEBUG_MENTION // console.groupEnd( '[TextWatcher] matched' );
280
+ // @if CK_DEBUG_MENTION // console.groupEnd();
285
281
  });
286
282
  watcher.on('unmatched', () => {
287
283
  this._hideUIAndRemoveMarker();
@@ -389,6 +385,7 @@ export default class MentionUI extends Plugin {
389
385
  const editing = editor.editing;
390
386
  const domConverter = editing.view.domConverter;
391
387
  const mapper = editing.mapper;
388
+ const uiLanguageDirection = editor.locale.uiLanguageDirection;
392
389
  return {
393
390
  target: () => {
394
391
  let modelRange = mentionMarker.getRange();
@@ -410,14 +407,14 @@ export default class MentionUI extends Plugin {
410
407
  }
411
408
  return null;
412
409
  },
413
- positions: getBalloonPanelPositions(preferredPosition)
410
+ positions: getBalloonPanelPositions(preferredPosition, uiLanguageDirection)
414
411
  };
415
412
  }
416
413
  }
417
414
  /**
418
415
  * Returns the balloon positions data callbacks.
419
416
  */
420
- function getBalloonPanelPositions(preferredPosition) {
417
+ function getBalloonPanelPositions(preferredPosition, uiLanguageDirection) {
421
418
  const positions = {
422
419
  // Positions the panel to the southeast of the caret rectangle.
423
420
  'caret_se': (targetRect) => {
@@ -470,12 +467,17 @@ function getBalloonPanelPositions(preferredPosition) {
470
467
  positions[preferredPosition]
471
468
  ];
472
469
  }
473
- // By default return all position callbacks.
474
- return [
470
+ // By default, return all position callbacks ordered depending on the UI language direction.
471
+ return uiLanguageDirection !== 'rtl' ? [
475
472
  positions.caret_se,
476
473
  positions.caret_sw,
477
474
  positions.caret_ne,
478
475
  positions.caret_nw
476
+ ] : [
477
+ positions.caret_sw,
478
+ positions.caret_se,
479
+ positions.caret_nw,
480
+ positions.caret_ne
479
481
  ];
480
482
  }
481
483
  /**
@@ -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
+ }
@@ -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 = false;
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
+ }