@ckeditor/ckeditor5-html-embed 36.0.1 → 37.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.
@@ -2,4 +2,4 @@
2
2
  /*!
3
3
  * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
4
4
  * For licensing, see LICENSE.md.
5
- */(()=>{var e={600:(e,t,n)=>{"use strict";n.d(t,{Z:()=>i});var r=n(609),a=n.n(r)()((function(e){return e[1]}));a.push([e.id,".ck-widget.raw-html-embed{display:flow-root;font-style:normal;margin:.9em auto;min-width:15em;position:relative}.ck-widget.raw-html-embed:before{position:absolute;z-index:1}.ck-widget.raw-html-embed .raw-html-embed__buttons-wrapper{display:flex;flex-direction:column;position:absolute}.ck-widget.raw-html-embed .raw-html-embed__preview{display:flex;overflow:hidden;position:relative}.ck-widget.raw-html-embed .raw-html-embed__preview-content{border-collapse:separate;border-spacing:7px;display:table;margin:auto;position:relative;width:100%}.ck-widget.raw-html-embed .raw-html-embed__preview-placeholder{align-items:center;bottom:0;display:flex;justify-content:center;left:0;position:absolute;right:0;top:0}:root{--ck-html-embed-content-width:calc(100% - var(--ck-icon-size)*1.5);--ck-html-embed-source-height:10em;--ck-html-embed-unfocused-outline-width:1px;--ck-html-embed-content-min-height:calc(var(--ck-icon-size) + var(--ck-spacing-standard));--ck-html-embed-source-disabled-background:var(--ck-color-base-foreground);--ck-html-embed-source-disabled-color:#737373}.ck-widget.raw-html-embed{background-color:var(--ck-color-base-foreground);font-size:var(--ck-font-size-base)}.ck-widget.raw-html-embed:not(.ck-widget_selected):not(:hover){outline:var(--ck-html-embed-unfocused-outline-width) dashed var(--ck-color-widget-blurred-border)}.ck-widget.raw-html-embed[dir=ltr]{text-align:left}.ck-widget.raw-html-embed[dir=rtl]{text-align:right}.ck-widget.raw-html-embed:before{background:#999;border-radius:0 0 var(--ck-border-radius) var(--ck-border-radius);color:var(--ck-color-base-background);content:attr(data-html-embed-label);font-family:var(--ck-font-face);font-size:var(--ck-font-size-tiny);left:var(--ck-spacing-standard);padding:calc(var(--ck-spacing-tiny) + var(--ck-html-embed-unfocused-outline-width)) var(--ck-spacing-small) var(--ck-spacing-tiny);top:calc(var(--ck-html-embed-unfocused-outline-width)*-1);transition:background var(--ck-widget-handler-animation-duration) var(--ck-widget-handler-animation-curve)}.ck-widget.raw-html-embed[dir=rtl]:before{left:auto;right:var(--ck-spacing-standard)}.ck-widget.raw-html-embed[dir=ltr] .ck-widget__type-around .ck-widget__type-around__button.ck-widget__type-around__button_before{margin-left:50px}.ck.ck-editor__editable.ck-blurred .ck-widget.raw-html-embed.ck-widget_selected:before{padding:var(--ck-spacing-tiny) var(--ck-spacing-small);top:0}.ck.ck-editor__editable:not(.ck-blurred) .ck-widget.raw-html-embed.ck-widget_selected:before{background:var(--ck-color-focus-border);padding:var(--ck-spacing-tiny) var(--ck-spacing-small);top:0}.ck.ck-editor__editable .ck-widget.raw-html-embed:not(.ck-widget_selected):hover:before{padding:var(--ck-spacing-tiny) var(--ck-spacing-small);top:0}.ck-widget.raw-html-embed .raw-html-embed__content-wrapper{padding:var(--ck-spacing-standard)}.ck-widget.raw-html-embed .raw-html-embed__buttons-wrapper{right:var(--ck-spacing-standard);top:var(--ck-spacing-standard)}.ck-widget.raw-html-embed .raw-html-embed__buttons-wrapper .ck-button.raw-html-embed__save-button{color:var(--ck-color-button-save)}.ck-widget.raw-html-embed .raw-html-embed__buttons-wrapper .ck-button.raw-html-embed__cancel-button{color:var(--ck-color-button-cancel)}.ck-widget.raw-html-embed .raw-html-embed__buttons-wrapper .ck-button:not(:first-child){margin-top:var(--ck-spacing-small)}.ck-widget.raw-html-embed[dir=rtl] .raw-html-embed__buttons-wrapper{left:var(--ck-spacing-standard);right:auto}.ck-widget.raw-html-embed .raw-html-embed__source{box-sizing:border-box;direction:ltr;font-family:monospace;font-size:var(--ck-font-size-base);height:var(--ck-html-embed-source-height);min-width:0;padding:var(--ck-spacing-standard);resize:none;tab-size:4;text-align:left;white-space:pre-wrap;width:var(--ck-html-embed-content-width)}.ck-widget.raw-html-embed .raw-html-embed__source[disabled]{-webkit-text-fill-color:var(--ck-html-embed-source-disabled-color);background:var(--ck-html-embed-source-disabled-background);color:var(--ck-html-embed-source-disabled-color);opacity:1}.ck-widget.raw-html-embed .raw-html-embed__preview{min-height:var(--ck-html-embed-content-min-height);width:var(--ck-html-embed-content-width)}.ck-editor__editable:not(.ck-read-only) .ck-widget.raw-html-embed .raw-html-embed__preview{pointer-events:none}.ck-widget.raw-html-embed .raw-html-embed__preview-content{background-color:var(--ck-color-base-foreground);box-sizing:border-box}.ck-widget.raw-html-embed .raw-html-embed__preview-content>*{margin-left:auto;margin-right:auto}.ck-widget.raw-html-embed .raw-html-embed__preview-placeholder{color:var(--ck-html-embed-source-disabled-color)}",""]);const i=a},609:e=>{"use strict";e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var n=e(t);return t[2]?"@media ".concat(t[2]," {").concat(n,"}"):n})).join("")},t.i=function(e,n,r){"string"==typeof e&&(e=[[null,e,""]]);var a={};if(r)for(var i=0;i<this.length;i++){var o=this[i][0];null!=o&&(a[o]=!0)}for(var c=0;c<e.length;c++){var l=[].concat(e[c]);r&&a[l[0]]||(n&&(l[2]?l[2]="".concat(n," and ").concat(l[2]):l[2]=n),t.push(l))}},t}},62:(e,t,n)=>{"use strict";var r,a=function(){return void 0===r&&(r=Boolean(window&&document&&document.all&&!window.atob)),r},i=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]}}(),o=[];function c(e){for(var t=-1,n=0;n<o.length;n++)if(o[n].identifier===e){t=n;break}return t}function l(e,t){for(var n={},r=[],a=0;a<e.length;a++){var i=e[a],l=t.base?i[0]+t.base:i[0],d=n[l]||0,s="".concat(l," ").concat(d);n[l]=d+1;var m=c(s),u={css:i[1],media:i[2],sourceMap:i[3]};-1!==m?(o[m].references++,o[m].updater(u)):o.push({identifier:s,updater:w(u,t),references:1}),r.push(s)}return r}function d(e){var t=document.createElement("style"),r=e.attributes||{};if(void 0===r.nonce){var a=n.nc;a&&(r.nonce=a)}if(Object.keys(r).forEach((function(e){t.setAttribute(e,r[e])})),"function"==typeof e.insert)e.insert(t);else{var o=i(e.insert||"head");if(!o)throw new Error("Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid.");o.appendChild(t)}return t}var s,m=(s=[],function(e,t){return s[e]=t,s.filter(Boolean).join("\n")});function u(e,t,n,r){var a=n?"":r.media?"@media ".concat(r.media," {").concat(r.css,"}"):r.css;if(e.styleSheet)e.styleSheet.cssText=m(t,a);else{var i=document.createTextNode(a),o=e.childNodes;o[t]&&e.removeChild(o[t]),o.length?e.insertBefore(i,o[t]):e.appendChild(i)}}function b(e,t,n){var r=n.css,a=n.media,i=n.sourceMap;if(a?e.setAttribute("media",a):e.removeAttribute("media"),i&&"undefined"!=typeof btoa&&(r+="\n/*# sourceMappingURL=data:application/json;base64,".concat(btoa(unescape(encodeURIComponent(JSON.stringify(i))))," */")),e.styleSheet)e.styleSheet.cssText=r;else{for(;e.firstChild;)e.removeChild(e.firstChild);e.appendChild(document.createTextNode(r))}}var h=null,p=0;function w(e,t){var n,r,a;if(t.singleton){var i=p++;n=h||(h=d(t)),r=u.bind(null,n,i,!1),a=u.bind(null,n,i,!0)}else n=d(t),r=b.bind(null,n,t),a=function(){!function(e){if(null===e.parentNode)return!1;e.parentNode.removeChild(e)}(n)};return r(e),function(t){if(t){if(t.css===e.css&&t.media===e.media&&t.sourceMap===e.sourceMap)return;r(e=t)}else a()}}e.exports=function(e,t){(t=t||{}).singleton||"boolean"==typeof t.singleton||(t.singleton=a());var n=l(e=e||[],t);return function(e){if(e=e||[],"[object Array]"===Object.prototype.toString.call(e)){for(var r=0;r<n.length;r++){var a=c(n[r]);o[a].references--}for(var i=l(e,t),d=0;d<n.length;d++){var s=c(n[d]);0===o[s].references&&(o[s].updater(),o.splice(s,1))}n=i}}}},704:(e,t,n)=>{e.exports=n(79)("./src/core.js")},273:(e,t,n)=>{e.exports=n(79)("./src/ui.js")},209:(e,t,n)=>{e.exports=n(79)("./src/utils.js")},995:(e,t,n)=>{e.exports=n(79)("./src/widget.js")},79:e=>{"use strict";e.exports=CKEditor5.dll}},t={};function n(r){var a=t[r];if(void 0!==a)return a.exports;var i=t[r]={id:r,exports:{}};return e[r](i,i.exports,n),i.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 r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},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 r={};(()=>{"use strict";n.r(r),n.d(r,{HtmlEmbed:()=>p,HtmlEmbedEditing:()=>u,HtmlEmbedUI:()=>h});var e=n(704),t=n(995),a=n(273),i=n(209);class o extends e.Command{refresh(){const e=this.editor.model,n=e.schema,r=e.document.selection,a=c(r);this.isEnabled=function(e,n,r){const a=function(e,n){const r=(0,t.findOptimalInsertionRange)(e,n),a=r.start.parent;if(a.isEmpty&&!a.is("element","$root"))return a.parent;return a}(e,r);return n.checkChild(a,"rawHtml")}(r,n,e),this.value=a?a.getAttribute("value")||"":null}execute(e){const t=this.editor.model,n=t.document.selection;t.change((r=>{let a;null!==this.value?a=c(n):(a=r.createElement("rawHtml"),t.insertObject(a,null,null,{setSelection:"on"})),r.setAttribute("value",e,a)}))}}function c(e){const t=e.getSelectedElement();return t&&t.is("element","rawHtml")?t:null}var l=n(62),d=n.n(l),s=n(600),m={injectType:"singletonStyleTag",attributes:{"data-cke":!0},insert:"head",singleton:!0};d()(s.Z,m);s.Z.locals;class u extends e.Plugin{static get pluginName(){return"HtmlEmbedEditing"}constructor(e){super(e),e.config.define("htmlEmbed",{showPreviews:!1,sanitizeHtml:e=>((0,i.logWarning)("html-embed-provide-sanitize-function"),{html:e,hasChanged:!1})}),this._widgetButtonViewReferences=new Set}init(){const e=this.editor;e.model.schema.register("rawHtml",{inheritAllFrom:"$blockObject",allowAttributes:["value"]}),e.commands.add("htmlEmbed",new o(e)),this._setupConversion()}_setupConversion(){const e=this.editor,n=e.t,r=e.editing.view,a=this._widgetButtonViewReferences,o=e.config.get("htmlEmbed");function c({domElement:e,editor:t,state:r,props:o}){e.textContent="";const c=e.ownerDocument;let d;if(r.isEditable){const t={isDisabled:!1,placeholder:o.textareaPlaceholder};d=l({domDocument:c,state:r,props:t}),e.append(d)}else if(r.showPreviews){const a={sanitizeHtml:o.sanitizeHtml};e.append(function({domDocument:e,state:t,props:r,editor:a}){const o=r.sanitizeHtml(t.getRawHtmlValue()),c=t.getRawHtmlValue().length>0?n("No preview available"):n("Empty snippet content"),l=(0,i.createElement)(e,"div",{class:"ck ck-reset_all raw-html-embed__preview-placeholder"},c),d=(0,i.createElement)(e,"div",{class:"raw-html-embed__preview-content",dir:a.locale.contentLanguageDirection}),s=e.createRange(),m=s.createContextualFragment(o.html);d.appendChild(m);const u=(0,i.createElement)(e,"div",{class:"raw-html-embed__preview"},[l,d]);return u}({domDocument:c,state:r,props:a,editor:t}))}else{const t={isDisabled:!0,placeholder:o.textareaPlaceholder};e.append(l({domDocument:c,state:r,props:t}))}const s={onEditClick:o.onEditClick,onSaveClick:()=>{o.onSaveClick(d.value)},onCancelClick:o.onCancelClick};e.prepend(function({editor:e,domDocument:t,state:n,props:r}){const o=(0,i.createElement)(t,"div",{class:"raw-html-embed__buttons-wrapper"});if(n.isEditable){const t=b(e,"save",r.onSaveClick),n=b(e,"cancel",r.onCancelClick);o.append(t.element,n.element),a.add(t).add(n)}else{const t=b(e,"edit",r.onEditClick);o.append(t.element),a.add(t)}return o}({editor:t,domDocument:c,state:r,props:s}))}function l({domDocument:e,state:t,props:n}){const r=(0,i.createElement)(e,"textarea",{placeholder:n.placeholder,class:"ck ck-reset ck-input ck-input-text raw-html-embed__source"});return r.disabled=n.isDisabled,r.value=t.getRawHtmlValue(),r}this.editor.editing.view.on("render",(()=>{for(const e of a){if(e.element.isConnected)return;e.destroy(),a.delete(e)}}),{priority:"lowest"}),e.data.registerRawContentMatcher({name:"div",classes:"raw-html-embed"}),e.conversion.for("upcast").elementToElement({view:{name:"div",classes:"raw-html-embed"},model:(e,{writer:t})=>t.createElement("rawHtml",{value:e.getCustomProperty("$rawContent")})}),e.conversion.for("dataDowncast").elementToElement({model:"rawHtml",view:(e,{writer:t})=>t.createRawElement("div",{class:"raw-html-embed"},(function(t){t.innerHTML=e.getAttribute("value")||""}))}),e.conversion.for("editingDowncast").elementToStructure({model:{name:"rawHtml",attributes:["value"]},view:(a,{writer:i})=>{let l,d,s;const m=i.createRawElement("div",{class:"raw-html-embed__content-wrapper"},(function(t){l=t,c({domElement:t,editor:e,state:d,props:s}),l.addEventListener("mousedown",(()=>{if(d.isEditable){const t=e.model;t.document.selection.getSelectedElement()!==a&&t.change((e=>e.setSelection(a,"on")))}}),!0)})),u={makeEditable(){d=Object.assign({},d,{isEditable:!0}),c({domElement:l,editor:e,state:d,props:s}),r.change((e=>{e.setAttribute("data-cke-ignore-events","true",m)})),l.querySelector("textarea").focus()},save(t){t!==d.getRawHtmlValue()?(e.execute("htmlEmbed",t),e.editing.view.focus()):this.cancel()},cancel(){d=Object.assign({},d,{isEditable:!1}),c({domElement:l,editor:e,state:d,props:s}),e.editing.view.focus(),r.change((e=>{e.removeAttribute("data-cke-ignore-events",m)}))}};d={showPreviews:o.showPreviews,isEditable:!1,getRawHtmlValue:()=>a.getAttribute("value")||""},s={sanitizeHtml:o.sanitizeHtml,textareaPlaceholder:n("Paste raw HTML here..."),onEditClick(){u.makeEditable()},onSaveClick(e){u.save(e)},onCancelClick(){u.cancel()}};const b=i.createContainerElement("div",{class:"raw-html-embed","data-html-embed-label":n("HTML snippet"),dir:e.locale.uiLanguageDirection},m);return i.setCustomProperty("rawHtmlApi",u,b),i.setCustomProperty("rawHtml",!0,b),(0,t.toWidget)(b,i,{widgetLabel:n("HTML snippet"),hasSelectionHandle:!0})}})}}function b(t,n,r){const i=t.locale.t,o=new a.ButtonView(t.locale),c=t.commands.get("htmlEmbed");return o.set({class:`raw-html-embed__${n}-button`,icon:e.icons.pencil,tooltip:!0,tooltipPosition:"rtl"===t.locale.uiLanguageDirection?"e":"w"}),o.render(),"edit"===n?(o.set({icon:e.icons.pencil,label:i("Edit source")}),o.bind("isEnabled").to(c)):"save"===n?(o.set({icon:e.icons.check,label:i("Save changes")}),o.bind("isEnabled").to(c)):o.set({icon:e.icons.cancel,label:i("Cancel")}),o.on("execute",r),o}class h extends e.Plugin{static get pluginName(){return"HtmlEmbedUI"}init(){const e=this.editor,t=e.t;e.ui.componentFactory.add("htmlEmbed",(n=>{const r=e.commands.get("htmlEmbed"),i=new a.ButtonView(n);return i.set({label:t("Insert HTML"),icon:'<svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M17 0a2 2 0 0 1 2 2v7a1 1 0 0 1 1 1v5a1 1 0 0 1-.883.993l-.118.006L19 17a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2l-.001-1.001-.116-.006A1 1 0 0 1 0 15v-5a1 1 0 0 1 .999-1L1 2a2 2 0 0 1 2-2h14zm.499 15.999h-15L2.5 17a.5.5 0 0 0 .5.5h14a.5.5 0 0 0 .5-.5l-.001-1.001zm-3.478-6.013-.014.014H14v.007l-1.525 1.525-1.46-1.46-.015.013V10h-1v5h1v-3.53l1.428 1.43.048.043.131-.129L14 11.421V15h1v-5h-.965l-.014-.014zM2 10H1v5h1v-2h2v2h1v-5H4v2H2v-2zm7 0H6v1h1v4h1v-4h1v-1zm8 0h-1v5h3v-1h-2v-4zm0-8.5H3a.5.5 0 0 0-.5.5l-.001 6.999h15L17.5 2a.5.5 0 0 0-.5-.5zM10 7v1H4V7h6zm3-2v1H4V5h9zm-3-2v1H4V3h6z"/></svg>',tooltip:!0}),i.bind("isEnabled").to(r,"isEnabled"),this.listenTo(i,"execute",(()=>{e.execute("htmlEmbed"),e.editing.view.focus();e.editing.view.document.selection.getSelectedElement().getCustomProperty("rawHtmlApi").makeEditable()})),i}))}}class p extends e.Plugin{static get requires(){return[u,h,t.Widget]}static get pluginName(){return"HtmlEmbed"}}})(),(window.CKEditor5=window.CKEditor5||{}).htmlEmbed=r})();
5
+ */(()=>{var e={600:(e,t,n)=>{"use strict";n.d(t,{Z:()=>i});var r=n(609),a=n.n(r)()((function(e){return e[1]}));a.push([e.id,".ck-widget.raw-html-embed{display:flow-root;font-style:normal;margin:.9em auto;min-width:15em;position:relative}.ck-widget.raw-html-embed:before{position:absolute;z-index:1}.ck-widget.raw-html-embed .raw-html-embed__buttons-wrapper{display:flex;flex-direction:column;position:absolute}.ck-widget.raw-html-embed .raw-html-embed__preview{display:flex;overflow:hidden;position:relative}.ck-widget.raw-html-embed .raw-html-embed__preview-content{border-collapse:separate;border-spacing:7px;display:table;margin:auto;position:relative;width:100%}.ck-widget.raw-html-embed .raw-html-embed__preview-placeholder{align-items:center;bottom:0;display:flex;justify-content:center;left:0;position:absolute;right:0;top:0}:root{--ck-html-embed-content-width:calc(100% - var(--ck-icon-size)*1.5);--ck-html-embed-source-height:10em;--ck-html-embed-unfocused-outline-width:1px;--ck-html-embed-content-min-height:calc(var(--ck-icon-size) + var(--ck-spacing-standard));--ck-html-embed-source-disabled-background:var(--ck-color-base-foreground);--ck-html-embed-source-disabled-color:#737373}.ck-widget.raw-html-embed{background-color:var(--ck-color-base-foreground);font-size:var(--ck-font-size-base)}.ck-widget.raw-html-embed:not(.ck-widget_selected):not(:hover){outline:var(--ck-html-embed-unfocused-outline-width) dashed var(--ck-color-widget-blurred-border)}.ck-widget.raw-html-embed[dir=ltr]{text-align:left}.ck-widget.raw-html-embed[dir=rtl]{text-align:right}.ck-widget.raw-html-embed:before{background:#999;border-radius:0 0 var(--ck-border-radius) var(--ck-border-radius);color:var(--ck-color-base-background);content:attr(data-html-embed-label);font-family:var(--ck-font-face);font-size:var(--ck-font-size-tiny);left:var(--ck-spacing-standard);padding:calc(var(--ck-spacing-tiny) + var(--ck-html-embed-unfocused-outline-width)) var(--ck-spacing-small) var(--ck-spacing-tiny);top:calc(var(--ck-html-embed-unfocused-outline-width)*-1);transition:background var(--ck-widget-handler-animation-duration) var(--ck-widget-handler-animation-curve)}.ck-widget.raw-html-embed[dir=rtl]:before{left:auto;right:var(--ck-spacing-standard)}.ck-widget.raw-html-embed[dir=ltr] .ck-widget__type-around .ck-widget__type-around__button.ck-widget__type-around__button_before{margin-left:50px}.ck.ck-editor__editable.ck-blurred .ck-widget.raw-html-embed.ck-widget_selected:before{padding:var(--ck-spacing-tiny) var(--ck-spacing-small);top:0}.ck.ck-editor__editable:not(.ck-blurred) .ck-widget.raw-html-embed.ck-widget_selected:before{background:var(--ck-color-focus-border);padding:var(--ck-spacing-tiny) var(--ck-spacing-small);top:0}.ck.ck-editor__editable .ck-widget.raw-html-embed:not(.ck-widget_selected):hover:before{padding:var(--ck-spacing-tiny) var(--ck-spacing-small);top:0}.ck-widget.raw-html-embed .raw-html-embed__content-wrapper{padding:var(--ck-spacing-standard)}.ck-widget.raw-html-embed .raw-html-embed__buttons-wrapper{right:var(--ck-spacing-standard);top:var(--ck-spacing-standard)}.ck-widget.raw-html-embed .raw-html-embed__buttons-wrapper .ck-button.raw-html-embed__save-button{color:var(--ck-color-button-save)}.ck-widget.raw-html-embed .raw-html-embed__buttons-wrapper .ck-button.raw-html-embed__cancel-button{color:var(--ck-color-button-cancel)}.ck-widget.raw-html-embed .raw-html-embed__buttons-wrapper .ck-button:not(:first-child){margin-top:var(--ck-spacing-small)}.ck-widget.raw-html-embed[dir=rtl] .raw-html-embed__buttons-wrapper{left:var(--ck-spacing-standard);right:auto}.ck-widget.raw-html-embed .raw-html-embed__source{box-sizing:border-box;direction:ltr;font-family:monospace;font-size:var(--ck-font-size-base);height:var(--ck-html-embed-source-height);min-width:0;padding:var(--ck-spacing-standard);resize:none;tab-size:4;text-align:left;white-space:pre-wrap;width:var(--ck-html-embed-content-width)}.ck-widget.raw-html-embed .raw-html-embed__source[disabled]{-webkit-text-fill-color:var(--ck-html-embed-source-disabled-color);background:var(--ck-html-embed-source-disabled-background);color:var(--ck-html-embed-source-disabled-color);opacity:1}.ck-widget.raw-html-embed .raw-html-embed__preview{min-height:var(--ck-html-embed-content-min-height);width:var(--ck-html-embed-content-width)}.ck-editor__editable:not(.ck-read-only) .ck-widget.raw-html-embed .raw-html-embed__preview{pointer-events:none}.ck-widget.raw-html-embed .raw-html-embed__preview-content{background-color:var(--ck-color-base-foreground);box-sizing:border-box}.ck-widget.raw-html-embed .raw-html-embed__preview-content>*{margin-left:auto;margin-right:auto}.ck-widget.raw-html-embed .raw-html-embed__preview-placeholder{color:var(--ck-html-embed-source-disabled-color)}",""]);const i=a},609:e=>{"use strict";e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var n=e(t);return t[2]?"@media ".concat(t[2]," {").concat(n,"}"):n})).join("")},t.i=function(e,n,r){"string"==typeof e&&(e=[[null,e,""]]);var a={};if(r)for(var i=0;i<this.length;i++){var o=this[i][0];null!=o&&(a[o]=!0)}for(var l=0;l<e.length;l++){var c=[].concat(e[l]);r&&a[c[0]]||(n&&(c[2]?c[2]="".concat(n," and ").concat(c[2]):c[2]=n),t.push(c))}},t}},62:(e,t,n)=>{"use strict";var r,a=function(){return void 0===r&&(r=Boolean(window&&document&&document.all&&!window.atob)),r},i=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]}}(),o=[];function l(e){for(var t=-1,n=0;n<o.length;n++)if(o[n].identifier===e){t=n;break}return t}function c(e,t){for(var n={},r=[],a=0;a<e.length;a++){var i=e[a],c=t.base?i[0]+t.base:i[0],d=n[c]||0,s="".concat(c," ").concat(d);n[c]=d+1;var m=l(s),u={css:i[1],media:i[2],sourceMap:i[3]};-1!==m?(o[m].references++,o[m].updater(u)):o.push({identifier:s,updater:w(u,t),references:1}),r.push(s)}return r}function d(e){var t=document.createElement("style"),r=e.attributes||{};if(void 0===r.nonce){var a=n.nc;a&&(r.nonce=a)}if(Object.keys(r).forEach((function(e){t.setAttribute(e,r[e])})),"function"==typeof e.insert)e.insert(t);else{var o=i(e.insert||"head");if(!o)throw new Error("Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid.");o.appendChild(t)}return t}var s,m=(s=[],function(e,t){return s[e]=t,s.filter(Boolean).join("\n")});function u(e,t,n,r){var a=n?"":r.media?"@media ".concat(r.media," {").concat(r.css,"}"):r.css;if(e.styleSheet)e.styleSheet.cssText=m(t,a);else{var i=document.createTextNode(a),o=e.childNodes;o[t]&&e.removeChild(o[t]),o.length?e.insertBefore(i,o[t]):e.appendChild(i)}}function b(e,t,n){var r=n.css,a=n.media,i=n.sourceMap;if(a?e.setAttribute("media",a):e.removeAttribute("media"),i&&"undefined"!=typeof btoa&&(r+="\n/*# sourceMappingURL=data:application/json;base64,".concat(btoa(unescape(encodeURIComponent(JSON.stringify(i))))," */")),e.styleSheet)e.styleSheet.cssText=r;else{for(;e.firstChild;)e.removeChild(e.firstChild);e.appendChild(document.createTextNode(r))}}var h=null,p=0;function w(e,t){var n,r,a;if(t.singleton){var i=p++;n=h||(h=d(t)),r=u.bind(null,n,i,!1),a=u.bind(null,n,i,!0)}else n=d(t),r=b.bind(null,n,t),a=function(){!function(e){if(null===e.parentNode)return!1;e.parentNode.removeChild(e)}(n)};return r(e),function(t){if(t){if(t.css===e.css&&t.media===e.media&&t.sourceMap===e.sourceMap)return;r(e=t)}else a()}}e.exports=function(e,t){(t=t||{}).singleton||"boolean"==typeof t.singleton||(t.singleton=a());var n=c(e=e||[],t);return function(e){if(e=e||[],"[object Array]"===Object.prototype.toString.call(e)){for(var r=0;r<n.length;r++){var a=l(n[r]);o[a].references--}for(var i=c(e,t),d=0;d<n.length;d++){var s=l(n[d]);0===o[s].references&&(o[s].updater(),o.splice(s,1))}n=i}}}},704:(e,t,n)=>{e.exports=n(79)("./src/core.js")},273:(e,t,n)=>{e.exports=n(79)("./src/ui.js")},209:(e,t,n)=>{e.exports=n(79)("./src/utils.js")},995:(e,t,n)=>{e.exports=n(79)("./src/widget.js")},79:e=>{"use strict";e.exports=CKEditor5.dll}},t={};function n(r){var a=t[r];if(void 0!==a)return a.exports;var i=t[r]={id:r,exports:{}};return e[r](i,i.exports,n),i.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 r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},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 r={};(()=>{"use strict";n.r(r),n.d(r,{HtmlEmbed:()=>p,HtmlEmbedEditing:()=>u,HtmlEmbedUI:()=>h});var e=n(704),t=n(995),a=n(273),i=n(209);class o extends e.Command{refresh(){const e=this.editor.model,n=e.schema,r=e.document.selection,a=l(r);this.isEnabled=function(e,n,r){const a=function(e,n){const r=(0,t.findOptimalInsertionRange)(e,n),a=r.start.parent;if(a.isEmpty&&!a.is("rootElement"))return a.parent;return a}(e,r);return n.checkChild(a,"rawHtml")}(r,n,e),this.value=a?a.getAttribute("value")||"":null}execute(e){const t=this.editor.model,n=t.document.selection;t.change((r=>{let a;null!==this.value?a=l(n):(a=r.createElement("rawHtml"),t.insertObject(a,null,null,{setSelection:"on"})),r.setAttribute("value",e,a)}))}}function l(e){const t=e.getSelectedElement();return t&&t.is("element","rawHtml")?t:null}var c=n(62),d=n.n(c),s=n(600),m={injectType:"singletonStyleTag",attributes:{"data-cke":!0},insert:"head",singleton:!0};d()(s.Z,m);s.Z.locals;class u extends e.Plugin{static get pluginName(){return"HtmlEmbedEditing"}constructor(e){super(e),this._widgetButtonViewReferences=new Set,e.config.define("htmlEmbed",{showPreviews:!1,sanitizeHtml:e=>((0,i.logWarning)("html-embed-provide-sanitize-function"),{html:e,hasChanged:!1})})}init(){const e=this.editor;e.model.schema.register("rawHtml",{inheritAllFrom:"$blockObject",allowAttributes:["value"]}),e.commands.add("htmlEmbed",new o(e)),this._setupConversion()}_setupConversion(){const e=this.editor,n=e.t,r=e.editing.view,a=this._widgetButtonViewReferences,o=e.config.get("htmlEmbed");function l({editor:e,domElement:t,state:r,props:o}){t.textContent="";const l=t.ownerDocument;let d;if(r.isEditable){const e={isDisabled:!1,placeholder:o.textareaPlaceholder};d=c({domDocument:l,state:r,props:e}),t.append(d)}else if(r.showPreviews){const a={sanitizeHtml:o.sanitizeHtml};t.append(function({editor:e,domDocument:t,state:r,props:a}){const o=a.sanitizeHtml(r.getRawHtmlValue()),l=r.getRawHtmlValue().length>0?n("No preview available"):n("Empty snippet content"),c=(0,i.createElement)(t,"div",{class:"ck ck-reset_all raw-html-embed__preview-placeholder"},l),d=(0,i.createElement)(t,"div",{class:"raw-html-embed__preview-content",dir:e.locale.contentLanguageDirection}),s=t.createRange(),m=s.createContextualFragment(o.html);d.appendChild(m);const u=(0,i.createElement)(t,"div",{class:"raw-html-embed__preview"},[c,d]);return u}({domDocument:l,state:r,props:a,editor:e}))}else{const e={isDisabled:!0,placeholder:o.textareaPlaceholder};t.append(c({domDocument:l,state:r,props:e}))}const s={onEditClick:o.onEditClick,onSaveClick:()=>{o.onSaveClick(d.value)},onCancelClick:o.onCancelClick};t.prepend(function({editor:e,domDocument:t,state:n,props:r}){const o=(0,i.createElement)(t,"div",{class:"raw-html-embed__buttons-wrapper"});if(n.isEditable){const t=b(e,"save",r.onSaveClick),n=b(e,"cancel",r.onCancelClick);o.append(t.element,n.element),a.add(t).add(n)}else{const t=b(e,"edit",r.onEditClick);o.append(t.element),a.add(t)}return o}({editor:e,domDocument:l,state:r,props:s}))}function c({domDocument:e,state:t,props:n}){const r=(0,i.createElement)(e,"textarea",{placeholder:n.placeholder,class:"ck ck-reset ck-input ck-input-text raw-html-embed__source"});return r.disabled=n.isDisabled,r.value=t.getRawHtmlValue(),r}this.editor.editing.view.on("render",(()=>{for(const e of a){if(e.element&&e.element.isConnected)return;e.destroy(),a.delete(e)}}),{priority:"lowest"}),e.data.registerRawContentMatcher({name:"div",classes:"raw-html-embed"}),e.conversion.for("upcast").elementToElement({view:{name:"div",classes:"raw-html-embed"},model:(e,{writer:t})=>t.createElement("rawHtml",{value:e.getCustomProperty("$rawContent")})}),e.conversion.for("dataDowncast").elementToElement({model:"rawHtml",view:(e,{writer:t})=>t.createRawElement("div",{class:"raw-html-embed"},(function(t){t.innerHTML=e.getAttribute("value")||""}))}),e.conversion.for("editingDowncast").elementToStructure({model:{name:"rawHtml",attributes:["value"]},view:(a,{writer:i})=>{let c,d,s;const m=i.createRawElement("div",{class:"raw-html-embed__content-wrapper"},(function(t){c=t,l({editor:e,domElement:t,state:d,props:s}),c.addEventListener("mousedown",(()=>{if(d.isEditable){const t=e.model;t.document.selection.getSelectedElement()!==a&&t.change((e=>e.setSelection(a,"on")))}}),!0)})),u={makeEditable(){d=Object.assign({},d,{isEditable:!0}),l({domElement:c,editor:e,state:d,props:s}),r.change((e=>{e.setAttribute("data-cke-ignore-events","true",m)})),c.querySelector("textarea").focus()},save(t){t!==d.getRawHtmlValue()?(e.execute("htmlEmbed",t),e.editing.view.focus()):this.cancel()},cancel(){d=Object.assign({},d,{isEditable:!1}),l({domElement:c,editor:e,state:d,props:s}),e.editing.view.focus(),r.change((e=>{e.removeAttribute("data-cke-ignore-events",m)}))}};d={showPreviews:o.showPreviews,isEditable:!1,getRawHtmlValue:()=>a.getAttribute("value")||""},s={sanitizeHtml:o.sanitizeHtml,textareaPlaceholder:n("Paste raw HTML here..."),onEditClick(){u.makeEditable()},onSaveClick(e){u.save(e)},onCancelClick(){u.cancel()}};const b=i.createContainerElement("div",{class:"raw-html-embed","data-html-embed-label":n("HTML snippet"),dir:e.locale.uiLanguageDirection},m);return i.setCustomProperty("rawHtmlApi",u,b),i.setCustomProperty("rawHtml",!0,b),(0,t.toWidget)(b,i,{label:n("HTML snippet"),hasSelectionHandle:!0})}})}}function b(t,n,r){const{t:i}=t.locale,o=new a.ButtonView(t.locale),l=t.commands.get("htmlEmbed");return o.set({class:`raw-html-embed__${n}-button`,icon:e.icons.pencil,tooltip:!0,tooltipPosition:"rtl"===t.locale.uiLanguageDirection?"e":"w"}),o.render(),"edit"===n?(o.set({icon:e.icons.pencil,label:i("Edit source")}),o.bind("isEnabled").to(l)):"save"===n?(o.set({icon:e.icons.check,label:i("Save changes")}),o.bind("isEnabled").to(l)):o.set({icon:e.icons.cancel,label:i("Cancel")}),o.on("execute",r),o}class h extends e.Plugin{static get pluginName(){return"HtmlEmbedUI"}init(){const e=this.editor,t=e.t;e.ui.componentFactory.add("htmlEmbed",(n=>{const r=e.commands.get("htmlEmbed"),i=new a.ButtonView(n);return i.set({label:t("Insert HTML"),icon:'<svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M17 0a2 2 0 0 1 2 2v7a1 1 0 0 1 1 1v5a1 1 0 0 1-.883.993l-.118.006L19 17a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2l-.001-1.001-.116-.006A1 1 0 0 1 0 15v-5a1 1 0 0 1 .999-1L1 2a2 2 0 0 1 2-2h14zm.499 15.999h-15L2.5 17a.5.5 0 0 0 .5.5h14a.5.5 0 0 0 .5-.5l-.001-1.001zm-3.478-6.013-.014.014H14v.007l-1.525 1.525-1.46-1.46-.015.013V10h-1v5h1v-3.53l1.428 1.43.048.043.131-.129L14 11.421V15h1v-5h-.965l-.014-.014zM2 10H1v5h1v-2h2v2h1v-5H4v2H2v-2zm7 0H6v1h1v4h1v-4h1v-1zm8 0h-1v5h3v-1h-2v-4zm0-8.5H3a.5.5 0 0 0-.5.5l-.001 6.999h15L17.5 2a.5.5 0 0 0-.5-.5zM10 7v1H4V7h6zm3-2v1H4V5h9zm-3-2v1H4V3h6z"/></svg>',tooltip:!0}),i.bind("isEnabled").to(r,"isEnabled"),this.listenTo(i,"execute",(()=>{e.execute("htmlEmbed"),e.editing.view.focus();e.editing.view.document.selection.getSelectedElement().getCustomProperty("rawHtmlApi").makeEditable()})),i}))}}class p extends e.Plugin{static get requires(){return[u,h,t.Widget]}static get pluginName(){return"HtmlEmbed"}}})(),(window.CKEditor5=window.CKEditor5||{}).htmlEmbed=r})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ckeditor/ckeditor5-html-embed",
3
- "version": "36.0.1",
3
+ "version": "37.0.0-alpha.0",
4
4
  "description": "HTML embed feature for CKEditor 5.",
