@ckeditor/ckeditor5-code-block 0.0.0-nightly-20240716.0 → 0.0.0-nightly-20240717.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,37 +1,4 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
- All changes in the package are documented in the main repository. See: https://github.com/ckeditor/ckeditor5/blob/master/CHANGELOG.md.
5
-
6
- Changes for the past releases are available below.
7
-
8
- ## [19.0.0](https://github.com/ckeditor/ckeditor5-code-block/compare/v18.0.0...v19.0.0) (April 29, 2020)
9
-
10
- ### Other changes
11
-
12
- * XML and HTML are no longer treated as the same language. Closes [ckeditor/ckeditor5#5794](https://github.com/ckeditor/ckeditor5/issues/5794). ([58a7009](https://github.com/ckeditor/ckeditor5-code-block/commit/58a7009))
13
- * Updated translations. ([5300e22](https://github.com/ckeditor/ckeditor5-code-block/commit/5300e22))
14
-
15
-
16
- ## [18.0.0](https://github.com/ckeditor/ckeditor5-code-block/compare/v17.0.0...v18.0.0) (March 19, 2020)
17
-
18
- ### Other changes
19
-
20
- * Updated translations. ([8613554](https://github.com/ckeditor/ckeditor5-code-block/commit/8613554))
21
-
22
-
23
- ## [17.0.0](https://github.com/ckeditor/ckeditor5-code-block/compare/v16.0.0...v17.0.0) (February 19, 2020)
24
-
25
- ### Bug fixes
26
-
27
- * It should be possible to use multiple CSS classes in the language configuration. Closes [ckeditor/ckeditor5#5924](https://github.com/ckeditor/ckeditor5/issues/5924). ([dca0fe4](https://github.com/ckeditor/ckeditor5-code-block/commit/dca0fe4))
28
- * Spell checker is now disabled inside code blocks. Closes [ckeditor/ckeditor5#5978](https://github.com/ckeditor/ckeditor5/issues/5978). ([cd03e20](https://github.com/ckeditor/ckeditor5-code-block/commit/cd03e20))
29
-
30
- ### Other changes
31
-
32
- * Updated translations. ([3604224](https://github.com/ckeditor/ckeditor5-code-block/commit/3604224))
33
-
34
-
35
- ## [16.0.0](https://github.com/ckeditor/ckeditor5-code-block/tree/v16.0.0) (December 4, 2019)
36
-
37
- The initial release.
4
+ All changes in the package are documented in https://github.com/ckeditor/ckeditor5/blob/master/CHANGELOG.md.
@@ -2,4 +2,4 @@
2
2
  /*!
3
3
  * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
4
4
  * For licensing, see LICENSE.md.
5
- */(()=>{var e={535:(e,t,n)=>{"use strict";n.d(t,{A:()=>r});var o=n(935),i=n.n(o)()((function(e){return e[1]}));i.push([e.id,".ck-content pre{background:hsla(0,0%,78%,.3);border:1px solid #c4c4c4;border-radius:2px;color:#353535;direction:ltr;font-style:normal;min-width:200px;padding:1em;tab-size:4;text-align:left;white-space:pre-wrap}.ck-content pre code{background:unset;border-radius:0;padding:0}.ck.ck-editor__editable pre{position:relative}.ck.ck-editor__editable pre[data-language]:after{content:attr(data-language);position:absolute}:root{--ck-color-code-block-label-background:#757575}.ck.ck-editor__editable pre[data-language]:after{background:var(--ck-color-code-block-label-background);color:#fff;font-family:var(--ck-font-face);font-size:10px;line-height:16px;padding:var(--ck-spacing-tiny) var(--ck-spacing-medium);right:10px;top:-1px;white-space:nowrap}.ck.ck-code-block-dropdown .ck-dropdown__panel{max-height:250px;overflow-x:hidden;overflow-y:auto}",""]);const r=i},935: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,o){"string"==typeof e&&(e=[[null,e,""]]);var i={};if(o)for(var r=0;r<this.length;r++){var c=this[r][0];null!=c&&(i[c]=!0)}for(var a=0;a<e.length;a++){var s=[].concat(e[a]);o&&i[s[0]]||(n&&(s[2]?s[2]="".concat(n," and ").concat(s[2]):s[2]=n),t.push(s))}},t}},591:(e,t,n)=>{"use strict";var o,i=function(){return void 0===o&&(o=Boolean(window&&document&&document.all&&!window.atob)),o},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]}}(),c=[];function a(e){for(var t=-1,n=0;n<c.length;n++)if(c[n].identifier===e){t=n;break}return t}function s(e,t){for(var n={},o=[],i=0;i<e.length;i++){var r=e[i],s=t.base?r[0]+t.base:r[0],l=n[s]||0,d="".concat(s," ").concat(l);n[s]=l+1;var u=a(d),g={css:r[1],media:r[2],sourceMap:r[3]};-1!==u?(c[u].references++,c[u].updater(g)):c.push({identifier:d,updater:h(g,t),references:1}),o.push(d)}return o}function l(e){var t=document.createElement("style"),o=e.attributes||{};if(void 0===o.nonce){var i=n.nc;i&&(o.nonce=i)}if(Object.keys(o).forEach((function(e){t.setAttribute(e,o[e])})),"function"==typeof e.insert)e.insert(t);else{var c=r(e.insert||"head");if(!c)throw new Error("Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid.");c.appendChild(t)}return t}var d,u=(d=[],function(e,t){return d[e]=t,d.filter(Boolean).join("\n")});function g(e,t,n,o){var i=n?"":o.media?"@media ".concat(o.media," {").concat(o.css,"}"):o.css;if(e.styleSheet)e.styleSheet.cssText=u(t,i);else{var r=document.createTextNode(i),c=e.childNodes;c[t]&&e.removeChild(c[t]),c.length?e.insertBefore(r,c[t]):e.appendChild(r)}}function f(e,t,n){var o=n.css,i=n.media,r=n.sourceMap;if(i?e.setAttribute("media",i):e.removeAttribute("media"),r&&"undefined"!=typeof btoa&&(o+="\n/*# sourceMappingURL=data:application/json;base64,".concat(btoa(unescape(encodeURIComponent(JSON.stringify(r))))," */")),e.styleSheet)e.styleSheet.cssText=o;else{for(;e.firstChild;)e.removeChild(e.firstChild);e.appendChild(document.createTextNode(o))}}var p=null,m=0;function h(e,t){var n,o,i;if(t.singleton){var r=m++;n=p||(p=l(t)),o=g.bind(null,n,r,!1),i=g.bind(null,n,r,!0)}else n=l(t),o=f.bind(null,n,t),i=function(){!function(e){if(null===e.parentNode)return!1;e.parentNode.removeChild(e)}(n)};return o(e),function(t){if(t){if(t.css===e.css&&t.media===e.media&&t.sourceMap===e.sourceMap)return;o(e=t)}else i()}}e.exports=function(e,t){(t=t||{}).singleton||"boolean"==typeof t.singleton||(t.singleton=i());var n=s(e=e||[],t);return function(e){if(e=e||[],"[object Array]"===Object.prototype.toString.call(e)){for(var o=0;o<n.length;o++){var i=a(n[o]);c[i].references--}for(var r=s(e,t),l=0;l<n.length;l++){var d=a(n[l]);0===c[d].references&&(c[d].updater(),c.splice(d,1))}n=r}}}},782:(e,t,n)=>{e.exports=n(237)("./src/core.js")},783:(e,t,n)=>{e.exports=n(237)("./src/engine.js")},507:(e,t,n)=>{e.exports=n(237)("./src/enter.js")},311:(e,t,n)=>{e.exports=n(237)("./src/ui.js")},584:(e,t,n)=>{e.exports=n(237)("./src/utils.js")},237:e=>{"use strict";e.exports=CKEditor5.dll}},t={};function n(o){var i=t[o];if(void 0!==i)return i.exports;var r=t[o]={id:o,exports:{}};return e[o](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 o in t)n.o(t,o)&&!n.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:t[o]})},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 o={};(()=>{"use strict";n.r(o),n.d(o,{CodeBlock:()=>_,CodeBlockEditing:()=>k,CodeBlockUI:()=>E});var e=n(782),t=n(507),i=n(783),r=n(584);function c(e){const t=e.t,n=e.config.get("codeBlock.languages");for(const e of n)"Plain text"===e.label&&(e.label=t("Plain text")),void 0===e.class&&(e.class=`language-${e.language}`);return n}function a(e,t,n){const o={};for(const i of e)if("class"===t){o[i[t].split(" ").shift()]=i[n]}else o[i[t]]=i[n];return o}function s(e){return e.data.match(/^(\s*)/)[0]}function l(e){const t=e.document.selection,n=[];if(t.isCollapsed)return[t.anchor];const o=t.getFirstRange().getWalker({ignoreElementEnd:!0,direction:"backward"});for(const{item:t}of o){if(!t.is("$textProxy"))continue;const{parent:o,startOffset:i}=t.textNode;if(!o.is("element","codeBlock"))continue;const r=s(t.textNode),c=e.createPositionAt(o,i+r.length);n.push(c)}return n}function d(e){const t=(0,r.first)(e.getSelectedBlocks());return!!t&&t.is("element","codeBlock")}function u(e,t){return!t.is("rootElement")&&!e.isLimit(t)&&e.checkChild(t.parent,"codeBlock")}function g(e,t,n,o){const i=a(t,"language","label"),r=n.getAttribute("language");if(r in i){const t=i[r];return e("enter"===o?"Entering %0 code snippet":"Leaving %0 code snippet",t)}return e("enter"===o?"Entering code snippet":"Leaving code snippet")}class f extends e.Command{constructor(e){super(e),this._lastLanguage=null}refresh(){this.value=this._getValue(),this.isEnabled=this._checkEnabled()}execute(e={}){const t=this.editor,n=t.model,o=n.document.selection,i=c(t)[0],r=Array.from(o.getSelectedBlocks()),a=null==e.forceValue?!this.value:e.forceValue,s=function(e,t,n){if(e.language)return e.language;if(e.usePreviousLanguageChoice&&t)return t;return n}(e,this._lastLanguage,i.language);n.change((e=>{a?this._applyCodeBlock(e,r,s):this._removeCodeBlock(e,r)}))}_getValue(){const e=this.editor.model.document.selection,t=(0,r.first)(e.getSelectedBlocks());return!!!(!t||!t.is("element","codeBlock"))&&t.getAttribute("language")}_checkEnabled(){if(this.value)return!0;const e=this.editor.model.document.selection,t=this.editor.model.schema,n=(0,r.first)(e.getSelectedBlocks());return!!n&&u(t,n)}_applyCodeBlock(e,t,n){this._lastLanguage=n;const o=this.editor.model.schema,i=t.filter((e=>u(o,e)));for(const t of i)e.rename(t,"codeBlock"),e.setAttribute("language",n,t),o.removeDisallowedAttributes([t],e),Array.from(t.getChildren()).filter((e=>!o.checkChild(t,e))).forEach((t=>e.remove(t)));i.reverse().forEach(((t,n)=>{const o=i[n+1];t.previousSibling===o&&(e.appendElement("softBreak",o),e.merge(e.createPositionBefore(t)))}))}_removeCodeBlock(e,t){const n=t.filter((e=>e.is("element","codeBlock")));for(const t of n){const n=e.createRangeOn(t);for(const t of Array.from(n.getItems()).reverse())if(t.is("element","softBreak")&&t.parent.is("element","codeBlock")){const{position:n}=e.split(e.createPositionBefore(t)),o=n.nodeAfter;e.rename(o,"paragraph"),e.removeAttribute("language",o),e.remove(t)}e.rename(t,"paragraph"),e.removeAttribute("language",t)}}}class p extends e.Command{constructor(e){super(e),this._indentSequence=e.config.get("codeBlock.indentSequence")}refresh(){this.isEnabled=this._checkEnabled()}execute(){const e=this.editor.model;e.change((t=>{const n=l(e);for(const o of n){const n=t.createText(this._indentSequence);e.insertContent(n,o)}}))}_checkEnabled(){return!!this._indentSequence&&d(this.editor.model.document.selection)}}class m extends e.Command{constructor(e){super(e),this._indentSequence=e.config.get("codeBlock.indentSequence")}refresh(){this.isEnabled=this._checkEnabled()}execute(){const e=this.editor.model;e.change((()=>{const t=l(e);for(const n of t){const t=h(e,n,this._indentSequence);t&&e.deleteContent(e.createSelection(t))}}))}_checkEnabled(){if(!this._indentSequence)return!1;const e=this.editor.model;return!!d(e.document.selection)&&l(e).some((t=>h(e,t,this._indentSequence)))}}function h(e,t,n){const o=function(e){let t=e.parent.getChild(e.index);t&&!t.is("element","softBreak")||(t=e.nodeBefore);if(!t||t.is("element","softBreak"))return null;return t}(t);if(!o)return null;const i=s(o),r=i.lastIndexOf(n);if(r+n.length!==i.length)return null;if(-1===r)return null;const{parent:c,startOffset:a}=o;return e.createRange(e.createPositionAt(c,a+r),e.createPositionAt(c,a+r+n.length))}function b(e,t,n=!1){const o=a(t,"language","class"),i=a(t,"language","label");return(t,r,c)=>{const{writer:a,mapper:s,consumable:l}=c;if(!l.consume(r.item,"insert"))return;const d=r.item.getAttribute("language"),u=s.toViewPosition(e.createPositionBefore(r.item)),g={};n&&(g["data-language"]=i[d],g.spellcheck="false");const f=o[d]?{class:o[d]}:void 0,p=a.createContainerElement("code",f),m=a.createContainerElement("pre",g,p);a.insert(u,m),s.bindElements(r.item,p)}}const v="paragraph";class k extends e.Plugin{static get pluginName(){return"CodeBlockEditing"}static get requires(){return[t.ShiftEnter]}constructor(e){super(e),e.config.define("codeBlock",{languages:[{language:"plaintext",label:"Plain text"},{language:"c",label:"C"},{language:"cs",label:"C#"},{language:"cpp",label:"C++"},{language:"css",label:"CSS"},{language:"diff",label:"Diff"},{language:"html",label:"HTML"},{language:"java",label:"Java"},{language:"javascript",label:"JavaScript"},{language:"php",label:"PHP"},{language:"python",label:"Python"},{language:"ruby",label:"Ruby"},{language:"typescript",label:"TypeScript"},{language:"xml",label:"XML"}],indentSequence:"\t"})}init(){const e=this.editor,t=e.model.schema,n=e.model,o=e.editing.view,r=c(e);e.commands.add("codeBlock",new f(e)),e.commands.add("indentCodeBlock",new p(e)),e.commands.add("outdentCodeBlock",new m(e)),this.listenTo(o.document,"tab",((t,n)=>{const o=n.shiftKey?"outdentCodeBlock":"indentCodeBlock";e.commands.get(o).isEnabled&&(e.execute(o),n.stopPropagation(),n.preventDefault(),t.stop())}),{context:"pre"}),t.register("codeBlock",{allowWhere:"$block",allowChildren:"$text",disallowChildren:"$inlineObject",allowAttributes:["language"],allowAttributesOf:"$listItem",isBlock:!0}),t.addAttributeCheck((e=>{if(e.endsWith("codeBlock $text"))return!1})),e.editing.downcastDispatcher.on("insert:codeBlock",b(n,r,!0)),e.data.downcastDispatcher.on("insert:codeBlock",b(n,r)),e.data.downcastDispatcher.on("insert:softBreak",function(e){return(t,n,o)=>{if("codeBlock"!==n.item.parent.name)return;const{writer:i,mapper:r,consumable:c}=o;if(!c.consume(n.item,"insert"))return;const a=r.toViewPosition(e.createPositionBefore(n.item));i.insert(a,i.createText("\n"))}}(n),{priority:"high"}),e.data.upcastDispatcher.on("element:code",function(e,t){const n=a(t,"class","language"),o=t[0].language;return(e,t,i)=>{const r=t.viewItem,c=r.parent;if(!c||!c.is("element","pre"))return;if(t.modelCursor.findAncestor("codeBlock"))return;const{consumable:a,writer:s}=i;if(!a.test(r,{name:!0}))return;const l=s.createElement("codeBlock"),d=[...r.getClassNames()];d.length||d.push("");for(const e of d){const t=n[e];if(t){s.setAttribute("language",t,l);break}}l.hasAttribute("language")||s.setAttribute("language",o,l),i.convertChildren(r,l),i.safeInsert(l,t.modelCursor)&&(a.consume(r,{name:!0}),i.updateConversionResult(l,t))}}(0,r)),e.data.upcastDispatcher.on("text",((e,t,{consumable:n,writer:o})=>{let i=t.modelCursor;if(!n.test(t.viewItem))return;if(!i.findAncestor("codeBlock"))return;n.consume(t.viewItem);const r=t.viewItem.data.split("\n").map((e=>o.createText(e))),c=r[r.length-1];for(const e of r)if(o.insert(e,i),i=i.getShiftedBy(e.offsetSize),e!==c){const e=o.createElement("softBreak");o.insert(e,i),i=o.createPositionAfter(e)}t.modelRange=o.createRange(t.modelCursor,i),t.modelCursor=i})),e.data.upcastDispatcher.on("element:pre",((e,t,{consumable:n})=>{const o=t.viewItem;if(o.findAncestor("pre"))return;const i=Array.from(o.getChildren()),r=i.find((e=>e.is("element","code")));if(r)for(const e of i)e!==r&&e.is("$text")&&n.consume(e,{name:!0})}),{priority:"high"}),this.listenTo(e.editing.view.document,"clipboardInput",((t,o)=>{let r=n.createRange(n.document.selection.anchor);if(o.targetRanges&&(r=e.editing.mapper.toModelRange(o.targetRanges[0])),!r.start.parent.is("element","codeBlock"))return;const c=o.dataTransfer.getData("text/plain"),a=new i.UpcastWriter(e.editing.view.document);o.content=function(e,t){const n=e.createDocumentFragment(),o=t.split("\n"),i=o.reduce(((t,n,i)=>(t.push(n),i<o.length-1&&t.push(e.createElement("br")),t)),[]);return e.appendChild(i,n),n}(a,c)})),this.listenTo(n,"getSelectedContent",((e,[o])=>{const i=o.anchor;!o.isCollapsed&&i.parent.is("element","codeBlock")&&i.hasSameParentAs(o.focus)&&n.change((n=>{const r=e.return;if(i.parent.is("element")&&(r.childCount>1||o.containsEntireContent(i.parent))){const t=n.createElement("codeBlock",i.parent.getAttributes());n.append(r,t);const o=n.createDocumentFragment();return n.append(t,o),void(e.return=o)}const c=r.getChild(0);t.checkAttribute(c,"code")&&n.setAttribute("code",!0,c)}))}))}afterInit(){const e=this.editor,t=e.commands,n=t.get("indent"),o=t.get("outdent");n&&n.registerChildCommand(t.get("indentCodeBlock"),{priority:"highest"}),o&&o.registerChildCommand(t.get("outdentCodeBlock")),this.listenTo(e.editing.view.document,"enter",((t,n)=>{e.model.document.selection.getLastPosition().parent.is("element","codeBlock")&&(function(e,t){const n=e.model,o=n.document,i=e.editing.view,r=o.selection.getLastPosition(),c=r.nodeAfter;if(t||!o.selection.isCollapsed||!r.isAtStart)return!1;if(!w(c))return!1;return e.model.change((t=>{e.execute("enter");const n=o.selection.anchor.parent.previousSibling;t.rename(n,v),t.setSelection(n,"in"),e.model.schema.removeDisallowedAttributes([n],t),t.remove(c)})),i.scrollToTheSelection(),!0}(e,n.isSoft)||function(e,t){const n=e.model,o=n.document,i=e.editing.view,r=o.selection.getLastPosition(),c=r.nodeBefore;let a;if(t||!o.selection.isCollapsed||!r.isAtEnd||!c||!c.previousSibling)return!1;if(w(c)&&w(c.previousSibling))a=n.createRange(n.createPositionBefore(c.previousSibling),n.createPositionAfter(c));else if(B(c)&&w(c.previousSibling)&&w(c.previousSibling.previousSibling))a=n.createRange(n.createPositionBefore(c.previousSibling.previousSibling),n.createPositionAfter(c));else{if(!(B(c)&&w(c.previousSibling)&&B(c.previousSibling.previousSibling)&&c.previousSibling.previousSibling&&w(c.previousSibling.previousSibling.previousSibling)))return!1;a=n.createRange(n.createPositionBefore(c.previousSibling.previousSibling.previousSibling),n.createPositionAfter(c))}return e.model.change((t=>{t.remove(a),e.execute("enter");const n=o.selection.anchor.parent;t.rename(n,v),e.model.schema.removeDisallowedAttributes([n],t)})),i.scrollToTheSelection(),!0}(e,n.isSoft)||function(e){const t=e.model,n=t.document,o=n.selection.getLastPosition(),i=o.nodeBefore||o.textNode;let r;i&&i.is("$text")&&(r=s(i));e.model.change((t=>{e.execute("shiftEnter"),r&&t.insertText(r,n.selection.anchor)}))}(e),n.preventDefault(),t.stop())}),{context:"pre"}),this._initAriaAnnouncements()}_initAriaAnnouncements(){const{model:e,ui:t,t:n}=this.editor,o=c(this.editor);let i=null;e.document.selection.on("change:range",(()=>{const r=e.document.selection.focus.parent;t&&i!==r&&r.is("element")&&(i&&i.is("element","codeBlock")&&t.ariaLiveAnnouncer.announce(g(n,o,i,"leave")),r.is("element","codeBlock")&&t.ariaLiveAnnouncer.announce(g(n,o,r,"enter")),i=r)}))}}function B(e){return e&&e.is("$text")&&!e.data.match(/\S/)}function w(e){return e&&e.is("element","softBreak")}var C=n(311),x=n(591),S=n.n(x),y=n(535),A={injectType:"singletonStyleTag",attributes:{"data-cke":!0},insert:"head",singleton:!0};S()(y.A,A);y.A.locals;class E extends e.Plugin{static get pluginName(){return"CodeBlockUI"}init(){const t=this.editor,n=t.t,o=t.ui.componentFactory,i=c(t),r=this._getLanguageListItemDefinitions(i),a=t.commands.get("codeBlock");o.add("codeBlock",(o=>{const i=(0,C.createDropdown)(o,C.SplitButtonView),c=i.buttonView,s=n("Insert code block");return c.set({label:s,tooltip:!0,icon:e.icons.codeBlock,isToggleable:!0}),c.bind("isOn").to(a,"value",(e=>!!e)),c.on("execute",(()=>{t.execute("codeBlock",{usePreviousLanguageChoice:!0}),t.editing.view.focus()})),i.on("execute",(e=>{t.execute("codeBlock",{language:e.source._codeBlockLanguage,forceValue:!0}),t.editing.view.focus()})),i.class="ck-code-block-dropdown",i.bind("isEnabled").to(a),(0,C.addListToDropdown)(i,r,{role:"menu",ariaLabel:s}),i})),o.add("menuBar:codeBlock",(o=>{const i=new C.MenuBarMenuView(o);i.buttonView.set({role:"menuitem",label:n("Code block"),icon:e.icons.codeBlock}),i.bind("isEnabled").to(a);const c=new C.MenuBarMenuListView(o);c.set({ariaLabel:n("Insert code block")});for(const e of r){const n=new C.MenuBarMenuListItemView(o,i),r=new C.MenuBarMenuListItemButtonView(o);r.bind(...Object.keys(e.model)).to(e.model),r.set({isToggleable:!0,role:"menuitemcheckbox"}),r.delegate("execute").to(i),r.on("execute",(()=>{t.execute("codeBlock",{language:e.model._codeBlockLanguage,forceValue:a.value!=e.model._codeBlockLanguage}),t.editing.view.focus()})),n.children.add(r),c.items.add(n)}return i.panelView.children.add(c),i}))}_getLanguageListItemDefinitions(e){const t=this.editor.commands.get("codeBlock"),n=new r.Collection;for(const o of e){const e={type:"button",model:new C.ViewModel({_codeBlockLanguage:o.language,label:o.label,role:"menuitemradio",withText:!0})};e.model.bind("isOn").to(t,"value",(t=>t===e.model._codeBlockLanguage)),n.add(e)}return n}}class _ extends e.Plugin{static get requires(){return[k,E]}static get pluginName(){return"CodeBlock"}}})(),(window.CKEditor5=window.CKEditor5||{}).codeBlock=o})();
5
+ */(()=>{var e={535:(e,t,n)=>{"use strict";n.d(t,{A:()=>r});var o=n(935),i=n.n(o)()((function(e){return e[1]}));i.push([e.id,".ck-content pre{background:hsla(0,0%,78%,.3);border:1px solid #c4c4c4;border-radius:2px;color:#353535;direction:ltr;font-style:normal;min-width:200px;padding:1em;tab-size:4;text-align:left;white-space:pre-wrap}.ck-content pre code{background:unset;border-radius:0;padding:0}.ck.ck-editor__editable pre{position:relative}.ck.ck-editor__editable pre[data-language]:after{content:attr(data-language);position:absolute}:root{--ck-color-code-block-label-background:#757575}.ck.ck-editor__editable pre[data-language]:after{background:var(--ck-color-code-block-label-background);color:#fff;font-family:var(--ck-font-face);font-size:10px;line-height:16px;padding:var(--ck-spacing-tiny) var(--ck-spacing-medium);right:10px;top:-1px;white-space:nowrap}.ck.ck-code-block-dropdown .ck-dropdown__panel{max-height:250px;overflow-x:hidden;overflow-y:auto}",""]);const r=i},935: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,o){"string"==typeof e&&(e=[[null,e,""]]);var i={};if(o)for(var r=0;r<this.length;r++){var c=this[r][0];null!=c&&(i[c]=!0)}for(var a=0;a<e.length;a++){var s=[].concat(e[a]);o&&i[s[0]]||(n&&(s[2]?s[2]="".concat(n," and ").concat(s[2]):s[2]=n),t.push(s))}},t}},591:(e,t,n)=>{"use strict";var o,i=function(){return void 0===o&&(o=Boolean(window&&document&&document.all&&!window.atob)),o},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]}}(),c=[];function a(e){for(var t=-1,n=0;n<c.length;n++)if(c[n].identifier===e){t=n;break}return t}function s(e,t){for(var n={},o=[],i=0;i<e.length;i++){var r=e[i],s=t.base?r[0]+t.base:r[0],l=n[s]||0,d="".concat(s," ").concat(l);n[s]=l+1;var u=a(d),g={css:r[1],media:r[2],sourceMap:r[3]};-1!==u?(c[u].references++,c[u].updater(g)):c.push({identifier:d,updater:h(g,t),references:1}),o.push(d)}return o}function l(e){var t=document.createElement("style"),o=e.attributes||{};if(void 0===o.nonce){var i=n.nc;i&&(o.nonce=i)}if(Object.keys(o).forEach((function(e){t.setAttribute(e,o[e])})),"function"==typeof e.insert)e.insert(t);else{var c=r(e.insert||"head");if(!c)throw new Error("Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid.");c.appendChild(t)}return t}var d,u=(d=[],function(e,t){return d[e]=t,d.filter(Boolean).join("\n")});function g(e,t,n,o){var i=n?"":o.media?"@media ".concat(o.media," {").concat(o.css,"}"):o.css;if(e.styleSheet)e.styleSheet.cssText=u(t,i);else{var r=document.createTextNode(i),c=e.childNodes;c[t]&&e.removeChild(c[t]),c.length?e.insertBefore(r,c[t]):e.appendChild(r)}}function f(e,t,n){var o=n.css,i=n.media,r=n.sourceMap;if(i?e.setAttribute("media",i):e.removeAttribute("media"),r&&"undefined"!=typeof btoa&&(o+="\n/*# sourceMappingURL=data:application/json;base64,".concat(btoa(unescape(encodeURIComponent(JSON.stringify(r))))," */")),e.styleSheet)e.styleSheet.cssText=o;else{for(;e.firstChild;)e.removeChild(e.firstChild);e.appendChild(document.createTextNode(o))}}var p=null,m=0;function h(e,t){var n,o,i;if(t.singleton){var r=m++;n=p||(p=l(t)),o=g.bind(null,n,r,!1),i=g.bind(null,n,r,!0)}else n=l(t),o=f.bind(null,n,t),i=function(){!function(e){if(null===e.parentNode)return!1;e.parentNode.removeChild(e)}(n)};return o(e),function(t){if(t){if(t.css===e.css&&t.media===e.media&&t.sourceMap===e.sourceMap)return;o(e=t)}else i()}}e.exports=function(e,t){(t=t||{}).singleton||"boolean"==typeof t.singleton||(t.singleton=i());var n=s(e=e||[],t);return function(e){if(e=e||[],"[object Array]"===Object.prototype.toString.call(e)){for(var o=0;o<n.length;o++){var i=a(n[o]);c[i].references--}for(var r=s(e,t),l=0;l<n.length;l++){var d=a(n[l]);0===c[d].references&&(c[d].updater(),c.splice(d,1))}n=r}}}},331:(e,t,n)=>{e.exports=n(237)("./src/clipboard.js")},782:(e,t,n)=>{e.exports=n(237)("./src/core.js")},783:(e,t,n)=>{e.exports=n(237)("./src/engine.js")},507:(e,t,n)=>{e.exports=n(237)("./src/enter.js")},311:(e,t,n)=>{e.exports=n(237)("./src/ui.js")},584:(e,t,n)=>{e.exports=n(237)("./src/utils.js")},237:e=>{"use strict";e.exports=CKEditor5.dll}},t={};function n(o){var i=t[o];if(void 0!==i)return i.exports;var r=t[o]={id:o,exports:{}};return e[o](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 o in t)n.o(t,o)&&!n.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:t[o]})},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 o={};(()=>{"use strict";n.r(o),n.d(o,{CodeBlock:()=>L,CodeBlockEditing:()=>w,CodeBlockUI:()=>P});var e=n(782),t=n(507),i=n(783),r=n(331),c=n(584);function a(e){const t=e.t,n=e.config.get("codeBlock.languages");for(const e of n)"Plain text"===e.label&&(e.label=t("Plain text")),void 0===e.class&&(e.class=`language-${e.language}`);return n}function s(e,t,n){const o={};for(const i of e)if("class"===t){o[i[t].split(" ").shift()]=i[n]}else o[i[t]]=i[n];return o}function l(e){return e.data.match(/^(\s*)/)[0]}function d(e){const t=e.document.selection,n=[];if(t.isCollapsed)return[t.anchor];const o=t.getFirstRange().getWalker({ignoreElementEnd:!0,direction:"backward"});for(const{item:t}of o){let o=t.is("$textProxy")?t.textNode:t;const i=o.parent;if(!i.is("element","codeBlock")||o.is("element","softBreak"))continue;for(;o.previousSibling&&!o.previousSibling.is("element","softBreak");)o=o.previousSibling;const r=o.is("$text")?o.startOffset+l(o).length:o.startOffset,c=e.createPositionAt(i,r);n.every((e=>!e.isEqual(c)))&&n.push(c)}return n}function u(e){const t=(0,c.first)(e.getSelectedBlocks());return!!t&&t.is("element","codeBlock")}function g(e,t){return!t.is("rootElement")&&!e.isLimit(t)&&e.checkChild(t.parent,"codeBlock")}function f(e,t,n,o){const i=s(t,"language","label"),r=n.getAttribute("language");if(r in i){const t=i[r];return e("enter"===o?"Entering %0 code snippet":"Leaving %0 code snippet",t)}return e("enter"===o?"Entering code snippet":"Leaving code snippet")}function p(e,t){for(e.textNode&&(e=t.createPositionBefore(e.textNode));e.nodeBefore&&!e.nodeBefore.is("element","softBreak");)e=t.createPositionBefore(e.nodeBefore);const n=e.nodeAfter;return n&&n.is("$text")?n:null}class m extends e.Command{constructor(e){super(e),this._lastLanguage=null}refresh(){this.value=this._getValue(),this.isEnabled=this._checkEnabled()}execute(e={}){const t=this.editor,n=t.model,o=n.document.selection,i=a(t)[0],r=Array.from(o.getSelectedBlocks()),c=null==e.forceValue?!this.value:e.forceValue,s=function(e,t,n){if(e.language)return e.language;if(e.usePreviousLanguageChoice&&t)return t;return n}(e,this._lastLanguage,i.language);n.change((e=>{c?this._applyCodeBlock(e,r,s):this._removeCodeBlock(e,r)}))}_getValue(){const e=this.editor.model.document.selection,t=(0,c.first)(e.getSelectedBlocks());return!!!(!t||!t.is("element","codeBlock"))&&t.getAttribute("language")}_checkEnabled(){if(this.value)return!0;const e=this.editor.model.document.selection,t=this.editor.model.schema,n=(0,c.first)(e.getSelectedBlocks());return!!n&&g(t,n)}_applyCodeBlock(e,t,n){this._lastLanguage=n;const o=this.editor.model.schema,i=t.filter((e=>g(o,e)));for(const t of i)e.rename(t,"codeBlock"),e.setAttribute("language",n,t),o.removeDisallowedAttributes([t],e),Array.from(t.getChildren()).filter((e=>!o.checkChild(t,e))).forEach((t=>e.remove(t)));i.reverse().forEach(((t,n)=>{const o=i[n+1];t.previousSibling===o&&(e.appendElement("softBreak",o),e.merge(e.createPositionBefore(t)))}))}_removeCodeBlock(e,t){const n=t.filter((e=>e.is("element","codeBlock")));for(const t of n){const n=e.createRangeOn(t);for(const t of Array.from(n.getItems()).reverse())if(t.is("element","softBreak")&&t.parent.is("element","codeBlock")){const{position:n}=e.split(e.createPositionBefore(t)),o=n.nodeAfter;e.rename(o,"paragraph"),e.removeAttribute("language",o),e.remove(t)}e.rename(t,"paragraph"),e.removeAttribute("language",t)}}}class h extends e.Command{constructor(e){super(e),this._indentSequence=e.config.get("codeBlock.indentSequence")}refresh(){this.isEnabled=this._checkEnabled()}execute(){const e=this.editor.model;e.change((t=>{const n=d(e);for(const o of n){const n=t.createText(this._indentSequence);e.insertContent(n,o)}}))}_checkEnabled(){return!!this._indentSequence&&u(this.editor.model.document.selection)}}class b extends e.Command{constructor(e){super(e),this._indentSequence=e.config.get("codeBlock.indentSequence")}refresh(){this.isEnabled=this._checkEnabled()}execute(){const e=this.editor.model;e.change((()=>{const t=d(e);for(const n of t){const t=v(e,n,this._indentSequence);t&&e.deleteContent(e.createSelection(t))}}))}_checkEnabled(){if(!this._indentSequence)return!1;const e=this.editor.model;return!!u(e.document.selection)&&d(e).some((t=>v(e,t,this._indentSequence)))}}function v(e,t,n){const o=p(t,e);if(!o)return null;const i=l(o),r=i.lastIndexOf(n);if(r+n.length!==i.length)return null;if(-1===r)return null;const{parent:c,startOffset:a}=o;return e.createRange(e.createPositionAt(c,a+r),e.createPositionAt(c,a+r+n.length))}function k(e,t,n=!1){const o=s(t,"language","class"),i=s(t,"language","label");return(t,r,c)=>{const{writer:a,mapper:s,consumable:l}=c;if(!l.consume(r.item,"insert"))return;const d=r.item.getAttribute("language"),u=s.toViewPosition(e.createPositionBefore(r.item)),g={};n&&(g["data-language"]=i[d],g.spellcheck="false");const f=o[d]?{class:o[d]}:void 0,p=a.createContainerElement("code",f),m=a.createContainerElement("pre",g,p);a.insert(u,m),s.bindElements(r.item,p)}}const B="paragraph";class w extends e.Plugin{static get pluginName(){return"CodeBlockEditing"}static get requires(){return[t.ShiftEnter]}constructor(e){super(e),e.config.define("codeBlock",{languages:[{language:"plaintext",label:"Plain text"},{language:"c",label:"C"},{language:"cs",label:"C#"},{language:"cpp",label:"C++"},{language:"css",label:"CSS"},{language:"diff",label:"Diff"},{language:"html",label:"HTML"},{language:"java",label:"Java"},{language:"javascript",label:"JavaScript"},{language:"php",label:"PHP"},{language:"python",label:"Python"},{language:"ruby",label:"Ruby"},{language:"typescript",label:"TypeScript"},{language:"xml",label:"XML"}],indentSequence:"\t"})}init(){const e=this.editor,t=e.model.schema,n=e.model,o=e.editing.view,c=a(e);e.commands.add("codeBlock",new m(e)),e.commands.add("indentCodeBlock",new h(e)),e.commands.add("outdentCodeBlock",new b(e)),this.listenTo(o.document,"tab",((t,n)=>{const o=n.shiftKey?"outdentCodeBlock":"indentCodeBlock";e.commands.get(o).isEnabled&&(e.execute(o),n.stopPropagation(),n.preventDefault(),t.stop())}),{context:"pre"}),t.register("codeBlock",{allowWhere:"$block",allowChildren:"$text",disallowChildren:"$inlineObject",allowAttributes:["language"],allowAttributesOf:"$listItem",isBlock:!0}),t.addAttributeCheck((e=>{if(e.endsWith("codeBlock $text"))return!1})),e.editing.downcastDispatcher.on("insert:codeBlock",k(n,c,!0)),e.data.downcastDispatcher.on("insert:codeBlock",k(n,c)),e.data.downcastDispatcher.on("insert:softBreak",function(e){return(t,n,o)=>{if("codeBlock"!==n.item.parent.name)return;const{writer:i,mapper:r,consumable:c}=o;if(!c.consume(n.item,"insert"))return;const a=r.toViewPosition(e.createPositionBefore(n.item));i.insert(a,i.createText("\n"))}}(n),{priority:"high"}),e.data.upcastDispatcher.on("element:code",function(e,t){const n=s(t,"class","language"),o=t[0].language;return(e,t,i)=>{const r=t.viewItem,c=r.parent;if(!c||!c.is("element","pre"))return;if(t.modelCursor.findAncestor("codeBlock"))return;const{consumable:a,writer:s}=i;if(!a.test(r,{name:!0}))return;const l=s.createElement("codeBlock"),d=[...r.getClassNames()];d.length||d.push("");for(const e of d){const t=n[e];if(t){s.setAttribute("language",t,l);break}}l.hasAttribute("language")||s.setAttribute("language",o,l),i.convertChildren(r,l),i.safeInsert(l,t.modelCursor)&&(a.consume(r,{name:!0}),i.updateConversionResult(l,t))}}(0,c)),e.data.upcastDispatcher.on("text",((e,t,{consumable:n,writer:o})=>{let i=t.modelCursor;if(!n.test(t.viewItem))return;if(!i.findAncestor("codeBlock"))return;n.consume(t.viewItem);const r=t.viewItem.data.split("\n").map((e=>o.createText(e))),c=r[r.length-1];for(const e of r)if(o.insert(e,i),i=i.getShiftedBy(e.offsetSize),e!==c){const e=o.createElement("softBreak");o.insert(e,i),i=o.createPositionAfter(e)}t.modelRange=o.createRange(t.modelCursor,i),t.modelCursor=i})),e.data.upcastDispatcher.on("element:pre",((e,t,{consumable:n})=>{const o=t.viewItem;if(o.findAncestor("pre"))return;const i=Array.from(o.getChildren()),r=i.find((e=>e.is("element","code")));if(r)for(const e of i)e!==r&&e.is("$text")&&n.consume(e,{name:!0})}),{priority:"high"}),this.listenTo(e.editing.view.document,"clipboardInput",((t,o)=>{let r=n.createRange(n.document.selection.anchor);if(o.targetRanges&&(r=e.editing.mapper.toModelRange(o.targetRanges[0])),!r.start.parent.is("element","codeBlock"))return;const c=o.dataTransfer.getData("text/plain"),a=new i.UpcastWriter(e.editing.view.document);o.content=function(e,t){const n=e.createDocumentFragment(),o=t.split("\n"),i=o.reduce(((t,n,i)=>(t.push(n),i<o.length-1&&t.push(e.createElement("br")),t)),[]);return e.appendChild(i,n),n}(a,c)})),e.plugins.has("ClipboardPipeline")&&e.plugins.get(r.ClipboardPipeline).on("contentInsertion",((n,o)=>{const i=e.model,r=i.document.selection;r.anchor.parent.is("element","codeBlock")&&i.change((e=>{const n=e.createRangeIn(o.content);for(const o of[...n.getItems()])o.is("node")&&!t.checkChild(r.anchor,o)&&e.remove(o)}))})),this.listenTo(n,"getSelectedContent",((e,[o])=>{const i=o.anchor;!o.isCollapsed&&i.parent.is("element","codeBlock")&&i.hasSameParentAs(o.focus)&&n.change((n=>{const r=e.return;if(i.parent.is("element")&&(r.childCount>1||o.containsEntireContent(i.parent))){const t=n.createElement("codeBlock",i.parent.getAttributes());n.append(r,t);const o=n.createDocumentFragment();return n.append(t,o),void(e.return=o)}const c=r.getChild(0);t.checkAttribute(c,"code")&&n.setAttribute("code",!0,c)}))}))}afterInit(){const e=this.editor,t=e.commands,n=t.get("indent"),o=t.get("outdent");n&&n.registerChildCommand(t.get("indentCodeBlock"),{priority:"highest"}),o&&o.registerChildCommand(t.get("outdentCodeBlock")),this.listenTo(e.editing.view.document,"enter",((t,n)=>{e.model.document.selection.getLastPosition().parent.is("element","codeBlock")&&(function(e,t){const n=e.model,o=n.document,i=e.editing.view,r=o.selection.getLastPosition(),c=r.nodeAfter;if(t||!o.selection.isCollapsed||!r.isAtStart)return!1;if(!x(c))return!1;return e.model.change((t=>{e.execute("enter");const n=o.selection.anchor.parent.previousSibling;t.rename(n,B),t.setSelection(n,"in"),e.model.schema.removeDisallowedAttributes([n],t),t.remove(c)})),i.scrollToTheSelection(),!0}(e,n.isSoft)||function(e,t){const n=e.model,o=n.document,i=e.editing.view,r=o.selection.getLastPosition(),c=r.nodeBefore;let a;if(t||!o.selection.isCollapsed||!r.isAtEnd||!c||!c.previousSibling)return!1;if(x(c)&&x(c.previousSibling))a=n.createRange(n.createPositionBefore(c.previousSibling),n.createPositionAfter(c));else if(C(c)&&x(c.previousSibling)&&x(c.previousSibling.previousSibling))a=n.createRange(n.createPositionBefore(c.previousSibling.previousSibling),n.createPositionAfter(c));else{if(!(C(c)&&x(c.previousSibling)&&C(c.previousSibling.previousSibling)&&c.previousSibling.previousSibling&&x(c.previousSibling.previousSibling.previousSibling)))return!1;a=n.createRange(n.createPositionBefore(c.previousSibling.previousSibling.previousSibling),n.createPositionAfter(c))}return e.model.change((t=>{t.remove(a),e.execute("enter");const n=o.selection.anchor.parent;t.rename(n,B),e.model.schema.removeDisallowedAttributes([n],t)})),i.scrollToTheSelection(),!0}(e,n.isSoft)||function(e){const t=e.model,n=t.document;let o;const i=p(n.selection.getLastPosition(),t);i&&i.is("$text")&&(o=l(i));e.model.change((t=>{e.execute("shiftEnter"),o&&t.insertText(o,n.selection.anchor)}))}(e),n.preventDefault(),t.stop())}),{context:"pre"}),this._initAriaAnnouncements()}_initAriaAnnouncements(){const{model:e,ui:t,t:n}=this.editor,o=a(this.editor);let i=null;e.document.selection.on("change:range",(()=>{const r=e.document.selection.focus.parent;t&&i!==r&&r.is("element")&&(i&&i.is("element","codeBlock")&&t.ariaLiveAnnouncer.announce(f(n,o,i,"leave")),r.is("element","codeBlock")&&t.ariaLiveAnnouncer.announce(f(n,o,r,"enter")),i=r)}))}}function C(e){return e&&e.is("$text")&&!e.data.match(/\S/)}function x(e){return e&&e.is("element","softBreak")}var S=n(311),y=n(591),A=n.n(y),E=n(535),_={injectType:"singletonStyleTag",attributes:{"data-cke":!0},insert:"head",singleton:!0};A()(E.A,_);E.A.locals;class P extends e.Plugin{static get pluginName(){return"CodeBlockUI"}init(){const t=this.editor,n=t.t,o=t.ui.componentFactory,i=a(t),r=this._getLanguageListItemDefinitions(i),c=t.commands.get("codeBlock");o.add("codeBlock",(o=>{const i=(0,S.createDropdown)(o,S.SplitButtonView),a=i.buttonView,s=n("Insert code block");return a.set({label:s,tooltip:!0,icon:e.icons.codeBlock,isToggleable:!0}),a.bind("isOn").to(c,"value",(e=>!!e)),a.on("execute",(()=>{t.execute("codeBlock",{usePreviousLanguageChoice:!0}),t.editing.view.focus()})),i.on("execute",(e=>{t.execute("codeBlock",{language:e.source._codeBlockLanguage,forceValue:!0}),t.editing.view.focus()})),i.class="ck-code-block-dropdown",i.bind("isEnabled").to(c),(0,S.addListToDropdown)(i,r,{role:"menu",ariaLabel:s}),i})),o.add("menuBar:codeBlock",(o=>{const i=new S.MenuBarMenuView(o);i.buttonView.set({role:"menuitem",label:n("Code block"),icon:e.icons.codeBlock}),i.bind("isEnabled").to(c);const a=new S.MenuBarMenuListView(o);a.set({ariaLabel:n("Insert code block")});for(const e of r){const n=new S.MenuBarMenuListItemView(o,i),r=new S.MenuBarMenuListItemButtonView(o);r.bind(...Object.keys(e.model)).to(e.model),r.set({isToggleable:!0,role:"menuitemcheckbox"}),r.delegate("execute").to(i),r.on("execute",(()=>{t.execute("codeBlock",{language:e.model._codeBlockLanguage,forceValue:c.value!=e.model._codeBlockLanguage}),t.editing.view.focus()})),n.children.add(r),a.items.add(n)}return i.panelView.children.add(a),i}))}_getLanguageListItemDefinitions(e){const t=this.editor.commands.get("codeBlock"),n=new c.Collection;for(const o of e){const e={type:"button",model:new S.ViewModel({_codeBlockLanguage:o.language,label:o.label,role:"menuitemradio",withText:!0})};e.model.bind("isOn").to(t,"value",(t=>t===e.model._codeBlockLanguage)),n.add(e)}return n}}class L extends e.Plugin{static get requires(){return[w,P]}static get pluginName(){return"CodeBlock"}}})(),(window.CKEditor5=window.CKEditor5||{}).codeBlock=o})();
package/dist/index.js CHANGED
@@ -5,6 +5,7 @@
5
5
  import { Command, Plugin, icons } from '@ckeditor/ckeditor5-core/dist/index.js';
