/*
 * This file is part of the TYPO3 CMS project.
 *
 * It is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License, either version 2
 * of the License, or any later version.
 *
 * For the full copyright and license information, please read the
 * LICENSE.txt file that was distributed with this source code.
 *
 * The TYPO3 project - inspiring people to share!
 */
import*as d from"@ckeditor/ckeditor5-ui";import*as k from"@ckeditor/ckeditor5-core";import*as P from"@ckeditor/ckeditor5-engine";import*as b from"@ckeditor/ckeditor5-typing";import*as I from"@ckeditor/ckeditor5-widget";import*as A from"@ckeditor/ckeditor5-utils";import*as f from"@ckeditor/ckeditor5-link";import{LinkUtils as h}from"@ckeditor/ckeditor5-link";import p from"@typo3/backend/modal.js";import{IconLink as R,IconUnlink as y,IconPencil as V}from"@ckeditor/ckeditor5-icons";const C=["href","title","class","target","rel"];function x(c){return"link"+(c.charAt(0).toUpperCase()+c.slice(1))}function v(c){return c.startsWith("link")&&c.length>=5?c.charAt(4).toLowerCase()+c.slice(5):c}class E extends k.Command{constructor(){super(...arguments),this.attrs={}}refresh(){const e=this.editor.model,n=e.document.selection,i=n.getSelectedElement()||A.first(n.getSelectedBlocks()),o=h.isLinkableElement(i,e.schema)?i:n;o===i?(this.value=i.getAttribute("linkHref"),this.isEnabled=e.schema.checkAttribute(i,"linkHref")):(this.value=n.getAttribute("linkHref"),this.isEnabled=e.schema.checkAttributeInSelection(n,"linkHref"));const s=this.editor.plugins.get("GeneralHtmlSupport").getGhsAttributeNameForElement("a"),l={};for(const a of this.getLinkAttributesAllowedOnText(e.schema))if(a!=="linkHref")if(a===s){const r=o.getAttribute(a);r?.classes&&r.classes.length!==0&&(l.class=r.classes.join(" "))}else{const r=o.getAttribute(a);r!==void 0&&(l[v(a)]=r)}this.attrs=l}execute(e,n={}){const i=this.editor.model,o=i.document.selection;i.change(t=>{if(o.isCollapsed){const s=o.getFirstPosition();if(o.hasAttribute("linkHref")){const l=b.findAttributeRange(s,"linkHref",o.getAttribute("linkHref"),i);t.setAttribute("linkHref",e,l);for(const[a,r]of Object.entries(this.composeLinkAttributes(n)))r!==null?t.setAttribute(a,r,l):t.removeAttribute(a,l);t.setSelection(t.createPositionAfter(l.end.nodeBefore))}else if(e!==""){const l=A.toMap(o.getAttributes());l.set("linkHref",e);for(const[r,m]of Object.entries(this.composeLinkAttributes(n)))m!==null&&l.set(r,m);const{end:a}=i.insertContent(t.createText(e,l),s);t.setSelection(a)}this.removeLinkAttributesFromSelection(t,this.getLinkAttributesAllowedOnText(i.schema))}else{const s=i.schema.getValidRanges(o.getRanges(),"linkHref"),l=[];for(const r of o.getSelectedBlocks())i.schema.checkAttribute(r,"linkHref")&&l.push(t.createRangeOn(r));const a=l.slice();for(const r of s)this.isRangeToUpdate(r,l)&&a.push(r);for(const r of a){t.setAttribute("linkHref",e,r);for(const[m,g]of Object.entries(this.composeLinkAttributes(n)))g!==null?t.setAttribute(m,g,r):t.removeAttribute(m,r)}}})}getLinkAttributesAllowedOnText(e){return e.getDefinition("$text").allowAttributes.filter(i=>i.startsWith("link")||i==="htmlA")}removeLinkAttributesFromSelection(e,n){e.removeSelectionAttribute("linkHref");for(const i of n)e.removeSelectionAttribute(i)}composeLinkAttributes(e){const n={};for(const[i,o]of Object.entries(e.attrs))if(i==="linkClass"){const s=this.editor.plugins.get("GeneralHtmlSupport").getGhsAttributeNameForElement("a"),l=this.editor.model.document.selection;let a;l.hasAttribute(s)?a={...l.getAttribute(s)}:a={};const r=o.replace(/\s+/g," ").trim();r!==""?a.classes=r.split(" "):"classes"in a&&delete a.classes,n[s]=Object.keys(a).length!==0?a:null}else n[i]=o!==""?o:null;return n}isRangeToUpdate(e,n){for(const i of n)if(i.containsRange(e))return!1;return!0}}class T extends k.Command{refresh(){const e=this.editor.model,n=e.document.selection,i=n.getSelectedElement();h.isLinkableElement(i,e.schema)?this.isEnabled=e.schema.checkAttribute(i,"linkHref"):this.isEnabled=e.schema.checkAttributeInSelection(n,"linkHref")}execute(){const e=this.editor.model,n=e.document.selection;e.change(i=>{const o=n.isCollapsed?[b.findAttributeRange(n.getFirstPosition(),"linkHref",n.getAttribute("linkHref"),e)]:e.schema.getValidRanges(n.getRanges(),"linkHref");for(const t of o)i.removeAttribute("linkHref",t),i.removeAttribute("linkTarget",t),i.removeAttribute("linkTitle",t),i.removeAttribute("linkRel",t),i.removeAttribute("linkDataRteError",t)})}}class L extends k.Plugin{static{this.pluginName="Typo3LinkEditing"}init(){const e=this.editor;window.editor=e,e.model.schema.extend("$text",{allowAttributes:["linkTitle","linkTarget","linkRel","linkDataRteError"]}),e.plugins.get("DataFilter").loadAllowedConfig([{name:"a",classes:!0}]),e.conversion.for("downcast").attributeToElement({model:"linkDataRteError",view:(i,{writer:o})=>{const t=o.createAttributeElement("a",{"data-rte-error":i},{priority:5});return o.setCustomProperty("linkDataRteError",!0,t),t}}),e.conversion.for("upcast").elementToAttribute({view:{name:"a",attributes:{"data-rte-error":!0}},model:{key:"linkDataRteError",value:i=>i.getAttribute("data-rte-error")}}),e.conversion.for("downcast").attributeToElement({model:"linkTitle",view:(i,{writer:o})=>{const t=o.createAttributeElement("a",{title:i},{priority:5});return o.setCustomProperty("linkTitle",!0,t),t}}),e.conversion.for("upcast").elementToAttribute({view:{name:"a",attributes:{title:!0}},model:{key:"linkTitle",value:i=>i.getAttribute("title")}}),e.conversion.for("downcast").attributeToElement({model:"linkTarget",view:(i,{writer:o})=>{const t=o.createAttributeElement("a",{target:i},{priority:5});return o.setCustomProperty("linkTarget",!0,t),t}}),e.conversion.for("upcast").elementToAttribute({view:{name:"a",attributes:{target:!0}},model:{key:"linkTarget",value:i=>i.getAttribute("target")}}),e.conversion.for("downcast").attributeToElement({model:"linkRel",view:(i,{writer:o})=>{const t=o.createAttributeElement("a",{rel:i},{priority:5});return o.setCustomProperty("linkRel",!0,t),t}}),e.conversion.for("upcast").elementToAttribute({view:{name:"a",attributes:{rel:!0}},model:{key:"linkRel",value:i=>i.getAttribute("rel")}}),e.commands.add("link",new E(e)),e.commands.add("unlink",new T(e))}}class w extends d.ButtonView{constructor(e){super(e);const n=this.bindTemplate;this.set({href:void 0,withText:!0}),this.setTemplate({tag:"span",attributes:{class:["ck-link-toolbar__preview"],title:n.to("href")},children:[{text:n.to("href")}]})}}const u="link-ui";class S extends k.Plugin{static get requires(){return[d.ContextualBalloon,f.LinkEditing]}static get pluginName(){return"Typo3LinkUI"}init(){const e=this.editor;e.editing.view.addObserver(P.ClickObserver),this.balloon=e.plugins.get(d.ContextualBalloon),this.createToolbarLinkButtons(),this.enableUserBalloonInteractions(),e.conversion.for("editingDowncast").markerToHighlight({model:u,view:{classes:["ck-fake-link-selection"]}}),e.conversion.for("editingDowncast").markerToElement({model:u,view:{name:"span",classes:["ck-fake-link-selection","ck-fake-link-selection_collapsed"]}})}createToolbarView(){const e=this.editor,n=new d.ToolbarView(e.locale),i=e.config.get("link.toolbar");return n.fillFromConfig(i,e.ui.componentFactory),n.keystrokes.set("Esc",(o,t)=>{this.hideUI(),t()}),e.ui.addToolbar(n,{isContextual:!0,beforeFocus:()=>{this.getSelectedLinkElement()&&!this.isToolbarVisible()&&this.showUI()},afterBlur:()=>{this.hideUI()}}),n}createToolbarLinkButtons(){const e=this.editor,n=e.commands.get("link"),i=e.t;e.keystrokes.set(h.LINK_KEYSTROKE,(o,t)=>{t(),n.isEnabled&&this.showUI()}),e.ui.componentFactory.add("link",o=>{const t=new d.ButtonView(o);return t.isEnabled=!0,t.label=i("Link"),t.icon=R,t.keystroke=h.LINK_KEYSTROKE,t.tooltip=!0,t.isToggleable=!0,t.bind("isEnabled").to(n,"isEnabled"),t.bind("isOn").to(n,"value",s=>!!s),this.listenTo(t,"execute",()=>this.showUI()),t}),e.ui.componentFactory.add("linkPreview",o=>{const t=new w(o),s=e.config.get("link.allowedProtocols"),l=e.commands.get("link");t.bind("isEnabled").to(l,"value",r=>!!r),t.bind("href").to(l,"value",r=>r&&h.ensureSafeUrl(r,s)),t.icon=void 0;const a=r=>{if(!r){t.label=void 0;return}t.label=r};return a(l.value),this.listenTo(l,"change:value",(r,m,g)=>{a(g)}),t}),e.ui.componentFactory.add("unlink",o=>{const t=e.commands.get("unlink"),s=new d.ButtonView(o),l=o.t;return s.set({label:l("Unlink"),icon:y,tooltip:!0}),s.bind("isEnabled").to(t),this.listenTo(s,"execute",()=>{e.execute("unlink"),this.hideUI()}),s}),e.ui.componentFactory.add("editLink",o=>{const t=e.commands.get("link"),s=new d.ButtonView(o),l=o.t;return s.set({label:l("Edit link"),icon:V,tooltip:!0}),s.bind("isEnabled").to(t),this.listenTo(s,"execute",()=>{this.openLinkBrowser(e)}),s})}enableUserBalloonInteractions(){const e=this.editor.editing.view.document;this.listenTo(e,"click",()=>{this.getSelectedLinkElement()&&this.showUI()}),this.editor.keystrokes.set("Esc",(n,i)=>{this.isUIVisible()&&(this.hideUI(),i())})}addToolbarView(){this.toolbarView||(this.toolbarView=this.createToolbarView()),!this.isToolbarInPanel()&&this.balloon.add({view:this.toolbarView,position:this.getBalloonPositionData(),balloonClassName:"ck-toolbar-container"})}hideUI(e=!0){const n=this.editor;this.stopListening(n.ui,"update"),this.stopListening(this.balloon,"change:visibleView"),e&&n.editing.view.focus(),this.isToolbarInPanel()&&this.balloon.remove(this.toolbarView),this.hideFakeVisualSelection()}showUI(){this.getSelectedLinkElement()?(this.addToolbarView(),this.balloon.showStack("main")):(this.showFakeVisualSelection(),this.openLinkBrowser(this.editor)),this.startUpdatingUI()}startUpdatingUI(){const e=this.editor,n=e.editing.view.document;let i=this.getSelectedLinkElement(),o=s();const t=()=>{const l=this.getSelectedLinkElement(),a=s();i&&!l||!i&&a!==o?this.hideUI():this.isUIVisible()&&this.balloon.updatePosition(this.getBalloonPositionData()),i=l,o=a};function s(){return n.selection.focus.getAncestors().reverse().find(l=>l.is("element"))}this.listenTo(e.ui,"update",t),this.listenTo(this.balloon,"change:visibleView",t)}isToolbarInPanel(){return!!this.toolbarView&&this.balloon.hasView(this.toolbarView)}isToolbarVisible(){return!!this.toolbarView&&this.balloon.visibleView===this.toolbarView}isUIVisible(){return this.isToolbarVisible()}getBalloonPositionData(){const e=this.editor.editing.view,n=this.editor.model,i=e.document;let o=null;if(n.markers.has(u)){const t=Array.from(this.editor.editing.mapper.markerNameToElements(u)),s=e.createRange(e.createPositionBefore(t[0]),e.createPositionAfter(t[t.length-1]));o=e.domConverter.viewRangeToDom(s)}else o=()=>{const t=this.getSelectedLinkElement();return t?e.domConverter.mapViewToDom(t):e.domConverter.viewRangeToDom(i.selection.getFirstRange())};return{target:o}}getSelectedLinkElement(){const e=this.editor.editing.view,n=e.document.selection,i=n.getSelectedElement();if(n.isCollapsed||i&&I.isWidget(i))return this.findLinkElementAncestor(n.getFirstPosition());{const o=n.getFirstRange().getTrimmed(),t=this.findLinkElementAncestor(o.start),s=this.findLinkElementAncestor(o.end);return!t||t!=s?null:e.createRangeIn(t).getTrimmed().isEqual(o)?t:null}}showFakeVisualSelection(){const e=this.editor.model;e.change(n=>{const i=e.document.selection.getFirstRange();if(e.markers.has(u))n.updateMarker(u,{range:i});else if(i.start.isAtEnd){const o=i.start.getLastMatchingPosition(({item:t})=>!e.schema.isContent(t),{startPosition:null,boundaries:i});n.addMarker(u,{usingOperation:!1,affectsData:!1,range:n.createRange(o,i.end)})}else n.addMarker(u,{usingOperation:!1,affectsData:!1,range:i})})}hideFakeVisualSelection(){const e=this.editor.model;e.markers.has(u)&&e.change(n=>{n.removeMarker(u)})}findLinkElementAncestor(e){return e.getAncestors().find(n=>h.isLinkElement(n))}expandSelectionToFullLink(){const e=this.editor.model,n=e.document.selection;if(!n.hasAttribute("linkHref"))return;const i=n.getAttribute("linkHref");i&&e.change(o=>{const t=n.getFirstPosition(),s=b.findAttributeRange(t,"linkHref",i,e);s&&o.setSelection(s)})}openLinkBrowser(e){const n=e.commands.get("link");let i="";if(n.value){this.expandSelectionToFullLink(),i+="&P[curUrl][url]="+encodeURIComponent(n.value);for(const[o,t]of Object.entries(n.attrs))i+="&P[curUrl]["+encodeURIComponent(o)+"]="+encodeURIComponent(t)}this.openElementBrowser(e,"Link",this.makeUrlFromModulePath(e,e.config.get("typo3link")?.routeUrl,i))}makeUrlFromModulePath(e,n,i){return n+(n.indexOf("?")===-1?"?":"&")+"&contentsLanguage=en&editorId=123"+(i||"")}openElementBrowser(e,n,i){p.advanced({type:p.types.iframe,title:n,content:i,size:p.sizes.large,callback:t=>{t.userData.editor=e,t.userData.selectionStartPosition=e.model.document.selection.getFirstPosition(),t.userData.selectionEndPosition=e.model.document.selection.getLastPosition(),t.querySelector(".t3js-modal-body")?.setAttribute("id","123")}}).addEventListener("typo3-modal-hide",()=>{this.hideUI(!1)})}}class U extends k.Plugin{static{this.overrides=[f.Link]}static get requires(){return["GeneralHtmlSupport",f.LinkEditing,f.AutoLink,L,S]}static get pluginName(){return"Typo3Link"}}export{C as LINK_ALLOWED_ATTRIBUTES,U as Typo3Link,E as Typo3LinkCommand,L as Typo3LinkEditing,w as Typo3LinkPreviewButtonView,S as Typo3LinkUI,T as Typo3UnlinkCommand,x as addLinkPrefix,U as default,v as removeLinkPrefix};