5
5
  "keywords": [
6
6
  "ckeditor",
@@ -12,23 +12,24 @@
12
12
  ],
13
13
  "main": "src/index.js",
14
14
  "dependencies": {
15
- "ckeditor5": "^36.0.1"
15
+ "ckeditor5": "^37.0.0-alpha.0"
16
16
  },
17
17
  "devDependencies": {
18
- "@ckeditor/ckeditor5-basic-styles": "^36.0.1",
19
- "@ckeditor/ckeditor5-core": "^36.0.1",
20
- "@ckeditor/ckeditor5-dev-utils": "^32.0.0",
21
- "@ckeditor/ckeditor5-clipboard": "^36.0.1",
22
- "@ckeditor/ckeditor5-editor-classic": "^36.0.1",
23
- "@ckeditor/ckeditor5-engine": "^36.0.1",
24
- "@ckeditor/ckeditor5-media-embed": "^36.0.1",
25
- "@ckeditor/ckeditor5-paragraph": "^36.0.1",
26
- "@ckeditor/ckeditor5-table": "^36.0.1",
27
- "@ckeditor/ckeditor5-ui": "^36.0.1",
28
- "@ckeditor/ckeditor5-theme-lark": "^36.0.1",
29
- "@ckeditor/ckeditor5-widget": "^36.0.1",
18
+ "@ckeditor/ckeditor5-basic-styles": "^37.0.0-alpha.0",
19
+ "@ckeditor/ckeditor5-core": "^37.0.0-alpha.0",
20
+ "@ckeditor/ckeditor5-dev-utils": "^34.0.0",
21
+ "@ckeditor/ckeditor5-clipboard": "^37.0.0-alpha.0",
22
+ "@ckeditor/ckeditor5-editor-classic": "^37.0.0-alpha.0",
23
+ "@ckeditor/ckeditor5-engine": "^37.0.0-alpha.0",
24
+ "@ckeditor/ckeditor5-media-embed": "^37.0.0-alpha.0",
25
+ "@ckeditor/ckeditor5-paragraph": "^37.0.0-alpha.0",
26
+ "@ckeditor/ckeditor5-table": "^37.0.0-alpha.0",
27
+ "@ckeditor/ckeditor5-ui": "^37.0.0-alpha.0",
28
+ "@ckeditor/ckeditor5-theme-lark": "^37.0.0-alpha.0",
29
+ "@ckeditor/ckeditor5-widget": "^37.0.0-alpha.0",
30
30
  "lodash-es": "^4.17.15",
31
31
  "sanitize-html": "^2.1.0",
32
+ "typescript": "^4.8.4",
32
33
  "webpack": "^5.58.1",
33
34
  "webpack-cli": "^4.9.0"
34
35
  },
