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 | |||
679 | daniel-mar | 12 | var global$7 = tinymce.util.Tools.resolve('tinymce.PluginManager'); |
597 | daniel-mar | 13 | |
679 | daniel-mar | 14 | var global$6 = tinymce.util.Tools.resolve('tinymce.util.VK'); |
597 | daniel-mar | 15 | |
16 | var typeOf = function (x) { |
||
17 | var t = typeof x; |
||
18 | if (x === null) { |
||
19 | return 'null'; |
||
20 | } else if (t === 'object' && (Array.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'Array')) { |
||
21 | return 'array'; |
||
22 | } else if (t === 'object' && (String.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'String')) { |
||
23 | return 'string'; |
||
24 | } else { |
||
25 | return t; |
||
26 | } |
||
27 | }; |
||
28 | var isType = function (type) { |
||
29 | return function (value) { |
||
30 | return typeOf(value) === type; |
||
31 | }; |
||
32 | }; |
||
33 | var isSimpleType = function (type) { |
||
34 | return function (value) { |
||
35 | return typeof value === type; |
||
36 | }; |
||
37 | }; |
||
38 | var eq = function (t) { |
||
39 | return function (a) { |
||
40 | return t === a; |
||
41 | }; |
||
42 | }; |
||
43 | var isString = isType('string'); |
||
44 | var isArray = isType('array'); |
||
45 | var isNull = eq(null); |
||
46 | var isBoolean = isSimpleType('boolean'); |
||
47 | var isFunction = isSimpleType('function'); |
||
48 | |||
49 | var noop = function () { |
||
50 | }; |
||
51 | var constant = function (value) { |
||
52 | return function () { |
||
53 | return value; |
||
54 | }; |
||
55 | }; |
||
637 | daniel-mar | 56 | var identity = function (x) { |
57 | return x; |
||
58 | }; |
||
59 | var tripleEquals = function (a, b) { |
||
60 | return a === b; |
||
61 | }; |
||
597 | daniel-mar | 62 | var never = constant(false); |
63 | var always = constant(true); |
||
64 | |||
65 | var none = function () { |
||
66 | return NONE; |
||
67 | }; |
||
68 | var NONE = function () { |
||
69 | var call = function (thunk) { |
||
70 | return thunk(); |
||
71 | }; |
||
637 | daniel-mar | 72 | var id = identity; |
597 | daniel-mar | 73 | var me = { |
74 | fold: function (n, _s) { |
||
75 | return n(); |
||
76 | }, |
||
77 | isSome: never, |
||
78 | isNone: always, |
||
79 | getOr: id, |
||
80 | getOrThunk: call, |
||
81 | getOrDie: function (msg) { |
||
82 | throw new Error(msg || 'error: getOrDie called on none.'); |
||
83 | }, |
||
84 | getOrNull: constant(null), |
||
85 | getOrUndefined: constant(undefined), |
||
86 | or: id, |
||
87 | orThunk: call, |
||
88 | map: none, |
||
89 | each: noop, |
||
90 | bind: none, |
||
91 | exists: never, |
||
92 | forall: always, |
||
637 | daniel-mar | 93 | filter: function () { |
94 | return none(); |
||
95 | }, |
||
597 | daniel-mar | 96 | toArray: function () { |
97 | return []; |
||
98 | }, |
||
99 | toString: constant('none()') |
||
100 | }; |
||
101 | return me; |
||
102 | }(); |
||
103 | var some = function (a) { |
||
104 | var constant_a = constant(a); |
||
105 | var self = function () { |
||
106 | return me; |
||
107 | }; |
||
108 | var bind = function (f) { |
||
109 | return f(a); |
||
110 | }; |
||
111 | var me = { |
||
112 | fold: function (n, s) { |
||
113 | return s(a); |
||
114 | }, |
||
115 | isSome: always, |
||
116 | isNone: never, |
||
117 | getOr: constant_a, |
||
118 | getOrThunk: constant_a, |
||
119 | getOrDie: constant_a, |
||
120 | getOrNull: constant_a, |
||
121 | getOrUndefined: constant_a, |
||
122 | or: self, |
||
123 | orThunk: self, |
||
124 | map: function (f) { |
||
125 | return some(f(a)); |
||
126 | }, |
||
127 | each: function (f) { |
||
128 | f(a); |
||
129 | }, |
||
130 | bind: bind, |
||
131 | exists: bind, |
||
132 | forall: bind, |
||
133 | filter: function (f) { |
||
134 | return f(a) ? me : NONE; |
||
135 | }, |
||
136 | toArray: function () { |
||
137 | return [a]; |
||
138 | }, |
||
139 | toString: function () { |
||
140 | return 'some(' + a + ')'; |
||
141 | } |
||
142 | }; |
||
143 | return me; |
||
144 | }; |
||
145 | var from = function (value) { |
||
146 | return value === null || value === undefined ? NONE : some(value); |
||
147 | }; |
||
148 | var Optional = { |
||
149 | some: some, |
||
150 | none: none, |
||
151 | from: from |
||
152 | }; |
||
153 | |||
154 | var nativeIndexOf = Array.prototype.indexOf; |
||
155 | var nativePush = Array.prototype.push; |
||
156 | var rawIndexOf = function (ts, t) { |
||
157 | return nativeIndexOf.call(ts, t); |
||
158 | }; |
||
159 | var contains = function (xs, x) { |
||
160 | return rawIndexOf(xs, x) > -1; |
||
161 | }; |
||
162 | var map = function (xs, f) { |
||
163 | var len = xs.length; |
||
164 | var r = new Array(len); |
||
165 | for (var i = 0; i < len; i++) { |
||
166 | var x = xs[i]; |
||
167 | r[i] = f(x, i); |
||
168 | } |
||
169 | return r; |
||
170 | }; |
||
637 | daniel-mar | 171 | var each$1 = function (xs, f) { |
597 | daniel-mar | 172 | for (var i = 0, len = xs.length; i < len; i++) { |
173 | var x = xs[i]; |
||
174 | f(x, i); |
||
175 | } |
||
176 | }; |
||
177 | var foldl = function (xs, f, acc) { |
||
637 | daniel-mar | 178 | each$1(xs, function (x, i) { |
179 | acc = f(acc, x, i); |
||
597 | daniel-mar | 180 | }); |
181 | return acc; |
||
182 | }; |
||
183 | var flatten = function (xs) { |
||
184 | var r = []; |
||
185 | for (var i = 0, len = xs.length; i < len; ++i) { |
||
186 | if (!isArray(xs[i])) { |
||
187 | throw new Error('Arr.flatten item ' + i + ' was not an array, input: ' + xs); |
||
188 | } |
||
189 | nativePush.apply(r, xs[i]); |
||
190 | } |
||
191 | return r; |
||
192 | }; |
||
193 | var bind = function (xs, f) { |
||
194 | return flatten(map(xs, f)); |
||
195 | }; |
||
196 | var findMap = function (arr, f) { |
||
197 | for (var i = 0; i < arr.length; i++) { |
||
198 | var r = f(arr[i], i); |
||
199 | if (r.isSome()) { |
||
200 | return r; |
||
201 | } |
||
202 | } |
||
203 | return Optional.none(); |
||
204 | }; |
||
205 | |||
637 | daniel-mar | 206 | var is = function (lhs, rhs, comparator) { |
207 | if (comparator === void 0) { |
||
208 | comparator = tripleEquals; |
||
209 | } |
||
210 | return lhs.exists(function (left) { |
||
211 | return comparator(left, rhs); |
||
212 | }); |
||
213 | }; |
||
597 | daniel-mar | 214 | var cat = function (arr) { |
215 | var r = []; |
||
216 | var push = function (x) { |
||
217 | r.push(x); |
||
218 | }; |
||
219 | for (var i = 0; i < arr.length; i++) { |
||
220 | arr[i].each(push); |
||
221 | } |
||
222 | return r; |
||
223 | }; |
||
224 | var someIf = function (b, a) { |
||
225 | return b ? Optional.some(a) : Optional.none(); |
||
226 | }; |
||
227 | |||
637 | daniel-mar | 228 | var assumeExternalTargets = function (editor) { |
229 | var externalTargets = editor.getParam('link_assume_external_targets', false); |
||
230 | if (isBoolean(externalTargets) && externalTargets) { |
||
231 | return 1; |
||
232 | } else if (isString(externalTargets) && (externalTargets === 'http' || externalTargets === 'https')) { |
||
233 | return externalTargets; |
||
234 | } |
||
235 | return 0; |
||
236 | }; |
||
237 | var hasContextToolbar = function (editor) { |
||
238 | return editor.getParam('link_context_toolbar', false, 'boolean'); |
||
239 | }; |
||
240 | var getLinkList = function (editor) { |
||
241 | return editor.getParam('link_list'); |
||
242 | }; |
||
243 | var getDefaultLinkTarget = function (editor) { |
||
244 | return editor.getParam('default_link_target'); |
||
245 | }; |
||
246 | var getTargetList = function (editor) { |
||
247 | return editor.getParam('target_list', true); |
||
248 | }; |
||
249 | var getRelList = function (editor) { |
||
250 | return editor.getParam('rel_list', [], 'array'); |
||
251 | }; |
||
252 | var getLinkClassList = function (editor) { |
||
253 | return editor.getParam('link_class_list', [], 'array'); |
||
254 | }; |
||
255 | var shouldShowLinkTitle = function (editor) { |
||
256 | return editor.getParam('link_title', true, 'boolean'); |
||
257 | }; |
||
258 | var allowUnsafeLinkTarget = function (editor) { |
||
259 | return editor.getParam('allow_unsafe_link_target', false, 'boolean'); |
||
260 | }; |
||
261 | var useQuickLink = function (editor) { |
||
262 | return editor.getParam('link_quicklink', false, 'boolean'); |
||
263 | }; |
||
264 | var getDefaultLinkProtocol = function (editor) { |
||
265 | return editor.getParam('link_default_protocol', 'http', 'string'); |
||
266 | }; |
||
597 | daniel-mar | 267 | |
679 | daniel-mar | 268 | var global$5 = tinymce.util.Tools.resolve('tinymce.util.Tools'); |
637 | daniel-mar | 269 | |
597 | daniel-mar | 270 | var getValue = function (item) { |
271 | return isString(item.value) ? item.value : ''; |
||
272 | }; |
||
273 | var getText = function (item) { |
||
274 | if (isString(item.text)) { |
||
275 | return item.text; |
||
276 | } else if (isString(item.title)) { |
||
277 | return item.title; |
||
278 | } else { |
||
279 | return ''; |
||
280 | } |
||
281 | }; |
||
282 | var sanitizeList = function (list, extractValue) { |
||
283 | var out = []; |
||
679 | daniel-mar | 284 | global$5.each(list, function (item) { |
597 | daniel-mar | 285 | var text = getText(item); |
286 | if (item.menu !== undefined) { |
||
287 | var items = sanitizeList(item.menu, extractValue); |
||
288 | out.push({ |
||
289 | text: text, |
||
290 | items: items |
||
291 | }); |
||
292 | } else { |
||
293 | var value = extractValue(item); |
||
294 | out.push({ |
||
295 | text: text, |
||
296 | value: value |
||
297 | }); |
||
298 | } |
||
299 | }); |
||
300 | return out; |
||
301 | }; |
||
302 | var sanitizeWith = function (extracter) { |
||
303 | if (extracter === void 0) { |
||
304 | extracter = getValue; |
||
305 | } |
||
306 | return function (list) { |
||
307 | return Optional.from(list).map(function (list) { |
||
308 | return sanitizeList(list, extracter); |
||
309 | }); |
||
310 | }; |
||
311 | }; |
||
312 | var sanitize = function (list) { |
||
313 | return sanitizeWith(getValue)(list); |
||
314 | }; |
||
315 | var createUi = function (name, label) { |
||
316 | return function (items) { |
||
317 | return { |
||
318 | name: name, |
||
319 | type: 'listbox', |
||
320 | label: label, |
||
321 | items: items |
||
322 | }; |
||
323 | }; |
||
324 | }; |
||
325 | var ListOptions = { |
||
326 | sanitize: sanitize, |
||
327 | sanitizeWith: sanitizeWith, |
||
328 | createUi: createUi, |
||
329 | getValue: getValue |
||
330 | }; |
||
331 | |||
332 | var __assign = function () { |
||
333 | __assign = Object.assign || function __assign(t) { |
||
334 | for (var s, i = 1, n = arguments.length; i < n; i++) { |
||
335 | s = arguments[i]; |
||
336 | for (var p in s) |
||
337 | if (Object.prototype.hasOwnProperty.call(s, p)) |
||
338 | t[p] = s[p]; |
||
339 | } |
||
340 | return t; |
||
341 | }; |
||
342 | return __assign.apply(this, arguments); |
||
343 | }; |
||
344 | |||
345 | var keys = Object.keys; |
||
346 | var hasOwnProperty = Object.hasOwnProperty; |
||
637 | daniel-mar | 347 | var each = function (obj, f) { |
597 | daniel-mar | 348 | var props = keys(obj); |
349 | for (var k = 0, len = props.length; k < len; k++) { |
||
350 | var i = props[k]; |
||
351 | var x = obj[i]; |
||
352 | f(x, i); |
||
353 | } |
||
354 | }; |
||
355 | var objAcc = function (r) { |
||
356 | return function (x, i) { |
||
357 | r[i] = x; |
||
358 | }; |
||
359 | }; |
||
360 | var internalFilter = function (obj, pred, onTrue, onFalse) { |
||
361 | var r = {}; |
||
637 | daniel-mar | 362 | each(obj, function (x, i) { |
597 | daniel-mar | 363 | (pred(x, i) ? onTrue : onFalse)(x, i); |
364 | }); |
||
365 | return r; |
||
366 | }; |
||
367 | var filter = function (obj, pred) { |
||
368 | var t = {}; |
||
369 | internalFilter(obj, pred, objAcc(t), noop); |
||
370 | return t; |
||
371 | }; |
||
372 | var has = function (obj, key) { |
||
373 | return hasOwnProperty.call(obj, key); |
||
374 | }; |
||
375 | var hasNonNullableKey = function (obj, key) { |
||
376 | return has(obj, key) && obj[key] !== undefined && obj[key] !== null; |
||
377 | }; |
||
378 | |||
679 | daniel-mar | 379 | var global$4 = tinymce.util.Tools.resolve('tinymce.dom.TreeWalker'); |
597 | daniel-mar | 380 | |
679 | daniel-mar | 381 | var global$3 = tinymce.util.Tools.resolve('tinymce.util.URI'); |
382 | |||
597 | daniel-mar | 383 | var isAnchor = function (elm) { |
384 | return elm && elm.nodeName.toLowerCase() === 'a'; |
||
385 | }; |
||
386 | var isLink = function (elm) { |
||
387 | return isAnchor(elm) && !!getHref(elm); |
||
388 | }; |
||
389 | var collectNodesInRange = function (rng, predicate) { |
||
390 | if (rng.collapsed) { |
||
391 | return []; |
||
392 | } else { |
||
393 | var contents = rng.cloneContents(); |
||
679 | daniel-mar | 394 | var walker = new global$4(contents.firstChild, contents); |
597 | daniel-mar | 395 | var elements = []; |
396 | var current = contents.firstChild; |
||
397 | do { |
||
398 | if (predicate(current)) { |
||
399 | elements.push(current); |
||
400 | } |
||
401 | } while (current = walker.next()); |
||
402 | return elements; |
||
403 | } |
||
404 | }; |
||
405 | var hasProtocol = function (url) { |
||
406 | return /^\w+:/i.test(url); |
||
407 | }; |
||
408 | var getHref = function (elm) { |
||
409 | var href = elm.getAttribute('data-mce-href'); |
||
410 | return href ? href : elm.getAttribute('href'); |
||
411 | }; |
||
412 | var applyRelTargetRules = function (rel, isUnsafe) { |
||
413 | var rules = ['noopener']; |
||
414 | var rels = rel ? rel.split(/\s+/) : []; |
||
415 | var toString = function (rels) { |
||
679 | daniel-mar | 416 | return global$5.trim(rels.sort().join(' ')); |
597 | daniel-mar | 417 | }; |
418 | var addTargetRules = function (rels) { |
||
419 | rels = removeTargetRules(rels); |
||
420 | return rels.length > 0 ? rels.concat(rules) : rules; |
||
421 | }; |
||
422 | var removeTargetRules = function (rels) { |
||
423 | return rels.filter(function (val) { |
||
679 | daniel-mar | 424 | return global$5.inArray(rules, val) === -1; |
597 | daniel-mar | 425 | }); |
426 | }; |
||
427 | var newRels = isUnsafe ? addTargetRules(rels) : removeTargetRules(rels); |
||
428 | return newRels.length > 0 ? toString(newRels) : ''; |
||
429 | }; |
||
430 | var trimCaretContainers = function (text) { |
||
431 | return text.replace(/\uFEFF/g, ''); |
||
432 | }; |
||
433 | var getAnchorElement = function (editor, selectedElm) { |
||
434 | selectedElm = selectedElm || editor.selection.getNode(); |
||
435 | if (isImageFigure(selectedElm)) { |
||
436 | return editor.dom.select('a[href]', selectedElm)[0]; |
||
437 | } else { |
||
438 | return editor.dom.getParent(selectedElm, 'a[href]'); |
||
439 | } |
||
440 | }; |
||
441 | var getAnchorText = function (selection, anchorElm) { |
||
442 | var text = anchorElm ? anchorElm.innerText || anchorElm.textContent : selection.getContent({ format: 'text' }); |
||
443 | return trimCaretContainers(text); |
||
444 | }; |
||
445 | var hasLinks = function (elements) { |
||
679 | daniel-mar | 446 | return global$5.grep(elements, isLink).length > 0; |
597 | daniel-mar | 447 | }; |
448 | var hasLinksInSelection = function (rng) { |
||
449 | return collectNodesInRange(rng, isLink).length > 0; |
||
450 | }; |
||
451 | var isOnlyTextSelected = function (editor) { |
||
452 | var inlineTextElements = editor.schema.getTextInlineElements(); |
||
453 | var isElement = function (elm) { |
||
454 | return elm.nodeType === 1 && !isAnchor(elm) && !has(inlineTextElements, elm.nodeName.toLowerCase()); |
||
455 | }; |
||
456 | var elements = collectNodesInRange(editor.selection.getRng(), isElement); |
||
457 | return elements.length === 0; |
||
458 | }; |
||
459 | var isImageFigure = function (elm) { |
||
460 | return elm && elm.nodeName === 'FIGURE' && /\bimage\b/i.test(elm.className); |
||
461 | }; |
||
462 | var getLinkAttrs = function (data) { |
||
637 | daniel-mar | 463 | var attrs = [ |
597 | daniel-mar | 464 | 'title', |
465 | 'rel', |
||
466 | 'class', |
||
467 | 'target' |
||
637 | daniel-mar | 468 | ]; |
469 | return foldl(attrs, function (acc, key) { |
||
597 | daniel-mar | 470 | data[key].each(function (value) { |
471 | acc[key] = value.length > 0 ? value : null; |
||
472 | }); |
||
473 | return acc; |
||
474 | }, { href: data.href }); |
||
475 | }; |
||
476 | var handleExternalTargets = function (href, assumeExternalTargets) { |
||
477 | if ((assumeExternalTargets === 'http' || assumeExternalTargets === 'https') && !hasProtocol(href)) { |
||
478 | return assumeExternalTargets + '://' + href; |
||
479 | } |
||
480 | return href; |
||
481 | }; |
||
482 | var applyLinkOverrides = function (editor, linkAttrs) { |
||
483 | var newLinkAttrs = __assign({}, linkAttrs); |
||
484 | if (!(getRelList(editor).length > 0) && allowUnsafeLinkTarget(editor) === false) { |
||
485 | var newRel = applyRelTargetRules(newLinkAttrs.rel, newLinkAttrs.target === '_blank'); |
||
486 | newLinkAttrs.rel = newRel ? newRel : null; |
||
487 | } |
||
488 | if (Optional.from(newLinkAttrs.target).isNone() && getTargetList(editor) === false) { |
||
489 | newLinkAttrs.target = getDefaultLinkTarget(editor); |
||
490 | } |
||
491 | newLinkAttrs.href = handleExternalTargets(newLinkAttrs.href, assumeExternalTargets(editor)); |
||
492 | return newLinkAttrs; |
||
493 | }; |
||
494 | var updateLink = function (editor, anchorElm, text, linkAttrs) { |
||
495 | text.each(function (text) { |
||
637 | daniel-mar | 496 | if (has(anchorElm, 'innerText')) { |
597 | daniel-mar | 497 | anchorElm.innerText = text; |
498 | } else { |
||
499 | anchorElm.textContent = text; |
||
500 | } |
||
501 | }); |
||
502 | editor.dom.setAttribs(anchorElm, linkAttrs); |
||
503 | editor.selection.select(anchorElm); |
||
504 | }; |
||
505 | var createLink = function (editor, selectedElm, text, linkAttrs) { |
||
506 | if (isImageFigure(selectedElm)) { |
||
507 | linkImageFigure(editor, selectedElm, linkAttrs); |
||
508 | } else { |
||
509 | text.fold(function () { |
||
510 | editor.execCommand('mceInsertLink', false, linkAttrs); |
||
511 | }, function (text) { |
||
512 | editor.insertContent(editor.dom.createHTML('a', linkAttrs, editor.dom.encode(text))); |
||
513 | }); |
||
514 | } |
||
515 | }; |
||
516 | var linkDomMutation = function (editor, attachState, data) { |
||
517 | var selectedElm = editor.selection.getNode(); |
||
518 | var anchorElm = getAnchorElement(editor, selectedElm); |
||
519 | var linkAttrs = applyLinkOverrides(editor, getLinkAttrs(data)); |
||
520 | editor.undoManager.transact(function () { |
||
521 | if (data.href === attachState.href) { |
||
522 | attachState.attach(); |
||
523 | } |
||
524 | if (anchorElm) { |
||
525 | editor.focus(); |
||
526 | updateLink(editor, anchorElm, data.text, linkAttrs); |
||
527 | } else { |
||
528 | createLink(editor, selectedElm, data.text, linkAttrs); |
||
529 | } |
||
530 | }); |
||
531 | }; |
||
532 | var unlinkSelection = function (editor) { |
||
533 | var dom = editor.dom, selection = editor.selection; |
||
534 | var bookmark = selection.getBookmark(); |
||
535 | var rng = selection.getRng().cloneRange(); |
||
536 | var startAnchorElm = dom.getParent(rng.startContainer, 'a[href]', editor.getBody()); |
||
537 | var endAnchorElm = dom.getParent(rng.endContainer, 'a[href]', editor.getBody()); |
||
538 | if (startAnchorElm) { |
||
539 | rng.setStartBefore(startAnchorElm); |
||
540 | } |
||
541 | if (endAnchorElm) { |
||
542 | rng.setEndAfter(endAnchorElm); |
||
543 | } |
||
544 | selection.setRng(rng); |
||
545 | editor.execCommand('unlink'); |
||
546 | selection.moveToBookmark(bookmark); |
||
547 | }; |
||
548 | var unlinkDomMutation = function (editor) { |
||
549 | editor.undoManager.transact(function () { |
||
550 | var node = editor.selection.getNode(); |
||
551 | if (isImageFigure(node)) { |
||
552 | unlinkImageFigure(editor, node); |
||
553 | } else { |
||
554 | unlinkSelection(editor); |
||
555 | } |
||
556 | editor.focus(); |
||
557 | }); |
||
558 | }; |
||
559 | var unwrapOptions = function (data) { |
||
560 | var cls = data.class, href = data.href, rel = data.rel, target = data.target, text = data.text, title = data.title; |
||
561 | return filter({ |
||
562 | class: cls.getOrNull(), |
||
563 | href: href, |
||
564 | rel: rel.getOrNull(), |
||
565 | target: target.getOrNull(), |
||
566 | text: text.getOrNull(), |
||
567 | title: title.getOrNull() |
||
568 | }, function (v, _k) { |
||
569 | return isNull(v) === false; |
||
570 | }); |
||
571 | }; |
||
679 | daniel-mar | 572 | var sanitizeData = function (editor, data) { |
573 | var href = data.href; |
||
574 | return __assign(__assign({}, data), { href: global$3.isDomSafe(href, 'a', editor.settings) ? href : '' }); |
||
575 | }; |
||
597 | daniel-mar | 576 | var link = function (editor, attachState, data) { |
679 | daniel-mar | 577 | var sanitizedData = sanitizeData(editor, data); |
578 | editor.hasPlugin('rtc', true) ? editor.execCommand('createlink', false, unwrapOptions(sanitizedData)) : linkDomMutation(editor, attachState, sanitizedData); |
||
597 | daniel-mar | 579 | }; |
580 | var unlink = function (editor) { |
||
581 | editor.hasPlugin('rtc', true) ? editor.execCommand('unlink') : unlinkDomMutation(editor); |
||
582 | }; |
||
583 | var unlinkImageFigure = function (editor, fig) { |
||
584 | var img = editor.dom.select('img', fig)[0]; |
||
585 | if (img) { |
||
586 | var a = editor.dom.getParents(img, 'a[href]', fig)[0]; |
||
587 | if (a) { |
||
588 | a.parentNode.insertBefore(img, a); |
||
589 | editor.dom.remove(a); |
||
590 | } |
||
591 | } |
||
592 | }; |
||
593 | var linkImageFigure = function (editor, fig, attrs) { |
||
594 | var img = editor.dom.select('img', fig)[0]; |
||
595 | if (img) { |
||
596 | var a = editor.dom.create('a', attrs); |
||
597 | img.parentNode.insertBefore(a, img); |
||
598 | a.appendChild(img); |
||
599 | } |
||
600 | }; |
||
601 | |||
602 | var isListGroup = function (item) { |
||
603 | return hasNonNullableKey(item, 'items'); |
||
604 | }; |
||
605 | var findTextByValue = function (value, catalog) { |
||
606 | return findMap(catalog, function (item) { |
||
607 | if (isListGroup(item)) { |
||
608 | return findTextByValue(value, item.items); |
||
609 | } else { |
||
610 | return someIf(item.value === value, item); |
||
611 | } |
||
612 | }); |
||
613 | }; |
||
614 | var getDelta = function (persistentText, fieldName, catalog, data) { |
||
615 | var value = data[fieldName]; |
||
616 | var hasPersistentText = persistentText.length > 0; |
||
617 | return value !== undefined ? findTextByValue(value, catalog).map(function (i) { |
||
618 | return { |
||
619 | url: { |
||
620 | value: i.value, |
||
621 | meta: { |
||
622 | text: hasPersistentText ? persistentText : i.text, |
||
623 | attach: noop |
||
624 | } |
||
625 | }, |
||
626 | text: hasPersistentText ? persistentText : i.text |
||
627 | }; |
||
628 | }) : Optional.none(); |
||
629 | }; |
||
630 | var findCatalog = function (catalogs, fieldName) { |
||
631 | if (fieldName === 'link') { |
||
632 | return catalogs.link; |
||
633 | } else if (fieldName === 'anchor') { |
||
634 | return catalogs.anchor; |
||
635 | } else { |
||
636 | return Optional.none(); |
||
637 | } |
||
638 | }; |
||
639 | var init = function (initialData, linkCatalog) { |
||
640 | var persistentData = { |
||
641 | text: initialData.text, |
||
642 | title: initialData.title |
||
643 | }; |
||
644 | var getTitleFromUrlChange = function (url) { |
||
645 | return someIf(persistentData.title.length <= 0, Optional.from(url.meta.title).getOr('')); |
||
646 | }; |
||
647 | var getTextFromUrlChange = function (url) { |
||
648 | return someIf(persistentData.text.length <= 0, Optional.from(url.meta.text).getOr(url.value)); |
||
649 | }; |
||
650 | var onUrlChange = function (data) { |
||
651 | var text = getTextFromUrlChange(data.url); |
||
652 | var title = getTitleFromUrlChange(data.url); |
||
653 | if (text.isSome() || title.isSome()) { |
||
654 | return Optional.some(__assign(__assign({}, text.map(function (text) { |
||
655 | return { text: text }; |
||
656 | }).getOr({})), title.map(function (title) { |
||
657 | return { title: title }; |
||
658 | }).getOr({}))); |
||
659 | } else { |
||
660 | return Optional.none(); |
||
661 | } |
||
662 | }; |
||
663 | var onCatalogChange = function (data, change) { |
||
664 | var catalog = findCatalog(linkCatalog, change.name).getOr([]); |
||
665 | return getDelta(persistentData.text, change.name, catalog, data); |
||
666 | }; |
||
667 | var onChange = function (getData, change) { |
||
668 | var name = change.name; |
||
669 | if (name === 'url') { |
||
670 | return onUrlChange(getData()); |
||
671 | } else if (contains([ |
||
672 | 'anchor', |
||
673 | 'link' |
||
674 | ], name)) { |
||
675 | return onCatalogChange(getData(), change); |
||
676 | } else if (name === 'text' || name === 'title') { |
||
677 | persistentData[name] = getData()[name]; |
||
678 | return Optional.none(); |
||
679 | } else { |
||
680 | return Optional.none(); |
||
681 | } |
||
682 | }; |
||
683 | return { onChange: onChange }; |
||
684 | }; |
||
685 | var DialogChanges = { |
||
686 | init: init, |
||
687 | getDelta: getDelta |
||
688 | }; |
||
689 | |||
637 | daniel-mar | 690 | var global$2 = tinymce.util.Tools.resolve('tinymce.util.Delay'); |
597 | daniel-mar | 691 | |
637 | daniel-mar | 692 | var global$1 = tinymce.util.Tools.resolve('tinymce.util.Promise'); |
597 | daniel-mar | 693 | |
694 | var delayedConfirm = function (editor, message, callback) { |
||
695 | var rng = editor.selection.getRng(); |
||
637 | daniel-mar | 696 | global$2.setEditorTimeout(editor, function () { |
597 | daniel-mar | 697 | editor.windowManager.confirm(message, function (state) { |
698 | editor.selection.setRng(rng); |
||
699 | callback(state); |
||
700 | }); |
||
701 | }); |
||
702 | }; |
||
703 | var tryEmailTransform = function (data) { |
||
704 | var url = data.href; |
||
705 | var suggestMailTo = url.indexOf('@') > 0 && url.indexOf('/') === -1 && url.indexOf('mailto:') === -1; |
||
706 | return suggestMailTo ? Optional.some({ |
||
707 | message: 'The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?', |
||
708 | preprocess: function (oldData) { |
||
709 | return __assign(__assign({}, oldData), { href: 'mailto:' + url }); |
||
710 | } |
||
711 | }) : Optional.none(); |
||
712 | }; |
||
713 | var tryProtocolTransform = function (assumeExternalTargets, defaultLinkProtocol) { |
||
714 | return function (data) { |
||
715 | var url = data.href; |
||
716 | var suggestProtocol = assumeExternalTargets === 1 && !hasProtocol(url) || assumeExternalTargets === 0 && /^\s*www(\.|\d\.)/i.test(url); |
||
717 | return suggestProtocol ? Optional.some({ |
||
718 | message: 'The URL you entered seems to be an external link. Do you want to add the required ' + defaultLinkProtocol + ':// prefix?', |
||
719 | preprocess: function (oldData) { |
||
720 | return __assign(__assign({}, oldData), { href: defaultLinkProtocol + '://' + url }); |
||
721 | } |
||
722 | }) : Optional.none(); |
||
723 | }; |
||
724 | }; |
||
725 | var preprocess = function (editor, data) { |
||
726 | return findMap([ |
||
727 | tryEmailTransform, |
||
728 | tryProtocolTransform(assumeExternalTargets(editor), getDefaultLinkProtocol(editor)) |
||
729 | ], function (f) { |
||
730 | return f(data); |
||
731 | }).fold(function () { |
||
637 | daniel-mar | 732 | return global$1.resolve(data); |
597 | daniel-mar | 733 | }, function (transform) { |
637 | daniel-mar | 734 | return new global$1(function (callback) { |
597 | daniel-mar | 735 | delayedConfirm(editor, transform.message, function (state) { |
736 | callback(state ? transform.preprocess(data) : data); |
||
737 | }); |
||
738 | }); |
||
739 | }); |
||
740 | }; |
||
741 | var DialogConfirms = { preprocess: preprocess }; |
||
742 | |||
743 | var getAnchors = function (editor) { |
||
744 | var anchorNodes = editor.dom.select('a:not([href])'); |
||
745 | var anchors = bind(anchorNodes, function (anchor) { |
||
746 | var id = anchor.name || anchor.id; |
||
747 | return id ? [{ |
||
748 | text: id, |
||
749 | value: '#' + id |
||
750 | }] : []; |
||
751 | }); |
||
752 | return anchors.length > 0 ? Optional.some([{ |
||
753 | text: 'None', |
||
754 | value: '' |
||
755 | }].concat(anchors)) : Optional.none(); |
||
756 | }; |
||
757 | var AnchorListOptions = { getAnchors: getAnchors }; |
||
758 | |||
759 | var getClasses = function (editor) { |
||
760 | var list = getLinkClassList(editor); |
||
761 | if (list.length > 0) { |
||
762 | return ListOptions.sanitize(list); |
||
763 | } |
||
764 | return Optional.none(); |
||
765 | }; |
||
766 | var ClassListOptions = { getClasses: getClasses }; |
||
767 | |||
637 | daniel-mar | 768 | var global = tinymce.util.Tools.resolve('tinymce.util.XHR'); |
597 | daniel-mar | 769 | |
770 | var parseJson = function (text) { |
||
771 | try { |
||
772 | return Optional.some(JSON.parse(text)); |
||
773 | } catch (err) { |
||
774 | return Optional.none(); |
||
775 | } |
||
776 | }; |
||
777 | var getLinks = function (editor) { |
||
778 | var extractor = function (item) { |
||
779 | return editor.convertURL(item.value || item.url, 'href'); |
||
780 | }; |
||
781 | var linkList = getLinkList(editor); |
||
637 | daniel-mar | 782 | return new global$1(function (callback) { |
597 | daniel-mar | 783 | if (isString(linkList)) { |
637 | daniel-mar | 784 | global.send({ |
597 | daniel-mar | 785 | url: linkList, |
786 | success: function (text) { |
||
787 | return callback(parseJson(text)); |
||
788 | }, |
||
789 | error: function (_) { |
||
790 | return callback(Optional.none()); |
||
791 | } |
||
792 | }); |
||
793 | } else if (isFunction(linkList)) { |
||
794 | linkList(function (output) { |
||
795 | return callback(Optional.some(output)); |
||
796 | }); |
||
797 | } else { |
||
798 | callback(Optional.from(linkList)); |
||
799 | } |
||
800 | }).then(function (optItems) { |
||
801 | return optItems.bind(ListOptions.sanitizeWith(extractor)).map(function (items) { |
||
802 | if (items.length > 0) { |
||
803 | var noneItem = [{ |
||
804 | text: 'None', |
||
805 | value: '' |
||
806 | }]; |
||
807 | return noneItem.concat(items); |
||
808 | } else { |
||
809 | return items; |
||
810 | } |
||
811 | }); |
||
812 | }); |
||
813 | }; |
||
814 | var LinkListOptions = { getLinks: getLinks }; |
||
815 | |||
816 | var getRels = function (editor, initialTarget) { |
||
817 | var list = getRelList(editor); |
||
818 | if (list.length > 0) { |
||
637 | daniel-mar | 819 | var isTargetBlank_1 = is(initialTarget, '_blank'); |
597 | daniel-mar | 820 | var enforceSafe = allowUnsafeLinkTarget(editor) === false; |
821 | var safeRelExtractor = function (item) { |
||
822 | return applyRelTargetRules(ListOptions.getValue(item), isTargetBlank_1); |
||
823 | }; |
||
824 | var sanitizer = enforceSafe ? ListOptions.sanitizeWith(safeRelExtractor) : ListOptions.sanitize; |
||
825 | return sanitizer(list); |
||
826 | } |
||
827 | return Optional.none(); |
||
828 | }; |
||
829 | var RelOptions = { getRels: getRels }; |
||
830 | |||
831 | var fallbacks = [ |
||
832 | { |
||
833 | text: 'Current window', |
||
834 | value: '' |
||
835 | }, |
||
836 | { |
||
837 | text: 'New window', |
||
838 | value: '_blank' |
||
839 | } |
||
840 | ]; |
||
841 | var getTargets = function (editor) { |
||
842 | var list = getTargetList(editor); |
||
843 | if (isArray(list)) { |
||
844 | return ListOptions.sanitize(list).orThunk(function () { |
||
845 | return Optional.some(fallbacks); |
||
846 | }); |
||
847 | } else if (list === false) { |
||
848 | return Optional.none(); |
||
849 | } |
||
850 | return Optional.some(fallbacks); |
||
851 | }; |
||
852 | var TargetOptions = { getTargets: getTargets }; |
||
853 | |||
854 | var nonEmptyAttr = function (dom, elem, name) { |
||
855 | var val = dom.getAttrib(elem, name); |
||
856 | return val !== null && val.length > 0 ? Optional.some(val) : Optional.none(); |
||
857 | }; |
||
858 | var extractFromAnchor = function (editor, anchor) { |
||
859 | var dom = editor.dom; |
||
860 | var onlyText = isOnlyTextSelected(editor); |
||
861 | var text = onlyText ? Optional.some(getAnchorText(editor.selection, anchor)) : Optional.none(); |
||
862 | var url = anchor ? Optional.some(dom.getAttrib(anchor, 'href')) : Optional.none(); |
||
863 | var target = anchor ? Optional.from(dom.getAttrib(anchor, 'target')) : Optional.none(); |
||
864 | var rel = nonEmptyAttr(dom, anchor, 'rel'); |
||
865 | var linkClass = nonEmptyAttr(dom, anchor, 'class'); |
||
866 | var title = nonEmptyAttr(dom, anchor, 'title'); |
||
867 | return { |
||
868 | url: url, |
||
869 | text: text, |
||
870 | title: title, |
||
871 | target: target, |
||
872 | rel: rel, |
||
873 | linkClass: linkClass |
||
874 | }; |
||
875 | }; |
||
876 | var collect = function (editor, linkNode) { |
||
877 | return LinkListOptions.getLinks(editor).then(function (links) { |
||
878 | var anchor = extractFromAnchor(editor, linkNode); |
||
879 | return { |
||
880 | anchor: anchor, |
||
881 | catalogs: { |
||
882 | targets: TargetOptions.getTargets(editor), |
||
883 | rels: RelOptions.getRels(editor, anchor.target), |
||
884 | classes: ClassListOptions.getClasses(editor), |
||
885 | anchor: AnchorListOptions.getAnchors(editor), |
||
886 | link: links |
||
887 | }, |
||
888 | optNode: Optional.from(linkNode), |
||
889 | flags: { titleEnabled: shouldShowLinkTitle(editor) } |
||
890 | }; |
||
891 | }); |
||
892 | }; |
||
893 | var DialogInfo = { collect: collect }; |
||
894 | |||
895 | var handleSubmit = function (editor, info) { |
||
896 | return function (api) { |
||
897 | var data = api.getData(); |
||
898 | if (!data.url.value) { |
||
899 | unlink(editor); |
||
900 | api.close(); |
||
901 | return; |
||
902 | } |
||
903 | var getChangedValue = function (key) { |
||
904 | return Optional.from(data[key]).filter(function (value) { |
||
637 | daniel-mar | 905 | return !is(info.anchor[key], value); |
597 | daniel-mar | 906 | }); |
907 | }; |
||
908 | var changedData = { |
||
909 | href: data.url.value, |
||
910 | text: getChangedValue('text'), |
||
911 | target: getChangedValue('target'), |
||
912 | rel: getChangedValue('rel'), |
||
913 | class: getChangedValue('linkClass'), |
||
914 | title: getChangedValue('title') |
||
915 | }; |
||
916 | var attachState = { |
||
917 | href: data.url.value, |
||
918 | attach: data.url.meta !== undefined && data.url.meta.attach ? data.url.meta.attach : noop |
||
919 | }; |
||
920 | DialogConfirms.preprocess(editor, changedData).then(function (pData) { |
||
921 | link(editor, attachState, pData); |
||
922 | }); |
||
923 | api.close(); |
||
924 | }; |
||
925 | }; |
||
926 | var collectData = function (editor) { |
||
927 | var anchorNode = getAnchorElement(editor); |
||
928 | return DialogInfo.collect(editor, anchorNode); |
||
929 | }; |
||
930 | var getInitialData = function (info, defaultTarget) { |
||
931 | var anchor = info.anchor; |
||
932 | var url = anchor.url.getOr(''); |
||
933 | return { |
||
934 | url: { |
||
935 | value: url, |
||
936 | meta: { original: { value: url } } |
||
937 | }, |
||
938 | text: anchor.text.getOr(''), |
||
939 | title: anchor.title.getOr(''), |
||
940 | anchor: url, |
||
941 | link: url, |
||
942 | rel: anchor.rel.getOr(''), |
||
943 | target: anchor.target.or(defaultTarget).getOr(''), |
||
944 | linkClass: anchor.linkClass.getOr('') |
||
945 | }; |
||
946 | }; |
||
947 | var makeDialog = function (settings, onSubmit, editor) { |
||
948 | var urlInput = [{ |
||
949 | name: 'url', |
||
950 | type: 'urlinput', |
||
951 | filetype: 'file', |
||
952 | label: 'URL' |
||
953 | }]; |
||
954 | var displayText = settings.anchor.text.map(function () { |
||
955 | return { |
||
956 | name: 'text', |
||
957 | type: 'input', |
||
958 | label: 'Text to display' |
||
959 | }; |
||
960 | }).toArray(); |
||
961 | var titleText = settings.flags.titleEnabled ? [{ |
||
962 | name: 'title', |
||
963 | type: 'input', |
||
964 | label: 'Title' |
||
965 | }] : []; |
||
966 | var defaultTarget = Optional.from(getDefaultLinkTarget(editor)); |
||
967 | var initialData = getInitialData(settings, defaultTarget); |
||
968 | var catalogs = settings.catalogs; |
||
969 | var dialogDelta = DialogChanges.init(initialData, catalogs); |
||
970 | var body = { |
||
971 | type: 'panel', |
||
972 | items: flatten([ |
||
973 | urlInput, |
||
974 | displayText, |
||
975 | titleText, |
||
976 | cat([ |
||
977 | catalogs.anchor.map(ListOptions.createUi('anchor', 'Anchors')), |
||
978 | catalogs.rels.map(ListOptions.createUi('rel', 'Rel')), |
||
979 | catalogs.targets.map(ListOptions.createUi('target', 'Open link in...')), |
||
980 | catalogs.link.map(ListOptions.createUi('link', 'Link list')), |
||
981 | catalogs.classes.map(ListOptions.createUi('linkClass', 'Class')) |
||
982 | ]) |
||
983 | ]) |
||
984 | }; |
||
985 | return { |
||
986 | title: 'Insert/Edit Link', |
||
987 | size: 'normal', |
||
988 | body: body, |
||
989 | buttons: [ |
||
990 | { |
||
991 | type: 'cancel', |
||
992 | name: 'cancel', |
||
993 | text: 'Cancel' |
||
994 | }, |
||
995 | { |
||
996 | type: 'submit', |
||
997 | name: 'save', |
||
998 | text: 'Save', |
||
999 | primary: true |
||
1000 | } |
||
1001 | ], |
||
1002 | initialData: initialData, |
||
1003 | onChange: function (api, _a) { |
||
1004 | var name = _a.name; |
||
1005 | dialogDelta.onChange(api.getData, { name: name }).each(function (newData) { |
||
1006 | api.setData(newData); |
||
1007 | }); |
||
1008 | }, |
||
1009 | onSubmit: onSubmit |
||
1010 | }; |
||
1011 | }; |
||
637 | daniel-mar | 1012 | var open$1 = function (editor) { |
597 | daniel-mar | 1013 | var data = collectData(editor); |
1014 | data.then(function (info) { |
||
1015 | var onSubmit = handleSubmit(editor, info); |
||
1016 | return makeDialog(info, onSubmit, editor); |
||
1017 | }).then(function (spec) { |
||
1018 | editor.windowManager.open(spec); |
||
1019 | }); |
||
1020 | }; |
||
1021 | |||
1022 | var appendClickRemove = function (link, evt) { |
||
1023 | document.body.appendChild(link); |
||
1024 | link.dispatchEvent(evt); |
||
1025 | document.body.removeChild(link); |
||
1026 | }; |
||
637 | daniel-mar | 1027 | var open = function (url) { |
597 | daniel-mar | 1028 | var link = document.createElement('a'); |
1029 | link.target = '_blank'; |
||
1030 | link.href = url; |
||
1031 | link.rel = 'noreferrer noopener'; |
||
1032 | var evt = document.createEvent('MouseEvents'); |
||
1033 | evt.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); |
||
1034 | appendClickRemove(link, evt); |
||
1035 | }; |
||
1036 | |||
1037 | var getLink = function (editor, elm) { |
||
1038 | return editor.dom.getParent(elm, 'a[href]'); |
||
1039 | }; |
||
1040 | var getSelectedLink = function (editor) { |
||
1041 | return getLink(editor, editor.selection.getStart()); |
||
1042 | }; |
||
1043 | var hasOnlyAltModifier = function (e) { |
||
1044 | return e.altKey === true && e.shiftKey === false && e.ctrlKey === false && e.metaKey === false; |
||
1045 | }; |
||
1046 | var gotoLink = function (editor, a) { |
||
1047 | if (a) { |
||
1048 | var href = getHref(a); |
||
1049 | if (/^#/.test(href)) { |
||
1050 | var targetEl = editor.$(href); |
||
1051 | if (targetEl.length) { |
||
1052 | editor.selection.scrollIntoView(targetEl[0], true); |
||
1053 | } |
||
1054 | } else { |
||
637 | daniel-mar | 1055 | open(a.href); |
597 | daniel-mar | 1056 | } |
1057 | } |
||
1058 | }; |
||
1059 | var openDialog = function (editor) { |
||
1060 | return function () { |
||
637 | daniel-mar | 1061 | open$1(editor); |
597 | daniel-mar | 1062 | }; |
1063 | }; |
||
1064 | var gotoSelectedLink = function (editor) { |
||
1065 | return function () { |
||
1066 | gotoLink(editor, getSelectedLink(editor)); |
||
1067 | }; |
||
1068 | }; |
||
1069 | var setupGotoLinks = function (editor) { |
||
1070 | editor.on('click', function (e) { |
||
1071 | var link = getLink(editor, e.target); |
||
679 | daniel-mar | 1072 | if (link && global$6.metaKeyPressed(e)) { |
597 | daniel-mar | 1073 | e.preventDefault(); |
1074 | gotoLink(editor, link); |
||
1075 | } |
||
1076 | }); |
||
1077 | editor.on('keydown', function (e) { |
||
1078 | var link = getSelectedLink(editor); |
||
1079 | if (link && e.keyCode === 13 && hasOnlyAltModifier(e)) { |
||
1080 | e.preventDefault(); |
||
1081 | gotoLink(editor, link); |
||
1082 | } |
||
1083 | }); |
||
1084 | }; |
||
1085 | var toggleState = function (editor, toggler) { |
||
1086 | editor.on('NodeChange', toggler); |
||
1087 | return function () { |
||
1088 | return editor.off('NodeChange', toggler); |
||
1089 | }; |
||
1090 | }; |
||
1091 | var toggleActiveState = function (editor) { |
||
1092 | return function (api) { |
||
637 | daniel-mar | 1093 | var updateState = function () { |
1094 | return api.setActive(!editor.mode.isReadOnly() && getAnchorElement(editor, editor.selection.getNode()) !== null); |
||
1095 | }; |
||
1096 | updateState(); |
||
1097 | return toggleState(editor, updateState); |
||
597 | daniel-mar | 1098 | }; |
1099 | }; |
||
1100 | var toggleEnabledState = function (editor) { |
||
1101 | return function (api) { |
||
1102 | var updateState = function () { |
||
1103 | return api.setDisabled(getAnchorElement(editor, editor.selection.getNode()) === null); |
||
1104 | }; |
||
1105 | updateState(); |
||
1106 | return toggleState(editor, updateState); |
||
1107 | }; |
||
1108 | }; |
||
1109 | var toggleUnlinkState = function (editor) { |
||
1110 | return function (api) { |
||
1111 | var hasLinks$1 = function (parents) { |
||
1112 | return hasLinks(parents) || hasLinksInSelection(editor.selection.getRng()); |
||
1113 | }; |
||
1114 | var parents = editor.dom.getParents(editor.selection.getStart()); |
||
1115 | api.setDisabled(!hasLinks$1(parents)); |
||
1116 | return toggleState(editor, function (e) { |
||
1117 | return api.setDisabled(!hasLinks$1(e.parents)); |
||
1118 | }); |
||
1119 | }; |
||
1120 | }; |
||
1121 | |||
1122 | var register = function (editor) { |
||
1123 | editor.addCommand('mceLink', function () { |
||
1124 | if (useQuickLink(editor)) { |
||
1125 | editor.fire('contexttoolbar-show', { toolbarKey: 'quicklink' }); |
||
1126 | } else { |
||
1127 | openDialog(editor)(); |
||
1128 | } |
||
1129 | }); |
||
1130 | }; |
||
1131 | |||
1132 | var setup = function (editor) { |
||
1133 | editor.addShortcut('Meta+K', '', function () { |
||
1134 | editor.execCommand('mceLink'); |
||
1135 | }); |
||
1136 | }; |
||
1137 | |||
1138 | var setupButtons = function (editor) { |
||
1139 | editor.ui.registry.addToggleButton('link', { |
||
1140 | icon: 'link', |
||
1141 | tooltip: 'Insert/edit link', |
||
1142 | onAction: openDialog(editor), |
||
1143 | onSetup: toggleActiveState(editor) |
||
1144 | }); |
||
1145 | editor.ui.registry.addButton('openlink', { |
||
1146 | icon: 'new-tab', |
||
1147 | tooltip: 'Open link', |
||
1148 | onAction: gotoSelectedLink(editor), |
||
1149 | onSetup: toggleEnabledState(editor) |
||
1150 | }); |
||
1151 | editor.ui.registry.addButton('unlink', { |
||
1152 | icon: 'unlink', |
||
1153 | tooltip: 'Remove link', |
||
1154 | onAction: function () { |
||
1155 | return unlink(editor); |
||
1156 | }, |
||
1157 | onSetup: toggleUnlinkState(editor) |
||
1158 | }); |
||
1159 | }; |
||
1160 | var setupMenuItems = function (editor) { |
||
1161 | editor.ui.registry.addMenuItem('openlink', { |
||
1162 | text: 'Open link', |
||
1163 | icon: 'new-tab', |
||
1164 | onAction: gotoSelectedLink(editor), |
||
1165 | onSetup: toggleEnabledState(editor) |
||
1166 | }); |
||
1167 | editor.ui.registry.addMenuItem('link', { |
||
1168 | icon: 'link', |
||
1169 | text: 'Link...', |
||
1170 | shortcut: 'Meta+K', |
||
1171 | onAction: openDialog(editor) |
||
1172 | }); |
||
1173 | editor.ui.registry.addMenuItem('unlink', { |
||
1174 | icon: 'unlink', |
||
1175 | text: 'Remove link', |
||
1176 | onAction: function () { |
||
1177 | return unlink(editor); |
||
1178 | }, |
||
1179 | onSetup: toggleUnlinkState(editor) |
||
1180 | }); |
||
1181 | }; |
||
1182 | var setupContextMenu = function (editor) { |
||
1183 | var inLink = 'link unlink openlink'; |
||
1184 | var noLink = 'link'; |
||
1185 | editor.ui.registry.addContextMenu('link', { |
||
1186 | update: function (element) { |
||
1187 | return hasLinks(editor.dom.getParents(element, 'a')) ? inLink : noLink; |
||
1188 | } |
||
1189 | }); |
||
1190 | }; |
||
1191 | var setupContextToolbars = function (editor) { |
||
1192 | var collapseSelectionToEnd = function (editor) { |
||
1193 | editor.selection.collapse(false); |
||
1194 | }; |
||
1195 | var onSetupLink = function (buttonApi) { |
||
1196 | var node = editor.selection.getNode(); |
||
1197 | buttonApi.setDisabled(!getAnchorElement(editor, node)); |
||
1198 | return noop; |
||
1199 | }; |
||
637 | daniel-mar | 1200 | var getLinkText = function (value) { |
1201 | var anchor = getAnchorElement(editor); |
||
1202 | var onlyText = isOnlyTextSelected(editor); |
||
1203 | if (!anchor && onlyText) { |
||
1204 | var text = getAnchorText(editor.selection, anchor); |
||
1205 | return Optional.some(text.length > 0 ? text : value); |
||
1206 | } else { |
||
1207 | return Optional.none(); |
||
1208 | } |
||
1209 | }; |
||
597 | daniel-mar | 1210 | editor.ui.registry.addContextForm('quicklink', { |
1211 | launch: { |
||
1212 | type: 'contextformtogglebutton', |
||
1213 | icon: 'link', |
||
1214 | tooltip: 'Link', |
||
1215 | onSetup: toggleActiveState(editor) |
||
1216 | }, |
||
1217 | label: 'Link', |
||
1218 | predicate: function (node) { |
||
1219 | return !!getAnchorElement(editor, node) && hasContextToolbar(editor); |
||
1220 | }, |
||
1221 | initValue: function () { |
||
1222 | var elm = getAnchorElement(editor); |
||
1223 | return !!elm ? getHref(elm) : ''; |
||
1224 | }, |
||
1225 | commands: [ |
||
1226 | { |
||
1227 | type: 'contextformtogglebutton', |
||
1228 | icon: 'link', |
||
1229 | tooltip: 'Link', |
||
1230 | primary: true, |
||
1231 | onSetup: function (buttonApi) { |
||
1232 | var node = editor.selection.getNode(); |
||
1233 | buttonApi.setActive(!!getAnchorElement(editor, node)); |
||
1234 | return toggleActiveState(editor)(buttonApi); |
||
1235 | }, |
||
1236 | onAction: function (formApi) { |
||
1237 | var value = formApi.getValue(); |
||
637 | daniel-mar | 1238 | var text = getLinkText(value); |
1239 | var attachState = { |
||
1240 | href: value, |
||
1241 | attach: noop |
||
1242 | }; |
||
1243 | link(editor, attachState, { |
||
1244 | href: value, |
||
1245 | text: text, |
||
1246 | title: Optional.none(), |
||
1247 | rel: Optional.none(), |
||
1248 | target: Optional.none(), |
||
1249 | class: Optional.none() |
||
1250 | }); |
||
1251 | collapseSelectionToEnd(editor); |
||
1252 | formApi.hide(); |
||
597 | daniel-mar | 1253 | } |
1254 | }, |
||
1255 | { |
||
1256 | type: 'contextformbutton', |
||
1257 | icon: 'unlink', |
||
1258 | tooltip: 'Remove link', |
||
1259 | onSetup: onSetupLink, |
||
1260 | onAction: function (formApi) { |
||
1261 | unlink(editor); |
||
1262 | formApi.hide(); |
||
1263 | } |
||
1264 | }, |
||
1265 | { |
||
1266 | type: 'contextformbutton', |
||
1267 | icon: 'new-tab', |
||
1268 | tooltip: 'Open link', |
||
1269 | onSetup: onSetupLink, |
||
1270 | onAction: function (formApi) { |
||
1271 | gotoSelectedLink(editor)(); |
||
1272 | formApi.hide(); |
||
1273 | } |
||
1274 | } |
||
1275 | ] |
||
1276 | }); |
||
1277 | }; |
||
1278 | |||
1279 | function Plugin () { |
||
679 | daniel-mar | 1280 | global$7.add('link', function (editor) { |
597 | daniel-mar | 1281 | setupButtons(editor); |
1282 | setupMenuItems(editor); |
||
1283 | setupContextMenu(editor); |
||
1284 | setupContextToolbars(editor); |
||
1285 | setupGotoLinks(editor); |
||
1286 | register(editor); |
||
1287 | setup(editor); |
||
1288 | }); |
||
1289 | } |
||
1290 | |||
1291 | Plugin(); |
||
1292 | |||
1293 | }()); |