From c16fb0f3c11ff25884586926554e912aaa44025f Mon Sep 17 00:00:00 2001 From: Guy Sartorelli <36352093+GuySartorelli@users.noreply.github.com> Date: Thu, 25 Jan 2024 15:46:26 +1300 Subject: [PATCH] ENH Refactor sslink slightly for easier maintenance (#1661) --- client/dist/js/TinyMCE_sslink.js | 2 +- client/src/legacy/TinyMCE_sslink.js | 39 +++++++++++++---------------- 2 files changed, 18 insertions(+), 23 deletions(-) diff --git a/client/dist/js/TinyMCE_sslink.js b/client/dist/js/TinyMCE_sslink.js index 2f6aac63e..c08260fb5 100644 --- a/client/dist/js/TinyMCE_sslink.js +++ b/client/dist/js/TinyMCE_sslink.js @@ -1 +1 @@ -!function(){"use strict";var t={265:function(t){t.exports=ShortcodeSerialiser},196:function(t){t.exports=TinyMCEActionRegistrar},754:function(t){t.exports=i18n},311:function(t){t.exports=jQuery}},e={};function n(i){var o=e[i];if(void 0!==o)return o.exports;var r=e[i]={exports:{}};return t[i](r,r.exports,n),r.exports}!function(){var t=r(n(196)),e=r(n(311)),i=n(265),o=r(n(754));function r(t){return t&&t.__esModule?t:{default:t}}const s={init(n){const i=navigator.platform.toUpperCase().includes("MAC")?"⌘":"Ctrl",r=o.default._t("Admin.INSERT_LINK","Insert link"),s=o.default.inject(o.default._t("Admin.INSERT_LINK_WITH_SHORTCUT","Insert link {shortcut}"),{shortcut:`[${i}+K]`});return n.addShortcut("Meta+k","Open link menu",(()=>{(0,e.default)(`[aria-label^="${r}"] > button`,n.container).first().click()})),n.ui.registry.addMenuButton("sslink",{icon:"link",tooltip:s,fetch:e=>e(t.default.getSortedActions("sslink",n.getParam("editorIdentifier"),!0).map((t=>Object.assign({},t,{onAction:()=>t.onAction(n)}))))}),n.on("preinit",(()=>{n.ui.registry.addNestedMenuItem("sslink",{icon:"link",text:r,getSubmenuItems:()=>t.default.getSortedActions("sslink",n.getParam("editorIdentifier"),!0).map((t=>Object.assign({},t,{onAction:()=>t.onAction(n)})))})})),n.ui.registry.addButton("sslink-edit",{text:o.default._t("Admin.EDIT_LINK","Edit link"),onAction:function(){const e=tinymce.activeEditor.selection.getNode().getAttribute("href");e&&n.execCommand(t.default.getEditorCommandFromUrl(e))}}),n.ui.registry.addButton("sslink-remove",{text:o.default._t("Admin.REMOVE_LINK","Remove link"),onAction:()=>this.handleRemoveLinkClick(n)}),n.ui.registry.addContextToolbar("sslink",{predicate:t=>n.dom.is(t,"a[href]"),position:"node",scope:"node",items:"sslink-edit sslink-remove"}),{getMetadata(){return{name:"Silverstripe Link",url:"https://docs.silverstripe.org/en/4/developer_guides/forms/field_types/htmleditorfield"}}}},handleRemoveLinkClick(t){const e=t.execCommand("unlink"),n=t.selection.getNode();return n&&void 0!==n.normalize&&n.normalize(),e}};e.default.entwine("ss",(t=>{t(".insert-link__dialog-wrapper").entwine({Element:null,Data:{},Bookmark:null,onunmatch(){this._clearModal()},_clearModal(){const t=this.getReactRoot();t&&(t.unmount(),this.setReactRoot(null))},open(){const t=this.getElement().getEditor().getInstance();this.setBookmark(t.selection.getBookmark(2,!0)),this.renderModal(!0)},close(){this.setData({}),this.renderModal(!1)},renderModal(){},checkNodeMatches(t,e){return t===e||1===e.children.length&&t===e.children[0]},linkCanWrapSelection(t,e){const n=t.getSelection()||"",i=e.getNode();if(n)return""!==n.trim();const o=document.createElement(i.nodeName);if(o.textContent="Check the outer HTML",o.outerHTML.includes("Check the outer HTML"))return!1;if(this.checkNodeMatches(i,e.getSel().focusNode)&&this.checkNodeMatches(i,e.getSel().anchorNode)){if(1===tinymce.activeEditor.dom.createFragment(`${i.outerHTML}`).childNodes.length)return!0}return!1},getRequireLinkText(){const t=this.getElement().getEditor(),e=t.getInstance().selection,n=this.linkCanWrapSelection(t,e);return"A"!==e.getNode().tagName&&!n},handleInsert(t){this.getElement().getEditor().getInstance().selection.moveToBookmark(this.getBookmark());const e=this.buildAttributes(t),n=(0,i.createHTMLSanitiser)()(t.Text);return this.insertLinkInEditor(e,n),this.close(),Promise.resolve()},buildAttributes(t){let{Anchor:e,Link:n,TargetBlank:i,Description:o}=t,r=e&&e.length?`#${e}`:"";r=r.replace(/^#+/,"#");return{href:`${n}${r}`,target:i?"_blank":"",title:o}},insertLinkInEditor(t,e){const n=this.getElement().getEditor();n.insertLink(t,null,e),n.addUndo(),n.repaint();const i=n.getInstance().selection;setTimeout((()=>i&&i.collapse()),0)},getOriginalAttributes(){const e=this.getElement().getEditor(),n=t(e.getSelectedNode()),i=(n.attr("href")||"").split("#");return{Link:i[0]||"",Anchor:i[1]||"",Description:n.attr("title"),TargetBlank:!!n.attr("target")}}})})),tinymce.PluginManager.add("sslink",(t=>s.init(t)))}()}(); \ No newline at end of file +!function(){"use strict";var t={265:function(t){t.exports=ShortcodeSerialiser},196:function(t){t.exports=TinyMCEActionRegistrar},754:function(t){t.exports=i18n},311:function(t){t.exports=jQuery}},e={};function n(i){var r=e[i];if(void 0!==r)return r.exports;var o=e[i]={exports:{}};return t[i](o,o.exports,n),o.exports}!function(){var t=o(n(196)),e=o(n(311)),i=n(265),r=o(n(754));function o(t){return t&&t.__esModule?t:{default:t}}const s={init(n){function i(){return t.default.getSortedActions("sslink",n.getParam("editorIdentifier"),!0).map((t=>Object.assign({},t,{onAction:()=>t.onAction(n)})))}const o=navigator.platform.toUpperCase().includes("MAC")?"⌘":"Ctrl",s=r.default._t("Admin.INSERT_LINK","Insert link"),l=r.default.inject(r.default._t("Admin.INSERT_LINK_WITH_SHORTCUT","Insert link {shortcut}"),{shortcut:`[${o}+K]`});return n.addShortcut("Meta+k","Open link menu",(()=>{(0,e.default)(`[aria-label^="${s}"] > button`,n.container).first().click()})),n.ui.registry.addMenuButton("sslink",{icon:"link",tooltip:l,fetch:t=>t(i())}),n.ui.registry.addNestedMenuItem("sslink",{icon:"link",text:s,getSubmenuItems:i}),n.ui.registry.addButton("sslink-edit",{text:r.default._t("Admin.EDIT_LINK","Edit link"),onAction:function(){const e=tinymce.activeEditor.selection.getNode().getAttribute("href");e&&n.execCommand(t.default.getEditorCommandFromUrl(e))}}),n.ui.registry.addButton("sslink-remove",{text:r.default._t("Admin.REMOVE_LINK","Remove link"),onAction:()=>this.handleRemoveLinkClick(n)}),n.ui.registry.addContextToolbar("sslink",{predicate:t=>n.dom.is(t,"a[href]"),position:"node",scope:"node",items:"sslink-edit sslink-remove"}),{getMetadata(){return{name:"Silverstripe Link",url:"https://docs.silverstripe.org/en/4/developer_guides/forms/field_types/htmleditorfield"}}}},handleRemoveLinkClick(t){const e=t.execCommand("unlink"),n=t.selection.getNode();return n&&void 0!==n.normalize&&n.normalize(),e}};e.default.entwine("ss",(t=>{t(".insert-link__dialog-wrapper").entwine({Element:null,Data:{},Bookmark:null,onunmatch(){this._clearModal()},_clearModal(){const t=this.getReactRoot();t&&(t.unmount(),this.setReactRoot(null))},open(){const t=this.getElement().getEditor().getInstance();this.setBookmark(t.selection.getBookmark(2,!0)),this.renderModal(!0)},close(){this.setData({}),this.renderModal(!1)},renderModal(){},checkNodeMatches(t,e){return t===e||1===e.children.length&&t===e.children[0]},linkCanWrapSelection(t,e){const n=t.getSelection()||"",i=e.getNode();if(n)return""!==n.trim();const r=document.createElement(i.nodeName);if(r.textContent="Check the outer HTML",r.outerHTML.includes("Check the outer HTML"))return!1;if(this.checkNodeMatches(i,e.getSel().focusNode)&&this.checkNodeMatches(i,e.getSel().anchorNode)){if(1===tinymce.activeEditor.dom.createFragment(`${i.outerHTML}`).childNodes.length)return!0}return!1},getRequireLinkText(){const t=this.getElement().getEditor(),e=t.getInstance().selection,n=this.linkCanWrapSelection(t,e);return"A"!==e.getNode().tagName&&!n},handleInsert(t){this.getElement().getEditor().getInstance().selection.moveToBookmark(this.getBookmark());const e=this.buildAttributes(t),n=(0,i.createHTMLSanitiser)()(t.Text);return this.insertLinkInEditor(e,n),this.close(),Promise.resolve()},buildAttributes(t){let{Anchor:e,Link:n,TargetBlank:i,Description:r}=t,o=e&&e.length?`#${e}`:"";o=o.replace(/^#+/,"#");return{href:`${n}${o}`,target:i?"_blank":"",title:r}},insertLinkInEditor(t,e){const n=this.getElement().getEditor();n.insertLink(t,null,e),n.addUndo(),n.repaint();const i=n.getInstance().selection;setTimeout((()=>i&&i.collapse()),0)},getOriginalAttributes(){const e=this.getElement().getEditor(),n=t(e.getSelectedNode()),i=(n.attr("href")||"").split("#");return{Link:i[0]||"",Anchor:i[1]||"",Description:n.attr("title"),TargetBlank:!!n.attr("target")}}})})),tinymce.PluginManager.add("sslink",(t=>s.init(t)))}()}(); \ No newline at end of file diff --git a/client/src/legacy/TinyMCE_sslink.js b/client/src/legacy/TinyMCE_sslink.js index c962c1d5c..374311cb0 100644 --- a/client/src/legacy/TinyMCE_sslink.js +++ b/client/src/legacy/TinyMCE_sslink.js @@ -11,6 +11,16 @@ const plugin = { * @param {Object} editor */ init(editor) { + function getActions() { + // Fetch the actions whenever the fetch function is called. + return TinyMCEActionRegistrar.getSortedActions('sslink', editor.getParam('editorIdentifier'), true) + .map(action => Object.assign( + {}, + action, + { onAction: () => action.onAction(editor) } + )); + } + const metaKey = navigator.platform.toUpperCase().includes('MAC') ? '⌘' : 'Ctrl'; const title = i18n._t('Admin.INSERT_LINK', 'Insert link'); const titleWithShortcut = i18n.inject( @@ -33,33 +43,18 @@ const plugin = { } } + // Button in main toolbar editor.ui.registry.addMenuButton('sslink', { icon: 'link', tooltip: titleWithShortcut, - fetch: (callback) => callback( - // Fetch the actions whenever the fetch function is called. - TinyMCEActionRegistrar.getSortedActions('sslink', editor.getParam('editorIdentifier'), true) - .map(action => Object.assign( - {}, - action, - { onAction: () => action.onAction(editor) } - )) - ), + fetch: (callback) => callback(getActions()), }); - editor.on('preinit', () => { - // Right click context menu item - editor.ui.registry.addNestedMenuItem('sslink', { - icon: 'link', - text: title, - getSubmenuItems: () => // Fetch the actions whenever the fetch function is called. - TinyMCEActionRegistrar.getSortedActions('sslink', editor.getParam('editorIdentifier'), true) - .map(action => Object.assign( - {}, - action, - { onAction: () => action.onAction(editor) } - )), - }); + // Right click context menu item + editor.ui.registry.addNestedMenuItem('sslink', { + icon: 'link', + text: title, + getSubmenuItems: getActions, }); // Context menu when a link is selected