@@ -47,13 +48,17 @@
47
48
  },
48
49
  "files": [
49
50
  "lang",
50
- "src",
51
+ "src/**/*.js",
52
+ "src/**/*.d.ts",
51
53
  "theme",
52
54
  "build",
53
55
  "ckeditor5-metadata.json",
54
56
  "CHANGELOG.md"
55
57
  ],
56
58
  "scripts": {
57
- "dll:build": "webpack"
58
- }
59
+ "dll:build": "webpack",
60
+ "build": "tsc -p ./tsconfig.release.json",
61
+ "postversion": "npm run build"
62
+ },
63
+ "types": "src/index.d.ts"
59
64
  }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module html-embed/htmlembed
7
+ */
8
+ import { Plugin, type PluginDependencies } from 'ckeditor5/src/core';
9
+ /**
10
+ * The HTML embed feature.
11
+ *
12
+ * It allows inserting HTML snippets directly into the editor.
13
+ *
14
+ * For a detailed overview, check the {@glink features/html-embed HTML embed feature} documentation.
15
+ */
16
+ export default class HtmlEmbed extends Plugin {
17
+ /**
18
+ * @inheritDoc
19
+ */
20
+ static get requires(): PluginDependencies;
21
+ /**
22
+ * @inheritDoc
23
+ */
24
+ static get pluginName(): 'HtmlEmbed';
25
+ }
26
+ declare module '@ckeditor/ckeditor5-core' {
27
+ interface PluginsMap {
28
+ [HtmlEmbed.pluginName]: HtmlEmbed;
29
+ }
30
+ }
package/src/htmlembed.js CHANGED
@@ -2,123 +2,31 @@
2
2
  * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