6
6
  import { ShiftEnter } from '@ckeditor/ckeditor5-enter/dist/index.js';
7
7
  import { UpcastWriter } from '@ckeditor/ckeditor5-engine/dist/index.js';
8
+ import { ClipboardPipeline } from '@ckeditor/ckeditor5-clipboard/dist/index.js';
8
9
  import { first, Collection } from '@ckeditor/ckeditor5-utils/dist/index.js';
9
10
  import { createDropdown, SplitButtonView, addListToDropdown, MenuBarMenuView, MenuBarMenuListView, MenuBarMenuListItemView, MenuBarMenuListItemButtonView, ViewModel } from '@ckeditor/ckeditor5-ui/dist/index.js';
10
11
 
@@ -174,17 +175,23 @@ import { createDropdown, SplitButtonView, addListToDropdown, MenuBarMenuView, Me
174
175
  direction: 'backward'
175
176
  });
176
177
  for (const { item } of walker){
177
- if (!item.is('$textProxy')) {
178
+ let node = item.is('$textProxy') ? item.textNode : item;
179
+ const parent = node.parent;
180
+ if (!parent.is('element', 'codeBlock') || node.is('element', 'softBreak')) {
178
181
  continue;
179
182
  }
180
- const { parent, startOffset } = item.textNode;
181
- if (!parent.is('element', 'codeBlock')) {
182
- continue;
183
+ // For each item in code block, move backwards until the beginning of the line it is in is found.
184
+ while(node.previousSibling && !node.previousSibling.is('element', 'softBreak')){
185
+ node = node.previousSibling;
186
+ }
187
+ // Take the leading white spaces into account (only for text nodes).
188
+ const startOffset = !node.is('$text') ? node.startOffset : node.startOffset + getLeadingWhiteSpaces(node).length;
189
+ const position = model.createPositionAt(parent, startOffset);
190
+ // Do not add the same position twice. Unfortunately using set doesn't deduplicate positions because
191
+ // they are different objects.
192
+ if (positions.every((pos)=>!pos.isEqual(position))) {
193
+ positions.push(position);
183
194
  }
184
- const leadingWhiteSpaces = getLeadingWhiteSpaces(item.textNode);
185
- // Make sure the position is after all leading whitespaces in the text node.
186
- const position = model.createPositionAt(parent, startOffset + leadingWhiteSpaces.length);
187
- positions.push(position);
188
195
  }
189
196
  return positions;
190
197
  }
@@ -223,6 +230,52 @@ import { createDropdown, SplitButtonView, addListToDropdown, MenuBarMenuView, Me
223
230
  }
224
231
  return t('Leaving code snippet');
225
232
  }
