123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- /**
- * TinyMCE version 6.4.2 (2023-04-26)
- */
- (function () {
- 'use strict';
- var global$1 = tinymce.util.Tools.resolve('tinymce.PluginManager');
- const link = () => /(?:[A-Za-z][A-Za-z\d.+-]{0,14}:\/\/(?:[-.~*+=!&;:'%@?^${}(),\w]+@)?|www\.|[-;:&=+$,.\w]+@)[A-Za-z\d-]+(?:\.[A-Za-z\d-]+)*(?::\d+)?(?:\/(?:[-.~*+=!;:'%@$(),\/\w]*[-~*+=%@$()\/\w])?)?(?:\?(?:[-.~*+=!&;:'%@?^${}(),\/\w]+))?(?:#(?:[-.~*+=!&;:'%@?^${}(),\/\w]+))?/g;
- const option = name => editor => editor.options.get(name);
- const register = editor => {
- const registerOption = editor.options.register;
- registerOption('autolink_pattern', {
- processor: 'regexp',
- default: new RegExp('^' + link().source + '$', 'i')
- });
- registerOption('link_default_target', { processor: 'string' });
- registerOption('link_default_protocol', {
- processor: 'string',
- default: 'https'
- });
- };
- const getAutoLinkPattern = option('autolink_pattern');
- const getDefaultLinkTarget = option('link_default_target');
- const getDefaultLinkProtocol = option('link_default_protocol');
- const allowUnsafeLinkTarget = option('allow_unsafe_link_target');
- const hasProto = (v, constructor, predicate) => {
- var _a;
- if (predicate(v, constructor.prototype)) {
- return true;
- } else {
- return ((_a = v.constructor) === null || _a === void 0 ? void 0 : _a.name) === constructor.name;
- }
- };
- const typeOf = x => {
- const t = typeof x;
- if (x === null) {
- return 'null';
- } else if (t === 'object' && Array.isArray(x)) {
- return 'array';
- } else if (t === 'object' && hasProto(x, String, (o, proto) => proto.isPrototypeOf(o))) {
- return 'string';
- } else {
- return t;
- }
- };
- const isType = type => value => typeOf(value) === type;
- const eq = t => a => t === a;
- const isString = isType('string');
- const isUndefined = eq(undefined);
- const isNullable = a => a === null || a === undefined;
- const isNonNullable = a => !isNullable(a);
- const not = f => t => !f(t);
- const hasOwnProperty = Object.hasOwnProperty;
- const has = (obj, key) => hasOwnProperty.call(obj, key);
- const checkRange = (str, substr, start) => substr === '' || str.length >= substr.length && str.substr(start, start + substr.length) === substr;
- const contains = (str, substr, start = 0, end) => {
- const idx = str.indexOf(substr, start);
- if (idx !== -1) {
- return isUndefined(end) ? true : idx + substr.length <= end;
- } else {
- return false;
- }
- };
- const startsWith = (str, prefix) => {
- return checkRange(str, prefix, 0);
- };
- const zeroWidth = '\uFEFF';
- const isZwsp = char => char === zeroWidth;
- const removeZwsp = s => s.replace(/\uFEFF/g, '');
- var global = tinymce.util.Tools.resolve('tinymce.dom.TextSeeker');
- const isTextNode = node => node.nodeType === 3;
- const isElement = node => node.nodeType === 1;
- const isBracketOrSpace = char => /^[(\[{ \u00a0]$/.test(char);
- const hasProtocol = url => /^([A-Za-z][A-Za-z\d.+-]*:\/\/)|mailto:/.test(url);
- const isPunctuation = char => /[?!,.;:]/.test(char);
- const findChar = (text, index, predicate) => {
- for (let i = index - 1; i >= 0; i--) {
- const char = text.charAt(i);
- if (!isZwsp(char) && predicate(char)) {
- return i;
- }
- }
- return -1;
- };
- const freefallRtl = (container, offset) => {
- let tempNode = container;
- let tempOffset = offset;
- while (isElement(tempNode) && tempNode.childNodes[tempOffset]) {
- tempNode = tempNode.childNodes[tempOffset];
- tempOffset = isTextNode(tempNode) ? tempNode.data.length : tempNode.childNodes.length;
- }
- return {
- container: tempNode,
- offset: tempOffset
- };
- };
- const parseCurrentLine = (editor, offset) => {
- var _a;
- const voidElements = editor.schema.getVoidElements();
- const autoLinkPattern = getAutoLinkPattern(editor);
- const {dom, selection} = editor;
- if (dom.getParent(selection.getNode(), 'a[href]') !== null) {
- return null;
- }
- const rng = selection.getRng();
- const textSeeker = global(dom, node => {
- return dom.isBlock(node) || has(voidElements, node.nodeName.toLowerCase()) || dom.getContentEditable(node) === 'false';
- });
- const {
- container: endContainer,
- offset: endOffset
- } = freefallRtl(rng.endContainer, rng.endOffset);
- const root = (_a = dom.getParent(endContainer, dom.isBlock)) !== null && _a !== void 0 ? _a : dom.getRoot();
- const endSpot = textSeeker.backwards(endContainer, endOffset + offset, (node, offset) => {
- const text = node.data;
- const idx = findChar(text, offset, not(isBracketOrSpace));
- return idx === -1 || isPunctuation(text[idx]) ? idx : idx + 1;
- }, root);
- if (!endSpot) {
- return null;
- }
- let lastTextNode = endSpot.container;
- const startSpot = textSeeker.backwards(endSpot.container, endSpot.offset, (node, offset) => {
- lastTextNode = node;
- const idx = findChar(node.data, offset, isBracketOrSpace);
- return idx === -1 ? idx : idx + 1;
- }, root);
- const newRng = dom.createRng();
- if (!startSpot) {
- newRng.setStart(lastTextNode, 0);
- } else {
- newRng.setStart(startSpot.container, startSpot.offset);
- }
- newRng.setEnd(endSpot.container, endSpot.offset);
- const rngText = removeZwsp(newRng.toString());
- const matches = rngText.match(autoLinkPattern);
- if (matches) {
- let url = matches[0];
- if (startsWith(url, 'www.')) {
- const protocol = getDefaultLinkProtocol(editor);
- url = protocol + '://' + url;
- } else if (contains(url, '@') && !hasProtocol(url)) {
- url = 'mailto:' + url;
- }
- return {
- rng: newRng,
- url
- };
- } else {
- return null;
- }
- };
- const convertToLink = (editor, result) => {
- const {dom, selection} = editor;
- const {rng, url} = result;
- const bookmark = selection.getBookmark();
- selection.setRng(rng);
- const command = 'createlink';
- const args = {
- command,
- ui: false,
- value: url
- };
- const beforeExecEvent = editor.dispatch('BeforeExecCommand', args);
- if (!beforeExecEvent.isDefaultPrevented()) {
- editor.getDoc().execCommand(command, false, url);
- editor.dispatch('ExecCommand', args);
- const defaultLinkTarget = getDefaultLinkTarget(editor);
- if (isString(defaultLinkTarget)) {
- const anchor = selection.getNode();
- dom.setAttrib(anchor, 'target', defaultLinkTarget);
- if (defaultLinkTarget === '_blank' && !allowUnsafeLinkTarget(editor)) {
- dom.setAttrib(anchor, 'rel', 'noopener');
- }
- }
- }
- selection.moveToBookmark(bookmark);
- editor.nodeChanged();
- };
- const handleSpacebar = editor => {
- const result = parseCurrentLine(editor, -1);
- if (isNonNullable(result)) {
- convertToLink(editor, result);
- }
- };
- const handleBracket = handleSpacebar;
- const handleEnter = editor => {
- const result = parseCurrentLine(editor, 0);
- if (isNonNullable(result)) {
- convertToLink(editor, result);
- }
- };
- const setup = editor => {
- editor.on('keydown', e => {
- if (e.keyCode === 13 && !e.isDefaultPrevented()) {
- handleEnter(editor);
- }
- });
- editor.on('keyup', e => {
- if (e.keyCode === 32) {
- handleSpacebar(editor);
- } else if (e.keyCode === 48 && e.shiftKey || e.keyCode === 221) {
- handleBracket(editor);
- }
- });
- };
- var Plugin = () => {
- global$1.add('autolink', editor => {
- register(editor);
- setup(editor);
- });
- };
- Plugin();
- })();
|