-
6
5
  /**
7
6
  * @module html-embed/htmlembed
8
7
  */
9
-
10
8
  import { Plugin } from 'ckeditor5/src/core';
11
9
  import { Widget } from 'ckeditor5/src/widget';
12
-
13
10
  import HtmlEmbedEditing from './htmlembedediting';
14
11
  import HtmlEmbedUI from './htmlembedui';
15
-
16
12
  /**
17
13
  * The HTML embed feature.
18
14
  *
19
15
  * It allows inserting HTML snippets directly into the editor.
20
16
  *
21
17
  * For a detailed overview, check the {@glink features/html-embed HTML embed feature} documentation.
22
- *
23
- * @extends module:core/plugin~Plugin
24
18
  */
25
19
  export default class HtmlEmbed extends Plugin {
26
- /**
27
- * @inheritDoc
28
- */
29
- static get requires() {
30
- return [ HtmlEmbedEditing, HtmlEmbedUI, Widget ];
31
- }
32
-
33
- /**
34
- * @inheritDoc
35
- */
36
- static get pluginName() {
37
- return 'HtmlEmbed';
38
- }
20
+ /**
21
+ * @inheritDoc
22
+ */
23
+ static get requires() {
24
+ return [HtmlEmbedEditing, HtmlEmbedUI, Widget];
25
+ }
26
+ /**
27
+ * @inheritDoc
28
+ */
29
+ static get pluginName() {
30
+ return 'HtmlEmbed';
31
+ }
39
32
  }
