Subversion Repositories oidplus

Rev

Rev 1422 | View as "text/javascript" | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /**
  2.  * Copyright (c) Tiny Technologies, Inc. All rights reserved.
  3.  * Licensed under the LGPL or a commercial license.
  4.  * For LGPL see License.txt in the project root for license information.
  5.  * For commercial licenses see https://www.tiny.cloud/
  6.  *
  7.  * Version: 5.10.9 (2023-11-15)
  8.  */
  9. (function () {
  10.     'use strict';
  11.  
  12.     var global$2 = tinymce.util.Tools.resolve('tinymce.PluginManager');
  13.  
  14.     var global$1 = tinymce.util.Tools.resolve('tinymce.dom.RangeUtils');
  15.  
  16.     var global = tinymce.util.Tools.resolve('tinymce.util.Tools');
  17.  
  18.     var allowHtmlInNamedAnchor = function (editor) {
  19.       return editor.getParam('allow_html_in_named_anchor', false, 'boolean');
  20.     };
  21.  
  22.     var namedAnchorSelector = 'a:not([href])';
  23.     var isEmptyString = function (str) {
  24.       return !str;
  25.     };
  26.     var getIdFromAnchor = function (elm) {
  27.       var id = elm.getAttribute('id') || elm.getAttribute('name');
  28.       return id || '';
  29.     };
  30.     var isAnchor = function (elm) {
  31.       return elm && elm.nodeName.toLowerCase() === 'a';
  32.     };
  33.     var isNamedAnchor = function (elm) {
  34.       return isAnchor(elm) && !elm.getAttribute('href') && getIdFromAnchor(elm) !== '';
  35.     };
  36.     var isEmptyNamedAnchor = function (elm) {
  37.       return isNamedAnchor(elm) && !elm.firstChild;
  38.     };
  39.  
  40.     var removeEmptyNamedAnchorsInSelection = function (editor) {
  41.       var dom = editor.dom;
  42.       global$1(dom).walk(editor.selection.getRng(), function (nodes) {
  43.         global.each(nodes, function (node) {
  44.           if (isEmptyNamedAnchor(node)) {
  45.             dom.remove(node, false);
  46.           }
  47.         });
  48.       });
  49.     };
  50.     var isValidId = function (id) {
  51.       return /^[A-Za-z][A-Za-z0-9\-:._]*$/.test(id);
  52.     };
  53.     var getNamedAnchor = function (editor) {
  54.       return editor.dom.getParent(editor.selection.getStart(), namedAnchorSelector);
  55.     };
  56.     var getId = function (editor) {
  57.       var anchor = getNamedAnchor(editor);
  58.       if (anchor) {
  59.         return getIdFromAnchor(anchor);
  60.       } else {
  61.         return '';
  62.       }
  63.     };
  64.     var createAnchor = function (editor, id) {
  65.       editor.undoManager.transact(function () {
  66.         if (!allowHtmlInNamedAnchor(editor)) {
  67.           editor.selection.collapse(true);
  68.         }
  69.         if (editor.selection.isCollapsed()) {
  70.           editor.insertContent(editor.dom.createHTML('a', { id: id }));
  71.         } else {
  72.           removeEmptyNamedAnchorsInSelection(editor);
  73.           editor.formatter.remove('namedAnchor', null, null, true);
  74.           editor.formatter.apply('namedAnchor', { value: id });
  75.           editor.addVisual();
  76.         }
  77.       });
  78.     };
  79.     var updateAnchor = function (editor, id, anchorElement) {
  80.       anchorElement.removeAttribute('name');
  81.       anchorElement.id = id;
  82.       editor.addVisual();
  83.       editor.undoManager.add();
  84.     };
  85.     var insert = function (editor, id) {
  86.       var anchor = getNamedAnchor(editor);
  87.       if (anchor) {
  88.         updateAnchor(editor, id, anchor);
  89.       } else {
  90.         createAnchor(editor, id);
  91.       }
  92.       editor.focus();
  93.     };
  94.  
  95.     var insertAnchor = function (editor, newId) {
  96.       if (!isValidId(newId)) {
  97.         editor.windowManager.alert('Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.');
  98.         return false;
  99.       } else {
  100.         insert(editor, newId);
  101.         return true;
  102.       }
  103.     };
  104.     var open = function (editor) {
  105.       var currentId = getId(editor);
  106.       editor.windowManager.open({
  107.         title: 'Anchor',
  108.         size: 'normal',
  109.         body: {
  110.           type: 'panel',
  111.           items: [{
  112.               name: 'id',
  113.               type: 'input',
  114.               label: 'ID',
  115.               placeholder: 'example'
  116.             }]
  117.         },
  118.         buttons: [
  119.           {
  120.             type: 'cancel',
  121.             name: 'cancel',
  122.             text: 'Cancel'
  123.           },
  124.           {
  125.             type: 'submit',
  126.             name: 'save',
  127.             text: 'Save',
  128.             primary: true
  129.           }
  130.         ],
  131.         initialData: { id: currentId },
  132.         onSubmit: function (api) {
  133.           if (insertAnchor(editor, api.getData().id)) {
  134.             api.close();
  135.           }
  136.         }
  137.       });
  138.     };
  139.  
  140.     var register$1 = function (editor) {
  141.       editor.addCommand('mceAnchor', function () {
  142.         open(editor);
  143.       });
  144.     };
  145.  
  146.     var isNamedAnchorNode = function (node) {
  147.       return node && isEmptyString(node.attr('href')) && !isEmptyString(node.attr('id') || node.attr('name'));
  148.     };
  149.     var isEmptyNamedAnchorNode = function (node) {
  150.       return isNamedAnchorNode(node) && !node.firstChild;
  151.     };
  152.     var setContentEditable = function (state) {
  153.       return function (nodes) {
  154.         for (var i = 0; i < nodes.length; i++) {
  155.           var node = nodes[i];
  156.           if (isEmptyNamedAnchorNode(node)) {
  157.             node.attr('contenteditable', state);
  158.           }
  159.         }
  160.       };
  161.     };
  162.     var setup = function (editor) {
  163.       editor.on('PreInit', function () {
  164.         editor.parser.addNodeFilter('a', setContentEditable('false'));
  165.         editor.serializer.addNodeFilter('a', setContentEditable(null));
  166.       });
  167.     };
  168.  
  169.     var registerFormats = function (editor) {
  170.       editor.formatter.register('namedAnchor', {
  171.         inline: 'a',
  172.         selector: namedAnchorSelector,
  173.         remove: 'all',
  174.         split: true,
  175.         deep: true,
  176.         attributes: { id: '%value' },
  177.         onmatch: function (node, _fmt, _itemName) {
  178.           return isNamedAnchor(node);
  179.         }
  180.       });
  181.     };
  182.  
  183.     var register = function (editor) {
  184.       editor.ui.registry.addToggleButton('anchor', {
  185.         icon: 'bookmark',
  186.         tooltip: 'Anchor',
  187.         onAction: function () {
  188.           return editor.execCommand('mceAnchor');
  189.         },
  190.         onSetup: function (buttonApi) {
  191.           return editor.selection.selectorChangedWithUnbind('a:not([href])', buttonApi.setActive).unbind;
  192.         }
  193.       });
  194.       editor.ui.registry.addMenuItem('anchor', {
  195.         icon: 'bookmark',
  196.         text: 'Anchor...',
  197.         onAction: function () {
  198.           return editor.execCommand('mceAnchor');
  199.         }
  200.       });
  201.     };
  202.  
  203.     function Plugin () {
  204.       global$2.add('anchor', function (editor) {
  205.         setup(editor);
  206.         register$1(editor);
  207.         register(editor);
  208.         editor.on('PreInit', function () {
  209.           registerFormats(editor);
  210.         });
  211.       });
  212.     }
  213.  
  214.     Plugin();
  215.  
  216. }());
  217.