@ckeditor/ckeditor5-code-block 41.4.2 → 42.0.0-alpha.1
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 +6 -0
- package/build/code-block.js +1 -1
- package/dist/index.js +191 -167
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/codeblockediting.js +8 -17
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).
|
package/build/code-block.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
230
|
-
|
|
240
|
+
* @inheritDoc
|
|
241
|
+
*/ refresh() {
|
|
231
242
|
this.value = this._getValue();
|
|
232
243
|
this.isEnabled = this._checkEnabled();
|
|
233
244
|
}
|
|
234
245
|
/**
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
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
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
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
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
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
|
-
|
|
354
|
+
/**
|
|
355
|
+
* The code block indentation increase command plugin.
|
|
356
|
+
*/ class IndentCodeBlockCommand extends Command {
|
|
350
357
|
/**
|
|
351
|
-
|
|
352
|
-
|
|
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
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
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
|
-
|
|
399
|
-
|
|
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
|
-
|
|
416
|
-
|
|
434
|
+
* @inheritDoc
|
|
435
|
+
*/ refresh() {
|
|
417
436
|
this.isEnabled = this._checkEnabled();
|
|
418
437
|
}
|
|
419
438
|
/**
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
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
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
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
|
-
|
|
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
|
-
|
|
830
|
-
|
|
848
|
+
* @inheritDoc
|
|
849
|
+
*/ static get pluginName() {
|
|
831
850
|
return 'CodeBlockEditing';
|
|
832
851
|
}
|
|
833
852
|
/**
|
|
834
|
-
|
|
835
|
-
|
|
853
|
+
* @inheritDoc
|
|
854
|
+
*/ static get requires() {
|
|
836
855
|
return [
|
|
837
856
|
ShiftEnter
|
|
838
857
|
];
|
|
839
858
|
}
|
|
840
859
|
/**
|
|
841
|
-
|
|
842
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
876
|
-
|
|
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
|
-
|
|
950
|
-
|
|
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
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
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
|
-
|
|
1239
|
+
/**
|
|
1240
|
+
* The code block UI plugin.
|
|
1241
|
+
*
|
|
1242
|
+
* Introduces the `'codeBlock'` dropdown.
|
|
1243
|
+
*/ class CodeBlockUI extends Plugin {
|
|
1228
1244
|
/**
|
|
1229
|
-
|
|
1230
|
-
|
|
1245
|
+
* @inheritDoc
|
|
1246
|
+
*/ static get pluginName() {
|
|
1231
1247
|
return 'CodeBlockUI';
|
|
1232
1248
|
}
|
|
1233
1249
|
/**
|
|
1234
|
-
|
|
1235
|
-
|
|
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
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1334
|
-
|
|
1357
|
+
* @inheritDoc
|
|
1358
|
+
*/ static get requires() {
|
|
1335
1359
|
return [
|
|
1336
1360
|
CodeBlockEditing,
|
|
1337
1361
|
CodeBlockUI
|
|
1338
1362
|
];
|
|
1339
1363
|
}
|
|
1340
1364
|
/**
|
|
1341
|
-
|
|
1342
|
-
|
|
1365
|
+
* @inheritDoc
|
|
1366
|
+
*/ static get pluginName() {
|
|
1343
1367
|
return 'CodeBlock';
|
|
1344
1368
|
}
|
|
1345
1369
|
}
|