40
-
41
- /**
42
- * The configuration of the HTML embed feature.
43
- *
44
- * ClassicEditor
45
- * .create( editorElement, {
46
- * htmlEmbed: ... // HTML embed feature options.
47
- * } )
48
- * .then( ... )
49
- * .catch( ... );
50
- *
51
- * See {@link module:core/editor/editorconfig~EditorConfig all editor options}.
52
- *
53
- * @interface HtmlEmbedConfig
54
- */
55
-
56
- /**
57
- * Whether the feature should render previews of the embedded HTML.
58
- *
59
- * When set to `true`, the feature will produce a preview of the inserted HTML based on a sanitized
60
- * version of the HTML provided by the user.
61
- *
62
- * The function responsible for sanitizing the HTML needs to be specified in
63
- * {@link module:html-embed/htmlembed~HtmlEmbedConfig#sanitizeHtml `config.htmlEmbed.sanitizeHtml()`}.
64
- *
65
- * Read more about the security aspect of this feature in the {@glink features/html-embed#security "Security"} section of
66
- * the {@glink features/html-embed HTML embed} feature guide.
67
- *
68
- * @member {Boolean} [module:html-embed/htmlembed~HtmlEmbedConfig#showPreviews=false]
69
- */
70
-
71
- /**
72
- * Callback used to sanitize the HTML provided by the user when generating previews of it in the editor.
73
- *
74
- * We strongly recommend overwriting the default function to avoid XSS vulnerabilities.
75
- *
76
- * Read more about the security aspect of this feature in the {@glink features/html-embed#security "Security"} section of
77
- * the {@glink features/html-embed HTML embed} feature guide.
78
- *
79
- * The function receives the input HTML (as a string), and should return an object
80
- * that matches the {@link module:html-embed/htmlembed~HtmlEmbedSanitizeOutput} interface.
81
- *
82
- * ClassicEditor
83
- * .create( editorElement, {
84
- * htmlEmbed: {
85
- * showPreviews: true,
86
- * sanitizeHtml( inputHtml ) {
87
- * // Strip unsafe elements and attributes, e.g.:
88
- * // the `<script>` elements and `on*` attributes.
89
- * const outputHtml = sanitize( inputHtml );
90
- *
91
- * return {
92
- * html: outputHtml,
93
- * // true or false depending on whether the sanitizer stripped anything.
94
- * hasChanged: ...
95
- * };
96
- * },
97
- * }
98
- * } )
99
- * .then( ... )
100
- * .catch( ... );
101
- *
102
- * **Note:** The function is used only when the feature
103
- * {@link module:html-embed/htmlembed~HtmlEmbedConfig#showPreviews is configured to render previews}.
104
- *
105
- * @member {Function} [module:html-embed/htmlembed~HtmlEmbedConfig#sanitizeHtml]
106
- */
107
-
108
- /**
109
- * An object returned by the {@link module:html-embed/htmlembed~HtmlEmbedConfig#sanitizeHtml} function.
110
- *
111
- * @interface HtmlEmbedSanitizeOutput
112
- */
113
-
114
- /**
115
- * An output (safe) HTML that will be inserted into the {@glink framework/guides/architecture/editing-engine editing view}.
116
- *
117
- * @member {String} module:html-embed/htmlembed~HtmlEmbedSanitizeOutput#html
118
- */
119
-
120
- /**
121
- * A flag that indicates whether the output HTML is different than the input value.
122
- *
123
- * @member {Boolean} [module:html-embed/htmlembed~HtmlEmbedSanitizeOutput#hasChanged]
124
- */
@@ -0,0 +1,49 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ import { Command } from 'ckeditor5/src/core';
6
+ /**
7
+ * The insert HTML embed element command.
8
+ *
9
+ * The command is registered by {@link module:html-embed/htmlembedediting~HtmlEmbedEditing} as `'htmlEmbed'`.
10
+ *
11
+ * To insert an empty HTML embed element at the current selection, execute the command:
12
+ *
13
+ * ```ts
14
+ * editor.execute( 'htmlEmbed' );
15
+ * ```
16
+ *
17
+ * You can specify the initial content of a new HTML embed in the argument:
18
+ *
19
+ * ```ts
20
+ * editor.execute( 'htmlEmbed', '<b>Initial content.</b>' );
21
+ * ```
22
+ *
23
+ * To update the content of the HTML embed, select it in the model and pass the content in the argument:
24
+ *
25
+ * ```ts
26
+ * editor.execute( 'htmlEmbed', '<b>New content of an existing embed.</b>' );
27
+ * ```
28
+ */
29
+ export default class HtmlEmbedCommand extends Command {
30
+ /**
31
+ * @inheritDoc
32
+ */
33
+ refresh(): void;
34
+ /**
35
+ * Executes the command, which either:
36
+ *
37
+ * * creates and inserts a new HTML embed element if none was selected,
38
+ * * updates the content of the HTML embed if one was selected.
39
+ *
40
+ * @fires execute
41
+ * @param value When passed, the value (content) will be set on a new embed or a selected one.
42
+ */
43
+ execute(value?: string): void;
44
+ }
45
+ declare module '@ckeditor/ckeditor5-core' {
46
+ interface CommandsMap {
47
+ htmlEmbed: HtmlEmbedCommand;
48
+ }
49
+ }
@@ -2,14 +2,8 @@
2
2
  * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