233
+ /**
234
+ * For given position, finds the closest position that is at the beginning of a line of code and returns a text node that is at the
235
+ * beginning of the line (or `null` if there's no text node at the beginning of a given line).
236
+ *
237
+ * Line beings at the start of a code block element and after each `softBreak` element.
238
+ *
239
+ * Note: even though code block doesn't allow inline elements other than `<softBreak>` by default, some features may overwrite this rule,
240
+ * so such inline elements are taken into account.
241
+ *
242
+ * Some examples of expected results:
243
+ *
244
+ * ```
245
+ * <codeBlock>^</codeBlock> -> null
246
+ * <codeBlock>^foobar</codeBlock> -> <codeBlock>[foobar]</codeBlock>
247
+ * <codeBlock>foobar^</codeBlock> -> <codeBlock>[foobar]</codeBlock>
248
+ * <codeBlock>foo^bar</codeBlock> -> <codeBlock>[foobar]</codeBlock>
249
+ * <codeBlock>foo^<softBreak />bar</codeBlock> -> <codeBlock>[foo]<softBreak />bar</codeBlock>
250
+ * <codeBlock>foo<softBreak />bar^</codeBlock> -> <codeBlock>foo<softBreak />[bar]</codeBlock>
251
+ * <codeBlock>foo<softBreak />b^ar</codeBlock> -> <codeBlock>foo<softBreak />[bar]</codeBlock>
252
+ * <codeBlock>foo<softBreak />^bar</codeBlock> -> <codeBlock>foo<softBreak />[bar]</codeBlock>
253
+ * <codeBlock>^<element /></codeBlock> -> null
254
+ * <codeBlock><element />^</codeBlock> -> null
255
+ * <codeBlock>foo^<element /></codeBlock> -> <codeBlock>[foo]<element /></codeBlock>
256
+ * <codeBlock>foo<element />^</codeBlock> -> <codeBlock>[foo]<element /></codeBlock>
257
+ * <codeBlock>foo<element />bar^</codeBlock> -> <codeBlock>[foo]<element />bar</codeBlock>
258
+ * <codeBlock><element />bar^</codeBlock> -> null
259
+ * <codeBlock>foo<softBreak />^<softBreak /></codeBlock> -> null
260
+ * <codeBlock>foo<softBreak />^<element /></codeBlock> -> null
261
+ * <codeBlock>foo<softBreak /><element />^</codeBlock> -> null
262
+ * <codeBlock>foo<softBreak />bar<element />^</codeBlock> -> <codeBlock>foo<softBreak />[bar]<element /></codeBlock>
263
+ * <codeBlock>foo<softBreak /><element />ba^r</codeBlock> -> null
264
+ * ```
265
+ */ function getTextNodeAtLineStart(position, model) {
266
+ // First, move position before a text node, if it is inside a text node.
267
+ if (position.textNode) {
268
+ position = model.createPositionBefore(position.textNode);
269
+ }
270
+ // Then, jump-back the position until it is before a `softBreak` or at the beginning of the `codeBlock`.
271
+ while(position.nodeBefore && !position.nodeBefore.is('element', 'softBreak')){
272
+ position = model.createPositionBefore(position.nodeBefore);
273
+ }
274
+ // Now, the position is at the beginning of a line.
275
+ // Return a text node after the position, if there is one.
276
+ const nodeAtStart = position.nodeAfter;
277
+ return nodeAtStart && nodeAtStart.is('$text') ? nodeAtStart : null;
278
+ }
226
279
 
