diff --git a/src/wp-includes/js/tinymce/plugins/link/plugin.js b/src/wp-includes/js/tinymce/plugins/link/plugin.js new file mode 100644 index 0000000000..d4aa001d1e --- /dev/null +++ b/src/wp-includes/js/tinymce/plugins/link/plugin.js @@ -0,0 +1,1162 @@ +(function () { + +var defs = {}; // id -> {dependencies, definition, instance (possibly undefined)} + +// Used when there is no 'main' module. +// The name is probably (hopefully) unique so minification removes for releases. +var register_3795 = function (id) { + var module = dem(id); + var fragments = id.split('.'); + var target = Function('return this;')(); + for (var i = 0; i < fragments.length - 1; ++i) { + if (target[fragments[i]] === undefined) + target[fragments[i]] = {}; + target = target[fragments[i]]; + } + target[fragments[fragments.length - 1]] = module; +}; + +var instantiate = function (id) { + var actual = defs[id]; + var dependencies = actual.deps; + var definition = actual.defn; + var len = dependencies.length; + var instances = new Array(len); + for (var i = 0; i < len; ++i) + instances[i] = dem(dependencies[i]); + var defResult = definition.apply(null, instances); + if (defResult === undefined) + throw 'module [' + id + '] returned undefined'; + actual.instance = defResult; +}; + +var def = function (id, dependencies, definition) { + if (typeof id !== 'string') + throw 'module id must be a string'; + else if (dependencies === undefined) + throw 'no dependencies for ' + id; + else if (definition === undefined) + throw 'no definition function for ' + id; + defs[id] = { + deps: dependencies, + defn: definition, + instance: undefined + }; +}; + +var dem = function (id) { + var actual = defs[id]; + if (actual === undefined) + throw 'module [' + id + '] was undefined'; + else if (actual.instance === undefined) + instantiate(id); + return actual.instance; +}; + +var req = function (ids, callback) { + var len = ids.length; + var instances = new Array(len); + for (var i = 0; i < len; ++i) + instances.push(dem(ids[i])); + callback.apply(null, callback); +}; + +var ephox = {}; + +ephox.bolt = { + module: { + api: { + define: def, + require: req, + demand: dem + } + } +}; + +var define = def; +var require = req; +var demand = dem; +// this helps with minificiation when using a lot of global references +var defineGlobal = function (id, ref) { + define(id, [], function () { return ref; }); +}; +/*jsc +["tinymce.plugins.link.Plugin","tinymce.core.PluginManager","tinymce.plugins.link.core.Actions","tinymce.plugins.link.ui.Controls","global!tinymce.util.Tools.resolve","tinymce.core.util.VK","tinymce.plugins.link.ui.Dialog","tinymce.plugins.link.core.OpenUrl","tinymce.plugins.link.core.Utils","tinymce.plugins.link.core.Settings","tinymce.core.util.Delay","tinymce.core.util.Tools","tinymce.core.util.XHR","global!RegExp","tinymce.core.dom.DOMUtils","tinymce.core.Env"] +jsc*/ +defineGlobal("global!tinymce.util.Tools.resolve", tinymce.util.Tools.resolve); +/** + * ResolveGlobal.js + * + * Released under LGPL License. + * Copyright (c) 1999-2017 Ephox Corp. All rights reserved + * + * License: http://www.tinymce.com/license + * Contributing: http://www.tinymce.com/contributing + */ + +define( + 'tinymce.core.PluginManager', + [ + 'global!tinymce.util.Tools.resolve' + ], + function (resolve) { + return resolve('tinymce.PluginManager'); + } +); + +/** + * ResolveGlobal.js + * + * Released under LGPL License. + * Copyright (c) 1999-2017 Ephox Corp. All rights reserved + * + * License: http://www.tinymce.com/license + * Contributing: http://www.tinymce.com/contributing + */ + +define( + 'tinymce.core.util.VK', + [ + 'global!tinymce.util.Tools.resolve' + ], + function (resolve) { + return resolve('tinymce.util.VK'); + } +); + +/** + * ResolveGlobal.js + * + * Released under LGPL License. + * Copyright (c) 1999-2017 Ephox Corp. All rights reserved + * + * License: http://www.tinymce.com/license + * Contributing: http://www.tinymce.com/contributing + */ + +define( + 'tinymce.core.util.Delay', + [ + 'global!tinymce.util.Tools.resolve' + ], + function (resolve) { + return resolve('tinymce.util.Delay'); + } +); + +/** + * ResolveGlobal.js + * + * Released under LGPL License. + * Copyright (c) 1999-2017 Ephox Corp. All rights reserved + * + * License: http://www.tinymce.com/license + * Contributing: http://www.tinymce.com/contributing + */ + +define( + 'tinymce.core.util.Tools', + [ + 'global!tinymce.util.Tools.resolve' + ], + function (resolve) { + return resolve('tinymce.util.Tools'); + } +); + +/** + * ResolveGlobal.js + * + * Released under LGPL License. + * Copyright (c) 1999-2017 Ephox Corp. All rights reserved + * + * License: http://www.tinymce.com/license + * Contributing: http://www.tinymce.com/contributing + */ + +define( + 'tinymce.core.util.XHR', + [ + 'global!tinymce.util.Tools.resolve' + ], + function (resolve) { + return resolve('tinymce.util.XHR'); + } +); + +define( + 'tinymce.plugins.link.core.Settings', + [ + + ], + function () { + var assumeExternalTargets = function (editorSettings) { + return typeof editorSettings.link_assume_external_targets === 'boolean' ? editorSettings.link_assume_external_targets : false; + }; + + var hasContextToolbar = function (editorSettings) { + return typeof editorSettings.link_context_toolbar === 'boolean' ? editorSettings.link_context_toolbar : false; + }; + + var getLinkList = function (editorSettings) { + return editorSettings.link_list; + }; + + var hasDefaultLinkTarget = function (editorSettings) { + return typeof editorSettings.default_link_target === 'string'; + }; + + var getDefaultLinkTarget = function (editorSettings) { + return editorSettings.default_link_target; + }; + + var getTargetList = function (editorSettings) { + return editorSettings.target_list; + }; + + var setTargetList = function (editor, list) { + editor.settings.target_list = list; + }; + + var shouldShowTargetList = function (editorSettings) { + return getTargetList(editorSettings) !== false; + }; + + var getRelList = function (editorSettings) { + return editorSettings.rel_list; + }; + + var hasRelList = function (editorSettings) { + return getRelList(editorSettings) !== undefined; + }; + + var getLinkClassList = function (editorSettings) { + return editorSettings.link_class_list; + }; + + var hasLinkClassList = function (editorSettings) { + return getLinkClassList(editorSettings) !== undefined; + }; + + var shouldShowLinkTitle = function (editorSettings) { + return editorSettings.link_title !== false; + }; + + var allowUnsafeLinkTarget = function (editorSettings) { + return typeof editorSettings.allow_unsafe_link_target === 'boolean' ? editorSettings.allow_unsafe_link_target : false; + }; + + return { + assumeExternalTargets: assumeExternalTargets, + hasContextToolbar: hasContextToolbar, + getLinkList: getLinkList, + hasDefaultLinkTarget: hasDefaultLinkTarget, + getDefaultLinkTarget: getDefaultLinkTarget, + getTargetList: getTargetList, + setTargetList: setTargetList, + shouldShowTargetList: shouldShowTargetList, + getRelList: getRelList, + hasRelList: hasRelList, + getLinkClassList: getLinkClassList, + hasLinkClassList: hasLinkClassList, + shouldShowLinkTitle: shouldShowLinkTitle, + allowUnsafeLinkTarget: allowUnsafeLinkTarget + }; + } +); + +defineGlobal("global!RegExp", RegExp); +/** + * Utils.js + * + * Released under LGPL License. + * Copyright (c) 1999-2017 Ephox Corp. All rights reserved + * + * License: http://www.tinymce.com/license + * Contributing: http://www.tinymce.com/contributing + */ + +define( + 'tinymce.plugins.link.core.Utils', + [ + 'tinymce.core.util.Tools', + 'tinymce.plugins.link.core.Settings', + 'global!RegExp' + ], + function (Tools, Settings, RegExp) { + + var toggleTargetRules = function (rel, isUnsafe) { + var rules = 'noopener'; + + var addTargetRules = function (rel) { + rel = removeTargetRules(rel); + return rel ? [rel, rules].join(' ') : rules; + }; + + var removeTargetRules = function (rel) { + var regExp = new RegExp('(' + rules.replace(' ', '|') + ')', 'g'); + if (rel) { + rel = Tools.trim(rel.replace(regExp, '')); + } + return rel ? rel : null; + }; + + return isUnsafe ? addTargetRules(rel) : removeTargetRules(rel); + }; + + + var trimCaretContainers = function (text) { + return text.replace(/\uFEFF/g, ''); + }; + + + var getAnchorElement = function (editor, selectedElm) { + selectedElm = selectedElm || editor.selection.getStart(); + if (isImageFigure(selectedElm)) { + // for an image conained in a figure we look for a link inside the selected element + return editor.dom.select('a[href]', selectedElm)[0]; + } else { + return editor.dom.getParent(selectedElm, 'a[href]'); + } + }; + + + var getAnchorText = function (selection, anchorElm) { + var text = anchorElm ? (anchorElm.innerText || anchorElm.textContent) : selection.getContent({ format: 'text' }); + return trimCaretContainers(text); + }; + + + var isLink = function (elm) { + return elm && elm.nodeName === 'A' && elm.href; + }; + + var hasLinks = function (elements) { + return Tools.grep(elements, isLink).length > 0; + }; + + + var isOnlyTextSelected = function (html) { + // Partial html and not a fully selected anchor element + if (/]+>[^<]+<\/a>$/.test(html) || html.indexOf('href=') == -1)) { + return false; + } + + return true; + }; + + + var isImageFigure = function (node) { + return node && node.nodeName === 'FIGURE' && /\bimage\b/i.test(node.className); + }; + + + var link = function (editor, attachState) { + return function (data) { + editor.undoManager.transact(function () { + var selectedElm = editor.selection.getNode(); + var anchorElm = getAnchorElement(editor, selectedElm); + + var linkAttrs = { + href: data.href, + target: data.target ? data.target : null, + rel: data.rel ? data.rel : null, + "class": data["class"] ? data["class"] : null, + title: data.title ? data.title : null + }; + + if (Settings.allowUnsafeLinkTarget(editor.settings) === false) { + linkAttrs.rel = toggleTargetRules(linkAttrs.rel, linkAttrs.target == '_blank'); + } + + if (data.href === attachState.href) { + attachState.attach(); + attachState = {}; + } + + if (anchorElm) { + editor.focus(); + + if (data.hasOwnProperty('text')) { + if ("innerText" in anchorElm) { + anchorElm.innerText = data.text; + } else { + anchorElm.textContent = data.text; + } + } + + editor.dom.setAttribs(anchorElm, linkAttrs); + + editor.selection.select(anchorElm); + editor.undoManager.add(); + } else { + if (isImageFigure(selectedElm)) { + linkImageFigure(editor, selectedElm, linkAttrs); + } else if (data.hasOwnProperty('text')) { + editor.insertContent(editor.dom.createHTML('a', linkAttrs, editor.dom.encode(data.text))); + } else { + editor.execCommand('mceInsertLink', false, linkAttrs); + } + } + }); + }; + }; + + + var unlink = function (editor) { + return function () { + editor.undoManager.transact(function () { + var node = editor.selection.getNode(); + if (isImageFigure(node)) { + unlinkImageFigure(editor, node); + } else { + editor.execCommand('unlink'); + } + }); + }; + }; + + + var unlinkImageFigure = function (editor, fig) { + var a, img; + img = editor.dom.select('img', fig)[0]; + if (img) { + a = editor.dom.getParents(img, 'a[href]', fig)[0]; + if (a) { + a.parentNode.insertBefore(img, a); + editor.dom.remove(a); + } + } + }; + + + var linkImageFigure = function (editor, fig, attrs) { + var a, img; + img = editor.dom.select('img', fig)[0]; + if (img) { + a = editor.dom.create('a', attrs); + img.parentNode.insertBefore(a, img); + a.appendChild(img); + } + }; + + return { + link: link, + unlink: unlink, + isLink: isLink, + hasLinks: hasLinks, + isOnlyTextSelected: isOnlyTextSelected, + getAnchorElement: getAnchorElement, + getAnchorText: getAnchorText + }; + } +); +/** + * Dialog.js + * + * Released under LGPL License. + * Copyright (c) 1999-2017 Ephox Corp. All rights reserved + * + * License: http://www.tinymce.com/license + * Contributing: http://www.tinymce.com/contributing + */ + +define( + 'tinymce.plugins.link.ui.Dialog', + [ + 'tinymce.core.util.Delay', + 'tinymce.core.util.Tools', + 'tinymce.core.util.XHR', + 'tinymce.plugins.link.core.Utils', + 'tinymce.plugins.link.core.Settings' + ], + function (Delay, Tools, XHR, Utils, Settings) { + var attachState = {}; + + var createLinkList = function (editor, callback) { + var linkList = Settings.getLinkList(editor.settings); + + if (typeof linkList == "string") { + XHR.send({ + url: linkList, + success: function (text) { + callback(editor, JSON.parse(text)); + } + }); + } else if (typeof linkList == "function") { + linkList(function (list) { + callback(editor, list); + }); + } else { + callback(editor, linkList); + } + }; + + var buildListItems = function (inputList, itemCallback, startItems) { + var appendItems = function (values, output) { + output = output || []; + + Tools.each(values, function (item) { + var menuItem = { text: item.text || item.title }; + + if (item.menu) { + menuItem.menu = appendItems(item.menu); + } else { + menuItem.value = item.value; + + if (itemCallback) { + itemCallback(menuItem); + } + } + + output.push(menuItem); + }); + + return output; + }; + + return appendItems(inputList, startItems || []); + }; + + // Delay confirm since onSubmit will move focus + var delayedConfirm = function (editor, message, callback) { + var rng = editor.selection.getRng(); + + Delay.setEditorTimeout(editor, function () { + editor.windowManager.confirm(message, function (state) { + editor.selection.setRng(rng); + callback(state); + }); + }); + }; + + var showDialog = function (editor, linkList) { + var data = {}, selection = editor.selection, dom = editor.dom, anchorElm, initialText; + var win, onlyText, textListCtrl, linkListCtrl, relListCtrl, targetListCtrl, classListCtrl, linkTitleCtrl, value; + + var linkListChangeHandler = function (e) { + var textCtrl = win.find('#text'); + + if (!textCtrl.value() || (e.lastControl && textCtrl.value() == e.lastControl.text())) { + textCtrl.value(e.control.text()); + } + + win.find('#href').value(e.control.value()); + }; + + var buildAnchorListControl = function (url) { + var anchorList = []; + + Tools.each(editor.dom.select('a:not([href])'), function (anchor) { + var id = anchor.name || anchor.id; + + if (id) { + anchorList.push({ + text: id, + value: '#' + id, + selected: url.indexOf('#' + id) != -1 + }); + } + }); + + if (anchorList.length) { + anchorList.unshift({ text: 'None', value: '' }); + + return { + name: 'anchor', + type: 'listbox', + label: 'Anchors', + values: anchorList, + onselect: linkListChangeHandler + }; + } + }; + + var updateText = function () { + if (!initialText && onlyText && !data.text) { + this.parent().parent().find('#text')[0].value(this.value()); + } + }; + + var urlChange = function (e) { + var meta = e.meta || {}; + + if (linkListCtrl) { + linkListCtrl.value(editor.convertURL(this.value(), 'href')); + } + + Tools.each(e.meta, function (value, key) { + var inp = win.find('#' + key); + + if (key === 'text') { + if (initialText.length === 0) { + inp.value(value); + data.text = value; + } + } else { + inp.value(value); + } + }); + + if (meta.attach) { + attachState = { + href: this.value(), + attach: meta.attach + }; + } + + if (!meta.text) { + updateText.call(this); + } + }; + + var onBeforeCall = function (e) { + e.meta = win.toJSON(); + }; + + onlyText = Utils.isOnlyTextSelected(selection.getContent()); + anchorElm = Utils.getAnchorElement(editor); + + data.text = initialText = Utils.getAnchorText(editor.selection, anchorElm); + data.href = anchorElm ? dom.getAttrib(anchorElm, 'href') : ''; + + if (anchorElm) { + data.target = dom.getAttrib(anchorElm, 'target'); + } else if (Settings.hasDefaultLinkTarget(editor.settings)) { + data.target = Settings.getDefaultLinkTarget(editor.settings); + } + + if ((value = dom.getAttrib(anchorElm, 'rel'))) { + data.rel = value; + } + + if ((value = dom.getAttrib(anchorElm, 'class'))) { + data['class'] = value; + } + + if ((value = dom.getAttrib(anchorElm, 'title'))) { + data.title = value; + } + + if (onlyText) { + textListCtrl = { + name: 'text', + type: 'textbox', + size: 40, + label: 'Text to display', + onchange: function () { + data.text = this.value(); + } + }; + } + + if (linkList) { + linkListCtrl = { + type: 'listbox', + label: 'Link list', + values: buildListItems( + linkList, + function (item) { + item.value = editor.convertURL(item.value || item.url, 'href'); + }, + [{ text: 'None', value: '' }] + ), + onselect: linkListChangeHandler, + value: editor.convertURL(data.href, 'href'), + onPostRender: function () { + /*eslint consistent-this:0*/ + linkListCtrl = this; + } + }; + } + + if (Settings.shouldShowTargetList(editor.settings)) { + if (Settings.getTargetList(editor.settings) === undefined) { + Settings.setTargetList(editor, [ + { text: 'None', value: '' }, + { text: 'New window', value: '_blank' } + ]); + } + + targetListCtrl = { + name: 'target', + type: 'listbox', + label: 'Target', + values: buildListItems(Settings.getTargetList(editor.settings)) + }; + } + + if (Settings.hasRelList(editor.settings)) { + relListCtrl = { + name: 'rel', + type: 'listbox', + label: 'Rel', + values: buildListItems(Settings.getRelList(editor.settings)) + }; + } + + if (Settings.hasLinkClassList(editor.settings)) { + classListCtrl = { + name: 'class', + type: 'listbox', + label: 'Class', + values: buildListItems( + Settings.getLinkClassList(editor.settings), + function (item) { + if (item.value) { + item.textStyle = function () { + return editor.formatter.getCssText({ inline: 'a', classes: [item.value] }); + }; + } + } + ) + }; + } + + if (Settings.shouldShowLinkTitle(editor.settings)) { + linkTitleCtrl = { + name: 'title', + type: 'textbox', + label: 'Title', + value: data.title + }; + } + + win = editor.windowManager.open({ + title: 'Insert link', + data: data, + body: [ + { + name: 'href', + type: 'filepicker', + filetype: 'file', + size: 40, + autofocus: true, + label: 'Url', + onchange: urlChange, + onkeyup: updateText, + onbeforecall: onBeforeCall + }, + textListCtrl, + linkTitleCtrl, + buildAnchorListControl(data.href), + linkListCtrl, + relListCtrl, + targetListCtrl, + classListCtrl + ], + onSubmit: function (e) { + var assumeExternalTargets = Settings.assumeExternalTargets(editor.settings); + var insertLink = Utils.link(editor, attachState); + var removeLink = Utils.unlink(editor); + + var resultData = Tools.extend({}, data, e.data); + /*eslint dot-notation: 0*/ + var href = resultData.href; + + if (!href) { + removeLink(); + return; + } + + if (!onlyText || resultData.text === initialText) { + delete resultData.text; + } + + // Is email and not //user@domain.com + if (href.indexOf('@') > 0 && href.indexOf('//') == -1 && href.indexOf('mailto:') == -1) { + delayedConfirm( + editor, + 'The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?', + function (state) { + if (state) { + resultData.href = 'mailto:' + href; + } + insertLink(resultData); + } + ); + return; + } + + // Is not protocol prefixed + if ((assumeExternalTargets === true && !/^\w+:/i.test(href)) || + (assumeExternalTargets === false && /^\s*www[\.|\d\.]/i.test(href))) { + delayedConfirm( + editor, + 'The URL you entered seems to be an external link. Do you want to add the required http:// prefix?', + function (state) { + if (state) { + resultData.href = 'http://' + href; + } + insertLink(resultData); + } + ); + return; + } + + insertLink(resultData); + } + }); + }; + + var open = function (editor) { + createLinkList(editor, showDialog); + }; + + return { + open: open + }; + } +); +/** + * ResolveGlobal.js + * + * Released under LGPL License. + * Copyright (c) 1999-2017 Ephox Corp. All rights reserved + * + * License: http://www.tinymce.com/license + * Contributing: http://www.tinymce.com/contributing + */ + +define( + 'tinymce.core.dom.DOMUtils', + [ + 'global!tinymce.util.Tools.resolve' + ], + function (resolve) { + return resolve('tinymce.dom.DOMUtils'); + } +); + +/** + * ResolveGlobal.js + * + * Released under LGPL License. + * Copyright (c) 1999-2017 Ephox Corp. All rights reserved + * + * License: http://www.tinymce.com/license + * Contributing: http://www.tinymce.com/contributing + */ + +define( + 'tinymce.core.Env', + [ + 'global!tinymce.util.Tools.resolve' + ], + function (resolve) { + return resolve('tinymce.Env'); + } +); + +/** + * OpenUrl.js + * + * Released under LGPL License. + * Copyright (c) 1999-2017 Ephox Corp. All rights reserved + * + * License: http://www.tinymce.com/license + * Contributing: http://www.tinymce.com/contributing + */ + +define( + 'tinymce.plugins.link.core.OpenUrl', + [ + 'tinymce.core.dom.DOMUtils', + 'tinymce.core.Env' + ], + function (DOMUtils, Env) { + var appendClickRemove = function (link, evt) { + document.body.appendChild(link); + link.dispatchEvent(evt); + document.body.removeChild(link); + }; + + var open = function (url) { + // Chrome and Webkit has implemented noopener and works correctly with/without popup blocker + // Firefox has it implemented noopener but when the popup blocker is activated it doesn't work + // Edge has only implemented noreferrer and it seems to remove opener as well + // Older IE versions pre IE 11 falls back to a window.open approach + if (!Env.ie || Env.ie > 10) { + var link = document.createElement('a'); + link.target = '_blank'; + link.href = url; + link.rel = 'noreferrer noopener'; + + var evt = document.createEvent('MouseEvents'); + evt.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); + + appendClickRemove(link, evt); + } else { + var win = window.open('', '_blank'); + if (win) { + win.opener = null; + var doc = win.document; + doc.open(); + doc.write(''); + doc.close(); + } + } + }; + + return { + open: open + }; + } +); +/** + * Actions.js + * + * Released under LGPL License. + * Copyright (c) 1999-2017 Ephox Corp. All rights reserved + * + * License: http://www.tinymce.com/license + * Contributing: http://www.tinymce.com/contributing + */ + +define( + 'tinymce.plugins.link.core.Actions', + [ + 'tinymce.core.util.VK', + 'tinymce.plugins.link.ui.Dialog', + 'tinymce.plugins.link.core.OpenUrl', + 'tinymce.plugins.link.core.Utils', + 'tinymce.plugins.link.core.Settings' + ], + function (VK, Dialog, OpenUrl, Utils, Settings) { + var getLink = function (editor, elm) { + return editor.dom.getParent(elm, 'a[href]'); + }; + + var getSelectedLink = function (editor) { + return getLink(editor, editor.selection.getStart()); + }; + + var getHref = function (elm) { + // Returns the real href value not the resolved a.href value + var href = elm.getAttribute('data-mce-href'); + return href ? href : elm.getAttribute('href'); + }; + + var isContextMenuVisible = function (editor) { + var contextmenu = editor.plugins.contextmenu; + return contextmenu ? contextmenu.isContextMenuVisible() : false; + }; + + var hasOnlyAltModifier = function (e) { + return e.altKey === true && e.shiftKey === false && e.ctrlKey === false && e.metaKey === false; + }; + + var gotoLink = function (editor, a) { + if (a) { + var href = getHref(a); + if (/^#/.test(href)) { + var targetEl = editor.$(href); + if (targetEl.length) { + editor.selection.scrollIntoView(targetEl[0], true); + } + } else { + OpenUrl.open(a.href); + } + } + }; + + var openDialog = function (editor) { + return function () { + Dialog.open(editor); + }; + }; + + var gotoSelectedLink = function (editor) { + return function () { + gotoLink(editor, getSelectedLink(editor)); + }; + }; + + var leftClickedOnAHref = function (editor) { + return function (elm) { + var sel, rng, node; + if (Settings.hasContextToolbar(editor.settings) && !isContextMenuVisible(editor) && Utils.isLink(elm)) { + sel = editor.selection; + rng = sel.getRng(); + node = rng.startContainer; + // ignore cursor positions at the beginning/end (to make context toolbar less noisy) + if (node.nodeType == 3 && sel.isCollapsed() && rng.startOffset > 0 && rng.startOffset < node.data.length) { + return true; + } + } + return false; + }; + }; + + var setupGotoLinks = function (editor) { + editor.on('click', function (e) { + var link = getLink(editor, e.target); + if (link && VK.metaKeyPressed(e)) { + e.preventDefault(); + gotoLink(editor, link); + } + }); + + editor.on('keydown', function (e) { + var link = getSelectedLink(editor); + if (link && e.keyCode === 13 && hasOnlyAltModifier(e)) { + e.preventDefault(); + gotoLink(editor, link); + } + }); + }; + + var toggleActiveState = function (editor) { + return function () { + var self = this; + editor.on('nodechange', function (e) { + self.active(!editor.readonly && !!Utils.getAnchorElement(editor, e.element)); + }); + }; + }; + + var toggleViewLinkState = function (editor) { + return function () { + var self = this; + + var toggleVisibility = function (e) { + if (Utils.hasLinks(e.parents)) { + self.show(); + } else { + self.hide(); + } + }; + + if (!Utils.hasLinks(editor.dom.getParents(editor.selection.getStart()))) { + self.hide(); + } + + editor.on('nodechange', toggleVisibility); + + self.on('remove', function () { + editor.off('nodechange', toggleVisibility); + }); + }; + }; + + return { + openDialog: openDialog, + gotoSelectedLink: gotoSelectedLink, + leftClickedOnAHref: leftClickedOnAHref, + setupGotoLinks: setupGotoLinks, + toggleActiveState: toggleActiveState, + toggleViewLinkState: toggleViewLinkState + }; + } +); +/** + * Controls.js + * + * Released under LGPL License. + * Copyright (c) 1999-2017 Ephox Corp. All rights reserved + * + * License: http://www.tinymce.com/license + * Contributing: http://www.tinymce.com/contributing + */ + +define( + 'tinymce.plugins.link.ui.Controls', + [ + 'tinymce.plugins.link.core.Actions', + 'tinymce.plugins.link.core.Utils' + ], + function (Actions, Utils) { + + var setupButtons = function (editor) { + editor.addButton('link', { + icon: 'link', + tooltip: 'Insert/edit link', + shortcut: 'Meta+K', + onclick: Actions.openDialog(editor), + onpostrender: Actions.toggleActiveState(editor) + }); + + editor.addButton('unlink', { + icon: 'unlink', + tooltip: 'Remove link', + onclick: Utils.unlink(editor), + onpostrender: Actions.toggleActiveState(editor) + }); + + if (editor.addContextToolbar) { + editor.addButton('openlink', { + icon: 'newtab', + tooltip: 'Open link', + onclick: Actions.gotoSelectedLink(editor) + }); + } + }; + + var setupMenuItems = function (editor) { + editor.addMenuItem('openlink', { + text: 'Open link', + icon: 'newtab', + onclick: Actions.gotoSelectedLink(editor), + onPostRender: Actions.toggleViewLinkState(editor), + prependToContext: true + }); + + editor.addMenuItem('link', { + icon: 'link', + text: 'Link', + shortcut: 'Meta+K', + onclick: Actions.openDialog(editor), + stateSelector: 'a[href]', + context: 'insert', + prependToContext: true + }); + }; + + var setupContextToolbars = function (editor) { + if (editor.addContextToolbar) { + editor.addContextToolbar( + Actions.leftClickedOnAHref(editor), + 'openlink | link unlink' + ); + } + }; + + return { + setupButtons: setupButtons, + setupMenuItems: setupMenuItems, + setupContextToolbars: setupContextToolbars + }; + } +); +/** + * Plugin.js + * + * Released under LGPL License. + * Copyright (c) 1999-2017 Ephox Corp. All rights reserved + * + * License: http://www.tinymce.com/license + * Contributing: http://www.tinymce.com/contributing + */ + +define( + 'tinymce.plugins.link.Plugin', + [ + 'tinymce.core.PluginManager', + 'tinymce.plugins.link.core.Actions', + 'tinymce.plugins.link.ui.Controls' + ], + function (PluginManager, Actions, Controls) { + PluginManager.add('link', function (editor) { + Controls.setupButtons(editor); + Controls.setupMenuItems(editor); + Controls.setupContextToolbars(editor); + Actions.setupGotoLinks(editor); + editor.addShortcut('Meta+K', '', Actions.openDialog(editor)); + editor.addCommand('mceLink', Actions.openDialog(editor)); + }); + + return function () { }; + } +); +dem('tinymce.plugins.link.Plugin')(); +})(); diff --git a/src/wp-includes/js/tinymce/plugins/link/plugin.min.js b/src/wp-includes/js/tinymce/plugins/link/plugin.min.js new file mode 100644 index 0000000000..37b1eab4be --- /dev/null +++ b/src/wp-includes/js/tinymce/plugins/link/plugin.min.js @@ -0,0 +1 @@ +!function(){var a={},b=function(b){for(var c=a[b],e=c.deps,f=c.defn,g=e.length,h=new Array(g),i=0;i0},j=function(a){return!(/]+>[^<]+<\/a>$/.test(a)||a.indexOf("href=")==-1))},k=function(a){return a&&"FIGURE"===a.nodeName&&/\bimage\b/i.test(a.className)},l=function(a,c){return function(e){a.undoManager.transact(function(){var g=a.selection.getNode(),h=f(a,g),i={href:e.href,target:e.target?e.target:null,rel:e.rel?e.rel:null,"class":e["class"]?e["class"]:null,title:e.title?e.title:null};b.allowUnsafeLinkTarget(a.settings)===!1&&(i.rel=d(i.rel,"_blank"==i.target)),e.href===c.href&&(c.attach(),c={}),h?(a.focus(),e.hasOwnProperty("text")&&("innerText"in h?h.innerText=e.text:h.textContent=e.text),a.dom.setAttribs(h,i),a.selection.select(h),a.undoManager.add()):k(g)?o(a,g,i):e.hasOwnProperty("text")?a.insertContent(a.dom.createHTML("a",i,a.dom.encode(e.text))):a.execCommand("mceInsertLink",!1,i)})}},m=function(a){return function(){a.undoManager.transact(function(){var b=a.selection.getNode();k(b)?n(a,b):a.execCommand("unlink")})}},n=function(a,b){var c,d;d=a.dom.select("img",b)[0],d&&(c=a.dom.getParents(d,"a[href]",b)[0],c&&(c.parentNode.insertBefore(d,c),a.dom.remove(c)))},o=function(a,b,c){var d,e;e=a.dom.select("img",b)[0],e&&(d=a.dom.create("a",c),e.parentNode.insertBefore(d,e),d.appendChild(e))};return{link:l,unlink:m,isLink:h,hasLinks:i,isOnlyTextSelected:j,getAnchorElement:f,getAnchorText:g}}),g("6",["a","b","c","8","9"],function(a,b,c,d,e){var f={},g=function(a,b){var d=e.getLinkList(a.settings);"string"==typeof d?c.send({url:d,success:function(c){b(a,JSON.parse(c))}}):"function"==typeof d?d(function(c){b(a,c)}):b(a,d)},h=function(a,c,d){var e=function(a,d){return d=d||[],b.each(a,function(a){var b={text:a.text||a.title};a.menu?b.menu=e(a.menu):(b.value=a.value,c&&c(b)),d.push(b)}),d};return e(a,d||[])},i=function(b,c,d){var e=b.selection.getRng();a.setEditorTimeout(b,function(){b.windowManager.confirm(c,function(a){b.selection.setRng(e),d(a)})})},j=function(a,c){var g,j,k,l,m,n,o,p,q,r,s,t={},u=a.selection,v=a.dom,w=function(a){var b=k.find("#text");(!b.value()||a.lastControl&&b.value()==a.lastControl.text())&&b.value(a.control.text()),k.find("#href").value(a.control.value())},x=function(c){var d=[];if(b.each(a.dom.select("a:not([href])"),function(a){var b=a.name||a.id;b&&d.push({text:b,value:"#"+b,selected:c.indexOf("#"+b)!=-1})}),d.length)return d.unshift({text:"None",value:""}),{name:"anchor",type:"listbox",label:"Anchors",values:d,onselect:w}},y=function(){j||!l||t.text||this.parent().parent().find("#text")[0].value(this.value())},z=function(c){var d=c.meta||{};n&&n.value(a.convertURL(this.value(),"href")),b.each(c.meta,function(a,b){var c=k.find("#"+b);"text"===b?0===j.length&&(c.value(a),t.text=a):c.value(a)}),d.attach&&(f={href:this.value(),attach:d.attach}),d.text||y.call(this)},A=function(a){a.meta=k.toJSON()};l=d.isOnlyTextSelected(u.getContent()),g=d.getAnchorElement(a),t.text=j=d.getAnchorText(a.selection,g),t.href=g?v.getAttrib(g,"href"):"",g?t.target=v.getAttrib(g,"target"):e.hasDefaultLinkTarget(a.settings)&&(t.target=e.getDefaultLinkTarget(a.settings)),(s=v.getAttrib(g,"rel"))&&(t.rel=s),(s=v.getAttrib(g,"class"))&&(t["class"]=s),(s=v.getAttrib(g,"title"))&&(t.title=s),l&&(m={name:"text",type:"textbox",size:40,label:"Text to display",onchange:function(){t.text=this.value()}}),c&&(n={type:"listbox",label:"Link list",values:h(c,function(b){b.value=a.convertURL(b.value||b.url,"href")},[{text:"None",value:""}]),onselect:w,value:a.convertURL(t.href,"href"),onPostRender:function(){n=this}}),e.shouldShowTargetList(a.settings)&&(void 0===e.getTargetList(a.settings)&&e.setTargetList(a,[{text:"None",value:""},{text:"New window",value:"_blank"}]),p={name:"target",type:"listbox",label:"Target",values:h(e.getTargetList(a.settings))}),e.hasRelList(a.settings)&&(o={name:"rel",type:"listbox",label:"Rel",values:h(e.getRelList(a.settings))}),e.hasLinkClassList(a.settings)&&(q={name:"class",type:"listbox",label:"Class",values:h(e.getLinkClassList(a.settings),function(b){b.value&&(b.textStyle=function(){return a.formatter.getCssText({inline:"a",classes:[b.value]})})})}),e.shouldShowLinkTitle(a.settings)&&(r={name:"title",type:"textbox",label:"Title",value:t.title}),k=a.windowManager.open({title:"Insert link",data:t,body:[{name:"href",type:"filepicker",filetype:"file",size:40,autofocus:!0,label:"Url",onchange:z,onkeyup:y,onbeforecall:A},m,r,x(t.href),n,o,p,q],onSubmit:function(c){var g=e.assumeExternalTargets(a.settings),h=d.link(a,f),k=d.unlink(a),m=b.extend({},t,c.data),n=m.href;return n?(l&&m.text!==j||delete m.text,n.indexOf("@")>0&&n.indexOf("//")==-1&&n.indexOf("mailto:")==-1?void i(a,"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?",function(a){a&&(m.href="mailto:"+n),h(m)}):g===!0&&!/^\w+:/i.test(n)||g===!1&&/^\s*www[\.|\d\.]/i.test(n)?void i(a,"The URL you entered seems to be an external link. Do you want to add the required http:// prefix?",function(a){a&&(m.href="http://"+n),h(m)}):void h(m)):void k()}})},k=function(a){g(a,j)};return{open:k}}),g("e",["4"],function(a){return a("tinymce.dom.DOMUtils")}),g("f",["4"],function(a){return a("tinymce.Env")}),g("7",["e","f"],function(a,b){var c=function(a,b){document.body.appendChild(a),a.dispatchEvent(b),document.body.removeChild(a)},d=function(d){if(!b.ie||b.ie>10){var e=document.createElement("a");e.target="_blank",e.href=d,e.rel="noreferrer noopener";var f=document.createEvent("MouseEvents");f.initMouseEvent("click",!0,!0,window,0,0,0,0,0,!1,!1,!1,!1,0,null),c(e,f)}else{var g=window.open("","_blank");if(g){g.opener=null;var h=g.document;h.open(),h.write(''),h.close()}}};return{open:d}}),g("2",["5","6","7","8","9"],function(a,b,c,d,e){var f=function(a,b){return a.dom.getParent(b,"a[href]")},g=function(a){return f(a,a.selection.getStart())},h=function(a){var b=a.getAttribute("data-mce-href");return b?b:a.getAttribute("href")},i=function(a){var b=a.plugins.contextmenu;return!!b&&b.isContextMenuVisible()},j=function(a){return a.altKey===!0&&a.shiftKey===!1&&a.ctrlKey===!1&&a.metaKey===!1},k=function(a,b){if(b){var d=h(b);if(/^#/.test(d)){var e=a.$(d);e.length&&a.selection.scrollIntoView(e[0],!0)}else c.open(b.href)}},l=function(a){return function(){b.open(a)}},m=function(a){return function(){k(a,g(a))}},n=function(a){return function(b){var c,f,g;return!!(e.hasContextToolbar(a.settings)&&!i(a)&&d.isLink(b)&&(c=a.selection,f=c.getRng(),g=f.startContainer,3==g.nodeType&&c.isCollapsed()&&f.startOffset>0&&f.startOffset