4
  */
5
-
6
- /**
7
- * @module html-embed/htmlembedcommand
8
- */
9
-
10
5
  import { Command } from 'ckeditor5/src/core';
11
6
  import { findOptimalInsertionRange } from 'ckeditor5/src/widget';
12
-
13
7
  /**
14
8
  * The insert HTML embed element command.
15
9
  *
@@ -17,100 +11,85 @@ import { findOptimalInsertionRange } from 'ckeditor5/src/widget';
17
11
  *
18
12
  * To insert an empty HTML embed element at the current selection, execute the command:
19
13
  *
20
- * editor.execute( 'htmlEmbed' );
14
+ * ```ts
15
+ * editor.execute( 'htmlEmbed' );
16
+ * ```
21
17
  *
22
18
  * You can specify the initial content of a new HTML embed in the argument:
23
19
  *
24
- * editor.execute( 'htmlEmbed', '<b>Initial content.</b>' );
20
+ * ```ts
21
+ * editor.execute( 'htmlEmbed', '<b>Initial content.</b>' );
22
+ * ```
25
23
  *
26
24
  * To update the content of the HTML embed, select it in the model and pass the content in the argument:
27
25
  *
28
- * editor.execute( 'htmlEmbed', '<b>New content of an existing embed.</b>' );
29
- *
30
- * @extends module:core/command~Command
26
+ * ```ts
27
+ * editor.execute( 'htmlEmbed', '<b>New content of an existing embed.</b>' );
28
+ * ```
31
29
  */
