@ckeditor/ckeditor5-code-block 41.4.2 → 42.0.0-alpha.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/README.md CHANGED
@@ -15,6 +15,12 @@ Check out the [demo in the code block feature guide](https://ckeditor.com/docs/c
15
15
 
16
16
  See the [`@ckeditor/ckeditor5-code-block` package](https://ckeditor.com/docs/ckeditor5/latest/api/code-block.html) page as well as the [code block feature](https://ckeditor.com/docs/ckeditor5/latest/features/code-blocks.html) guide in the [CKEditor 5 documentation](https://ckeditor.com/docs/ckeditor5/latest/).
17
17
 
18
+ ## Installation
19
+
20
+ ```bash
21
+ npm install ckeditor5
22
+ ```
23
+
18
24
  ## License
19
25
 
20
26
  Licensed under the terms of [GNU General Public License Version 2 or later](http://www.gnu.org/licenses/gpl.html). For full details about the license, please check the `LICENSE.md` file or [https://ckeditor.com/legal/ckeditor-oss-license](https://ckeditor.com/legal/ckeditor-oss-license).
@@ -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=e.plugins.has("ListEditing")?e.plugins.get("ListEditing"):null,s=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",isBlock:!0,allowAttributes:["language"]}),t.addAttributeCheck(((e,t)=>!!(e.endsWith("codeBlock")&&r&&r.getListAttributeNames().includes(t))||!e.endsWith("codeBlock $text")&&void 0)),e.model.schema.addChildCheck(((e,t)=>{if(e.endsWith("codeBlock")&&t.isObject)return!1})),e.editing.downcastDispatcher.on("insert:codeBlock",b(n,s,!0)),e.data.downcastDispatcher.on("insert:codeBlock",b(n,s)),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,s)),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({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.bind("ariaChecked").to(r,"isOn"),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}}}},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({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.bind("ariaChecked").to(r,"isOn"),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})();
package/dist/index.js CHANGED
@@ -224,26 +224,37 @@ import { createDropdown, SplitButtonView, addListToDropdown, MenuBarMenuView, Me
224
224
  return t('Leaving code snippet');
225
225
  }
226
226
 
227
- class CodeBlockCommand extends Command {
227
+ /**
228
+ * The code block command plugin.
229
+ */ class CodeBlockCommand extends Command {
230
+ /**
231
+ * Contains the last used language.
232
+ */ _lastLanguage;
233
+ /**
234
+ * @inheritDoc
235
+ */ constructor(editor){
236
+ super(editor);
237
+ this._lastLanguage = null;
238
+ }
228
239
  /**
229
- * @inheritDoc
230
- */ refresh() {
240
+ * @inheritDoc
241
+ */ refresh() {
231
242
  this.value = this._getValue();
232
243
  this.isEnabled = this._checkEnabled();
233
244
  }
234
245
  /**
235
- * Executes the command. When the command {@link #value is on}, all topmost code blocks within
236
- * the selection will be removed. If it is off, all selected blocks will be flattened and
237
- * wrapped by a code block.
238
- *
239
- * @fires execute
240
- * @param options Command options.
241
- * @param options.language The code block language.
242
- * @param options.forceValue If set, it will force the command behavior. If `true`, the command will apply a code block,
243
- * otherwise the command will remove the code block. If not set, the command will act basing on its current value.
244
- * @param options.usePreviousLanguageChoice If set on `true` and the `options.language` is not specified, the command
245
- * will apply the previous language (if the command was already executed) when inserting the `codeBlock` element.
246
- */ execute(options = {}) {
246
+ * Executes the command. When the command {@link #value is on}, all topmost code blocks within
247
+ * the selection will be removed. If it is off, all selected blocks will be flattened and
248
+ * wrapped by a code block.
249
+ *
250
+ * @fires execute
251
+ * @param options Command options.
252
+ * @param options.language The code block language.
253
+ * @param options.forceValue If set, it will force the command behavior. If `true`, the command will apply a code block,
254
+ * otherwise the command will remove the code block. If not set, the command will act basing on its current value.
255
+ * @param options.usePreviousLanguageChoice If set on `true` and the `options.language` is not specified, the command
256
+ * will apply the previous language (if the command was already executed) when inserting the `codeBlock` element.
257
+ */ execute(options = {}) {
247
258
  const editor = this.editor;
248
259
  const model = editor.model;
249
260
  const selection = model.document.selection;
@@ -261,20 +272,20 @@ class CodeBlockCommand extends Command {
261
272
  });
262
273
  }
263
274
  /**
264
- * Checks the command's {@link #value}.
265
- *
266
- * @returns The current value.
267
- */ _getValue() {
275
+ * Checks the command's {@link #value}.
276
+ *
277
+ * @returns The current value.
278
+ */ _getValue() {
268
279
  const selection = this.editor.model.document.selection;
269
280
  const firstBlock = first(selection.getSelectedBlocks());
270
281
  const isCodeBlock = !!(firstBlock && firstBlock.is('element', 'codeBlock'));
271
282
  return isCodeBlock ? firstBlock.getAttribute('language') : false;
272
283
  }
273
284
  /**
274
- * Checks whether the command can be enabled in the current context.
275
- *
276
- * @returns Whether the command should be enabled.
277
- */ _checkEnabled() {
285
+ * Checks whether the command can be enabled in the current context.
286
+ *
287
+ * @returns Whether the command should be enabled.
288
+ */ _checkEnabled() {
278
289
  if (this.value) {
279
290
  return true;
280
291
  }
@@ -324,12 +335,6 @@ class CodeBlockCommand extends Command {
324
335
  writer.removeAttribute('language', block);
325
336
  }
326
337
  }
327
- /**
328
- * @inheritDoc
329
- */ constructor(editor){
330
- super(editor);
331
- this._lastLanguage = null;
332
- }
333
338
  }
334
339
  /**
335
340
  * Picks the language for the new code block. If any language is passed as an option,
@@ -346,18 +351,27 @@ class CodeBlockCommand extends Command {
346
351
  return defaultLanguage;
347
352
  }
348
353
 
349
- class IndentCodeBlockCommand extends Command {
354
+ /**
355
+ * The code block indentation increase command plugin.
356
+ */ class IndentCodeBlockCommand extends Command {
350
357
  /**
351
- * @inheritDoc
352
- */ refresh() {
358
+ * A sequence of characters added to the line when the command is executed.
359
+ */ _indentSequence;
360
+ constructor(editor){
361
+ super(editor);
362
+ this._indentSequence = editor.config.get('codeBlock.indentSequence');
363
+ }
364
+ /**
365
+ * @inheritDoc
366
+ */ refresh() {
353
367
  this.isEnabled = this._checkEnabled();
354
368
  }
355
369
  /**
356
- * Executes the command. When the command {@link #isEnabled is enabled}, the indentation of the
357
- * code lines in the selection will be increased.
358
- *
359
- * @fires execute
360
- */ execute() {
370
+ * Executes the command. When the command {@link #isEnabled is enabled}, the indentation of the
371
+ * code lines in the selection will be increased.
372
+ *
373
+ * @fires execute
374
+ */ execute() {
361
375
  const editor = this.editor;
362
376
  const model = editor.model;
363
377
  model.change((writer)=>{
@@ -395,8 +409,8 @@ class IndentCodeBlockCommand extends Command {
395
409
  });
396
410
  }
397
411
  /**
398
- * Checks whether the command can be enabled in the current context.
399
- */ _checkEnabled() {
412
+ * Checks whether the command can be enabled in the current context.
413
+ */ _checkEnabled() {
400
414
  if (!this._indentSequence) {
401
415
  return false;
402
416
  }
@@ -404,24 +418,29 @@ class IndentCodeBlockCommand extends Command {
404
418
  // because you can always indent code lines.
405
419
  return isModelSelectionInCodeBlock(this.editor.model.document.selection);
406
420
  }
421
+ }
422
+
423
+ /**
424
+ * The code block indentation decrease command plugin.
425
+ */ class OutdentCodeBlockCommand extends Command {
426
+ /**
427
+ * A sequence of characters removed from the line when the command is executed.
428
+ */ _indentSequence;
407
429
  constructor(editor){
408
430
  super(editor);
409
431
  this._indentSequence = editor.config.get('codeBlock.indentSequence');
410
432
  }
411
- }
412
-
413
- class OutdentCodeBlockCommand extends Command {
414
433
  /**
415
- * @inheritDoc
416
- */ refresh() {
434
+ * @inheritDoc
435
+ */ refresh() {
417
436
  this.isEnabled = this._checkEnabled();
418
437
  }
419
438
  /**
420
- * Executes the command. When the command {@link #isEnabled is enabled}, the indentation of the
421
- * code lines in the selection will be decreased.
422
- *
423
- * @fires execute
424
- */ execute() {
439
+ * Executes the command. When the command {@link #isEnabled is enabled}, the indentation of the
440
+ * code lines in the selection will be decreased.
441
+ *
442
+ * @fires execute
443
+ */ execute() {
425
444
  const editor = this.editor;
426
445
  const model = editor.model;
427
446
  model.change(()=>{
@@ -460,11 +479,11 @@ class OutdentCodeBlockCommand extends Command {
460
479
  });
461
480
  }
462
481
  /**
463
- * Checks whether the command can be enabled in the current context.
464
- *
465
- * @private
466
- * @returns {Boolean} Whether the command should be enabled.
467
- */ _checkEnabled() {
482
+ * Checks whether the command can be enabled in the current context.
483
+ *
484
+ * @private
485
+ * @returns {Boolean} Whether the command should be enabled.
486
+ */ _checkEnabled() {
468
487
  if (!this._indentSequence) {
469
488
  return false;
470
489
  }
@@ -478,10 +497,6 @@ class OutdentCodeBlockCommand extends Command {
478
497
  return getLastOutdentableSequenceRange(model, position, this._indentSequence);
479
498
  });
480
499
  }
481
- constructor(editor){
482
- super(editor);
483
- this._indentSequence = editor.config.get('codeBlock.indentSequence');
484
- }
485
500
  }
486
501
  // For a position coming from `getIndentOutdentPositions()`, it returns the range representing
487
502
  // the last occurrence of the indent sequence among the leading whitespaces of the code line the
@@ -824,27 +839,97 @@ function getCodeLineTextNodeAtPosition(position) {
824
839
  }
825
840
 
826
841
  const DEFAULT_ELEMENT = 'paragraph';
827
- class CodeBlockEditing extends Plugin {
842
+ /**
843
+ * The editing part of the code block feature.
844
+ *
845
+ * Introduces the `'codeBlock'` command and the `'codeBlock'` model element.
846
+ */ class CodeBlockEditing extends Plugin {
828
847
  /**
829
- * @inheritDoc
830
- */ static get pluginName() {
848
+ * @inheritDoc
849
+ */ static get pluginName() {
831
850
  return 'CodeBlockEditing';
832
851
  }
833
852
  /**
834
- * @inheritDoc
835
- */ static get requires() {
853
+ * @inheritDoc
854
+ */ static get requires() {
836
855
  return [
837
856
  ShiftEnter
838
857
  ];
839
858
  }
840
859
  /**
841
- * @inheritDoc
842
- */ init() {
860
+ * @inheritDoc
861
+ */ constructor(editor){
862
+ super(editor);
863
+ editor.config.define('codeBlock', {
864
+ languages: [
865
+ {
866
+ language: 'plaintext',
867
+ label: 'Plain text'
868
+ },
869
+ {
870
+ language: 'c',
871
+ label: 'C'
872
+ },
873
+ {
874
+ language: 'cs',
875
+ label: 'C#'
876
+ },
877
+ {
878
+ language: 'cpp',
879
+ label: 'C++'
880
+ },
881
+ {
882
+ language: 'css',
883
+ label: 'CSS'
884
+ },
885
+ {
886
+ language: 'diff',
887
+ label: 'Diff'
888
+ },
889
+ {
890
+ language: 'html',
891
+ label: 'HTML'
892
+ },
893
+ {
894
+ language: 'java',
895
+ label: 'Java'
896
+ },
897
+ {
898
+ language: 'javascript',
899
+ label: 'JavaScript'
900
+ },
901
+ {
902
+ language: 'php',
903
+ label: 'PHP'
904
+ },
905
+ {
906
+ language: 'python',
907
+ label: 'Python'
908
+ },
909
+ {
910
+ language: 'ruby',
911
+ label: 'Ruby'
912
+ },
913
+ {
914
+ language: 'typescript',
915
+ label: 'TypeScript'
916
+ },
917
+ {
918
+ language: 'xml',
919
+ label: 'XML'
920
+ }
921
+ ],
922
+ // A single tab.
923
+ indentSequence: '\t'
924
+ });
925
+ }
926
+ /**
927
+ * @inheritDoc
928
+ */ init() {
843
929
  const editor = this.editor;
844
930
  const schema = editor.model.schema;
845
931
  const model = editor.model;
846
932
  const view = editor.editing.view;
847
- const listEditing = editor.plugins.has('ListEditing') ? editor.plugins.get('ListEditing') : null;
848
933
  const normalizedLanguagesDefs = getNormalizedAndLocalizedLanguageDefinitions(editor);
849
934
  // The main command.
850
935
  editor.commands.add('codeBlock', new CodeBlockCommand(editor));
@@ -867,27 +952,21 @@ class CodeBlockEditing extends Plugin {
867
952
  schema.register('codeBlock', {
868
953
  allowWhere: '$block',
869
954
  allowChildren: '$text',
870
- isBlock: true,
955
+ // Disallow `$inlineObject` and its derivatives like `inlineWidget` inside `codeBlock` to ensure that only text,
956
+ // not other inline elements like inline images, are allowed. This maintains the semantic integrity of code blocks.
957
+ disallowChildren: '$inlineObject',
871
958
  allowAttributes: [
872
959
  'language'
873
- ]
960
+ ],
961
+ allowAttributesOf: '$listItem',
962
+ isBlock: true
874
963
  });
875
- // Allow all list* attributes on `codeBlock` (integration with DocumentList).
876
- // Disallow all attributes on $text inside `codeBlock`.
877
- schema.addAttributeCheck((context, attributeName)=>{
878
- if (context.endsWith('codeBlock') && listEditing && listEditing.getListAttributeNames().includes(attributeName)) {
879
- return true;
880
- }
964
+ // Disallow all attributes on `$text` inside `codeBlock`.
965
+ schema.addAttributeCheck((context)=>{
881
966
  if (context.endsWith('codeBlock $text')) {
882
967
  return false;
883
968
  }
884
969
  });
885
- // Disallow object elements inside `codeBlock`. See #9567.
886
- editor.model.schema.addChildCheck((context, childDefinition)=>{
887
- if (context.endsWith('codeBlock') && childDefinition.isObject) {
888
- return false;
889
- }
890
- });
891
970
  // Conversion.
892
971
  editor.editing.downcastDispatcher.on('insert:codeBlock', modelToViewCodeBlockInsertion(model, normalizedLanguagesDefs, true));
893
972
  editor.data.downcastDispatcher.on('insert:codeBlock', modelToViewCodeBlockInsertion(model, normalizedLanguagesDefs));
@@ -946,8 +1025,8 @@ class CodeBlockEditing extends Plugin {
946
1025
  });
947
1026
  }
948
1027
  /**
949
- * @inheritDoc
950
- */ afterInit() {
1028
+ * @inheritDoc
1029
+ */ afterInit() {
951
1030
  const editor = this.editor;
952
1031
  const commands = editor.commands;
953
1032
  const indent = commands.get('indent');
@@ -984,11 +1063,11 @@ class CodeBlockEditing extends Plugin {
984
1063
  this._initAriaAnnouncements();
985
1064
  }
986
1065
  /**
987
- * Observe when user enters or leaves code block and set proper aria value in global live announcer.
988
- * This allows screen readers to indicate when the user has entered and left the specified code block.
989
- *
990
- * @internal
991
- */ _initAriaAnnouncements() {
1066
+ * Observe when user enters or leaves code block and set proper aria value in global live announcer.
1067
+ * This allows screen readers to indicate when the user has entered and left the specified code block.
1068
+ *
1069
+ * @internal
1070
+ */ _initAriaAnnouncements() {
992
1071
  const { model, ui, t } = this.editor;
993
1072
  const languageDefs = getNormalizedAndLocalizedLanguageDefinitions(this.editor);
994
1073
  let lastFocusedCodeBlock = null;
@@ -1006,73 +1085,6 @@ class CodeBlockEditing extends Plugin {
1006
1085
  lastFocusedCodeBlock = focusParent;
1007
1086
  });
1008
1087
  }
1009
- /**
1010
- * @inheritDoc
1011
- */ constructor(editor){
1012
- super(editor);
1013
- editor.config.define('codeBlock', {
1014
- languages: [
1015
- {
1016
- language: 'plaintext',
1017
- label: 'Plain text'
1018
- },
1019
- {
1020
- language: 'c',
1021
- label: 'C'
1022
- },
1023
- {
1024
- language: 'cs',
1025
- label: 'C#'
1026
- },
1027
- {
1028
- language: 'cpp',
1029
- label: 'C++'
1030
- },
1031
- {
1032
- language: 'css',
1033
- label: 'CSS'
1034
- },
1035
- {
1036
- language: 'diff',
1037
- label: 'Diff'
1038
- },
1039
- {
1040
- language: 'html',
1041
- label: 'HTML'
1042
- },
1043
- {
1044
- language: 'java',
1045
- label: 'Java'
1046
- },
1047
- {
1048
- language: 'javascript',
1049
- label: 'JavaScript'
1050
- },
1051
- {
1052
- language: 'php',
1053
- label: 'PHP'
1054
- },
1055
- {
1056
- language: 'python',
1057
- label: 'Python'
1058
- },
1059
- {
1060
- language: 'ruby',
1061
- label: 'Ruby'
1062
- },
1063
- {
1064
- language: 'typescript',
1065
- label: 'TypeScript'
1066
- },
1067
- {
1068
- language: 'xml',
1069
- label: 'XML'
1070
- }
1071
- ],
1072
- // A single tab.
1073
- indentSequence: '\t'
1074
- });
1075
- }
1076
1088
  }
1077
1089
  /**
1078
1090
  * Normally, when the Enter (or Shift+Enter) key is pressed, a soft line break is to be added to the
@@ -1224,15 +1236,19 @@ function isSoftBreakNode(node) {
1224
1236
  return node && node.is('element', 'softBreak');
1225
1237
  }
1226
1238
 
1227
- class CodeBlockUI extends Plugin {
1239
+ /**
1240
+ * The code block UI plugin.
1241
+ *
1242
+ * Introduces the `'codeBlock'` dropdown.
1243
+ */ class CodeBlockUI extends Plugin {
1228
1244
  /**
1229
- * @inheritDoc
1230
- */ static get pluginName() {
1245
+ * @inheritDoc
1246
+ */ static get pluginName() {
1231
1247
  return 'CodeBlockUI';
1232
1248
  }
1233
1249
  /**
1234
- * @inheritDoc
1235
- */ init() {
1250
+ * @inheritDoc
1251
+ */ init() {
1236
1252
  const editor = this.editor;
1237
1253
  const t = editor.t;
1238
1254
  const componentFactory = editor.ui.componentFactory;
@@ -1303,9 +1319,9 @@ class CodeBlockUI extends Plugin {
1303
1319
  });
1304
1320
  }
1305
1321
  /**
1306
- * A helper returning a collection of the `codeBlock` dropdown items representing languages
1307
- * available for the user to choose from.
1308
- */ _getLanguageListItemDefinitions(normalizedLanguageDefs) {
1322
+ * A helper returning a collection of the `codeBlock` dropdown items representing languages
1323
+ * available for the user to choose from.
1324
+ */ _getLanguageListItemDefinitions(normalizedLanguageDefs) {
1309
1325
  const editor = this.editor;
1310
1326
  const command = editor.commands.get('codeBlock');
1311
1327
  const itemDefinitions = new Collection();
@@ -1328,18 +1344,26 @@ class CodeBlockUI extends Plugin {
1328
1344
  }
1329
1345
  }
1330
1346
 
1331
- class CodeBlock extends Plugin {
1347
+ /**
1348
+ * The code block plugin.
1349
+ *
1350
+ * For more information about this feature check the {@glink api/code-block package page} and the
1351
+ * {@glink features/code-blocks code block} feature guide.
1352
+ *
1353
+ * This is a "glue" plugin that loads the {@link module:code-block/codeblockediting~CodeBlockEditing code block editing feature}
1354
+ * and the {@link module:code-block/codeblockui~CodeBlockUI code block UI feature}.
1355
+ */ class CodeBlock extends Plugin {
1332
1356
  /**
1333
- * @inheritDoc
1334
- */ static get requires() {
1357
+ * @inheritDoc
1358
+ */ static get requires() {
1335
1359
  return [
1336
1360
  CodeBlockEditing,
1337
1361
  CodeBlockUI
1338
1362
  ];
1339
1363
  }
1340
1364
  /**
1341
- * @inheritDoc
1342
- */ static get pluginName() {
1365
+ * @inheritDoc
1366
+ */ static get pluginName() {
1343
1367
  return 'CodeBlock';
1344
1368
  }
1345
1369
  }