diff --git a/.circleci/test.sh b/.circleci/test.sh index 6a65db138..2b5f5dd8f 100755 --- a/.circleci/test.sh +++ b/.circleci/test.sh @@ -13,6 +13,8 @@ ahoy cli "./vendor/bin/behat --strict --colors --tags="~@skipped" tests" ahoy cli "drush en tide_webform -y" ahoy cli "./vendor/bin/behat --strict --colors --tags="~@skipped" modules/tide_webform" ahoy cli "drush en tide_media -y" +ahoy cli "drush en tide_media_secure_files -y" +ahoy cli "drush en tide_media_file_overwrite -y" ahoy cli "./vendor/bin/behat --strict --colors --tags="~@skipped" modules/tide_media" ahoy cli "drush en tide_event -y" ahoy cli "./vendor/bin/behat --strict --colors --tags="~@skipped" modules/tide_event" diff --git a/composer.json b/composer.json index 2e15e5e19..7248fd111 100644 --- a/composer.json +++ b/composer.json @@ -462,6 +462,9 @@ }, "drupal/views_bulk_operations": { "getSubscribedEvents() fails on `drush updb` due to autoloader negative-cache (missing class_exists() guard) - https://www.drupal.org/project/views_bulk_operations/issues/3589629#comment-16583537": "https://www.drupal.org/files/issues/2026-05-12/views_bulk_operations-class-exists-guard-3589629-2.patch" + }, + "drupal/entity_embed": { + "Entity embed dialog can no longer use custom data- attributes in CKEditor 5 - https://www.drupal.org/project/entity_embed/issues/3410132": "https://www.drupal.org/files/issues/2026-06-15/entity-embed-allow-custom-data-attrs-javascript.patch" } }, "installer-paths": { diff --git a/modules/tide_media/tests/behat/features/media_browser.feature b/modules/tide_media/tests/behat/features/media_browser.feature index 13d5f3265..61696aebe 100644 --- a/modules/tide_media/tests/behat/features/media_browser.feature +++ b/modules/tide_media/tests/behat/features/media_browser.feature @@ -15,3 +15,26 @@ Feature: Media browser And I wait for AJAX to finish Then I should see the text "Select media item to embed" And I press the "Close" button + + @api @javascript + Scenario: Media Browser allows embed with custom data attribute + Given I am logged in as a user with the "create test content, access media overview, access tide_media_browser entity browser pages, access tide_media_browser_iframe entity browser pages, use text format rich_text" permission + And media document entity: + | name | mid | + | Demo Document | 888666 | + + When I visit "/node/add/test" + Then I press "Media" + And I wait for AJAX to finish + Then I should see the text "Select media item to embed" + + When I click on iFramed element ".views-field-entity-browser-select .form-checkbox" within "entity_browser_iframe_tide_media_browser_iframe" + Then I click on iFramed element "#edit-submit" within "entity_browser_iframe_tide_media_browser_iframe" + And I wait for AJAX to finish + Then I should see the text "Embed media item" + + When I check "Display last update date" + Then I click on the element ".ui-dialog-buttonpane .button--primary" + And I wait for AJAX to finish + And I wait for 1 seconds + Then I should see a ".embedded-entity[data-show-last-updated='1']" element diff --git a/patches/entity_embed/3396133-ckeditor-5-interface_26.patch b/patches/entity_embed/3396133-ckeditor-5-interface_26.patch deleted file mode 100644 index e3a32fdde..000000000 --- a/patches/entity_embed/3396133-ckeditor-5-interface_26.patch +++ /dev/null @@ -1,122 +0,0 @@ - From 91633515fac9ef6db5c141451d97986b30c25f47 Mon Sep 17 00:00:00 2001 -From: bnjmnm -Date: Tue, 24 Oct 2023 15:29:18 -0400 -Subject: [PATCH 1/3] check for attribute existience before using them - ---- - js/build/drupalentity.js | 2 +- - js/ckeditor5_plugins/drupalentity/src/toolbar.js | 6 ++++++ - 2 files changed, 7 insertions(+), 1 deletion(-) - -diff --git a/js/build/drupalentity.js b/js/build/drupalentity.js -index 4a151d7..37bdb23 100644 ---- a/js/build/drupalentity.js -+++ b/js/build/drupalentity.js -@@ -1 +1 @@ --!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.CKEditor5=e():(t.CKEditor5=t.CKEditor5||{},t.CKEditor5.drupalentity=e())}(self,(()=>(()=>{var t={"ckeditor5/src/core.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/core.js")},"ckeditor5/src/engine.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/engine.js")},"ckeditor5/src/ui.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/ui.js")},"ckeditor5/src/utils.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/utils.js")},"ckeditor5/src/widget.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/widget.js")},"dll-reference CKEditor5.dll":t=>{"use strict";t.exports=CKEditor5.dll}},e={};function i(r){var n=e[r];if(void 0!==n)return n.exports;var o=e[r]={exports:{}};return t[r](o,o.exports,i),o.exports}i.d=(t,e)=>{for(var r in e)i.o(e,r)&&!i.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:e[r]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e);var r={};return(()=>{"use strict";i.d(r,{default:()=>A});var t=i("ckeditor5/src/core.js"),e=i("ckeditor5/src/widget.js");class n extends t.Command{execute(t){const{model:e}=this.editor,i=this.editor.plugins.get("EntityEmbedEditing"),r=Object.fromEntries(Object.entries(i.attrs).map((([t,e])=>[e,t]))),n=Object.fromEntries(Object.keys(r).filter((e=>t[e])).map((e=>[r[e],t[e]])));e.change((t=>{e.insertContent(function(t,e){return t.createElement("drupalEntity",e)}(t,n))}))}refresh(){const t=this.editor.model,e=t.document.selection,i=t.schema.findAllowedParent(e.getFirstPosition(),"drupalEntity");this.isEnabled=null!==i}}class o extends t.Plugin{static get requires(){return[e.Widget]}init(){this.attrs={alt:"alt",title:"title",dataCaption:"data-caption",dataAlign:"data-align",drupalEntityLangCode:"data-langcode",drupalEntityEntityType:"data-entity-type",drupalEntityEntityUuid:"data-entity-uuid",drupalEntityViewMode:"data-view-mode",drupalEntityEmbedButton:"data-embed-button",drupalEntityEmbedDisplay:"data-entity-embed-display",drupalEntityEmbedDisplaySettings:"data-entity-embed-display-settings"};const t=this.editor.config.get("entityEmbed");if(!t)throw new Error("Error on initializing entityEmbed plugin: entityEmbed config is required.");this.options=t,this.labelError=Drupal.t("Preview failed"),this.previewError=`\n

${Drupal.t("An error occurred while trying to preview the embedded content. Please save your work and reload this page.")}

\n `,this._defineSchema(),this._defineConverters(),this.editor.commands.add("insertEntityEmbed",new n(this.editor))}_defineSchema(){this.editor.model.schema.register("drupalEntity",{isObject:!0,isContent:!0,isBlock:!0,allowWhere:"$block",allowAttributes:Object.keys(this.attrs)}),this.editor.editing.view.domConverter.blockElements.push("drupal-entity")}_defineConverters(){const{conversion:t}=this.editor,i={model:"drupalEntity",view:{name:"drupal-entity"}};t.for("upcast").elementToElement(i),t.for("dataDowncast").elementToElement(i),t.for("editingDowncast").elementToElement({...i,view:(t,{writer:i})=>{const r=t.hasAttribute("dataAlign")?` align-${t.getAttribute("dataAlign")}`:"",n=i.createContainerElement("figure",{class:`drupal-entity${r}`});return i.setCustomProperty("drupalEntity",!0,n),(0,e.toWidget)(n,i,{label:Drupal.t("Entity Embed widget")})}}).add((t=>(t.on("attribute:drupalEntityEntityUuid:drupalEntity",((t,e,i)=>{const r=i.writer,n=e.item,o=i.mapper.toViewElement(e.item);let a=this._getPreviewContainer(o.getChildren());if(a){if("ready"!==a.getAttribute("data-drupal-entity-preview"))return;r.setAttribute("data-drupal-entity-preview","loading",a)}else a=r.createRawElement("div",{"data-drupal-entity-preview":"loading"}),r.insert(r.createPositionAt(o,0),a);this._loadPreview(n).then((({label:t,preview:e})=>{a&&this.editor.editing.view.change((i=>{const r=i.createRawElement("div",{"data-drupal-entity-preview":"ready","aria-label":t},(t=>{t.innerHTML=e}));i.insert(i.createPositionBefore(a),r),i.remove(a)}))}))})),t))),Object.keys(this.attrs).forEach((e=>{const i={model:{key:e,name:"drupalEntity"},view:{name:"drupal-entity",key:this.attrs[e]}};t.for("dataDowncast").attributeToAttribute(i),t.for("upcast").attributeToAttribute(i)}))}async _loadPreview(t){const e={text:this._renderElement(t)},i=await fetch(Drupal.url("embed/preview/"+this.options.format+"?"+new URLSearchParams(e)),{headers:{"X-Drupal-EmbedPreview-CSRF-Token":this.options.previewCsrfToken}});if(i.ok){return{label:Drupal.t("Entity Embed widget"),preview:await i.text()}}return{label:this.labelError,preview:this.previewError}}_renderElement(t){const e=this.editor.model.change((e=>{const i=e.createDocumentFragment(),r=e.cloneElement(t,!1);return["linkHref","dataAlign"].forEach((t=>{e.removeAttribute(t,r)})),e.append(r,i),i}));return this.editor.data.stringify(e)}_getPreviewContainer(t){for(const e of t){if(e.hasAttribute("data-drupal-entity-preview"))return e;if(e.childCount){const t=this._getPreviewContainer(e.getChildren());if(t)return t}}return null}static get pluginName(){return"EntityEmbedEditing"}}var a=i("ckeditor5/src/ui.js");class s extends t.Plugin{static get requires(){return[e.WidgetToolbarRepository]}init(){const e=this.editor,i=e.plugins.get("EntityEmbedEditing"),r=e.config.get("entityEmbed"),{dialogSettings:n={}}=r;e.ui.componentFactory.add("entityEmbedEdit",(o=>{let s=new a.ButtonView(o);return s.set({label:e.t("Edit"),icon:t.icons.pencil,tooltip:!0}),this.listenTo(s,"execute",(t=>{const o=e.model.document.selection.getSelectedElement(),a=Drupal.url("entity-embed/dialog/"+r.format+"/"+o.getAttribute("drupalEntityEmbedButton"));let s={};for(let[t,e]of o.getAttributes()){let r=i.attrs[t];r&&(s[r]=e)}this._openDialog(a,s,(({attributes:t})=>{e.execute("insertEntityEmbed",t),e.editing.view.focus()}),n)})),s})),e.ui.componentFactory.add("editEmbeddedEntity",(i=>{const r=new a.ButtonView(i),n=e.model.document.selection.getSelectedElement(),o=n.getAttribute("drupalEntityEntityUuid"),s=n.getAttribute("drupalEntityEntityType"),l=Drupal.url(`entity-embed/edit-embedded/${s}/${o}`);return r.set({isEnabled:!0,label:Drupal.t("Edit the embedded entity (opens in new tab)"),icon:t.icons.cog,tooltip:!0}),fetch(l).then((t=>{t.ok||r.set({label:Drupal.t(`You do not have the permissions needed to edit this ${s}.`),isEnabled:!1})})),this.listenTo(r,"execute",(()=>{window.open(l,"_blank")})),r}))}afterInit(){const{editor:t}=this;if(!t.plugins.has("WidgetToolbarRepository"))return;t.plugins.get(e.WidgetToolbarRepository).register("entityEmbed",{ariaLabel:Drupal.t("Entity Embed toolbar"),items:["entityEmbedEdit","entityEmbedLink","editEmbeddedEntity"],getRelatedElement(t){const i=t.getSelectedElement();return i&&(0,e.isWidget)(i)&&i.getCustomProperty("drupalEntity")?i:null}})}_openDialog(t,e,i,r){const n=r.dialogClass?r.dialogClass.split(" "):[];n.push("ui-dialog--narrow"),r.dialogClass=n.join(" "),r.autoResize=window.matchMedia("(min-width: 600px)").matches,r.width="auto";Drupal.ajax({dialog:r,dialogType:"modal",selector:".ckeditor5-dialog-loading-link",url:t,progress:{type:"fullscreen"},submit:{editor_object:e}}).execute(),Drupal.ckeditor5.saveCallback=i}static get pluginName(){return"EntityEmbedToolbar"}}class l extends t.Plugin{static get requires(){return["Widget"]}init(){const t=this.editor,e=t.commands.get("insertEntityEmbed"),i=t.config.get("entityEmbed");if(!i)return;const{dialogSettings:r={}}=i,n=i.buttons;Object.keys(n).forEach((o=>{const s=Drupal.url("entity-embed/dialog/"+i.format+"/"+o);t.ui.componentFactory.add(o,(i=>{const l=n[o],d=new a.ButtonView(i);let u=null;if(l.icon.endsWith("svg")){let t=new XMLHttpRequest;t.open("GET",l.icon,!1),t.send(null),u=t.response}else console.warn(`CKEditor 5 only supports enity embed icons in SVG format. The icon provided is ${l.icon}`);return d.set({label:l.label,icon:u??'\n\n \n\n',tooltip:!0}),d.bind("isOn","isEnabled").to(e,"value","isEnabled"),this.listenTo(d,"execute",(()=>Drupal.ckeditor5.openDialog(s,(({attributes:e})=>{t.execute("insertEntityEmbed",e)}),r))),d}))}))}static get pluginName(){return"EntityEmbedUI"}}function d(t,e,i){if(e.attributes)for(const[r,n]of Object.entries(e.attributes))t.setAttribute(r,n,i);e.styles&&t.setStyle(e.styles,i),e.classes&&t.addClass(e.classes,i)}function u(t,e,i){if(!i.consumable.consume(e.item,t.name))return;const r=i.mapper.toViewElement(e.item);d(i.writer,e.attributeNewValue,r)}class c extends t.Plugin{constructor(t){if(super(t),!t.plugins.has("GeneralHtmlSupport"))return;t.plugins.has("DataFilter")&&t.plugins.has("DataSchema")||console.error("DataFilter and DataSchema plugins are required for Entity Embed to integrate with General HTML Support plugin.");const{schema:e}=t.model,{conversion:i}=t,r=this.editor.plugins.get("DataFilter");this.editor.plugins.get("DataSchema").registerBlockElement({model:"drupalEntity",view:"drupal-entity"}),r.on("register:drupal-entity",((t,n)=>{"drupalEntity"===n.model&&(e.extend("drupalEntity",{allowAttributes:["htmlLinkAttributes","htmlAttributes"]}),i.for("upcast").add(function(t){return e=>{e.on("element:drupal-entity",((e,i,r)=>{function n(e,n){const o=t.processViewAttributes(e,r);o&&r.writer.setAttribute(n,o,i.modelRange)}const o=i.viewItem,a=o.parent;n(o,"htmlAttributes"),a.is("element","a")&&n(a,"htmlLinkAttributes")}),{priority:"low"})}}(r)),i.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item),n=function(t,e,i){const r=t.createRangeOn(e);for(const{item:t}of r.getWalker())if(t.is("element",i))return t}(i.writer,r,"a");d(i.writer,e.item.getAttribute("htmlLinkAttributes"),n)}),{priority:"low"})})),i.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item).parent;d(i.writer,e.item.getAttribute("htmlLinkAttributes"),r)}),{priority:"low"}),t.on("attribute:htmlAttributes:drupalEntity",u,{priority:"low"})})),t.stop())}))}static get pluginName(){return"EntityEmbedGeneralHtmlSupport"}}var m=i("ckeditor5/src/engine.js"),p=i("ckeditor5/src/utils.js");function g(t){return Array.from(t.getChildren()).find((t=>"drupal-entity"===t.name))}function E(t){return e=>{e.on(`attribute:${t.id}:drupalEntity`,((e,i,r)=>{const n=r.mapper.toViewElement(i.item);let o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o=!o&&n.is("element","a")?n:Array.from(n.getAncestors()).find((t=>"a"===t.name)),o){for(const[e,i]of(0,p.toMap)(t.attributes))r.writer.setAttribute(e,i,o);t.classes&&r.writer.addClass(t.classes,o);for(const e in t.styles)Object.prototype.hasOwnProperty.call(t.styles,e)&&r.writer.setStyle(e,t.styles[e],o)}}))}}function b(t,e){return t=>{t.on("element:a",((t,i,r)=>{const n=i.viewItem;if(!g(n))return;const o=new m.Matcher(e._createPattern()).match(n);if(!o)return;if(!r.consumable.consume(n,o.match))return;const a=i.modelCursor.nodeBefore;r.writer.setAttribute(e.id,!0,a)}),{priority:"high"})}}class y extends t.Plugin{static get requires(){return["EntityEmbedEditing"]}static get pluginName(){return"EntityEmbedLinkEditing"}init(){const{editor:t}=this;t.model.schema.extend("drupalEntity",{allowAttributes:["linkHref"]}),t.conversion.for("upcast").add((t=>{t.on("element:a",((t,e,i)=>{const r=e.viewItem,n=g(r);if(!n)return;if(!i.consumable.consume(r,{attributes:["href"],name:!0}))return;const o=r.getAttribute("href");if(!o)return;const a=i.convertItem(n,e.modelCursor);e.modelRange=a.modelRange,e.modelCursor=a.modelCursor;const s=e.modelCursor.nodeBefore;s&&s.is("element","drupalEntity")&&i.writer.setAttribute("linkHref",o,s)}),{priority:"high"})})),t.conversion.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o)e.attributeNewValue?r.setAttribute("href",e.attributeNewValue,o):(r.move(r.createRangeIn(o),r.createPositionAt(n,0)),r.remove(o));else{const t=Array.from(n.getChildren()).find((t=>t.getAttribute("data-drupal-entity-preview"))),i=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionAt(n,0),i),r.move(r.createRangeOn(t),r.createPositionAt(i,0))}}),{priority:"high"})})),t.conversion.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionBefore(n),o),r.move(r.createRangeOn(n),r.createPositionAt(o,0))}),{priority:"high"})})),this._enableManualDecorators();if(t.commands.get("link").automaticDecorators.length>0)throw new Error("The Drupal Entity plugin is not compatible with automatic link decorators. To use Drupal Entity, disable any plugins providing automatic link decorators.")}_enableManualDecorators(){const t=this.editor,e=t.commands.get("link");for(const i of e.manualDecorators)t.model.schema.extend("drupalEntity",{allowAttributes:i.id}),t.conversion.for("downcast").add(E(i)),t.conversion.for("upcast").add(b(0,i))}}class h extends t.Plugin{static get requires(){return["LinkEditing","LinkUI","EntityEmbedEditing","EntityEmbedUI"]}static get pluginName(){return"EntityEmbedLinkUi"}init(){const{editor:t}=this,e=t.editing.view.document;this.listenTo(e,"click",((e,i)=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)&&(i.preventDefault(),e.stop())}),{priority:"high"}),this._createToolbarLinkEntityEmbedButton()}_createToolbarLinkEntityEmbedButton(){const{editor:t}=this;t.ui.componentFactory.add("entityEmbedLink",(e=>{const i=new a.ButtonView(e),r=t.plugins.get("LinkUI"),n=t.commands.get("link");return i.set({isEnabled:!0,label:Drupal.t("Link entity embed"),icon:'',keystroke:"Ctrl+K",tooltip:!0,isToggleable:!0}),i.bind("isEnabled").to(n,"isEnabled"),i.bind("isOn").to(n,"value",(t=>!!t)),this.listenTo(i,"execute",(()=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)?r._addActionsView():r._showUI(!0)})),i}))}_isSelectedLinkedEntityEmbed(t){const e=t.getSelectedElement();return!!e&&e.is("element","drupalEntity")&&e.hasAttribute("linkHref")}}class w extends t.Plugin{static get requires(){return[y,h]}static get pluginName(){return"EntityEmbedLink"}}class f extends t.Plugin{static get requires(){return[o,l,s,c,w]}static get pluginName(){return"EntityEmbed"}}const A={EntityEmbed:f}})(),r=r.default})())); -\ No newline at end of file -+!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.CKEditor5=e():(t.CKEditor5=t.CKEditor5||{},t.CKEditor5.drupalentity=e())}(self,(()=>(()=>{var t={"ckeditor5/src/core.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/core.js")},"ckeditor5/src/engine.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/engine.js")},"ckeditor5/src/ui.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/ui.js")},"ckeditor5/src/utils.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/utils.js")},"ckeditor5/src/widget.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/widget.js")},"dll-reference CKEditor5.dll":t=>{"use strict";t.exports=CKEditor5.dll}},e={};function i(r){var n=e[r];if(void 0!==n)return n.exports;var o=e[r]={exports:{}};return t[r](o,o.exports,i),o.exports}i.d=(t,e)=>{for(var r in e)i.o(e,r)&&!i.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:e[r]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e);var r={};return(()=>{"use strict";i.d(r,{default:()=>A});var t=i("ckeditor5/src/core.js"),e=i("ckeditor5/src/widget.js");class n extends t.Command{execute(t){const{model:e}=this.editor,i=this.editor.plugins.get("EntityEmbedEditing"),r=Object.fromEntries(Object.entries(i.attrs).map((([t,e])=>[e,t]))),n=Object.fromEntries(Object.keys(r).filter((e=>t[e])).map((e=>[r[e],t[e]])));e.change((t=>{e.insertContent(function(t,e){return t.createElement("drupalEntity",e)}(t,n))}))}refresh(){const t=this.editor.model,e=t.document.selection,i=t.schema.findAllowedParent(e.getFirstPosition(),"drupalEntity");this.isEnabled=null!==i}}class o extends t.Plugin{static get requires(){return[e.Widget]}init(){this.attrs={alt:"alt",title:"title",dataCaption:"data-caption",dataAlign:"data-align",drupalEntityLangCode:"data-langcode",drupalEntityEntityType:"data-entity-type",drupalEntityEntityUuid:"data-entity-uuid",drupalEntityViewMode:"data-view-mode",drupalEntityEmbedButton:"data-embed-button",drupalEntityEmbedDisplay:"data-entity-embed-display",drupalEntityEmbedDisplaySettings:"data-entity-embed-display-settings"};const t=this.editor.config.get("entityEmbed");if(!t)throw new Error("Error on initializing entityEmbed plugin: entityEmbed config is required.");this.options=t,this.labelError=Drupal.t("Preview failed"),this.previewError=`\n

${Drupal.t("An error occurred while trying to preview the embedded content. Please save your work and reload this page.")}

\n `,this._defineSchema(),this._defineConverters(),this.editor.commands.add("insertEntityEmbed",new n(this.editor))}_defineSchema(){this.editor.model.schema.register("drupalEntity",{isObject:!0,isContent:!0,isBlock:!0,allowWhere:"$block",allowAttributes:Object.keys(this.attrs)}),this.editor.editing.view.domConverter.blockElements.push("drupal-entity")}_defineConverters(){const{conversion:t}=this.editor,i={model:"drupalEntity",view:{name:"drupal-entity"}};t.for("upcast").elementToElement(i),t.for("dataDowncast").elementToElement(i),t.for("editingDowncast").elementToElement({...i,view:(t,{writer:i})=>{const r=t.hasAttribute("dataAlign")?` align-${t.getAttribute("dataAlign")}`:"",n=i.createContainerElement("figure",{class:`drupal-entity${r}`});return i.setCustomProperty("drupalEntity",!0,n),(0,e.toWidget)(n,i,{label:Drupal.t("Entity Embed widget")})}}).add((t=>(t.on("attribute:drupalEntityEntityUuid:drupalEntity",((t,e,i)=>{const r=i.writer,n=e.item,o=i.mapper.toViewElement(e.item);let a=this._getPreviewContainer(o.getChildren());if(a){if("ready"!==a.getAttribute("data-drupal-entity-preview"))return;r.setAttribute("data-drupal-entity-preview","loading",a)}else a=r.createRawElement("div",{"data-drupal-entity-preview":"loading"}),r.insert(r.createPositionAt(o,0),a);this._loadPreview(n).then((({label:t,preview:e})=>{a&&this.editor.editing.view.change((i=>{const r=i.createRawElement("div",{"data-drupal-entity-preview":"ready","aria-label":t},(t=>{t.innerHTML=e}));i.insert(i.createPositionBefore(a),r),i.remove(a)}))}))})),t))),Object.keys(this.attrs).forEach((e=>{const i={model:{key:e,name:"drupalEntity"},view:{name:"drupal-entity",key:this.attrs[e]}};t.for("dataDowncast").attributeToAttribute(i),t.for("upcast").attributeToAttribute(i)}))}async _loadPreview(t){const e={text:this._renderElement(t)},i=await fetch(Drupal.url("embed/preview/"+this.options.format+"?"+new URLSearchParams(e)),{headers:{"X-Drupal-EmbedPreview-CSRF-Token":this.options.previewCsrfToken}});if(i.ok){return{label:Drupal.t("Entity Embed widget"),preview:await i.text()}}return{label:this.labelError,preview:this.previewError}}_renderElement(t){const e=this.editor.model.change((e=>{const i=e.createDocumentFragment(),r=e.cloneElement(t,!1);return["linkHref","dataAlign"].forEach((t=>{e.removeAttribute(t,r)})),e.append(r,i),i}));return this.editor.data.stringify(e)}_getPreviewContainer(t){for(const e of t){if(e.hasAttribute("data-drupal-entity-preview"))return e;if(e.childCount){const t=this._getPreviewContainer(e.getChildren());if(t)return t}}return null}static get pluginName(){return"EntityEmbedEditing"}}var a=i("ckeditor5/src/ui.js");class s extends t.Plugin{static get requires(){return[e.WidgetToolbarRepository]}init(){const e=this.editor,i=e.plugins.get("EntityEmbedEditing"),r=e.config.get("entityEmbed"),{dialogSettings:n={}}=r;e.ui.componentFactory.add("entityEmbedEdit",(o=>{let s=new a.ButtonView(o);return s.set({label:e.t("Edit"),icon:t.icons.pencil,tooltip:!0}),this.listenTo(s,"execute",(t=>{const o=e.model.document.selection.getSelectedElement(),a=Drupal.url("entity-embed/dialog/"+r.format+"/"+o.getAttribute("drupalEntityEmbedButton"));let s={};for(let[t,e]of o.getAttributes()){let r=i.attrs[t];r&&(s[r]=e)}this._openDialog(a,s,(({attributes:t})=>{e.execute("insertEntityEmbed",t),e.editing.view.focus()}),n)})),s})),e.ui.componentFactory.add("editEmbeddedEntity",(i=>{const r=new a.ButtonView(i),n=e.model.document.selection.getSelectedElement();n.hasAttribute("drupalEntityEntityUuid")||console.warn(Drupal.t("Unable to create edit link. There must be a value for data-entity-uuid.")),n.hasAttribute("drupalEntityEntityType")||console.warn(Drupal.t("Unable to create edit link. There must be a value for data-entity-type."));const o=n.getAttribute("drupalEntityEntityUuid"),s=n.getAttribute("drupalEntityEntityType"),l=Drupal.url(`entity-embed/edit-embedded/${s}/${o}`);return r.set({isEnabled:!0,label:Drupal.t("Edit the embedded entity (opens in new tab)"),icon:t.icons.cog,tooltip:!0}),fetch(l).then((t=>{t.ok||r.set({label:Drupal.t(`You do not have the permissions needed to edit this ${s}.`),isEnabled:!1})})),this.listenTo(r,"execute",(()=>{window.open(l,"_blank")})),r}))}afterInit(){const{editor:t}=this;if(!t.plugins.has("WidgetToolbarRepository"))return;t.plugins.get(e.WidgetToolbarRepository).register("entityEmbed",{ariaLabel:Drupal.t("Entity Embed toolbar"),items:["entityEmbedEdit","entityEmbedLink","editEmbeddedEntity"],getRelatedElement(t){const i=t.getSelectedElement();return i&&(0,e.isWidget)(i)&&i.getCustomProperty("drupalEntity")?i:null}})}_openDialog(t,e,i,r){const n=r.dialogClass?r.dialogClass.split(" "):[];n.push("ui-dialog--narrow"),r.dialogClass=n.join(" "),r.autoResize=window.matchMedia("(min-width: 600px)").matches,r.width="auto";Drupal.ajax({dialog:r,dialogType:"modal",selector:".ckeditor5-dialog-loading-link",url:t,progress:{type:"fullscreen"},submit:{editor_object:e}}).execute(),Drupal.ckeditor5.saveCallback=i}static get pluginName(){return"EntityEmbedToolbar"}}class l extends t.Plugin{static get requires(){return["Widget"]}init(){const t=this.editor,e=t.commands.get("insertEntityEmbed"),i=t.config.get("entityEmbed");if(!i)return;const{dialogSettings:r={}}=i,n=i.buttons;Object.keys(n).forEach((o=>{const s=Drupal.url("entity-embed/dialog/"+i.format+"/"+o);t.ui.componentFactory.add(o,(i=>{const l=n[o],d=new a.ButtonView(i);let u=null;if(l.icon.endsWith("svg")){let t=new XMLHttpRequest;t.open("GET",l.icon,!1),t.send(null),u=t.response}else console.warn(`CKEditor 5 only supports enity embed icons in SVG format. The icon provided is ${l.icon}`);return d.set({label:l.label,icon:u??'\n\n \n\n',tooltip:!0}),d.bind("isOn","isEnabled").to(e,"value","isEnabled"),this.listenTo(d,"execute",(()=>Drupal.ckeditor5.openDialog(s,(({attributes:e})=>{t.execute("insertEntityEmbed",e)}),r))),d}))}))}static get pluginName(){return"EntityEmbedUI"}}function d(t,e,i){if(e.attributes)for(const[r,n]of Object.entries(e.attributes))t.setAttribute(r,n,i);e.styles&&t.setStyle(e.styles,i),e.classes&&t.addClass(e.classes,i)}function u(t,e,i){if(!i.consumable.consume(e.item,t.name))return;const r=i.mapper.toViewElement(e.item);d(i.writer,e.attributeNewValue,r)}class c extends t.Plugin{constructor(t){if(super(t),!t.plugins.has("GeneralHtmlSupport"))return;t.plugins.has("DataFilter")&&t.plugins.has("DataSchema")||console.error("DataFilter and DataSchema plugins are required for Entity Embed to integrate with General HTML Support plugin.");const{schema:e}=t.model,{conversion:i}=t,r=this.editor.plugins.get("DataFilter");this.editor.plugins.get("DataSchema").registerBlockElement({model:"drupalEntity",view:"drupal-entity"}),r.on("register:drupal-entity",((t,n)=>{"drupalEntity"===n.model&&(e.extend("drupalEntity",{allowAttributes:["htmlLinkAttributes","htmlAttributes"]}),i.for("upcast").add(function(t){return e=>{e.on("element:drupal-entity",((e,i,r)=>{function n(e,n){const o=t.processViewAttributes(e,r);o&&r.writer.setAttribute(n,o,i.modelRange)}const o=i.viewItem,a=o.parent;n(o,"htmlAttributes"),a.is("element","a")&&n(a,"htmlLinkAttributes")}),{priority:"low"})}}(r)),i.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item),n=function(t,e,i){const r=t.createRangeOn(e);for(const{item:t}of r.getWalker())if(t.is("element",i))return t}(i.writer,r,"a");d(i.writer,e.item.getAttribute("htmlLinkAttributes"),n)}),{priority:"low"})})),i.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item).parent;d(i.writer,e.item.getAttribute("htmlLinkAttributes"),r)}),{priority:"low"}),t.on("attribute:htmlAttributes:drupalEntity",u,{priority:"low"})})),t.stop())}))}static get pluginName(){return"EntityEmbedGeneralHtmlSupport"}}var m=i("ckeditor5/src/engine.js"),p=i("ckeditor5/src/utils.js");function g(t){return Array.from(t.getChildren()).find((t=>"drupal-entity"===t.name))}function E(t){return e=>{e.on(`attribute:${t.id}:drupalEntity`,((e,i,r)=>{const n=r.mapper.toViewElement(i.item);let o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o=!o&&n.is("element","a")?n:Array.from(n.getAncestors()).find((t=>"a"===t.name)),o){for(const[e,i]of(0,p.toMap)(t.attributes))r.writer.setAttribute(e,i,o);t.classes&&r.writer.addClass(t.classes,o);for(const e in t.styles)Object.prototype.hasOwnProperty.call(t.styles,e)&&r.writer.setStyle(e,t.styles[e],o)}}))}}function b(t,e){return t=>{t.on("element:a",((t,i,r)=>{const n=i.viewItem;if(!g(n))return;const o=new m.Matcher(e._createPattern()).match(n);if(!o)return;if(!r.consumable.consume(n,o.match))return;const a=i.modelCursor.nodeBefore;r.writer.setAttribute(e.id,!0,a)}),{priority:"high"})}}class y extends t.Plugin{static get requires(){return["EntityEmbedEditing"]}static get pluginName(){return"EntityEmbedLinkEditing"}init(){const{editor:t}=this;t.model.schema.extend("drupalEntity",{allowAttributes:["linkHref"]}),t.conversion.for("upcast").add((t=>{t.on("element:a",((t,e,i)=>{const r=e.viewItem,n=g(r);if(!n)return;if(!i.consumable.consume(r,{attributes:["href"],name:!0}))return;const o=r.getAttribute("href");if(!o)return;const a=i.convertItem(n,e.modelCursor);e.modelRange=a.modelRange,e.modelCursor=a.modelCursor;const s=e.modelCursor.nodeBefore;s&&s.is("element","drupalEntity")&&i.writer.setAttribute("linkHref",o,s)}),{priority:"high"})})),t.conversion.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o)e.attributeNewValue?r.setAttribute("href",e.attributeNewValue,o):(r.move(r.createRangeIn(o),r.createPositionAt(n,0)),r.remove(o));else{const t=Array.from(n.getChildren()).find((t=>t.getAttribute("data-drupal-entity-preview"))),i=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionAt(n,0),i),r.move(r.createRangeOn(t),r.createPositionAt(i,0))}}),{priority:"high"})})),t.conversion.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionBefore(n),o),r.move(r.createRangeOn(n),r.createPositionAt(o,0))}),{priority:"high"})})),this._enableManualDecorators();if(t.commands.get("link").automaticDecorators.length>0)throw new Error("The Drupal Entity plugin is not compatible with automatic link decorators. To use Drupal Entity, disable any plugins providing automatic link decorators.")}_enableManualDecorators(){const t=this.editor,e=t.commands.get("link");for(const i of e.manualDecorators)t.model.schema.extend("drupalEntity",{allowAttributes:i.id}),t.conversion.for("downcast").add(E(i)),t.conversion.for("upcast").add(b(0,i))}}class h extends t.Plugin{static get requires(){return["LinkEditing","LinkUI","EntityEmbedEditing","EntityEmbedUI"]}static get pluginName(){return"EntityEmbedLinkUi"}init(){const{editor:t}=this,e=t.editing.view.document;this.listenTo(e,"click",((e,i)=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)&&(i.preventDefault(),e.stop())}),{priority:"high"}),this._createToolbarLinkEntityEmbedButton()}_createToolbarLinkEntityEmbedButton(){const{editor:t}=this;t.ui.componentFactory.add("entityEmbedLink",(e=>{const i=new a.ButtonView(e),r=t.plugins.get("LinkUI"),n=t.commands.get("link");return i.set({isEnabled:!0,label:Drupal.t("Link entity embed"),icon:'',keystroke:"Ctrl+K",tooltip:!0,isToggleable:!0}),i.bind("isEnabled").to(n,"isEnabled"),i.bind("isOn").to(n,"value",(t=>!!t)),this.listenTo(i,"execute",(()=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)?r._addActionsView():r._showUI(!0)})),i}))}_isSelectedLinkedEntityEmbed(t){const e=t.getSelectedElement();return!!e&&e.is("element","drupalEntity")&&e.hasAttribute("linkHref")}}class w extends t.Plugin{static get requires(){return[y,h]}static get pluginName(){return"EntityEmbedLink"}}class f extends t.Plugin{static get requires(){return[o,l,s,c,w]}static get pluginName(){return"EntityEmbed"}}const A={EntityEmbed:f}})(),r=r.default})())); -\ No newline at end of file -diff --git a/js/ckeditor5_plugins/drupalentity/src/toolbar.js b/js/ckeditor5_plugins/drupalentity/src/toolbar.js -index 1541fcc..1413b57 100644 ---- a/js/ckeditor5_plugins/drupalentity/src/toolbar.js -+++ b/js/ckeditor5_plugins/drupalentity/src/toolbar.js -@@ -60,6 +60,12 @@ export default class EntityEmbedToolbar extends Plugin { - editor.ui.componentFactory.add('editEmbeddedEntity', (locale) => { - const button = new ButtonView(locale); - const element = editor.model.document.selection.getSelectedElement(); -+ if (!element.hasAttribute('drupalEntityEntityUuid')) { -+ console.warn(Drupal.t('Unable to create edit link. There must be a value for data-entity-uuid.')) -+ } -+ if (!element.hasAttribute('drupalEntityEntityType')) { -+ console.warn(Drupal.t('Unable to create edit link. There must be a value for data-entity-type.')) -+ } - const uuid = element.getAttribute('drupalEntityEntityUuid'); - const type = element.getAttribute('drupalEntityEntityType'); - const editUrl = Drupal.url(`entity-embed/edit-embedded/${type}/${uuid}`) --- -GitLab - - -From fa9277e5cfaa41fff56944f58d0ef7686c5963af Mon Sep 17 00:00:00 2001 -From: bnjmnm -Date: Tue, 24 Oct 2023 15:37:11 -0400 -Subject: [PATCH 2/3] return early if no selected element - ---- - js/build/drupalentity.js | 2 +- - js/ckeditor5_plugins/drupalentity/src/toolbar.js | 3 +++ - 2 files changed, 4 insertions(+), 1 deletion(-) - -diff --git a/js/build/drupalentity.js b/js/build/drupalentity.js -index 37bdb23..52a33de 100644 ---- a/js/build/drupalentity.js -+++ b/js/build/drupalentity.js -@@ -1 +1 @@ --!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.CKEditor5=e():(t.CKEditor5=t.CKEditor5||{},t.CKEditor5.drupalentity=e())}(self,(()=>(()=>{var t={"ckeditor5/src/core.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/core.js")},"ckeditor5/src/engine.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/engine.js")},"ckeditor5/src/ui.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/ui.js")},"ckeditor5/src/utils.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/utils.js")},"ckeditor5/src/widget.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/widget.js")},"dll-reference CKEditor5.dll":t=>{"use strict";t.exports=CKEditor5.dll}},e={};function i(r){var n=e[r];if(void 0!==n)return n.exports;var o=e[r]={exports:{}};return t[r](o,o.exports,i),o.exports}i.d=(t,e)=>{for(var r in e)i.o(e,r)&&!i.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:e[r]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e);var r={};return(()=>{"use strict";i.d(r,{default:()=>A});var t=i("ckeditor5/src/core.js"),e=i("ckeditor5/src/widget.js");class n extends t.Command{execute(t){const{model:e}=this.editor,i=this.editor.plugins.get("EntityEmbedEditing"),r=Object.fromEntries(Object.entries(i.attrs).map((([t,e])=>[e,t]))),n=Object.fromEntries(Object.keys(r).filter((e=>t[e])).map((e=>[r[e],t[e]])));e.change((t=>{e.insertContent(function(t,e){return t.createElement("drupalEntity",e)}(t,n))}))}refresh(){const t=this.editor.model,e=t.document.selection,i=t.schema.findAllowedParent(e.getFirstPosition(),"drupalEntity");this.isEnabled=null!==i}}class o extends t.Plugin{static get requires(){return[e.Widget]}init(){this.attrs={alt:"alt",title:"title",dataCaption:"data-caption",dataAlign:"data-align",drupalEntityLangCode:"data-langcode",drupalEntityEntityType:"data-entity-type",drupalEntityEntityUuid:"data-entity-uuid",drupalEntityViewMode:"data-view-mode",drupalEntityEmbedButton:"data-embed-button",drupalEntityEmbedDisplay:"data-entity-embed-display",drupalEntityEmbedDisplaySettings:"data-entity-embed-display-settings"};const t=this.editor.config.get("entityEmbed");if(!t)throw new Error("Error on initializing entityEmbed plugin: entityEmbed config is required.");this.options=t,this.labelError=Drupal.t("Preview failed"),this.previewError=`\n

${Drupal.t("An error occurred while trying to preview the embedded content. Please save your work and reload this page.")}

\n `,this._defineSchema(),this._defineConverters(),this.editor.commands.add("insertEntityEmbed",new n(this.editor))}_defineSchema(){this.editor.model.schema.register("drupalEntity",{isObject:!0,isContent:!0,isBlock:!0,allowWhere:"$block",allowAttributes:Object.keys(this.attrs)}),this.editor.editing.view.domConverter.blockElements.push("drupal-entity")}_defineConverters(){const{conversion:t}=this.editor,i={model:"drupalEntity",view:{name:"drupal-entity"}};t.for("upcast").elementToElement(i),t.for("dataDowncast").elementToElement(i),t.for("editingDowncast").elementToElement({...i,view:(t,{writer:i})=>{const r=t.hasAttribute("dataAlign")?` align-${t.getAttribute("dataAlign")}`:"",n=i.createContainerElement("figure",{class:`drupal-entity${r}`});return i.setCustomProperty("drupalEntity",!0,n),(0,e.toWidget)(n,i,{label:Drupal.t("Entity Embed widget")})}}).add((t=>(t.on("attribute:drupalEntityEntityUuid:drupalEntity",((t,e,i)=>{const r=i.writer,n=e.item,o=i.mapper.toViewElement(e.item);let a=this._getPreviewContainer(o.getChildren());if(a){if("ready"!==a.getAttribute("data-drupal-entity-preview"))return;r.setAttribute("data-drupal-entity-preview","loading",a)}else a=r.createRawElement("div",{"data-drupal-entity-preview":"loading"}),r.insert(r.createPositionAt(o,0),a);this._loadPreview(n).then((({label:t,preview:e})=>{a&&this.editor.editing.view.change((i=>{const r=i.createRawElement("div",{"data-drupal-entity-preview":"ready","aria-label":t},(t=>{t.innerHTML=e}));i.insert(i.createPositionBefore(a),r),i.remove(a)}))}))})),t))),Object.keys(this.attrs).forEach((e=>{const i={model:{key:e,name:"drupalEntity"},view:{name:"drupal-entity",key:this.attrs[e]}};t.for("dataDowncast").attributeToAttribute(i),t.for("upcast").attributeToAttribute(i)}))}async _loadPreview(t){const e={text:this._renderElement(t)},i=await fetch(Drupal.url("embed/preview/"+this.options.format+"?"+new URLSearchParams(e)),{headers:{"X-Drupal-EmbedPreview-CSRF-Token":this.options.previewCsrfToken}});if(i.ok){return{label:Drupal.t("Entity Embed widget"),preview:await i.text()}}return{label:this.labelError,preview:this.previewError}}_renderElement(t){const e=this.editor.model.change((e=>{const i=e.createDocumentFragment(),r=e.cloneElement(t,!1);return["linkHref","dataAlign"].forEach((t=>{e.removeAttribute(t,r)})),e.append(r,i),i}));return this.editor.data.stringify(e)}_getPreviewContainer(t){for(const e of t){if(e.hasAttribute("data-drupal-entity-preview"))return e;if(e.childCount){const t=this._getPreviewContainer(e.getChildren());if(t)return t}}return null}static get pluginName(){return"EntityEmbedEditing"}}var a=i("ckeditor5/src/ui.js");class s extends t.Plugin{static get requires(){return[e.WidgetToolbarRepository]}init(){const e=this.editor,i=e.plugins.get("EntityEmbedEditing"),r=e.config.get("entityEmbed"),{dialogSettings:n={}}=r;e.ui.componentFactory.add("entityEmbedEdit",(o=>{let s=new a.ButtonView(o);return s.set({label:e.t("Edit"),icon:t.icons.pencil,tooltip:!0}),this.listenTo(s,"execute",(t=>{const o=e.model.document.selection.getSelectedElement(),a=Drupal.url("entity-embed/dialog/"+r.format+"/"+o.getAttribute("drupalEntityEmbedButton"));let s={};for(let[t,e]of o.getAttributes()){let r=i.attrs[t];r&&(s[r]=e)}this._openDialog(a,s,(({attributes:t})=>{e.execute("insertEntityEmbed",t),e.editing.view.focus()}),n)})),s})),e.ui.componentFactory.add("editEmbeddedEntity",(i=>{const r=new a.ButtonView(i),n=e.model.document.selection.getSelectedElement();n.hasAttribute("drupalEntityEntityUuid")||console.warn(Drupal.t("Unable to create edit link. There must be a value for data-entity-uuid.")),n.hasAttribute("drupalEntityEntityType")||console.warn(Drupal.t("Unable to create edit link. There must be a value for data-entity-type."));const o=n.getAttribute("drupalEntityEntityUuid"),s=n.getAttribute("drupalEntityEntityType"),l=Drupal.url(`entity-embed/edit-embedded/${s}/${o}`);return r.set({isEnabled:!0,label:Drupal.t("Edit the embedded entity (opens in new tab)"),icon:t.icons.cog,tooltip:!0}),fetch(l).then((t=>{t.ok||r.set({label:Drupal.t(`You do not have the permissions needed to edit this ${s}.`),isEnabled:!1})})),this.listenTo(r,"execute",(()=>{window.open(l,"_blank")})),r}))}afterInit(){const{editor:t}=this;if(!t.plugins.has("WidgetToolbarRepository"))return;t.plugins.get(e.WidgetToolbarRepository).register("entityEmbed",{ariaLabel:Drupal.t("Entity Embed toolbar"),items:["entityEmbedEdit","entityEmbedLink","editEmbeddedEntity"],getRelatedElement(t){const i=t.getSelectedElement();return i&&(0,e.isWidget)(i)&&i.getCustomProperty("drupalEntity")?i:null}})}_openDialog(t,e,i,r){const n=r.dialogClass?r.dialogClass.split(" "):[];n.push("ui-dialog--narrow"),r.dialogClass=n.join(" "),r.autoResize=window.matchMedia("(min-width: 600px)").matches,r.width="auto";Drupal.ajax({dialog:r,dialogType:"modal",selector:".ckeditor5-dialog-loading-link",url:t,progress:{type:"fullscreen"},submit:{editor_object:e}}).execute(),Drupal.ckeditor5.saveCallback=i}static get pluginName(){return"EntityEmbedToolbar"}}class l extends t.Plugin{static get requires(){return["Widget"]}init(){const t=this.editor,e=t.commands.get("insertEntityEmbed"),i=t.config.get("entityEmbed");if(!i)return;const{dialogSettings:r={}}=i,n=i.buttons;Object.keys(n).forEach((o=>{const s=Drupal.url("entity-embed/dialog/"+i.format+"/"+o);t.ui.componentFactory.add(o,(i=>{const l=n[o],d=new a.ButtonView(i);let u=null;if(l.icon.endsWith("svg")){let t=new XMLHttpRequest;t.open("GET",l.icon,!1),t.send(null),u=t.response}else console.warn(`CKEditor 5 only supports enity embed icons in SVG format. The icon provided is ${l.icon}`);return d.set({label:l.label,icon:u??'\n\n \n\n',tooltip:!0}),d.bind("isOn","isEnabled").to(e,"value","isEnabled"),this.listenTo(d,"execute",(()=>Drupal.ckeditor5.openDialog(s,(({attributes:e})=>{t.execute("insertEntityEmbed",e)}),r))),d}))}))}static get pluginName(){return"EntityEmbedUI"}}function d(t,e,i){if(e.attributes)for(const[r,n]of Object.entries(e.attributes))t.setAttribute(r,n,i);e.styles&&t.setStyle(e.styles,i),e.classes&&t.addClass(e.classes,i)}function u(t,e,i){if(!i.consumable.consume(e.item,t.name))return;const r=i.mapper.toViewElement(e.item);d(i.writer,e.attributeNewValue,r)}class c extends t.Plugin{constructor(t){if(super(t),!t.plugins.has("GeneralHtmlSupport"))return;t.plugins.has("DataFilter")&&t.plugins.has("DataSchema")||console.error("DataFilter and DataSchema plugins are required for Entity Embed to integrate with General HTML Support plugin.");const{schema:e}=t.model,{conversion:i}=t,r=this.editor.plugins.get("DataFilter");this.editor.plugins.get("DataSchema").registerBlockElement({model:"drupalEntity",view:"drupal-entity"}),r.on("register:drupal-entity",((t,n)=>{"drupalEntity"===n.model&&(e.extend("drupalEntity",{allowAttributes:["htmlLinkAttributes","htmlAttributes"]}),i.for("upcast").add(function(t){return e=>{e.on("element:drupal-entity",((e,i,r)=>{function n(e,n){const o=t.processViewAttributes(e,r);o&&r.writer.setAttribute(n,o,i.modelRange)}const o=i.viewItem,a=o.parent;n(o,"htmlAttributes"),a.is("element","a")&&n(a,"htmlLinkAttributes")}),{priority:"low"})}}(r)),i.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item),n=function(t,e,i){const r=t.createRangeOn(e);for(const{item:t}of r.getWalker())if(t.is("element",i))return t}(i.writer,r,"a");d(i.writer,e.item.getAttribute("htmlLinkAttributes"),n)}),{priority:"low"})})),i.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item).parent;d(i.writer,e.item.getAttribute("htmlLinkAttributes"),r)}),{priority:"low"}),t.on("attribute:htmlAttributes:drupalEntity",u,{priority:"low"})})),t.stop())}))}static get pluginName(){return"EntityEmbedGeneralHtmlSupport"}}var m=i("ckeditor5/src/engine.js"),p=i("ckeditor5/src/utils.js");function g(t){return Array.from(t.getChildren()).find((t=>"drupal-entity"===t.name))}function E(t){return e=>{e.on(`attribute:${t.id}:drupalEntity`,((e,i,r)=>{const n=r.mapper.toViewElement(i.item);let o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o=!o&&n.is("element","a")?n:Array.from(n.getAncestors()).find((t=>"a"===t.name)),o){for(const[e,i]of(0,p.toMap)(t.attributes))r.writer.setAttribute(e,i,o);t.classes&&r.writer.addClass(t.classes,o);for(const e in t.styles)Object.prototype.hasOwnProperty.call(t.styles,e)&&r.writer.setStyle(e,t.styles[e],o)}}))}}function b(t,e){return t=>{t.on("element:a",((t,i,r)=>{const n=i.viewItem;if(!g(n))return;const o=new m.Matcher(e._createPattern()).match(n);if(!o)return;if(!r.consumable.consume(n,o.match))return;const a=i.modelCursor.nodeBefore;r.writer.setAttribute(e.id,!0,a)}),{priority:"high"})}}class y extends t.Plugin{static get requires(){return["EntityEmbedEditing"]}static get pluginName(){return"EntityEmbedLinkEditing"}init(){const{editor:t}=this;t.model.schema.extend("drupalEntity",{allowAttributes:["linkHref"]}),t.conversion.for("upcast").add((t=>{t.on("element:a",((t,e,i)=>{const r=e.viewItem,n=g(r);if(!n)return;if(!i.consumable.consume(r,{attributes:["href"],name:!0}))return;const o=r.getAttribute("href");if(!o)return;const a=i.convertItem(n,e.modelCursor);e.modelRange=a.modelRange,e.modelCursor=a.modelCursor;const s=e.modelCursor.nodeBefore;s&&s.is("element","drupalEntity")&&i.writer.setAttribute("linkHref",o,s)}),{priority:"high"})})),t.conversion.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o)e.attributeNewValue?r.setAttribute("href",e.attributeNewValue,o):(r.move(r.createRangeIn(o),r.createPositionAt(n,0)),r.remove(o));else{const t=Array.from(n.getChildren()).find((t=>t.getAttribute("data-drupal-entity-preview"))),i=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionAt(n,0),i),r.move(r.createRangeOn(t),r.createPositionAt(i,0))}}),{priority:"high"})})),t.conversion.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionBefore(n),o),r.move(r.createRangeOn(n),r.createPositionAt(o,0))}),{priority:"high"})})),this._enableManualDecorators();if(t.commands.get("link").automaticDecorators.length>0)throw new Error("The Drupal Entity plugin is not compatible with automatic link decorators. To use Drupal Entity, disable any plugins providing automatic link decorators.")}_enableManualDecorators(){const t=this.editor,e=t.commands.get("link");for(const i of e.manualDecorators)t.model.schema.extend("drupalEntity",{allowAttributes:i.id}),t.conversion.for("downcast").add(E(i)),t.conversion.for("upcast").add(b(0,i))}}class h extends t.Plugin{static get requires(){return["LinkEditing","LinkUI","EntityEmbedEditing","EntityEmbedUI"]}static get pluginName(){return"EntityEmbedLinkUi"}init(){const{editor:t}=this,e=t.editing.view.document;this.listenTo(e,"click",((e,i)=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)&&(i.preventDefault(),e.stop())}),{priority:"high"}),this._createToolbarLinkEntityEmbedButton()}_createToolbarLinkEntityEmbedButton(){const{editor:t}=this;t.ui.componentFactory.add("entityEmbedLink",(e=>{const i=new a.ButtonView(e),r=t.plugins.get("LinkUI"),n=t.commands.get("link");return i.set({isEnabled:!0,label:Drupal.t("Link entity embed"),icon:'',keystroke:"Ctrl+K",tooltip:!0,isToggleable:!0}),i.bind("isEnabled").to(n,"isEnabled"),i.bind("isOn").to(n,"value",(t=>!!t)),this.listenTo(i,"execute",(()=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)?r._addActionsView():r._showUI(!0)})),i}))}_isSelectedLinkedEntityEmbed(t){const e=t.getSelectedElement();return!!e&&e.is("element","drupalEntity")&&e.hasAttribute("linkHref")}}class w extends t.Plugin{static get requires(){return[y,h]}static get pluginName(){return"EntityEmbedLink"}}class f extends t.Plugin{static get requires(){return[o,l,s,c,w]}static get pluginName(){return"EntityEmbed"}}const A={EntityEmbed:f}})(),r=r.default})())); -\ No newline at end of file -+!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.CKEditor5=e():(t.CKEditor5=t.CKEditor5||{},t.CKEditor5.drupalentity=e())}(self,(()=>(()=>{var t={"ckeditor5/src/core.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/core.js")},"ckeditor5/src/engine.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/engine.js")},"ckeditor5/src/ui.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/ui.js")},"ckeditor5/src/utils.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/utils.js")},"ckeditor5/src/widget.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/widget.js")},"dll-reference CKEditor5.dll":t=>{"use strict";t.exports=CKEditor5.dll}},e={};function i(r){var n=e[r];if(void 0!==n)return n.exports;var o=e[r]={exports:{}};return t[r](o,o.exports,i),o.exports}i.d=(t,e)=>{for(var r in e)i.o(e,r)&&!i.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:e[r]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e);var r={};return(()=>{"use strict";i.d(r,{default:()=>A});var t=i("ckeditor5/src/core.js"),e=i("ckeditor5/src/widget.js");class n extends t.Command{execute(t){const{model:e}=this.editor,i=this.editor.plugins.get("EntityEmbedEditing"),r=Object.fromEntries(Object.entries(i.attrs).map((([t,e])=>[e,t]))),n=Object.fromEntries(Object.keys(r).filter((e=>t[e])).map((e=>[r[e],t[e]])));e.change((t=>{e.insertContent(function(t,e){return t.createElement("drupalEntity",e)}(t,n))}))}refresh(){const t=this.editor.model,e=t.document.selection,i=t.schema.findAllowedParent(e.getFirstPosition(),"drupalEntity");this.isEnabled=null!==i}}class o extends t.Plugin{static get requires(){return[e.Widget]}init(){this.attrs={alt:"alt",title:"title",dataCaption:"data-caption",dataAlign:"data-align",drupalEntityLangCode:"data-langcode",drupalEntityEntityType:"data-entity-type",drupalEntityEntityUuid:"data-entity-uuid",drupalEntityViewMode:"data-view-mode",drupalEntityEmbedButton:"data-embed-button",drupalEntityEmbedDisplay:"data-entity-embed-display",drupalEntityEmbedDisplaySettings:"data-entity-embed-display-settings"};const t=this.editor.config.get("entityEmbed");if(!t)throw new Error("Error on initializing entityEmbed plugin: entityEmbed config is required.");this.options=t,this.labelError=Drupal.t("Preview failed"),this.previewError=`\n

${Drupal.t("An error occurred while trying to preview the embedded content. Please save your work and reload this page.")}

\n `,this._defineSchema(),this._defineConverters(),this.editor.commands.add("insertEntityEmbed",new n(this.editor))}_defineSchema(){this.editor.model.schema.register("drupalEntity",{isObject:!0,isContent:!0,isBlock:!0,allowWhere:"$block",allowAttributes:Object.keys(this.attrs)}),this.editor.editing.view.domConverter.blockElements.push("drupal-entity")}_defineConverters(){const{conversion:t}=this.editor,i={model:"drupalEntity",view:{name:"drupal-entity"}};t.for("upcast").elementToElement(i),t.for("dataDowncast").elementToElement(i),t.for("editingDowncast").elementToElement({...i,view:(t,{writer:i})=>{const r=t.hasAttribute("dataAlign")?` align-${t.getAttribute("dataAlign")}`:"",n=i.createContainerElement("figure",{class:`drupal-entity${r}`});return i.setCustomProperty("drupalEntity",!0,n),(0,e.toWidget)(n,i,{label:Drupal.t("Entity Embed widget")})}}).add((t=>(t.on("attribute:drupalEntityEntityUuid:drupalEntity",((t,e,i)=>{const r=i.writer,n=e.item,o=i.mapper.toViewElement(e.item);let a=this._getPreviewContainer(o.getChildren());if(a){if("ready"!==a.getAttribute("data-drupal-entity-preview"))return;r.setAttribute("data-drupal-entity-preview","loading",a)}else a=r.createRawElement("div",{"data-drupal-entity-preview":"loading"}),r.insert(r.createPositionAt(o,0),a);this._loadPreview(n).then((({label:t,preview:e})=>{a&&this.editor.editing.view.change((i=>{const r=i.createRawElement("div",{"data-drupal-entity-preview":"ready","aria-label":t},(t=>{t.innerHTML=e}));i.insert(i.createPositionBefore(a),r),i.remove(a)}))}))})),t))),Object.keys(this.attrs).forEach((e=>{const i={model:{key:e,name:"drupalEntity"},view:{name:"drupal-entity",key:this.attrs[e]}};t.for("dataDowncast").attributeToAttribute(i),t.for("upcast").attributeToAttribute(i)}))}async _loadPreview(t){const e={text:this._renderElement(t)},i=await fetch(Drupal.url("embed/preview/"+this.options.format+"?"+new URLSearchParams(e)),{headers:{"X-Drupal-EmbedPreview-CSRF-Token":this.options.previewCsrfToken}});if(i.ok){return{label:Drupal.t("Entity Embed widget"),preview:await i.text()}}return{label:this.labelError,preview:this.previewError}}_renderElement(t){const e=this.editor.model.change((e=>{const i=e.createDocumentFragment(),r=e.cloneElement(t,!1);return["linkHref","dataAlign"].forEach((t=>{e.removeAttribute(t,r)})),e.append(r,i),i}));return this.editor.data.stringify(e)}_getPreviewContainer(t){for(const e of t){if(e.hasAttribute("data-drupal-entity-preview"))return e;if(e.childCount){const t=this._getPreviewContainer(e.getChildren());if(t)return t}}return null}static get pluginName(){return"EntityEmbedEditing"}}var a=i("ckeditor5/src/ui.js");class s extends t.Plugin{static get requires(){return[e.WidgetToolbarRepository]}init(){const e=this.editor,i=e.plugins.get("EntityEmbedEditing"),r=e.config.get("entityEmbed"),{dialogSettings:n={}}=r;e.ui.componentFactory.add("entityEmbedEdit",(o=>{let s=new a.ButtonView(o);return s.set({label:e.t("Edit"),icon:t.icons.pencil,tooltip:!0}),this.listenTo(s,"execute",(t=>{const o=e.model.document.selection.getSelectedElement(),a=Drupal.url("entity-embed/dialog/"+r.format+"/"+o.getAttribute("drupalEntityEmbedButton"));let s={};for(let[t,e]of o.getAttributes()){let r=i.attrs[t];r&&(s[r]=e)}this._openDialog(a,s,(({attributes:t})=>{e.execute("insertEntityEmbed",t),e.editing.view.focus()}),n)})),s})),e.ui.componentFactory.add("editEmbeddedEntity",(i=>{const r=new a.ButtonView(i),n=e.model.document.selection.getSelectedElement();if(!n)return;n.hasAttribute("drupalEntityEntityUuid")||console.warn(Drupal.t("Unable to create edit link. There must be a value for data-entity-uuid.")),n.hasAttribute("drupalEntityEntityType")||console.warn(Drupal.t("Unable to create edit link. There must be a value for data-entity-type."));const o=n.getAttribute("drupalEntityEntityUuid"),s=n.getAttribute("drupalEntityEntityType"),l=Drupal.url(`entity-embed/edit-embedded/${s}/${o}`);return r.set({isEnabled:!0,label:Drupal.t("Edit the embedded entity (opens in new tab)"),icon:t.icons.cog,tooltip:!0}),fetch(l).then((t=>{t.ok||r.set({label:Drupal.t(`You do not have the permissions needed to edit this ${s}.`),isEnabled:!1})})),this.listenTo(r,"execute",(()=>{window.open(l,"_blank")})),r}))}afterInit(){const{editor:t}=this;if(!t.plugins.has("WidgetToolbarRepository"))return;t.plugins.get(e.WidgetToolbarRepository).register("entityEmbed",{ariaLabel:Drupal.t("Entity Embed toolbar"),items:["entityEmbedEdit","entityEmbedLink","editEmbeddedEntity"],getRelatedElement(t){const i=t.getSelectedElement();return i&&(0,e.isWidget)(i)&&i.getCustomProperty("drupalEntity")?i:null}})}_openDialog(t,e,i,r){const n=r.dialogClass?r.dialogClass.split(" "):[];n.push("ui-dialog--narrow"),r.dialogClass=n.join(" "),r.autoResize=window.matchMedia("(min-width: 600px)").matches,r.width="auto";Drupal.ajax({dialog:r,dialogType:"modal",selector:".ckeditor5-dialog-loading-link",url:t,progress:{type:"fullscreen"},submit:{editor_object:e}}).execute(),Drupal.ckeditor5.saveCallback=i}static get pluginName(){return"EntityEmbedToolbar"}}class l extends t.Plugin{static get requires(){return["Widget"]}init(){const t=this.editor,e=t.commands.get("insertEntityEmbed"),i=t.config.get("entityEmbed");if(!i)return;const{dialogSettings:r={}}=i,n=i.buttons;Object.keys(n).forEach((o=>{const s=Drupal.url("entity-embed/dialog/"+i.format+"/"+o);t.ui.componentFactory.add(o,(i=>{const l=n[o],d=new a.ButtonView(i);let u=null;if(l.icon.endsWith("svg")){let t=new XMLHttpRequest;t.open("GET",l.icon,!1),t.send(null),u=t.response}else console.warn(`CKEditor 5 only supports enity embed icons in SVG format. The icon provided is ${l.icon}`);return d.set({label:l.label,icon:u??'\n\n \n\n',tooltip:!0}),d.bind("isOn","isEnabled").to(e,"value","isEnabled"),this.listenTo(d,"execute",(()=>Drupal.ckeditor5.openDialog(s,(({attributes:e})=>{t.execute("insertEntityEmbed",e)}),r))),d}))}))}static get pluginName(){return"EntityEmbedUI"}}function d(t,e,i){if(e.attributes)for(const[r,n]of Object.entries(e.attributes))t.setAttribute(r,n,i);e.styles&&t.setStyle(e.styles,i),e.classes&&t.addClass(e.classes,i)}function u(t,e,i){if(!i.consumable.consume(e.item,t.name))return;const r=i.mapper.toViewElement(e.item);d(i.writer,e.attributeNewValue,r)}class c extends t.Plugin{constructor(t){if(super(t),!t.plugins.has("GeneralHtmlSupport"))return;t.plugins.has("DataFilter")&&t.plugins.has("DataSchema")||console.error("DataFilter and DataSchema plugins are required for Entity Embed to integrate with General HTML Support plugin.");const{schema:e}=t.model,{conversion:i}=t,r=this.editor.plugins.get("DataFilter");this.editor.plugins.get("DataSchema").registerBlockElement({model:"drupalEntity",view:"drupal-entity"}),r.on("register:drupal-entity",((t,n)=>{"drupalEntity"===n.model&&(e.extend("drupalEntity",{allowAttributes:["htmlLinkAttributes","htmlAttributes"]}),i.for("upcast").add(function(t){return e=>{e.on("element:drupal-entity",((e,i,r)=>{function n(e,n){const o=t.processViewAttributes(e,r);o&&r.writer.setAttribute(n,o,i.modelRange)}const o=i.viewItem,a=o.parent;n(o,"htmlAttributes"),a.is("element","a")&&n(a,"htmlLinkAttributes")}),{priority:"low"})}}(r)),i.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item),n=function(t,e,i){const r=t.createRangeOn(e);for(const{item:t}of r.getWalker())if(t.is("element",i))return t}(i.writer,r,"a");d(i.writer,e.item.getAttribute("htmlLinkAttributes"),n)}),{priority:"low"})})),i.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item).parent;d(i.writer,e.item.getAttribute("htmlLinkAttributes"),r)}),{priority:"low"}),t.on("attribute:htmlAttributes:drupalEntity",u,{priority:"low"})})),t.stop())}))}static get pluginName(){return"EntityEmbedGeneralHtmlSupport"}}var m=i("ckeditor5/src/engine.js"),p=i("ckeditor5/src/utils.js");function g(t){return Array.from(t.getChildren()).find((t=>"drupal-entity"===t.name))}function E(t){return e=>{e.on(`attribute:${t.id}:drupalEntity`,((e,i,r)=>{const n=r.mapper.toViewElement(i.item);let o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o=!o&&n.is("element","a")?n:Array.from(n.getAncestors()).find((t=>"a"===t.name)),o){for(const[e,i]of(0,p.toMap)(t.attributes))r.writer.setAttribute(e,i,o);t.classes&&r.writer.addClass(t.classes,o);for(const e in t.styles)Object.prototype.hasOwnProperty.call(t.styles,e)&&r.writer.setStyle(e,t.styles[e],o)}}))}}function b(t,e){return t=>{t.on("element:a",((t,i,r)=>{const n=i.viewItem;if(!g(n))return;const o=new m.Matcher(e._createPattern()).match(n);if(!o)return;if(!r.consumable.consume(n,o.match))return;const a=i.modelCursor.nodeBefore;r.writer.setAttribute(e.id,!0,a)}),{priority:"high"})}}class y extends t.Plugin{static get requires(){return["EntityEmbedEditing"]}static get pluginName(){return"EntityEmbedLinkEditing"}init(){const{editor:t}=this;t.model.schema.extend("drupalEntity",{allowAttributes:["linkHref"]}),t.conversion.for("upcast").add((t=>{t.on("element:a",((t,e,i)=>{const r=e.viewItem,n=g(r);if(!n)return;if(!i.consumable.consume(r,{attributes:["href"],name:!0}))return;const o=r.getAttribute("href");if(!o)return;const a=i.convertItem(n,e.modelCursor);e.modelRange=a.modelRange,e.modelCursor=a.modelCursor;const s=e.modelCursor.nodeBefore;s&&s.is("element","drupalEntity")&&i.writer.setAttribute("linkHref",o,s)}),{priority:"high"})})),t.conversion.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o)e.attributeNewValue?r.setAttribute("href",e.attributeNewValue,o):(r.move(r.createRangeIn(o),r.createPositionAt(n,0)),r.remove(o));else{const t=Array.from(n.getChildren()).find((t=>t.getAttribute("data-drupal-entity-preview"))),i=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionAt(n,0),i),r.move(r.createRangeOn(t),r.createPositionAt(i,0))}}),{priority:"high"})})),t.conversion.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionBefore(n),o),r.move(r.createRangeOn(n),r.createPositionAt(o,0))}),{priority:"high"})})),this._enableManualDecorators();if(t.commands.get("link").automaticDecorators.length>0)throw new Error("The Drupal Entity plugin is not compatible with automatic link decorators. To use Drupal Entity, disable any plugins providing automatic link decorators.")}_enableManualDecorators(){const t=this.editor,e=t.commands.get("link");for(const i of e.manualDecorators)t.model.schema.extend("drupalEntity",{allowAttributes:i.id}),t.conversion.for("downcast").add(E(i)),t.conversion.for("upcast").add(b(0,i))}}class h extends t.Plugin{static get requires(){return["LinkEditing","LinkUI","EntityEmbedEditing","EntityEmbedUI"]}static get pluginName(){return"EntityEmbedLinkUi"}init(){const{editor:t}=this,e=t.editing.view.document;this.listenTo(e,"click",((e,i)=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)&&(i.preventDefault(),e.stop())}),{priority:"high"}),this._createToolbarLinkEntityEmbedButton()}_createToolbarLinkEntityEmbedButton(){const{editor:t}=this;t.ui.componentFactory.add("entityEmbedLink",(e=>{const i=new a.ButtonView(e),r=t.plugins.get("LinkUI"),n=t.commands.get("link");return i.set({isEnabled:!0,label:Drupal.t("Link entity embed"),icon:'',keystroke:"Ctrl+K",tooltip:!0,isToggleable:!0}),i.bind("isEnabled").to(n,"isEnabled"),i.bind("isOn").to(n,"value",(t=>!!t)),this.listenTo(i,"execute",(()=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)?r._addActionsView():r._showUI(!0)})),i}))}_isSelectedLinkedEntityEmbed(t){const e=t.getSelectedElement();return!!e&&e.is("element","drupalEntity")&&e.hasAttribute("linkHref")}}class w extends t.Plugin{static get requires(){return[y,h]}static get pluginName(){return"EntityEmbedLink"}}class f extends t.Plugin{static get requires(){return[o,l,s,c,w]}static get pluginName(){return"EntityEmbed"}}const A={EntityEmbed:f}})(),r=r.default})())); -\ No newline at end of file -diff --git a/js/ckeditor5_plugins/drupalentity/src/toolbar.js b/js/ckeditor5_plugins/drupalentity/src/toolbar.js -index 1413b57..c8e9673 100644 ---- a/js/ckeditor5_plugins/drupalentity/src/toolbar.js -+++ b/js/ckeditor5_plugins/drupalentity/src/toolbar.js -@@ -60,6 +60,9 @@ export default class EntityEmbedToolbar extends Plugin { - editor.ui.componentFactory.add('editEmbeddedEntity', (locale) => { - const button = new ButtonView(locale); - const element = editor.model.document.selection.getSelectedElement(); -+ if (!element) { -+ return; -+ } - if (!element.hasAttribute('drupalEntityEntityUuid')) { - console.warn(Drupal.t('Unable to create edit link. There must be a value for data-entity-uuid.')) - } --- -GitLab - - -From 1cf7eae7239c19d56f0afb4b98f86aa14085f39a Mon Sep 17 00:00:00 2001 -From: bnjmnm -Date: Tue, 24 Oct 2023 15:38:58 -0400 -Subject: [PATCH 3/3] return null if any essential is unavailable - ---- - js/build/drupalentity.js | 2 +- - js/ckeditor5_plugins/drupalentity/src/toolbar.js | 8 +++++--- - 2 files changed, 6 insertions(+), 4 deletions(-) - -diff --git a/js/build/drupalentity.js b/js/build/drupalentity.js -index 52a33de..273ea45 100644 ---- a/js/build/drupalentity.js -+++ b/js/build/drupalentity.js -@@ -1 +1 @@ --!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.CKEditor5=e():(t.CKEditor5=t.CKEditor5||{},t.CKEditor5.drupalentity=e())}(self,(()=>(()=>{var t={"ckeditor5/src/core.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/core.js")},"ckeditor5/src/engine.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/engine.js")},"ckeditor5/src/ui.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/ui.js")},"ckeditor5/src/utils.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/utils.js")},"ckeditor5/src/widget.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/widget.js")},"dll-reference CKEditor5.dll":t=>{"use strict";t.exports=CKEditor5.dll}},e={};function i(r){var n=e[r];if(void 0!==n)return n.exports;var o=e[r]={exports:{}};return t[r](o,o.exports,i),o.exports}i.d=(t,e)=>{for(var r in e)i.o(e,r)&&!i.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:e[r]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e);var r={};return(()=>{"use strict";i.d(r,{default:()=>A});var t=i("ckeditor5/src/core.js"),e=i("ckeditor5/src/widget.js");class n extends t.Command{execute(t){const{model:e}=this.editor,i=this.editor.plugins.get("EntityEmbedEditing"),r=Object.fromEntries(Object.entries(i.attrs).map((([t,e])=>[e,t]))),n=Object.fromEntries(Object.keys(r).filter((e=>t[e])).map((e=>[r[e],t[e]])));e.change((t=>{e.insertContent(function(t,e){return t.createElement("drupalEntity",e)}(t,n))}))}refresh(){const t=this.editor.model,e=t.document.selection,i=t.schema.findAllowedParent(e.getFirstPosition(),"drupalEntity");this.isEnabled=null!==i}}class o extends t.Plugin{static get requires(){return[e.Widget]}init(){this.attrs={alt:"alt",title:"title",dataCaption:"data-caption",dataAlign:"data-align",drupalEntityLangCode:"data-langcode",drupalEntityEntityType:"data-entity-type",drupalEntityEntityUuid:"data-entity-uuid",drupalEntityViewMode:"data-view-mode",drupalEntityEmbedButton:"data-embed-button",drupalEntityEmbedDisplay:"data-entity-embed-display",drupalEntityEmbedDisplaySettings:"data-entity-embed-display-settings"};const t=this.editor.config.get("entityEmbed");if(!t)throw new Error("Error on initializing entityEmbed plugin: entityEmbed config is required.");this.options=t,this.labelError=Drupal.t("Preview failed"),this.previewError=`\n

${Drupal.t("An error occurred while trying to preview the embedded content. Please save your work and reload this page.")}

\n `,this._defineSchema(),this._defineConverters(),this.editor.commands.add("insertEntityEmbed",new n(this.editor))}_defineSchema(){this.editor.model.schema.register("drupalEntity",{isObject:!0,isContent:!0,isBlock:!0,allowWhere:"$block",allowAttributes:Object.keys(this.attrs)}),this.editor.editing.view.domConverter.blockElements.push("drupal-entity")}_defineConverters(){const{conversion:t}=this.editor,i={model:"drupalEntity",view:{name:"drupal-entity"}};t.for("upcast").elementToElement(i),t.for("dataDowncast").elementToElement(i),t.for("editingDowncast").elementToElement({...i,view:(t,{writer:i})=>{const r=t.hasAttribute("dataAlign")?` align-${t.getAttribute("dataAlign")}`:"",n=i.createContainerElement("figure",{class:`drupal-entity${r}`});return i.setCustomProperty("drupalEntity",!0,n),(0,e.toWidget)(n,i,{label:Drupal.t("Entity Embed widget")})}}).add((t=>(t.on("attribute:drupalEntityEntityUuid:drupalEntity",((t,e,i)=>{const r=i.writer,n=e.item,o=i.mapper.toViewElement(e.item);let a=this._getPreviewContainer(o.getChildren());if(a){if("ready"!==a.getAttribute("data-drupal-entity-preview"))return;r.setAttribute("data-drupal-entity-preview","loading",a)}else a=r.createRawElement("div",{"data-drupal-entity-preview":"loading"}),r.insert(r.createPositionAt(o,0),a);this._loadPreview(n).then((({label:t,preview:e})=>{a&&this.editor.editing.view.change((i=>{const r=i.createRawElement("div",{"data-drupal-entity-preview":"ready","aria-label":t},(t=>{t.innerHTML=e}));i.insert(i.createPositionBefore(a),r),i.remove(a)}))}))})),t))),Object.keys(this.attrs).forEach((e=>{const i={model:{key:e,name:"drupalEntity"},view:{name:"drupal-entity",key:this.attrs[e]}};t.for("dataDowncast").attributeToAttribute(i),t.for("upcast").attributeToAttribute(i)}))}async _loadPreview(t){const e={text:this._renderElement(t)},i=await fetch(Drupal.url("embed/preview/"+this.options.format+"?"+new URLSearchParams(e)),{headers:{"X-Drupal-EmbedPreview-CSRF-Token":this.options.previewCsrfToken}});if(i.ok){return{label:Drupal.t("Entity Embed widget"),preview:await i.text()}}return{label:this.labelError,preview:this.previewError}}_renderElement(t){const e=this.editor.model.change((e=>{const i=e.createDocumentFragment(),r=e.cloneElement(t,!1);return["linkHref","dataAlign"].forEach((t=>{e.removeAttribute(t,r)})),e.append(r,i),i}));return this.editor.data.stringify(e)}_getPreviewContainer(t){for(const e of t){if(e.hasAttribute("data-drupal-entity-preview"))return e;if(e.childCount){const t=this._getPreviewContainer(e.getChildren());if(t)return t}}return null}static get pluginName(){return"EntityEmbedEditing"}}var a=i("ckeditor5/src/ui.js");class s extends t.Plugin{static get requires(){return[e.WidgetToolbarRepository]}init(){const e=this.editor,i=e.plugins.get("EntityEmbedEditing"),r=e.config.get("entityEmbed"),{dialogSettings:n={}}=r;e.ui.componentFactory.add("entityEmbedEdit",(o=>{let s=new a.ButtonView(o);return s.set({label:e.t("Edit"),icon:t.icons.pencil,tooltip:!0}),this.listenTo(s,"execute",(t=>{const o=e.model.document.selection.getSelectedElement(),a=Drupal.url("entity-embed/dialog/"+r.format+"/"+o.getAttribute("drupalEntityEmbedButton"));let s={};for(let[t,e]of o.getAttributes()){let r=i.attrs[t];r&&(s[r]=e)}this._openDialog(a,s,(({attributes:t})=>{e.execute("insertEntityEmbed",t),e.editing.view.focus()}),n)})),s})),e.ui.componentFactory.add("editEmbeddedEntity",(i=>{const r=new a.ButtonView(i),n=e.model.document.selection.getSelectedElement();if(!n)return;n.hasAttribute("drupalEntityEntityUuid")||console.warn(Drupal.t("Unable to create edit link. There must be a value for data-entity-uuid.")),n.hasAttribute("drupalEntityEntityType")||console.warn(Drupal.t("Unable to create edit link. There must be a value for data-entity-type."));const o=n.getAttribute("drupalEntityEntityUuid"),s=n.getAttribute("drupalEntityEntityType"),l=Drupal.url(`entity-embed/edit-embedded/${s}/${o}`);return r.set({isEnabled:!0,label:Drupal.t("Edit the embedded entity (opens in new tab)"),icon:t.icons.cog,tooltip:!0}),fetch(l).then((t=>{t.ok||r.set({label:Drupal.t(`You do not have the permissions needed to edit this ${s}.`),isEnabled:!1})})),this.listenTo(r,"execute",(()=>{window.open(l,"_blank")})),r}))}afterInit(){const{editor:t}=this;if(!t.plugins.has("WidgetToolbarRepository"))return;t.plugins.get(e.WidgetToolbarRepository).register("entityEmbed",{ariaLabel:Drupal.t("Entity Embed toolbar"),items:["entityEmbedEdit","entityEmbedLink","editEmbeddedEntity"],getRelatedElement(t){const i=t.getSelectedElement();return i&&(0,e.isWidget)(i)&&i.getCustomProperty("drupalEntity")?i:null}})}_openDialog(t,e,i,r){const n=r.dialogClass?r.dialogClass.split(" "):[];n.push("ui-dialog--narrow"),r.dialogClass=n.join(" "),r.autoResize=window.matchMedia("(min-width: 600px)").matches,r.width="auto";Drupal.ajax({dialog:r,dialogType:"modal",selector:".ckeditor5-dialog-loading-link",url:t,progress:{type:"fullscreen"},submit:{editor_object:e}}).execute(),Drupal.ckeditor5.saveCallback=i}static get pluginName(){return"EntityEmbedToolbar"}}class l extends t.Plugin{static get requires(){return["Widget"]}init(){const t=this.editor,e=t.commands.get("insertEntityEmbed"),i=t.config.get("entityEmbed");if(!i)return;const{dialogSettings:r={}}=i,n=i.buttons;Object.keys(n).forEach((o=>{const s=Drupal.url("entity-embed/dialog/"+i.format+"/"+o);t.ui.componentFactory.add(o,(i=>{const l=n[o],d=new a.ButtonView(i);let u=null;if(l.icon.endsWith("svg")){let t=new XMLHttpRequest;t.open("GET",l.icon,!1),t.send(null),u=t.response}else console.warn(`CKEditor 5 only supports enity embed icons in SVG format. The icon provided is ${l.icon}`);return d.set({label:l.label,icon:u??'\n\n \n\n',tooltip:!0}),d.bind("isOn","isEnabled").to(e,"value","isEnabled"),this.listenTo(d,"execute",(()=>Drupal.ckeditor5.openDialog(s,(({attributes:e})=>{t.execute("insertEntityEmbed",e)}),r))),d}))}))}static get pluginName(){return"EntityEmbedUI"}}function d(t,e,i){if(e.attributes)for(const[r,n]of Object.entries(e.attributes))t.setAttribute(r,n,i);e.styles&&t.setStyle(e.styles,i),e.classes&&t.addClass(e.classes,i)}function u(t,e,i){if(!i.consumable.consume(e.item,t.name))return;const r=i.mapper.toViewElement(e.item);d(i.writer,e.attributeNewValue,r)}class c extends t.Plugin{constructor(t){if(super(t),!t.plugins.has("GeneralHtmlSupport"))return;t.plugins.has("DataFilter")&&t.plugins.has("DataSchema")||console.error("DataFilter and DataSchema plugins are required for Entity Embed to integrate with General HTML Support plugin.");const{schema:e}=t.model,{conversion:i}=t,r=this.editor.plugins.get("DataFilter");this.editor.plugins.get("DataSchema").registerBlockElement({model:"drupalEntity",view:"drupal-entity"}),r.on("register:drupal-entity",((t,n)=>{"drupalEntity"===n.model&&(e.extend("drupalEntity",{allowAttributes:["htmlLinkAttributes","htmlAttributes"]}),i.for("upcast").add(function(t){return e=>{e.on("element:drupal-entity",((e,i,r)=>{function n(e,n){const o=t.processViewAttributes(e,r);o&&r.writer.setAttribute(n,o,i.modelRange)}const o=i.viewItem,a=o.parent;n(o,"htmlAttributes"),a.is("element","a")&&n(a,"htmlLinkAttributes")}),{priority:"low"})}}(r)),i.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item),n=function(t,e,i){const r=t.createRangeOn(e);for(const{item:t}of r.getWalker())if(t.is("element",i))return t}(i.writer,r,"a");d(i.writer,e.item.getAttribute("htmlLinkAttributes"),n)}),{priority:"low"})})),i.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item).parent;d(i.writer,e.item.getAttribute("htmlLinkAttributes"),r)}),{priority:"low"}),t.on("attribute:htmlAttributes:drupalEntity",u,{priority:"low"})})),t.stop())}))}static get pluginName(){return"EntityEmbedGeneralHtmlSupport"}}var m=i("ckeditor5/src/engine.js"),p=i("ckeditor5/src/utils.js");function g(t){return Array.from(t.getChildren()).find((t=>"drupal-entity"===t.name))}function E(t){return e=>{e.on(`attribute:${t.id}:drupalEntity`,((e,i,r)=>{const n=r.mapper.toViewElement(i.item);let o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o=!o&&n.is("element","a")?n:Array.from(n.getAncestors()).find((t=>"a"===t.name)),o){for(const[e,i]of(0,p.toMap)(t.attributes))r.writer.setAttribute(e,i,o);t.classes&&r.writer.addClass(t.classes,o);for(const e in t.styles)Object.prototype.hasOwnProperty.call(t.styles,e)&&r.writer.setStyle(e,t.styles[e],o)}}))}}function b(t,e){return t=>{t.on("element:a",((t,i,r)=>{const n=i.viewItem;if(!g(n))return;const o=new m.Matcher(e._createPattern()).match(n);if(!o)return;if(!r.consumable.consume(n,o.match))return;const a=i.modelCursor.nodeBefore;r.writer.setAttribute(e.id,!0,a)}),{priority:"high"})}}class y extends t.Plugin{static get requires(){return["EntityEmbedEditing"]}static get pluginName(){return"EntityEmbedLinkEditing"}init(){const{editor:t}=this;t.model.schema.extend("drupalEntity",{allowAttributes:["linkHref"]}),t.conversion.for("upcast").add((t=>{t.on("element:a",((t,e,i)=>{const r=e.viewItem,n=g(r);if(!n)return;if(!i.consumable.consume(r,{attributes:["href"],name:!0}))return;const o=r.getAttribute("href");if(!o)return;const a=i.convertItem(n,e.modelCursor);e.modelRange=a.modelRange,e.modelCursor=a.modelCursor;const s=e.modelCursor.nodeBefore;s&&s.is("element","drupalEntity")&&i.writer.setAttribute("linkHref",o,s)}),{priority:"high"})})),t.conversion.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o)e.attributeNewValue?r.setAttribute("href",e.attributeNewValue,o):(r.move(r.createRangeIn(o),r.createPositionAt(n,0)),r.remove(o));else{const t=Array.from(n.getChildren()).find((t=>t.getAttribute("data-drupal-entity-preview"))),i=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionAt(n,0),i),r.move(r.createRangeOn(t),r.createPositionAt(i,0))}}),{priority:"high"})})),t.conversion.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionBefore(n),o),r.move(r.createRangeOn(n),r.createPositionAt(o,0))}),{priority:"high"})})),this._enableManualDecorators();if(t.commands.get("link").automaticDecorators.length>0)throw new Error("The Drupal Entity plugin is not compatible with automatic link decorators. To use Drupal Entity, disable any plugins providing automatic link decorators.")}_enableManualDecorators(){const t=this.editor,e=t.commands.get("link");for(const i of e.manualDecorators)t.model.schema.extend("drupalEntity",{allowAttributes:i.id}),t.conversion.for("downcast").add(E(i)),t.conversion.for("upcast").add(b(0,i))}}class h extends t.Plugin{static get requires(){return["LinkEditing","LinkUI","EntityEmbedEditing","EntityEmbedUI"]}static get pluginName(){return"EntityEmbedLinkUi"}init(){const{editor:t}=this,e=t.editing.view.document;this.listenTo(e,"click",((e,i)=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)&&(i.preventDefault(),e.stop())}),{priority:"high"}),this._createToolbarLinkEntityEmbedButton()}_createToolbarLinkEntityEmbedButton(){const{editor:t}=this;t.ui.componentFactory.add("entityEmbedLink",(e=>{const i=new a.ButtonView(e),r=t.plugins.get("LinkUI"),n=t.commands.get("link");return i.set({isEnabled:!0,label:Drupal.t("Link entity embed"),icon:'',keystroke:"Ctrl+K",tooltip:!0,isToggleable:!0}),i.bind("isEnabled").to(n,"isEnabled"),i.bind("isOn").to(n,"value",(t=>!!t)),this.listenTo(i,"execute",(()=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)?r._addActionsView():r._showUI(!0)})),i}))}_isSelectedLinkedEntityEmbed(t){const e=t.getSelectedElement();return!!e&&e.is("element","drupalEntity")&&e.hasAttribute("linkHref")}}class w extends t.Plugin{static get requires(){return[y,h]}static get pluginName(){return"EntityEmbedLink"}}class f extends t.Plugin{static get requires(){return[o,l,s,c,w]}static get pluginName(){return"EntityEmbed"}}const A={EntityEmbed:f}})(),r=r.default})())); -\ No newline at end of file -+!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.CKEditor5=e():(t.CKEditor5=t.CKEditor5||{},t.CKEditor5.drupalentity=e())}(self,(()=>(()=>{var t={"ckeditor5/src/core.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/core.js")},"ckeditor5/src/engine.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/engine.js")},"ckeditor5/src/ui.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/ui.js")},"ckeditor5/src/utils.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/utils.js")},"ckeditor5/src/widget.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/widget.js")},"dll-reference CKEditor5.dll":t=>{"use strict";t.exports=CKEditor5.dll}},e={};function i(r){var n=e[r];if(void 0!==n)return n.exports;var o=e[r]={exports:{}};return t[r](o,o.exports,i),o.exports}i.d=(t,e)=>{for(var r in e)i.o(e,r)&&!i.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:e[r]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e);var r={};return(()=>{"use strict";i.d(r,{default:()=>A});var t=i("ckeditor5/src/core.js"),e=i("ckeditor5/src/widget.js");class n extends t.Command{execute(t){const{model:e}=this.editor,i=this.editor.plugins.get("EntityEmbedEditing"),r=Object.fromEntries(Object.entries(i.attrs).map((([t,e])=>[e,t]))),n=Object.fromEntries(Object.keys(r).filter((e=>t[e])).map((e=>[r[e],t[e]])));e.change((t=>{e.insertContent(function(t,e){return t.createElement("drupalEntity",e)}(t,n))}))}refresh(){const t=this.editor.model,e=t.document.selection,i=t.schema.findAllowedParent(e.getFirstPosition(),"drupalEntity");this.isEnabled=null!==i}}class o extends t.Plugin{static get requires(){return[e.Widget]}init(){this.attrs={alt:"alt",title:"title",dataCaption:"data-caption",dataAlign:"data-align",drupalEntityLangCode:"data-langcode",drupalEntityEntityType:"data-entity-type",drupalEntityEntityUuid:"data-entity-uuid",drupalEntityViewMode:"data-view-mode",drupalEntityEmbedButton:"data-embed-button",drupalEntityEmbedDisplay:"data-entity-embed-display",drupalEntityEmbedDisplaySettings:"data-entity-embed-display-settings"};const t=this.editor.config.get("entityEmbed");if(!t)throw new Error("Error on initializing entityEmbed plugin: entityEmbed config is required.");this.options=t,this.labelError=Drupal.t("Preview failed"),this.previewError=`\n

${Drupal.t("An error occurred while trying to preview the embedded content. Please save your work and reload this page.")}

\n `,this._defineSchema(),this._defineConverters(),this.editor.commands.add("insertEntityEmbed",new n(this.editor))}_defineSchema(){this.editor.model.schema.register("drupalEntity",{isObject:!0,isContent:!0,isBlock:!0,allowWhere:"$block",allowAttributes:Object.keys(this.attrs)}),this.editor.editing.view.domConverter.blockElements.push("drupal-entity")}_defineConverters(){const{conversion:t}=this.editor,i={model:"drupalEntity",view:{name:"drupal-entity"}};t.for("upcast").elementToElement(i),t.for("dataDowncast").elementToElement(i),t.for("editingDowncast").elementToElement({...i,view:(t,{writer:i})=>{const r=t.hasAttribute("dataAlign")?` align-${t.getAttribute("dataAlign")}`:"",n=i.createContainerElement("figure",{class:`drupal-entity${r}`});return i.setCustomProperty("drupalEntity",!0,n),(0,e.toWidget)(n,i,{label:Drupal.t("Entity Embed widget")})}}).add((t=>(t.on("attribute:drupalEntityEntityUuid:drupalEntity",((t,e,i)=>{const r=i.writer,n=e.item,o=i.mapper.toViewElement(e.item);let a=this._getPreviewContainer(o.getChildren());if(a){if("ready"!==a.getAttribute("data-drupal-entity-preview"))return;r.setAttribute("data-drupal-entity-preview","loading",a)}else a=r.createRawElement("div",{"data-drupal-entity-preview":"loading"}),r.insert(r.createPositionAt(o,0),a);this._loadPreview(n).then((({label:t,preview:e})=>{a&&this.editor.editing.view.change((i=>{const r=i.createRawElement("div",{"data-drupal-entity-preview":"ready","aria-label":t},(t=>{t.innerHTML=e}));i.insert(i.createPositionBefore(a),r),i.remove(a)}))}))})),t))),Object.keys(this.attrs).forEach((e=>{const i={model:{key:e,name:"drupalEntity"},view:{name:"drupal-entity",key:this.attrs[e]}};t.for("dataDowncast").attributeToAttribute(i),t.for("upcast").attributeToAttribute(i)}))}async _loadPreview(t){const e={text:this._renderElement(t)},i=await fetch(Drupal.url("embed/preview/"+this.options.format+"?"+new URLSearchParams(e)),{headers:{"X-Drupal-EmbedPreview-CSRF-Token":this.options.previewCsrfToken}});if(i.ok){return{label:Drupal.t("Entity Embed widget"),preview:await i.text()}}return{label:this.labelError,preview:this.previewError}}_renderElement(t){const e=this.editor.model.change((e=>{const i=e.createDocumentFragment(),r=e.cloneElement(t,!1);return["linkHref","dataAlign"].forEach((t=>{e.removeAttribute(t,r)})),e.append(r,i),i}));return this.editor.data.stringify(e)}_getPreviewContainer(t){for(const e of t){if(e.hasAttribute("data-drupal-entity-preview"))return e;if(e.childCount){const t=this._getPreviewContainer(e.getChildren());if(t)return t}}return null}static get pluginName(){return"EntityEmbedEditing"}}var a=i("ckeditor5/src/ui.js");class s extends t.Plugin{static get requires(){return[e.WidgetToolbarRepository]}init(){const e=this.editor,i=e.plugins.get("EntityEmbedEditing"),r=e.config.get("entityEmbed"),{dialogSettings:n={}}=r;e.ui.componentFactory.add("entityEmbedEdit",(o=>{let s=new a.ButtonView(o);return s.set({label:e.t("Edit"),icon:t.icons.pencil,tooltip:!0}),this.listenTo(s,"execute",(t=>{const o=e.model.document.selection.getSelectedElement(),a=Drupal.url("entity-embed/dialog/"+r.format+"/"+o.getAttribute("drupalEntityEmbedButton"));let s={};for(let[t,e]of o.getAttributes()){let r=i.attrs[t];r&&(s[r]=e)}this._openDialog(a,s,(({attributes:t})=>{e.execute("insertEntityEmbed",t),e.editing.view.focus()}),n)})),s})),e.ui.componentFactory.add("editEmbeddedEntity",(i=>{const r=new a.ButtonView(i),n=e.model.document.selection.getSelectedElement();if(!n)return null;if(!n.hasAttribute("drupalEntityEntityUuid"))return console.warn(Drupal.t("Unable to create edit link. There must be a value for data-entity-uuid.")),null;if(!n.hasAttribute("drupalEntityEntityType"))return console.warn(Drupal.t("Unable to create edit link. There must be a value for data-entity-type.")),null;const o=n.getAttribute("drupalEntityEntityUuid"),s=n.getAttribute("drupalEntityEntityType"),l=Drupal.url(`entity-embed/edit-embedded/${s}/${o}`);return r.set({isEnabled:!0,label:Drupal.t("Edit the embedded entity (opens in new tab)"),icon:t.icons.cog,tooltip:!0}),fetch(l).then((t=>{t.ok||r.set({label:Drupal.t(`You do not have the permissions needed to edit this ${s}.`),isEnabled:!1})})),this.listenTo(r,"execute",(()=>{window.open(l,"_blank")})),r}))}afterInit(){const{editor:t}=this;if(!t.plugins.has("WidgetToolbarRepository"))return;t.plugins.get(e.WidgetToolbarRepository).register("entityEmbed",{ariaLabel:Drupal.t("Entity Embed toolbar"),items:["entityEmbedEdit","entityEmbedLink","editEmbeddedEntity"],getRelatedElement(t){const i=t.getSelectedElement();return i&&(0,e.isWidget)(i)&&i.getCustomProperty("drupalEntity")?i:null}})}_openDialog(t,e,i,r){const n=r.dialogClass?r.dialogClass.split(" "):[];n.push("ui-dialog--narrow"),r.dialogClass=n.join(" "),r.autoResize=window.matchMedia("(min-width: 600px)").matches,r.width="auto";Drupal.ajax({dialog:r,dialogType:"modal",selector:".ckeditor5-dialog-loading-link",url:t,progress:{type:"fullscreen"},submit:{editor_object:e}}).execute(),Drupal.ckeditor5.saveCallback=i}static get pluginName(){return"EntityEmbedToolbar"}}class l extends t.Plugin{static get requires(){return["Widget"]}init(){const t=this.editor,e=t.commands.get("insertEntityEmbed"),i=t.config.get("entityEmbed");if(!i)return;const{dialogSettings:r={}}=i,n=i.buttons;Object.keys(n).forEach((o=>{const s=Drupal.url("entity-embed/dialog/"+i.format+"/"+o);t.ui.componentFactory.add(o,(i=>{const l=n[o],d=new a.ButtonView(i);let u=null;if(l.icon.endsWith("svg")){let t=new XMLHttpRequest;t.open("GET",l.icon,!1),t.send(null),u=t.response}else console.warn(`CKEditor 5 only supports enity embed icons in SVG format. The icon provided is ${l.icon}`);return d.set({label:l.label,icon:u??'\n\n \n\n',tooltip:!0}),d.bind("isOn","isEnabled").to(e,"value","isEnabled"),this.listenTo(d,"execute",(()=>Drupal.ckeditor5.openDialog(s,(({attributes:e})=>{t.execute("insertEntityEmbed",e)}),r))),d}))}))}static get pluginName(){return"EntityEmbedUI"}}function d(t,e,i){if(e.attributes)for(const[r,n]of Object.entries(e.attributes))t.setAttribute(r,n,i);e.styles&&t.setStyle(e.styles,i),e.classes&&t.addClass(e.classes,i)}function u(t,e,i){if(!i.consumable.consume(e.item,t.name))return;const r=i.mapper.toViewElement(e.item);d(i.writer,e.attributeNewValue,r)}class c extends t.Plugin{constructor(t){if(super(t),!t.plugins.has("GeneralHtmlSupport"))return;t.plugins.has("DataFilter")&&t.plugins.has("DataSchema")||console.error("DataFilter and DataSchema plugins are required for Entity Embed to integrate with General HTML Support plugin.");const{schema:e}=t.model,{conversion:i}=t,r=this.editor.plugins.get("DataFilter");this.editor.plugins.get("DataSchema").registerBlockElement({model:"drupalEntity",view:"drupal-entity"}),r.on("register:drupal-entity",((t,n)=>{"drupalEntity"===n.model&&(e.extend("drupalEntity",{allowAttributes:["htmlLinkAttributes","htmlAttributes"]}),i.for("upcast").add(function(t){return e=>{e.on("element:drupal-entity",((e,i,r)=>{function n(e,n){const o=t.processViewAttributes(e,r);o&&r.writer.setAttribute(n,o,i.modelRange)}const o=i.viewItem,a=o.parent;n(o,"htmlAttributes"),a.is("element","a")&&n(a,"htmlLinkAttributes")}),{priority:"low"})}}(r)),i.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item),n=function(t,e,i){const r=t.createRangeOn(e);for(const{item:t}of r.getWalker())if(t.is("element",i))return t}(i.writer,r,"a");d(i.writer,e.item.getAttribute("htmlLinkAttributes"),n)}),{priority:"low"})})),i.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item).parent;d(i.writer,e.item.getAttribute("htmlLinkAttributes"),r)}),{priority:"low"}),t.on("attribute:htmlAttributes:drupalEntity",u,{priority:"low"})})),t.stop())}))}static get pluginName(){return"EntityEmbedGeneralHtmlSupport"}}var m=i("ckeditor5/src/engine.js"),p=i("ckeditor5/src/utils.js");function g(t){return Array.from(t.getChildren()).find((t=>"drupal-entity"===t.name))}function E(t){return e=>{e.on(`attribute:${t.id}:drupalEntity`,((e,i,r)=>{const n=r.mapper.toViewElement(i.item);let o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o=!o&&n.is("element","a")?n:Array.from(n.getAncestors()).find((t=>"a"===t.name)),o){for(const[e,i]of(0,p.toMap)(t.attributes))r.writer.setAttribute(e,i,o);t.classes&&r.writer.addClass(t.classes,o);for(const e in t.styles)Object.prototype.hasOwnProperty.call(t.styles,e)&&r.writer.setStyle(e,t.styles[e],o)}}))}}function b(t,e){return t=>{t.on("element:a",((t,i,r)=>{const n=i.viewItem;if(!g(n))return;const o=new m.Matcher(e._createPattern()).match(n);if(!o)return;if(!r.consumable.consume(n,o.match))return;const a=i.modelCursor.nodeBefore;r.writer.setAttribute(e.id,!0,a)}),{priority:"high"})}}class y extends t.Plugin{static get requires(){return["EntityEmbedEditing"]}static get pluginName(){return"EntityEmbedLinkEditing"}init(){const{editor:t}=this;t.model.schema.extend("drupalEntity",{allowAttributes:["linkHref"]}),t.conversion.for("upcast").add((t=>{t.on("element:a",((t,e,i)=>{const r=e.viewItem,n=g(r);if(!n)return;if(!i.consumable.consume(r,{attributes:["href"],name:!0}))return;const o=r.getAttribute("href");if(!o)return;const a=i.convertItem(n,e.modelCursor);e.modelRange=a.modelRange,e.modelCursor=a.modelCursor;const s=e.modelCursor.nodeBefore;s&&s.is("element","drupalEntity")&&i.writer.setAttribute("linkHref",o,s)}),{priority:"high"})})),t.conversion.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o)e.attributeNewValue?r.setAttribute("href",e.attributeNewValue,o):(r.move(r.createRangeIn(o),r.createPositionAt(n,0)),r.remove(o));else{const t=Array.from(n.getChildren()).find((t=>t.getAttribute("data-drupal-entity-preview"))),i=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionAt(n,0),i),r.move(r.createRangeOn(t),r.createPositionAt(i,0))}}),{priority:"high"})})),t.conversion.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionBefore(n),o),r.move(r.createRangeOn(n),r.createPositionAt(o,0))}),{priority:"high"})})),this._enableManualDecorators();if(t.commands.get("link").automaticDecorators.length>0)throw new Error("The Drupal Entity plugin is not compatible with automatic link decorators. To use Drupal Entity, disable any plugins providing automatic link decorators.")}_enableManualDecorators(){const t=this.editor,e=t.commands.get("link");for(const i of e.manualDecorators)t.model.schema.extend("drupalEntity",{allowAttributes:i.id}),t.conversion.for("downcast").add(E(i)),t.conversion.for("upcast").add(b(0,i))}}class h extends t.Plugin{static get requires(){return["LinkEditing","LinkUI","EntityEmbedEditing","EntityEmbedUI"]}static get pluginName(){return"EntityEmbedLinkUi"}init(){const{editor:t}=this,e=t.editing.view.document;this.listenTo(e,"click",((e,i)=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)&&(i.preventDefault(),e.stop())}),{priority:"high"}),this._createToolbarLinkEntityEmbedButton()}_createToolbarLinkEntityEmbedButton(){const{editor:t}=this;t.ui.componentFactory.add("entityEmbedLink",(e=>{const i=new a.ButtonView(e),r=t.plugins.get("LinkUI"),n=t.commands.get("link");return i.set({isEnabled:!0,label:Drupal.t("Link entity embed"),icon:'',keystroke:"Ctrl+K",tooltip:!0,isToggleable:!0}),i.bind("isEnabled").to(n,"isEnabled"),i.bind("isOn").to(n,"value",(t=>!!t)),this.listenTo(i,"execute",(()=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)?r._addActionsView():r._showUI(!0)})),i}))}_isSelectedLinkedEntityEmbed(t){const e=t.getSelectedElement();return!!e&&e.is("element","drupalEntity")&&e.hasAttribute("linkHref")}}class f extends t.Plugin{static get requires(){return[y,h]}static get pluginName(){return"EntityEmbedLink"}}class w extends t.Plugin{static get requires(){return[o,l,s,c,f]}static get pluginName(){return"EntityEmbed"}}const A={EntityEmbed:w}})(),r=r.default})())); -\ No newline at end of file -diff --git a/js/ckeditor5_plugins/drupalentity/src/toolbar.js b/js/ckeditor5_plugins/drupalentity/src/toolbar.js -index c8e9673..ef9ea7f 100644 ---- a/js/ckeditor5_plugins/drupalentity/src/toolbar.js -+++ b/js/ckeditor5_plugins/drupalentity/src/toolbar.js -@@ -61,13 +61,15 @@ export default class EntityEmbedToolbar extends Plugin { - const button = new ButtonView(locale); - const element = editor.model.document.selection.getSelectedElement(); - if (!element) { -- return; -+ return null; - } - if (!element.hasAttribute('drupalEntityEntityUuid')) { -- console.warn(Drupal.t('Unable to create edit link. There must be a value for data-entity-uuid.')) -+ console.warn(Drupal.t('Unable to create edit link. There must be a value for data-entity-uuid.')); -+ return null; - } - if (!element.hasAttribute('drupalEntityEntityType')) { -- console.warn(Drupal.t('Unable to create edit link. There must be a value for data-entity-type.')) -+ console.warn(Drupal.t('Unable to create edit link. There must be a value for data-entity-type.')); -+ return null; - } - const uuid = element.getAttribute('drupalEntityEntityUuid'); - const type = element.getAttribute('drupalEntityEntityType'); --- -GitLab - diff --git a/tests/behat/bootstrap/TideCommonTrait.php b/tests/behat/bootstrap/TideCommonTrait.php index 639ae166a..3e37a7993 100644 --- a/tests/behat/bootstrap/TideCommonTrait.php +++ b/tests/behat/bootstrap/TideCommonTrait.php @@ -160,6 +160,30 @@ public function clickOnModalElement(string $selector) { $element->click(); } + /** + * @Then /^I click on iFramed element "([^"]*)" within "([^"]*)"$/ + * + * @param string $selector + * A CSS selector. + * @param string $name + * An iFrame name. + */ + public function clickOnIframedElement(string $selector, string $name) { + $this->getSession()->switchToIFrame($name); + + $page = $this->getSession()->getPage(); + $element = $page->find('css', $selector); + + if ($element === NULL) { + throw new \Exception('The element "' . $selector . '" was not found in iframe.'); + } + + $element->focus(); + $element->click(); + + $this->getSession()->switchToIFrame(); + } + /** * @Then /^I click on the detail "([^"]*)"$/ * @Then /^I click on the detail with text "([^"]*)"$/