32
30
  export default class HtmlEmbedCommand extends Command {
33
- /**
34
- * @inheritDoc
35
- */
36
- refresh() {
37
- const model = this.editor.model;
38
- const schema = model.schema;
39
- const selection = model.document.selection;
40
- const selectedRawHtmlElement = getSelectedRawHtmlModelWidget( selection );
41
-
42
- this.isEnabled = isHtmlEmbedAllowedInParent( selection, schema, model );
43
- this.value = selectedRawHtmlElement ? selectedRawHtmlElement.getAttribute( 'value' ) || '' : null;
44
- }
45
-
46
- /**
47
- * Executes the command, which either:
48
- *
49
- * * creates and inserts a new HTML embed element if none was selected,
50
- * * updates the content of the HTML embed if one was selected.
51
- *
52
- * @fires execute
53
- * @param {String} [value] When passed, the value (content) will be set on a new embed or a selected one.
54
- */
55
- execute( value ) {
56
- const model = this.editor.model;
57
- const selection = model.document.selection;
58
-
59
- model.change( writer => {
60
- let htmlEmbedElement;
61
-
62
- // If the command has a non-null value, there must be some HTML embed selected in the model.
63
- if ( this.value !== null ) {
64
- htmlEmbedElement = getSelectedRawHtmlModelWidget( selection );
65
- } else {
66
- htmlEmbedElement = writer.createElement( 'rawHtml' );
67
-
68
- model.insertObject( htmlEmbedElement, null, null, { setSelection: 'on' } );
69
- }
70
-
71
- writer.setAttribute( 'value', value, htmlEmbedElement );
72
- } );
73
- }
31
+ /**
32
+ * @inheritDoc
33
+ */
34
+ refresh() {
35
+ const model = this.editor.model;
36
+ const schema = model.schema;
37
+ const selection = model.document.selection;
38
+ const selectedRawHtmlElement = getSelectedRawHtmlModelWidget(selection);
39
+ this.isEnabled = isHtmlEmbedAllowedInParent(selection, schema, model);
40
+ this.value = selectedRawHtmlElement ? selectedRawHtmlElement.getAttribute('value') || '' : null;
41
+ }
42
+ /**
43
+ * Executes the command, which either:
44
+ *
45
+ * * creates and inserts a new HTML embed element if none was selected,
46
+ * * updates the content of the HTML embed if one was selected.
47
+ *
48
+ * @fires execute
49
+ * @param value When passed, the value (content) will be set on a new embed or a selected one.
50
+ */
51
+ execute(value) {
52
+ const model = this.editor.model;
53
+ const selection = model.document.selection;
54
+ model.change(writer => {
55
+ let htmlEmbedElement;
56
+ // If the command has a non-null value, there must be some HTML embed selected in the model.
57
+ if (this.value !== null) {
58
+ htmlEmbedElement = getSelectedRawHtmlModelWidget(selection);
59
+ }
60
+ else {
61
+ htmlEmbedElement = writer.createElement('rawHtml');
62
+ model.insertObject(htmlEmbedElement, null, null, { setSelection: 'on' });
63
+ }
64
+ writer.setAttribute('value', value, htmlEmbedElement);
65
+ });
66
+ }
74
67
  }
