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 | |||
12 | var Cell = function (initial) { |
||
13 | var value = initial; |
||
14 | var get = function () { |
||
15 | return value; |
||
16 | }; |
||
17 | var set = function (v) { |
||
18 | value = v; |
||
19 | }; |
||
20 | return { |
||
21 | get: get, |
||
22 | set: set |
||
23 | }; |
||
24 | }; |
||
25 | |||
637 | daniel-mar | 26 | var global$1 = tinymce.util.Tools.resolve('tinymce.PluginManager'); |
597 | daniel-mar | 27 | |
637 | daniel-mar | 28 | var get$2 = function (toggleState) { |
597 | daniel-mar | 29 | var isEnabled = function () { |
30 | return toggleState.get(); |
||
31 | }; |
||
32 | return { isEnabled: isEnabled }; |
||
33 | }; |
||
34 | |||
35 | var fireVisualChars = function (editor, state) { |
||
36 | return editor.fire('VisualChars', { state: state }); |
||
37 | }; |
||
38 | |||
39 | var typeOf = function (x) { |
||
40 | var t = typeof x; |
||
41 | if (x === null) { |
||
42 | return 'null'; |
||
43 | } else if (t === 'object' && (Array.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'Array')) { |
||
44 | return 'array'; |
||
45 | } else if (t === 'object' && (String.prototype.isPrototypeOf(x) || x.constructor && x.constructor.name === 'String')) { |
||
46 | return 'string'; |
||
47 | } else { |
||
48 | return t; |
||
49 | } |
||
50 | }; |
||
637 | daniel-mar | 51 | var isType$1 = function (type) { |
597 | daniel-mar | 52 | return function (value) { |
53 | return typeOf(value) === type; |
||
54 | }; |
||
55 | }; |
||
56 | var isSimpleType = function (type) { |
||
57 | return function (value) { |
||
58 | return typeof value === type; |
||
59 | }; |
||
60 | }; |
||
637 | daniel-mar | 61 | var isString = isType$1('string'); |
597 | daniel-mar | 62 | var isBoolean = isSimpleType('boolean'); |
63 | var isNumber = isSimpleType('number'); |
||
64 | |||
65 | var noop = function () { |
||
66 | }; |
||
67 | var constant = function (value) { |
||
68 | return function () { |
||
69 | return value; |
||
70 | }; |
||
71 | }; |
||
637 | daniel-mar | 72 | var identity = function (x) { |
73 | return x; |
||
74 | }; |
||
597 | daniel-mar | 75 | var never = constant(false); |
76 | var always = constant(true); |
||
77 | |||
78 | var none = function () { |
||
79 | return NONE; |
||
80 | }; |
||
81 | var NONE = function () { |
||
82 | var call = function (thunk) { |
||
83 | return thunk(); |
||
84 | }; |
||
637 | daniel-mar | 85 | var id = identity; |
597 | daniel-mar | 86 | var me = { |
87 | fold: function (n, _s) { |
||
88 | return n(); |
||
89 | }, |
||
90 | isSome: never, |
||
91 | isNone: always, |
||
92 | getOr: id, |
||
93 | getOrThunk: call, |
||
94 | getOrDie: function (msg) { |
||
95 | throw new Error(msg || 'error: getOrDie called on none.'); |
||
96 | }, |
||
97 | getOrNull: constant(null), |
||
98 | getOrUndefined: constant(undefined), |
||
99 | or: id, |
||
100 | orThunk: call, |
||
101 | map: none, |
||
102 | each: noop, |
||
103 | bind: none, |
||
104 | exists: never, |
||
105 | forall: always, |
||
637 | daniel-mar | 106 | filter: function () { |
107 | return none(); |
||
108 | }, |
||
597 | daniel-mar | 109 | toArray: function () { |
110 | return []; |
||
111 | }, |
||
112 | toString: constant('none()') |
||
113 | }; |
||
114 | return me; |
||
115 | }(); |
||
116 | var some = function (a) { |
||
117 | var constant_a = constant(a); |
||
118 | var self = function () { |
||
119 | return me; |
||
120 | }; |
||
121 | var bind = function (f) { |
||
122 | return f(a); |
||
123 | }; |
||
124 | var me = { |
||
125 | fold: function (n, s) { |
||
126 | return s(a); |
||
127 | }, |
||
128 | isSome: always, |
||
129 | isNone: never, |
||
130 | getOr: constant_a, |
||
131 | getOrThunk: constant_a, |
||
132 | getOrDie: constant_a, |
||
133 | getOrNull: constant_a, |
||
134 | getOrUndefined: constant_a, |
||
135 | or: self, |
||
136 | orThunk: self, |
||
137 | map: function (f) { |
||
138 | return some(f(a)); |
||
139 | }, |
||
140 | each: function (f) { |
||
141 | f(a); |
||
142 | }, |
||
143 | bind: bind, |
||
144 | exists: bind, |
||
145 | forall: bind, |
||
146 | filter: function (f) { |
||
147 | return f(a) ? me : NONE; |
||
148 | }, |
||
149 | toArray: function () { |
||
150 | return [a]; |
||
151 | }, |
||
152 | toString: function () { |
||
153 | return 'some(' + a + ')'; |
||
154 | } |
||
155 | }; |
||
156 | return me; |
||
157 | }; |
||
158 | var from = function (value) { |
||
159 | return value === null || value === undefined ? NONE : some(value); |
||
160 | }; |
||
161 | var Optional = { |
||
162 | some: some, |
||
163 | none: none, |
||
164 | from: from |
||
165 | }; |
||
166 | |||
167 | var map = function (xs, f) { |
||
168 | var len = xs.length; |
||
169 | var r = new Array(len); |
||
170 | for (var i = 0; i < len; i++) { |
||
171 | var x = xs[i]; |
||
172 | r[i] = f(x, i); |
||
173 | } |
||
174 | return r; |
||
175 | }; |
||
637 | daniel-mar | 176 | var each$1 = function (xs, f) { |
597 | daniel-mar | 177 | for (var i = 0, len = xs.length; i < len; i++) { |
178 | var x = xs[i]; |
||
179 | f(x, i); |
||
180 | } |
||
181 | }; |
||
182 | var filter = function (xs, pred) { |
||
183 | var r = []; |
||
184 | for (var i = 0, len = xs.length; i < len; i++) { |
||
185 | var x = xs[i]; |
||
186 | if (pred(x, i)) { |
||
187 | r.push(x); |
||
188 | } |
||
189 | } |
||
190 | return r; |
||
191 | }; |
||
192 | |||
193 | var keys = Object.keys; |
||
637 | daniel-mar | 194 | var each = function (obj, f) { |
597 | daniel-mar | 195 | var props = keys(obj); |
196 | for (var k = 0, len = props.length; k < len; k++) { |
||
197 | var i = props[k]; |
||
198 | var x = obj[i]; |
||
199 | f(x, i); |
||
200 | } |
||
201 | }; |
||
202 | |||
637 | daniel-mar | 203 | typeof window !== 'undefined' ? window : Function('return this;')(); |
597 | daniel-mar | 204 | |
205 | var TEXT = 3; |
||
206 | |||
207 | var type = function (element) { |
||
208 | return element.dom.nodeType; |
||
209 | }; |
||
210 | var value = function (element) { |
||
211 | return element.dom.nodeValue; |
||
212 | }; |
||
637 | daniel-mar | 213 | var isType = function (t) { |
597 | daniel-mar | 214 | return function (element) { |
215 | return type(element) === t; |
||
216 | }; |
||
217 | }; |
||
637 | daniel-mar | 218 | var isText = isType(TEXT); |
597 | daniel-mar | 219 | |
220 | var rawSet = function (dom, key, value) { |
||
221 | if (isString(value) || isBoolean(value) || isNumber(value)) { |
||
222 | dom.setAttribute(key, value + ''); |
||
223 | } else { |
||
224 | console.error('Invalid call to Attribute.set. Key ', key, ':: Value ', value, ':: Element ', dom); |
||
225 | throw new Error('Attribute value was not simple'); |
||
226 | } |
||
227 | }; |
||
228 | var set = function (element, key, value) { |
||
229 | rawSet(element.dom, key, value); |
||
230 | }; |
||
231 | var get$1 = function (element, key) { |
||
232 | var v = element.dom.getAttribute(key); |
||
233 | return v === null ? undefined : v; |
||
234 | }; |
||
637 | daniel-mar | 235 | var remove$3 = function (element, key) { |
597 | daniel-mar | 236 | element.dom.removeAttribute(key); |
237 | }; |
||
238 | |||
239 | var read = function (element, attr) { |
||
240 | var value = get$1(element, attr); |
||
241 | return value === undefined || value === '' ? [] : value.split(' '); |
||
242 | }; |
||
637 | daniel-mar | 243 | var add$2 = function (element, attr, id) { |
597 | daniel-mar | 244 | var old = read(element, attr); |
245 | var nu = old.concat([id]); |
||
246 | set(element, attr, nu.join(' ')); |
||
247 | return true; |
||
248 | }; |
||
637 | daniel-mar | 249 | var remove$2 = function (element, attr, id) { |
597 | daniel-mar | 250 | var nu = filter(read(element, attr), function (v) { |
251 | return v !== id; |
||
252 | }); |
||
253 | if (nu.length > 0) { |
||
254 | set(element, attr, nu.join(' ')); |
||
255 | } else { |
||
637 | daniel-mar | 256 | remove$3(element, attr); |
597 | daniel-mar | 257 | } |
258 | return false; |
||
259 | }; |
||
260 | |||
261 | var supports = function (element) { |
||
262 | return element.dom.classList !== undefined; |
||
263 | }; |
||
637 | daniel-mar | 264 | var get = function (element) { |
597 | daniel-mar | 265 | return read(element, 'class'); |
266 | }; |
||
267 | var add$1 = function (element, clazz) { |
||
637 | daniel-mar | 268 | return add$2(element, 'class', clazz); |
597 | daniel-mar | 269 | }; |
637 | daniel-mar | 270 | var remove$1 = function (element, clazz) { |
271 | return remove$2(element, 'class', clazz); |
||
597 | daniel-mar | 272 | }; |
273 | |||
637 | daniel-mar | 274 | var add = function (element, clazz) { |
597 | daniel-mar | 275 | if (supports(element)) { |
276 | element.dom.classList.add(clazz); |
||
277 | } else { |
||
278 | add$1(element, clazz); |
||
279 | } |
||
280 | }; |
||
281 | var cleanClass = function (element) { |
||
637 | daniel-mar | 282 | var classList = supports(element) ? element.dom.classList : get(element); |
597 | daniel-mar | 283 | if (classList.length === 0) { |
637 | daniel-mar | 284 | remove$3(element, 'class'); |
597 | daniel-mar | 285 | } |
286 | }; |
||
637 | daniel-mar | 287 | var remove = function (element, clazz) { |
597 | daniel-mar | 288 | if (supports(element)) { |
289 | var classList = element.dom.classList; |
||
290 | classList.remove(clazz); |
||
291 | } else { |
||
637 | daniel-mar | 292 | remove$1(element, clazz); |
597 | daniel-mar | 293 | } |
294 | cleanClass(element); |
||
295 | }; |
||
296 | |||
297 | var fromHtml = function (html, scope) { |
||
298 | var doc = scope || document; |
||
299 | var div = doc.createElement('div'); |
||
300 | div.innerHTML = html; |
||
301 | if (!div.hasChildNodes() || div.childNodes.length > 1) { |
||
302 | console.error('HTML does not have a single root node', html); |
||
303 | throw new Error('HTML must have a single root node'); |
||
304 | } |
||
305 | return fromDom(div.childNodes[0]); |
||
306 | }; |
||
307 | var fromTag = function (tag, scope) { |
||
308 | var doc = scope || document; |
||
309 | var node = doc.createElement(tag); |
||
310 | return fromDom(node); |
||
311 | }; |
||
312 | var fromText = function (text, scope) { |
||
313 | var doc = scope || document; |
||
314 | var node = doc.createTextNode(text); |
||
315 | return fromDom(node); |
||
316 | }; |
||
317 | var fromDom = function (node) { |
||
318 | if (node === null || node === undefined) { |
||
319 | throw new Error('Node cannot be null or undefined'); |
||
320 | } |
||
321 | return { dom: node }; |
||
322 | }; |
||
323 | var fromPoint = function (docElm, x, y) { |
||
324 | return Optional.from(docElm.dom.elementFromPoint(x, y)).map(fromDom); |
||
325 | }; |
||
326 | var SugarElement = { |
||
327 | fromHtml: fromHtml, |
||
328 | fromTag: fromTag, |
||
329 | fromText: fromText, |
||
330 | fromDom: fromDom, |
||
331 | fromPoint: fromPoint |
||
332 | }; |
||
333 | |||
334 | var charMap = { |
||
335 | '\xA0': 'nbsp', |
||
336 | '\xAD': 'shy' |
||
337 | }; |
||
338 | var charMapToRegExp = function (charMap, global) { |
||
339 | var regExp = ''; |
||
637 | daniel-mar | 340 | each(charMap, function (_value, key) { |
597 | daniel-mar | 341 | regExp += key; |
342 | }); |
||
343 | return new RegExp('[' + regExp + ']', global ? 'g' : ''); |
||
344 | }; |
||
345 | var charMapToSelector = function (charMap) { |
||
346 | var selector = ''; |
||
637 | daniel-mar | 347 | each(charMap, function (value) { |
597 | daniel-mar | 348 | if (selector) { |
349 | selector += ','; |
||
350 | } |
||
351 | selector += 'span.mce-' + value; |
||
352 | }); |
||
353 | return selector; |
||
354 | }; |
||
355 | var regExp = charMapToRegExp(charMap); |
||
356 | var regExpGlobal = charMapToRegExp(charMap, true); |
||
357 | var selector = charMapToSelector(charMap); |
||
358 | var nbspClass = 'mce-nbsp'; |
||
359 | |||
360 | var wrapCharWithSpan = function (value) { |
||
361 | return '<span data-mce-bogus="1" class="mce-' + charMap[value] + '">' + value + '</span>'; |
||
362 | }; |
||
363 | |||
364 | var isMatch = function (n) { |
||
365 | var value$1 = value(n); |
||
366 | return isText(n) && value$1 !== undefined && regExp.test(value$1); |
||
367 | }; |
||
368 | var filterDescendants = function (scope, predicate) { |
||
369 | var result = []; |
||
370 | var dom = scope.dom; |
||
371 | var children = map(dom.childNodes, SugarElement.fromDom); |
||
637 | daniel-mar | 372 | each$1(children, function (x) { |
597 | daniel-mar | 373 | if (predicate(x)) { |
374 | result = result.concat([x]); |
||
375 | } |
||
376 | result = result.concat(filterDescendants(x, predicate)); |
||
377 | }); |
||
378 | return result; |
||
379 | }; |
||
380 | var findParentElm = function (elm, rootElm) { |
||
381 | while (elm.parentNode) { |
||
382 | if (elm.parentNode === rootElm) { |
||
383 | return elm; |
||
384 | } |
||
385 | elm = elm.parentNode; |
||
386 | } |
||
387 | }; |
||
388 | var replaceWithSpans = function (text) { |
||
389 | return text.replace(regExpGlobal, wrapCharWithSpan); |
||
390 | }; |
||
391 | |||
392 | var isWrappedNbsp = function (node) { |
||
393 | return node.nodeName.toLowerCase() === 'span' && node.classList.contains('mce-nbsp-wrap'); |
||
394 | }; |
||
395 | var show = function (editor, rootElm) { |
||
396 | var nodeList = filterDescendants(SugarElement.fromDom(rootElm), isMatch); |
||
637 | daniel-mar | 397 | each$1(nodeList, function (n) { |
597 | daniel-mar | 398 | var parent = n.dom.parentNode; |
399 | if (isWrappedNbsp(parent)) { |
||
637 | daniel-mar | 400 | add(SugarElement.fromDom(parent), nbspClass); |
597 | daniel-mar | 401 | } else { |
402 | var withSpans = replaceWithSpans(editor.dom.encode(value(n))); |
||
403 | var div = editor.dom.create('div', null, withSpans); |
||
404 | var node = void 0; |
||
405 | while (node = div.lastChild) { |
||
406 | editor.dom.insertAfter(node, n.dom); |
||
407 | } |
||
408 | editor.dom.remove(n.dom); |
||
409 | } |
||
410 | }); |
||
411 | }; |
||
412 | var hide = function (editor, rootElm) { |
||
413 | var nodeList = editor.dom.select(selector, rootElm); |
||
637 | daniel-mar | 414 | each$1(nodeList, function (node) { |
597 | daniel-mar | 415 | if (isWrappedNbsp(node)) { |
637 | daniel-mar | 416 | remove(SugarElement.fromDom(node), nbspClass); |
597 | daniel-mar | 417 | } else { |
418 | editor.dom.remove(node, true); |
||
419 | } |
||
420 | }); |
||
421 | }; |
||
422 | var toggle = function (editor) { |
||
423 | var body = editor.getBody(); |
||
424 | var bookmark = editor.selection.getBookmark(); |
||
425 | var parentNode = findParentElm(editor.selection.getNode(), body); |
||
426 | parentNode = parentNode !== undefined ? parentNode : body; |
||
427 | hide(editor, parentNode); |
||
428 | show(editor, parentNode); |
||
429 | editor.selection.moveToBookmark(bookmark); |
||
430 | }; |
||
431 | |||
432 | var applyVisualChars = function (editor, toggleState) { |
||
433 | fireVisualChars(editor, toggleState.get()); |
||
434 | var body = editor.getBody(); |
||
435 | if (toggleState.get() === true) { |
||
436 | show(editor, body); |
||
437 | } else { |
||
438 | hide(editor, body); |
||
439 | } |
||
440 | }; |
||
441 | var toggleVisualChars = function (editor, toggleState) { |
||
442 | toggleState.set(!toggleState.get()); |
||
443 | var bookmark = editor.selection.getBookmark(); |
||
444 | applyVisualChars(editor, toggleState); |
||
445 | editor.selection.moveToBookmark(bookmark); |
||
446 | }; |
||
447 | |||
637 | daniel-mar | 448 | var register$1 = function (editor, toggleState) { |
597 | daniel-mar | 449 | editor.addCommand('mceVisualChars', function () { |
450 | toggleVisualChars(editor, toggleState); |
||
451 | }); |
||
452 | }; |
||
453 | |||
454 | var isEnabledByDefault = function (editor) { |
||
455 | return editor.getParam('visualchars_default_state', false); |
||
456 | }; |
||
457 | var hasForcedRootBlock = function (editor) { |
||
458 | return editor.getParam('forced_root_block') !== false; |
||
459 | }; |
||
460 | |||
637 | daniel-mar | 461 | var setup$1 = function (editor, toggleState) { |
597 | daniel-mar | 462 | editor.on('init', function () { |
463 | applyVisualChars(editor, toggleState); |
||
464 | }); |
||
465 | }; |
||
466 | |||
637 | daniel-mar | 467 | var global = tinymce.util.Tools.resolve('tinymce.util.Delay'); |
597 | daniel-mar | 468 | |
637 | daniel-mar | 469 | var setup = function (editor, toggleState) { |
470 | var debouncedToggle = global.debounce(function () { |
||
597 | daniel-mar | 471 | toggle(editor); |
472 | }, 300); |
||
473 | if (hasForcedRootBlock(editor)) { |
||
474 | editor.on('keydown', function (e) { |
||
475 | if (toggleState.get() === true) { |
||
476 | e.keyCode === 13 ? toggle(editor) : debouncedToggle(); |
||
477 | } |
||
478 | }); |
||
479 | } |
||
480 | editor.on('remove', debouncedToggle.stop); |
||
481 | }; |
||
482 | |||
483 | var toggleActiveState = function (editor, enabledStated) { |
||
484 | return function (api) { |
||
485 | api.setActive(enabledStated.get()); |
||
486 | var editorEventCallback = function (e) { |
||
487 | return api.setActive(e.state); |
||
488 | }; |
||
489 | editor.on('VisualChars', editorEventCallback); |
||
490 | return function () { |
||
491 | return editor.off('VisualChars', editorEventCallback); |
||
492 | }; |
||
493 | }; |
||
494 | }; |
||
637 | daniel-mar | 495 | var register = function (editor, toggleState) { |
496 | var onAction = function () { |
||
497 | return editor.execCommand('mceVisualChars'); |
||
498 | }; |
||
597 | daniel-mar | 499 | editor.ui.registry.addToggleButton('visualchars', { |
500 | tooltip: 'Show invisible characters', |
||
501 | icon: 'visualchars', |
||
637 | daniel-mar | 502 | onAction: onAction, |
597 | daniel-mar | 503 | onSetup: toggleActiveState(editor, toggleState) |
504 | }); |
||
505 | editor.ui.registry.addToggleMenuItem('visualchars', { |
||
506 | text: 'Show invisible characters', |
||
507 | icon: 'visualchars', |
||
637 | daniel-mar | 508 | onAction: onAction, |
597 | daniel-mar | 509 | onSetup: toggleActiveState(editor, toggleState) |
510 | }); |
||
511 | }; |
||
512 | |||
513 | function Plugin () { |
||
637 | daniel-mar | 514 | global$1.add('visualchars', function (editor) { |
597 | daniel-mar | 515 | var toggleState = Cell(isEnabledByDefault(editor)); |
637 | daniel-mar | 516 | register$1(editor, toggleState); |
597 | daniel-mar | 517 | register(editor, toggleState); |
637 | daniel-mar | 518 | setup(editor, toggleState); |
597 | daniel-mar | 519 | setup$1(editor, toggleState); |
637 | daniel-mar | 520 | return get$2(toggleState); |
597 | daniel-mar | 521 | }); |
522 | } |
||
523 | |||
524 | Plugin(); |
||
525 | |||
526 | }()); |