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