75
-
76
- // Checks if an HTML embed is allowed by the schema in the optimal insertion parent.
77
- //
78
- // @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection} selection
79
- // @param {module:engine/model/schema~Schema} schema
80
- // @param {module:engine/model/model~Model} model
81
- // @returns {Boolean}
82
- function isHtmlEmbedAllowedInParent( selection, schema, model ) {
83
- const parent = getInsertHtmlEmbedParent( selection, model );
84
-
85
- return schema.checkChild( parent, 'rawHtml' );
68
+ /**
69
+ * Checks if an HTML embed is allowed by the schema in the optimal insertion parent.
70
+ */
71
+ function isHtmlEmbedAllowedInParent(selection, schema, model) {
72
+ const parent = getInsertHtmlEmbedParent(selection, model);
73
+ return schema.checkChild(parent, 'rawHtml');
86
74
  }
87
-
88
- // Returns a node that will be used to insert a html embed with `model.insertContent` to check if a html embed element can be placed there.
89
- //
90
- // @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection} selection
91
- // @param {module:engine/model/model~Model} model
92
- // @returns {module:engine/model/element~Element}
93
- function getInsertHtmlEmbedParent( selection, model ) {
94
- const insertionRange = findOptimalInsertionRange( selection, model );
95
- const parent = insertionRange.start.parent;
96
-
97
- if ( parent.isEmpty && !parent.is( 'element', '$root' ) ) {
98
- return parent.parent;
99
- }
100
-
101
- return parent;
75
+ /**
76
+ * Returns a node that will be used to insert a html embed with `model.insertContent` to check if a html embed element can be placed there.
77
+ */
78
+ function getInsertHtmlEmbedParent(selection, model) {
79
+ const insertionRange = findOptimalInsertionRange(selection, model);
80
+ const parent = insertionRange.start.parent;
81
+ if (parent.isEmpty && !parent.is('rootElement')) {
82
+ return parent.parent;
83
+ }
84
+ return parent;
102
85
  }
103
-
104
- // Returns the selected HTML embed element in the model, if any.
105
- //
106
- // @param {module:engine/model/selection~Selection} selection
107
- // @returns {module:engine/model/element~Element|null}
108
- function getSelectedRawHtmlModelWidget( selection ) {
109
- const selectedElement = selection.getSelectedElement();
110
-
111
- if ( selectedElement && selectedElement.is( 'element', 'rawHtml' ) ) {
112
- return selectedElement;
113
- }
114
-
115
- return null;
86
+ /**
87
+ * Returns the selected HTML embed element in the model, if any.
88
+ */
89
+ function getSelectedRawHtmlModelWidget(selection) {
90
+ const selectedElement = selection.getSelectedElement();
91
+ if (selectedElement && selectedElement.is('element', 'rawHtml')) {
92
+ return selectedElement;
93
+ }
94
+ return null;
116
95
  }
@@ -0,0 +1,96 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module html-embed/htmlembedconfig
7
+ */
8
+ /**
9
+ * The configuration of the HTML embed feature.
10
+ *
11
+ * ```ts
12
+ * ClassicEditor
13
+ * .create( editorElement, {
14
+ * htmlEmbed: ... // HTML embed feature options.
15
+ * } )
16
+ * .then( ... )
17
+ * .catch( ... );
18
+ * ```
19
+ *
20
+ * See {@link module:core/editor/editorconfig~EditorConfig all editor options}.
21
+ */
22
+ export interface HtmlEmbedConfig {
23
+ /**
24
+ * Whether the feature should render previews of the embedded HTML.
25
+ *
26
+ * When set to `true`, the feature will produce a preview of the inserted HTML based on a sanitized
27
+ * version of the HTML provided by the user.
28
+ *
29
+ * The function responsible for sanitizing the HTML needs to be specified in
30
+ * {@link module:html-embed/htmlembedconfig~HtmlEmbedConfig#sanitizeHtml `config.htmlEmbed.sanitizeHtml()`}.
31
+ *
32
+ * Read more about the security aspect of this feature in the {@glink features/html-embed#security "Security"} section of
33
+ * the {@glink features/html-embed HTML embed} feature guide.
34
+ */
35
+ showPreviews?: boolean;
36
+ /**
37
+ * Callback used to sanitize the HTML provided by the user when generating previews of it in the editor.
38
+ *
39
+ * We strongly recommend overwriting the default function to avoid XSS vulnerabilities.
40
+ *
41
+ * Read more about the security aspect of this feature in the {@glink features/html-embed#security "Security"} section of
42
+ * the {@glink features/html-embed HTML embed} feature guide.
43
+ *
44
+ * The function receives the input HTML (as a string), and should return an object
45
+ * that matches the {@link module:html-embed/htmlembedconfig~HtmlEmbedSanitizeOutput} interface.
46
+ *
47
+ * ```ts
48
+ * ClassicEditor
49
+ * .create( editorElement, {
50
+ * htmlEmbed: {
51
+ * showPreviews: true,
52
+ * sanitizeHtml( inputHtml ) {
53
+ * // Strip unsafe elements and attributes, e.g.:
54
+ * // the `<script>` elements and `on*` attributes.
55
+ * const outputHtml = sanitize( inputHtml );
56
+ *
57
+ * return {
58
+ * html: outputHtml,
59
+ * // true or false depending on whether the sanitizer stripped anything.
60
+ * hasChanged: ...
61
+ * };
62
+ * },
63
+ * }
64
+ * } )
65
+ * .then( ... )
66
+ * .catch( ... );
67
+ * ```
68
+ *
69
+ * **Note:** The function is used only when the feature
70
+ * {@link module:html-embed/htmlembedconfig~HtmlEmbedConfig#showPreviews is configured to render previews}.
71
+ */
72
+ sanitizeHtml?: (html: string) => HtmlEmbedSanitizeOutput;
73
+ }
74
+ /**
75
+ * An object returned by the {@link module:html-embed/htmlembedconfig~HtmlEmbedConfig#sanitizeHtml} function.
76
+ */
77
+ export interface HtmlEmbedSanitizeOutput {
78
+ /**
79
+ * An output (safe) HTML that will be inserted into the {@glink framework/guides/architecture/editing-engine editing view}.
80
+ */
81
+ html: string;
82
+ /**
83
+ * A flag that indicates whether the output HTML is different than the input value.
84
+ */
85
+ hasChanged: boolean;
86
+ }
87
+ declare module '@ckeditor/ckeditor5-core' {
88
+ /**
89
+ * The configuration of the HTML embed feature. Introduced by the {@link module:html-embed/htmlembedediting~HtmlEmbedEditing} feature.
90
+ *
91
+ * Read more in {@link module:core/editor/editorconfig~EditorConfig all editor options}.
92
+ */
93
+ interface EditorConfig {
94
+ htmlEmbed?: HtmlEmbedConfig;
95
+ }
96
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ export {};