Rev 1042 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
597 | daniel-mar | 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 | * |
||
1422 | daniel-mar | 7 | * Version: 5.10.8 (2023-10-19) |
597 | daniel-mar | 8 | */ |
9 | (function () { |
||
10 | 'use strict'; |
||
11 | |||
637 | daniel-mar | 12 | var global$1 = tinymce.util.Tools.resolve('tinymce.PluginManager'); |
597 | daniel-mar | 13 | |
637 | daniel-mar | 14 | var checkRange = function (str, substr, start) { |
15 | return substr === '' || str.length >= substr.length && str.substr(start, start + substr.length) === substr; |
||
16 | }; |
||
17 | var contains = function (str, substr) { |
||
18 | return str.indexOf(substr) !== -1; |
||
19 | }; |
||
20 | var startsWith = function (str, prefix) { |
||
21 | return checkRange(str, prefix, 0); |
||
22 | }; |
||
597 | daniel-mar | 23 | |
637 | daniel-mar | 24 | var global = tinymce.util.Tools.resolve('tinymce.Env'); |
25 | |||
26 | var link = function () { |
||
1021 | daniel-mar | 27 | return /(?:[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; |
637 | daniel-mar | 28 | }; |
29 | |||
30 | var defaultLinkPattern = new RegExp('^' + link().source + '$', 'i'); |
||
597 | daniel-mar | 31 | var getAutoLinkPattern = function (editor) { |
637 | daniel-mar | 32 | return editor.getParam('autolink_pattern', defaultLinkPattern); |
597 | daniel-mar | 33 | }; |
34 | var getDefaultLinkTarget = function (editor) { |
||
35 | return editor.getParam('default_link_target', false); |
||
36 | }; |
||
37 | var getDefaultLinkProtocol = function (editor) { |
||
38 | return editor.getParam('link_default_protocol', 'http', 'string'); |
||
39 | }; |
||
40 | |||
679 | daniel-mar | 41 | var rangeEqualsBracketOrSpace = function (rangeString) { |
42 | return /^[(\[{ \u00a0]$/.test(rangeString); |
||
597 | daniel-mar | 43 | }; |
679 | daniel-mar | 44 | var isTextNode = function (node) { |
45 | return node.nodeType === 3; |
||
597 | daniel-mar | 46 | }; |
679 | daniel-mar | 47 | var isElement = function (node) { |
48 | return node.nodeType === 1; |
||
49 | }; |
||
50 | var handleBracket = function (editor) { |
||
51 | return parseCurrentLine(editor, -1); |
||
52 | }; |
||
597 | daniel-mar | 53 | var handleSpacebar = function (editor) { |
679 | daniel-mar | 54 | return parseCurrentLine(editor, 0); |
597 | daniel-mar | 55 | }; |
56 | var handleEnter = function (editor) { |
||
679 | daniel-mar | 57 | return parseCurrentLine(editor, -1); |
597 | daniel-mar | 58 | }; |
59 | var scopeIndex = function (container, index) { |
||
60 | if (index < 0) { |
||
61 | index = 0; |
||
62 | } |
||
679 | daniel-mar | 63 | if (isTextNode(container)) { |
597 | daniel-mar | 64 | var len = container.data.length; |
65 | if (index > len) { |
||
66 | index = len; |
||
67 | } |
||
68 | } |
||
69 | return index; |
||
70 | }; |
||
71 | var setStart = function (rng, container, offset) { |
||
679 | daniel-mar | 72 | if (!isElement(container) || container.hasChildNodes()) { |
597 | daniel-mar | 73 | rng.setStart(container, scopeIndex(container, offset)); |
74 | } else { |
||
75 | rng.setStartBefore(container); |
||
76 | } |
||
77 | }; |
||
78 | var setEnd = function (rng, container, offset) { |
||
679 | daniel-mar | 79 | if (!isElement(container) || container.hasChildNodes()) { |
597 | daniel-mar | 80 | rng.setEnd(container, scopeIndex(container, offset)); |
81 | } else { |
||
82 | rng.setEndAfter(container); |
||
83 | } |
||
84 | }; |
||
637 | daniel-mar | 85 | var hasProtocol = function (url) { |
86 | return /^([A-Za-z][A-Za-z\d.+-]*:\/\/)|mailto:/.test(url); |
||
87 | }; |
||
88 | var isPunctuation = function (char) { |
||
89 | return /[?!,.;:]/.test(char); |
||
90 | }; |
||
679 | daniel-mar | 91 | var parseCurrentLine = function (editor, endOffset) { |
597 | daniel-mar | 92 | var end, endContainer, bookmark, text, prev, len, rngText; |
93 | var autoLinkPattern = getAutoLinkPattern(editor); |
||
94 | var defaultLinkTarget = getDefaultLinkTarget(editor); |
||
679 | daniel-mar | 95 | if (editor.dom.getParent(editor.selection.getNode(), 'a[href]') !== null) { |
597 | daniel-mar | 96 | return; |
97 | } |
||
98 | var rng = editor.selection.getRng().cloneRange(); |
||
99 | if (rng.startOffset < 5) { |
||
100 | prev = rng.endContainer.previousSibling; |
||
101 | if (!prev) { |
||
102 | if (!rng.endContainer.firstChild || !rng.endContainer.firstChild.nextSibling) { |
||
103 | return; |
||
104 | } |
||
105 | prev = rng.endContainer.firstChild.nextSibling; |
||
106 | } |
||
107 | len = prev.length; |
||
108 | setStart(rng, prev, len); |
||
109 | setEnd(rng, prev, len); |
||
110 | if (rng.endOffset < 5) { |
||
111 | return; |
||
112 | } |
||
113 | end = rng.endOffset; |
||
114 | endContainer = prev; |
||
115 | } else { |
||
116 | endContainer = rng.endContainer; |
||
679 | daniel-mar | 117 | if (!isTextNode(endContainer) && endContainer.firstChild) { |
118 | while (!isTextNode(endContainer) && endContainer.firstChild) { |
||
597 | daniel-mar | 119 | endContainer = endContainer.firstChild; |
120 | } |
||
679 | daniel-mar | 121 | if (isTextNode(endContainer)) { |
597 | daniel-mar | 122 | setStart(rng, endContainer, 0); |
123 | setEnd(rng, endContainer, endContainer.nodeValue.length); |
||
124 | } |
||
125 | } |
||
126 | if (rng.endOffset === 1) { |
||
127 | end = 2; |
||
128 | } else { |
||
129 | end = rng.endOffset - 1 - endOffset; |
||
130 | } |
||
131 | } |
||
132 | var start = end; |
||
133 | do { |
||
134 | setStart(rng, endContainer, end >= 2 ? end - 2 : 0); |
||
135 | setEnd(rng, endContainer, end >= 1 ? end - 1 : 0); |
||
136 | end -= 1; |
||
137 | rngText = rng.toString(); |
||
679 | daniel-mar | 138 | } while (!rangeEqualsBracketOrSpace(rngText) && end - 2 >= 0); |
139 | if (rangeEqualsBracketOrSpace(rng.toString())) { |
||
597 | daniel-mar | 140 | setStart(rng, endContainer, end); |
141 | setEnd(rng, endContainer, start); |
||
142 | end += 1; |
||
143 | } else if (rng.startOffset === 0) { |
||
144 | setStart(rng, endContainer, 0); |
||
145 | setEnd(rng, endContainer, start); |
||
146 | } else { |
||
147 | setStart(rng, endContainer, end); |
||
148 | setEnd(rng, endContainer, start); |
||
149 | } |
||
150 | text = rng.toString(); |
||
637 | daniel-mar | 151 | if (isPunctuation(text.charAt(text.length - 1))) { |
597 | daniel-mar | 152 | setEnd(rng, endContainer, start - 1); |
153 | } |
||
154 | text = rng.toString().trim(); |
||
155 | var matches = text.match(autoLinkPattern); |
||
156 | var protocol = getDefaultLinkProtocol(editor); |
||
157 | if (matches) { |
||
637 | daniel-mar | 158 | var url = matches[0]; |
159 | if (startsWith(url, 'www.')) { |
||
160 | url = protocol + '://' + url; |
||
161 | } else if (contains(url, '@') && !hasProtocol(url)) { |
||
162 | url = 'mailto:' + url; |
||
597 | daniel-mar | 163 | } |
164 | bookmark = editor.selection.getBookmark(); |
||
165 | editor.selection.setRng(rng); |
||
637 | daniel-mar | 166 | editor.execCommand('createlink', false, url); |
597 | daniel-mar | 167 | if (defaultLinkTarget !== false) { |
168 | editor.dom.setAttrib(editor.selection.getNode(), 'target', defaultLinkTarget); |
||
169 | } |
||
170 | editor.selection.moveToBookmark(bookmark); |
||
171 | editor.nodeChanged(); |
||
172 | } |
||
173 | }; |
||
174 | var setup = function (editor) { |
||
175 | var autoUrlDetectState; |
||
176 | editor.on('keydown', function (e) { |
||
177 | if (e.keyCode === 13) { |
||
178 | return handleEnter(editor); |
||
179 | } |
||
180 | }); |
||
637 | daniel-mar | 181 | if (global.browser.isIE()) { |
597 | daniel-mar | 182 | editor.on('focus', function () { |
183 | if (!autoUrlDetectState) { |
||
184 | autoUrlDetectState = true; |
||
185 | try { |
||
186 | editor.execCommand('AutoUrlDetect', false, true); |
||
187 | } catch (ex) { |
||
188 | } |
||
189 | } |
||
190 | }); |
||
191 | return; |
||
192 | } |
||
193 | editor.on('keypress', function (e) { |
||
679 | daniel-mar | 194 | if (e.keyCode === 41 || e.keyCode === 93 || e.keyCode === 125) { |
195 | return handleBracket(editor); |
||
597 | daniel-mar | 196 | } |
197 | }); |
||
198 | editor.on('keyup', function (e) { |
||
199 | if (e.keyCode === 32) { |
||
200 | return handleSpacebar(editor); |
||
201 | } |
||
202 | }); |
||
203 | }; |
||
204 | |||
205 | function Plugin () { |
||
637 | daniel-mar | 206 | global$1.add('autolink', function (editor) { |
597 | daniel-mar | 207 | setup(editor); |
208 | }); |
||
209 | } |
||
210 | |||
211 | Plugin(); |
||
212 | |||
213 | }()); |