/*
 * 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{UI,Core,Engine,Typing,Link,LinkUtils,LinkActionsView,Widget,Utils}from"@typo3/ckeditor5-bundle.js";import{default as modalObject}from"@typo3/backend/modal.js";const linkIcon='<svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="m11.077 15 .991-1.416a.75.75 0 1 1 1.229.86l-1.148 1.64a.748.748 0 0 1-.217.206 5.251 5.251 0 0 1-8.503-5.955.741.741 0 0 1 .12-.274l1.147-1.639a.75.75 0 1 1 1.228.86L4.933 10.7l.006.003a3.75 3.75 0 0 0 6.132 4.294l.006.004zm5.494-5.335a.748.748 0 0 1-.12.274l-1.147 1.639a.75.75 0 1 1-1.228-.86l.86-1.23a3.75 3.75 0 0 0-6.144-4.301l-.86 1.229a.75.75 0 0 1-1.229-.86l1.148-1.64a.748.748 0 0 1 .217-.206 5.251 5.251 0 0 1 8.503 5.955zm-4.563-2.532a.75.75 0 0 1 .184 1.045l-3.155 4.505a.75.75 0 1 1-1.229-.86l3.155-4.506a.75.75 0 0 1 1.045-.184z"/></svg>';export const LINK_ALLOWED_ATTRIBUTES=["href","title","class","target","rel"];export function addLinkPrefix(e){return"link"+(e.charAt(0).toUpperCase()+e.slice(1))}export class Typo3TextView extends UI.View{constructor(e){super(e),this.set("text",void 0);const t=this.bindTemplate;this.setTemplate({tag:"span",attributes:{class:["ck","ck-linktext"],title:t.to("text")},children:[{text:t.to("text")}]})}}export class Typo3LinkCommand extends Core.Command{refresh(){const e=this.editor.model,t=e.document.selection,i=t.getSelectedElement()||Utils.first(t.getSelectedBlocks());LinkUtils.isLinkableElement(i,e.schema)?(this.value=i.getAttribute("linkHref"),this.isEnabled=e.schema.checkAttribute(i,"linkHref")):(this.value=t.getAttribute("linkHref"),this.isEnabled=e.schema.checkAttributeInSelection(t,"linkHref"))}execute(e,t={}){const i=this.editor.model,n=i.document.selection;i.change((s=>{if(n.isCollapsed){const o=n.getFirstPosition();if(n.hasAttribute("linkHref")){const r=Typing.findAttributeRange(o,"linkHref",n.getAttribute("linkHref"),i);s.setAttribute("linkHref",e,r);for(const[e,i]of Object.entries(t.attrs))s.setAttribute(e,i,r);s.setSelection(s.createPositionAfter(r.end.nodeBefore))}else if(""!==e){const r=Utils.toMap(n.getAttributes());r.set("linkHref",e);for(const[e,i]of Object.entries(t.attrs))r.set(e,i);const{end:l}=i.insertContent(s.createText(e,r),o);s.setSelection(l)}s.removeSelectionAttribute("linkHref")}else{const t=i.schema.getValidRanges(n.getRanges(),"linkHref"),o=[];for(const e of n.getSelectedBlocks())i.schema.checkAttribute(e,"linkHref")&&o.push(s.createRangeOn(e));const r=o.slice();for(const e of t)this.isRangeToUpdate(e,o)&&r.push(e);for(const t of r)s.setAttribute("linkHref",e,t)}}))}isRangeToUpdate(e,t){for(const i of t)if(i.containsRange(e))return!1;return!0}}export class Typo3UnlinkCommand extends Core.Command{refresh(){const e=this.editor.model,t=e.document.selection,i=t.getSelectedElement();LinkUtils.isLinkableElement(i,e.schema)?(this.value=i.getAttribute("linkHref"),this.isEnabled=e.schema.checkAttribute(i,"linkHref")):(this.value=t.getAttribute("linkHref"),this.isEnabled=e.schema.checkAttributeInSelection(t,"linkHref"))}execute(){const e=this.editor.model,t=e.document.selection;e.change((i=>{const n=t.isCollapsed?[Typing.findAttributeRange(t.getFirstPosition(),"linkHref",t.getAttribute("linkHref"),e)]:e.schema.getValidRanges(t.getRanges(),"linkHref");for(const e of n)i.removeAttribute("linkHref",e),i.removeAttribute("linkTarget",e),i.removeAttribute("linkClass",e),i.removeAttribute("linkTitle",e),i.removeAttribute("linkRel",e)}))}}export class Typo3LinkEditing extends Core.Plugin{init(){const e=this.editor;window.editor=e,e.model.schema.extend("$text",{allowAttributes:["linkTitle","linkClass","linkTarget","linkRel"]}),e.conversion.for("downcast").attributeToElement({model:"linkTitle",view:(e,{writer:t})=>{const i=t.createAttributeElement("a",{title:e},{priority:5});return t.setCustomProperty("linkTitle",!0,i),i}}),e.conversion.for("upcast").elementToAttribute({view:{name:"a",attributes:{title:!0}},model:{key:"linkTitle",value:e=>e.getAttribute("title")}}),e.conversion.for("downcast").attributeToElement({model:"linkClass",view:(e,{writer:t})=>{const i=t.createAttributeElement("a",{class:e},{priority:5});return t.setCustomProperty("linkClass",!0,i),i}}),e.conversion.for("upcast").elementToAttribute({view:{name:"a",attributes:{title:!0}},model:{key:"linkClass",value:e=>e.getAttribute("class")}}),e.conversion.for("downcast").attributeToElement({model:"linkTarget",view:(e,{writer:t})=>{const i=t.createAttributeElement("a",{target:e},{priority:5});return t.setCustomProperty("linkTarget",!0,i),i}}),e.conversion.for("upcast").elementToAttribute({view:{name:"a",attributes:{title:!0}},model:{key:"linkTarget",value:e=>e.getAttribute("target")}}),e.conversion.for("downcast").attributeToElement({model:"linkRel",view:(e,{writer:t})=>{const i=t.createAttributeElement("a",{rel:e},{priority:5});return t.setCustomProperty("linkRel",!0,i),i}}),e.conversion.for("upcast").elementToAttribute({view:{name:"a",attributes:{title:!0}},model:{key:"linkRel",value:e=>e.getAttribute("rel")}}),e.commands.add("link",new Typo3LinkCommand(e)),e.commands.add("unlink",new Typo3UnlinkCommand(e))}}Typo3LinkEditing.pluginName="Typo3LinkEditing";export class Typo3LinkActionsView extends LinkActionsView{_createPreviewButton(){const e=new Typo3TextView(this.locale),t=this.t;return e.bind("text").to(this,"href",(e=>e||t("This link has no URL"))),e}}const VISUAL_SELECTION_MARKER_NAME="link-ui";export class Typo3LinkUI extends Core.Plugin{init(){const e=this.editor;e.editing.view.addObserver(Engine.ClickObserver),this.actionsView=this.createActionsView(),this.balloon=e.plugins.get(UI.ContextualBalloon),this.createToolbarLinkButtons(),this.enableUserBalloonInteractions(),e.conversion.for("editingDowncast").markerToHighlight({model:"link-ui",view:{classes:["ck-fake-link-selection"]}}),e.conversion.for("editingDowncast").markerToElement({model:"link-ui",view:{name:"span",classes:["ck-fake-link-selection","ck-fake-link-selection_collapsed"]}})}createActionsView(){const e=this.editor,t=new Typo3LinkActionsView(e.locale),i=e.commands.get("link"),n=e.commands.get("unlink");return t.bind("href").to(i,"value"),t.editButtonView.bind("isEnabled").to(i),t.unlinkButtonView.bind("isEnabled").to(n),this.listenTo(t,"edit",(()=>{const e=this.getSelectedLinkElement();this.openLinkBrowser(this.editor,e)})),this.listenTo(t,"unlink",(()=>{e.execute("unlink"),this.hideUI()})),t.keystrokes.set("Esc",((e,t)=>{this.hideUI(),t()})),t}createToolbarLinkButtons(){const e=this.editor,t=e.commands.get("link"),i=e.t;e.keystrokes.set(LinkUtils.LINK_KEYSTROKE,((e,i)=>{i(),t.isEnabled&&this.showUI()})),e.ui.componentFactory.add("link",(e=>{const n=new UI.ButtonView(e);return n.isEnabled=!0,n.label=i("Link"),n.icon=linkIcon,n.keystroke=LinkUtils.LINK_KEYSTROKE,n.tooltip=!0,n.isToggleable=!0,n.bind("isEnabled").to(t,"isEnabled"),n.bind("isOn").to(t,"value",(e=>!!e)),this.listenTo(n,"execute",(()=>this.showUI())),n}))}enableUserBalloonInteractions(){const e=this.editor.editing.view.document;this.listenTo(e,"click",(()=>{this.getSelectedLinkElement()&&this.showUI()})),this.editor.keystrokes.set("Esc",((e,t)=>{this.isUIVisible()&&(this.hideUI(),t())}))}addActionsView(){this.areActionsInPanel()||this.balloon.add({view:this.actionsView,position:this.getBalloonPositionData()})}hideUI(){if(!this.isUIInPanel())return;const e=this.editor;this.stopListening(e.ui,"update"),this.stopListening(this.balloon,"change:visibleView"),e.editing.view.focus(),this.balloon.remove(this.actionsView),this.hideFakeVisualSelection()}showUI(){if(this.getSelectedLinkElement())this.addActionsView(),this.balloon.showStack("main");else{this.showFakeVisualSelection();const e=this.getSelectedLinkElement();this.openLinkBrowser(this.editor,e)}this.startUpdatingUI()}startUpdatingUI(){const e=this.editor,t=e.editing.view.document;let i=this.getSelectedLinkElement(),n=o();const s=()=>{const e=this.getSelectedLinkElement(),t=o();i&&!e||!i&&t!==n?this.hideUI():this.isUIVisible()&&this.balloon.updatePosition(this.getBalloonPositionData()),i=e,n=t};function o(){return t.selection.focus.getAncestors().reverse().find((e=>e.is("element")))}this.listenTo(e.ui,"update",s),this.listenTo(this.balloon,"change:visibleView",s)}areActionsInPanel(){return this.balloon.hasView(this.actionsView)}areActionsVisible(){return this.balloon.visibleView===this.actionsView}isUIInPanel(){return this.areActionsInPanel()}isUIVisible(){return this.areActionsVisible()}getBalloonPositionData(){const e=this.editor.editing.view,t=this.editor.model,i=e.document;let n=null;if(t.markers.has("link-ui")){const t=Array.from(this.editor.editing.mapper.markerNameToElements("link-ui")),i=e.createRange(e.createPositionBefore(t[0]),e.createPositionAfter(t[t.length-1]));n=e.domConverter.viewRangeToDom(i)}else n=()=>{const t=this.getSelectedLinkElement();return t?e.domConverter.mapViewToDom(t):e.domConverter.viewRangeToDom(i.selection.getFirstRange())};return{target:n}}getSelectedLinkElement(){const e=this.editor.editing.view,t=e.document.selection,i=t.getSelectedElement();if(t.isCollapsed||i&&Widget.isWidget(i))return this.findLinkElementAncestor(t.getFirstPosition());{const i=t.getFirstRange().getTrimmed(),n=this.findLinkElementAncestor(i.start),s=this.findLinkElementAncestor(i.end);return n&&n==s&&e.createRangeIn(n).getTrimmed().isEqual(i)?n:null}}showFakeVisualSelection(){const e=this.editor.model;e.change((t=>{const i=e.document.selection.getFirstRange();if(e.markers.has("link-ui"))t.updateMarker("link-ui",{range:i});else if(i.start.isAtEnd){const n=i.start.getLastMatchingPosition((({item:t})=>!e.schema.isContent(t)),{startPosition:null,boundaries:i});t.addMarker("link-ui",{usingOperation:!1,affectsData:!1,range:t.createRange(n,i.end)})}else t.addMarker("link-ui",{usingOperation:!1,affectsData:!1,range:i})}))}hideFakeVisualSelection(){const e=this.editor.model;e.markers.has("link-ui")&&e.change((e=>{e.removeMarker("link-ui")}))}findLinkElementAncestor(e){return e.getAncestors().find((e=>LinkUtils.isLinkElement(e)))}openLinkBrowser(e,t){let i="";t&&(i+="&P[curUrl][url]="+encodeURIComponent(t.getAttribute("href")),["target","class","title","rel"].forEach((e=>{const n=t.getAttribute(e);n&&(i+="&P[curUrl]["+e+"]="+encodeURIComponent(n))}))),this.openElementBrowser(e,"Link",this.makeUrlFromModulePath(e,e.config.get("typo3link")?.routeUrl,i))}makeUrlFromModulePath(e,t,i){return t+(-1===t.indexOf("?")?"?":"&")+"&contentsLanguage=en&editorId=123"+(i||"")}openElementBrowser(e,t,i){modalObject.advanced({type:modalObject.types.iframe,title:t,content:i,size:modalObject.sizes.large,callback:t=>{t.userData.ckeditor=e,t.querySelector(".t3js-modal-body")?.setAttribute("id","123")}})}}Typo3LinkUI.pluginName="Typo3LinkUI",Typo3LinkUI.requires=[UI.ContextualBalloon];export default class Typo3Link extends Core.Plugin{}Typo3Link.pluginName="Typo3Link",Typo3Link.requires=[Link.LinkEditing,Link.AutoLink,Typo3LinkEditing,Typo3LinkUI],Typo3Link.overrides=[Link.Link];