227
280
  /**
228
281
  * The code block command plugin.
@@ -516,7 +569,7 @@ import { createDropdown, SplitButtonView, addListToDropdown, MenuBarMenuView, Me
516
569
  // @returns {<module:engine/model/range~Range>|null}
517
570
  function getLastOutdentableSequenceRange(model, position, sequence) {
518
571
  // Positions start before each text node (code line). Get the node corresponding to the position.
519
- const nodeAtPosition = getCodeLineTextNodeAtPosition(position);
572
+ const nodeAtPosition = getTextNodeAtLineStart(position, model);
520
573
  if (!nodeAtPosition) {
521
574
  return null;
522
575
  }
@@ -546,21 +599,6 @@ function getLastOutdentableSequenceRange(model, position, sequence) {
546
599
  //
547
600
  return model.createRange(model.createPositionAt(parent, startOffset + lastIndexOfSequence), model.createPositionAt(parent, startOffset + lastIndexOfSequence + sequence.length));
548
601
  }
549
- function getCodeLineTextNodeAtPosition(position) {
550
- // Positions start before each text node (code line). Get the node corresponding to the position.
551
- let nodeAtPosition = position.parent.getChild(position.index);
552
- // <codeBlock>foo^</codeBlock>
553
- // <codeBlock>foo^<softBreak></softBreak>bar</codeBlock>
554
- if (!nodeAtPosition || nodeAtPosition.is('element', 'softBreak')) {
555
- nodeAtPosition = position.nodeBefore;
556
- }
557
- // <codeBlock>^</codeBlock>
558
- // <codeBlock>foo^<softBreak></softBreak>bar</codeBlock>
559
- if (!nodeAtPosition || nodeAtPosition.is('element', 'softBreak')) {
560
- return null;
561
- }
562
- return nodeAtPosition;
563
- }
564
602
 
565
603
  /**
566
604
  * A model-to-view (both editing and data) converter for the `codeBlock` element.
@@ -995,6 +1033,29 @@ const DEFAULT_ELEMENT = 'paragraph';
995
1033
  // Pass the view fragment to the default clipboardInput handler.
996
1034
  data.content = rawSnippetTextToViewDocumentFragment(writer, text);
997
1035
  });
1036
+ if (editor.plugins.has('ClipboardPipeline')) {
1037
+ // Elements may have a plain textual representation (hence be present in the 'text/plain' data transfer),
1038
+ // but not be allowed in the code block.
1039
+ // Filter them out before inserting the content to the model.
1040
+ editor.plugins.get(ClipboardPipeline).on('contentInsertion', (evt, data)=>{
1041
+ const model = editor.model;
1042
+ const selection = model.document.selection;
1043
+ if (!selection.anchor.parent.is('element', 'codeBlock')) {
1044
+ return;
1045
+ }
1046
+ model.change((writer)=>{
1047
+ const contentRange = writer.createRangeIn(data.content);
1048
+ for (const item of [
1049
+ ...contentRange.getItems()
1050
+ ]){
1051
+ // Remove all nodes disallowed in the code block.
1052
+ if (item.is('node') && !schema.checkChild(selection.anchor, item)) {
1053
+ writer.remove(item);
1054
+ }
1055
+ }
1056
+ });
1057
+ });
1058
+ }
998
1059
  // Make sure multi–line selection is always wrapped in a code block when `getSelectedContent()`
999
1060
  // is used (e.g. clipboard copy). Otherwise, only the raw text will be copied to the clipboard and,
1000
1061
  // upon next paste, this bare text will not be inserted as a code block, which is not the best UX.
@@ -1106,9 +1167,10 @@ const DEFAULT_ELEMENT = 'paragraph';
1106
1167
  */ function breakLineOnEnter(editor) {
1107
1168
  const model = editor.model;
1108
1169
  const modelDoc = model.document;
1170
+ // Use last position as other mechanisms (e.g. condition deciding whether this function should be called) also check that.
1109
1171
  const lastSelectionPosition = modelDoc.selection.getLastPosition();
1110
- const node = lastSelectionPosition.nodeBefore || lastSelectionPosition.textNode;
1111
1172
  let leadingWhiteSpaces;
1173
+ const node = getTextNodeAtLineStart(lastSelectionPosition, model);
1112
1174
  // Figure out the indentation (white space chars) at the beginning of the line.
1113
1175
  if (node && node.is('$text')) {
1114
1176
  leadingWhiteSpaces = getLeadingWhiteSpaces(node);