PageSourceSearch

https://admin.51microshop.com/tinymce/plugins/anchor/plugin.js

js 51microshop.com collected 2026-10-04 00:20:00 UTC 6,447 bytes, 214 lines download raw bytes

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.