tinymce-rails 8.0.2 → 8.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +4 -0
- data/app/assets/source/tinymce/tinymce.js +323 -347
- data/lib/tinymce/rails/version.rb +2 -2
- data/vendor/assets/javascripts/tinymce/icons/default/icons.js +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.inline.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.inline.js +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.inline.min.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.js +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide/content.min.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide/skin.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide/skin.js +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide/skin.min.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.inline.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.inline.js +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.inline.min.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.js +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/content.min.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/skin.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/skin.js +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/oxide-dark/skin.min.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.inline.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.inline.js +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.inline.min.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.js +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/content.min.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/skin.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/skin.js +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5/skin.min.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.inline.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.inline.js +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.inline.min.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.js +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/content.min.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/skin.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/skin.js +1 -1
- data/vendor/assets/javascripts/tinymce/skins/ui/tinymce-5-dark/skin.min.css +1 -1
- data/vendor/assets/javascripts/tinymce/themes/silver/theme.js +1 -1
- data/vendor/assets/javascripts/tinymce/tinymce.d.ts +405 -399
- data/vendor/assets/javascripts/tinymce/tinymce.js +2 -2
- metadata +1 -1
@@ -1,5 +1,5 @@
|
|
1
1
|
/**
|
2
|
-
* TinyMCE version 8.
|
2
|
+
* TinyMCE version 8.1.1 (2025-09-17)
|
3
3
|
*/
|
4
4
|
|
5
5
|
(function () {
|
@@ -580,7 +580,7 @@
|
|
580
580
|
}
|
581
581
|
return Optional.none();
|
582
582
|
};
|
583
|
-
const flatten = (xs) => {
|
583
|
+
const flatten$1 = (xs) => {
|
584
584
|
// Note, this is possible because push supports multiple arguments:
|
585
585
|
// http://jsperf.com/concat-push/6
|
586
586
|
// Note that in the past, concat() would silently work (very slowly) for array-like objects.
|
@@ -595,7 +595,7 @@
|
|
595
595
|
}
|
596
596
|
return r;
|
597
597
|
};
|
598
|
-
const bind$3 = (xs, f) => flatten(map$3(xs, f));
|
598
|
+
const bind$3 = (xs, f) => flatten$1(map$3(xs, f));
|
599
599
|
const forall = (xs, pred) => {
|
600
600
|
for (let i = 0, len = xs.length; i < len; ++i) {
|
601
601
|
const x = xs[i];
|
@@ -719,7 +719,7 @@
|
|
719
719
|
* Generates a church encoded ADT (https://en.wikipedia.org/wiki/Church_encoding)
|
720
720
|
* For syntax and use, look at the test code.
|
721
721
|
*/
|
722
|
-
const generate$
|
722
|
+
const generate$1 = (cases) => {
|
723
723
|
// validation
|
724
724
|
if (!isArray$1(cases)) {
|
725
725
|
throw new Error('cases must be an array');
|
@@ -800,7 +800,7 @@
|
|
800
800
|
return adt;
|
801
801
|
};
|
802
802
|
const Adt = {
|
803
|
-
generate: generate$
|
803
|
+
generate: generate$1
|
804
804
|
};
|
805
805
|
|
806
806
|
const Cell = (initial) => {
|
@@ -945,7 +945,7 @@
|
|
945
945
|
* generate :: String -> String
|
946
946
|
*/
|
947
947
|
let unique = 0;
|
948
|
-
const generate
|
948
|
+
const generate = (prefix) => {
|
949
949
|
const date = new Date();
|
950
950
|
const time = date.getTime();
|
951
951
|
const random$1 = Math.floor(random() * 1000000000);
|
@@ -1019,6 +1019,7 @@
|
|
1019
1019
|
*/
|
1020
1020
|
const lift2 = (oa, ob, f) => oa.isSome() && ob.isSome() ? Optional.some(f(oa.getOrDie(), ob.getOrDie())) : Optional.none();
|
1021
1021
|
const lift3 = (oa, ob, oc, f) => oa.isSome() && ob.isSome() && oc.isSome() ? Optional.some(f(oa.getOrDie(), ob.getOrDie(), oc.getOrDie())) : Optional.none();
|
1022
|
+
const flatten = (oot) => oot.bind(identity);
|
1022
1023
|
// This can help with type inference, by specifying the type param on the none case, so the caller doesn't have to.
|
1023
1024
|
const someIf = (b, a) => b ? Optional.some(a) : Optional.none();
|
1024
1025
|
|
@@ -7565,7 +7566,7 @@
|
|
7565
7566
|
* alert('All scripts are now loaded.');
|
7566
7567
|
* });
|
7567
7568
|
*/
|
7568
|
-
const DOM$
|
7569
|
+
const DOM$e = DOMUtils.DOM;
|
7569
7570
|
const QUEUED = 0;
|
7570
7571
|
const LOADING = 1;
|
7571
7572
|
const LOADED = 2;
|
@@ -7594,7 +7595,7 @@
|
|
7594
7595
|
*/
|
7595
7596
|
loadScript(url) {
|
7596
7597
|
return new Promise((resolve, reject) => {
|
7597
|
-
const dom = DOM$
|
7598
|
+
const dom = DOM$e;
|
7598
7599
|
let elm;
|
7599
7600
|
const cleanup = () => {
|
7600
7601
|
dom.remove(id);
|
@@ -9443,7 +9444,7 @@
|
|
9443
9444
|
selection.moveToBookmark({ id, keep: true, forward });
|
9444
9445
|
return { id, forward };
|
9445
9446
|
};
|
9446
|
-
const getBookmark$
|
9447
|
+
const getBookmark$2 = (selection, type, normalized = false) => {
|
9447
9448
|
if (type === 2) {
|
9448
9449
|
return getOffsetBookmark(trim$2, normalized, selection);
|
9449
9450
|
}
|
@@ -9459,6 +9460,15 @@
|
|
9459
9460
|
};
|
9460
9461
|
const getUndoBookmark = curry(getOffsetBookmark, identity, true);
|
9461
9462
|
|
9463
|
+
/**
|
9464
|
+
* Checks if the direction is forwards.
|
9465
|
+
*/
|
9466
|
+
const isForwards = (direction) => direction === 1 /* HDirection.Forwards */;
|
9467
|
+
/**
|
9468
|
+
* Checks if the direction is backwards.
|
9469
|
+
*/
|
9470
|
+
const isBackwards = (direction) => direction === -1 /* HDirection.Backwards */;
|
9471
|
+
|
9462
9472
|
const isInlinePattern = (pattern) => pattern.type === 'inline-command' || pattern.type === 'inline-format';
|
9463
9473
|
const isBlockPattern = (pattern) => pattern.type === 'block-command' || pattern.type === 'block-format';
|
9464
9474
|
const hasBlockTrigger = (pattern, trigger) => (pattern.type === 'block-command' || pattern.type === 'block-format') && pattern.trigger === trigger;
|
@@ -9640,7 +9650,7 @@
|
|
9640
9650
|
|
9641
9651
|
const deviceDetection$1 = detect$1().deviceType;
|
9642
9652
|
const isTouch = deviceDetection$1.isTouch();
|
9643
|
-
const DOM$
|
9653
|
+
const DOM$d = DOMUtils.DOM;
|
9644
9654
|
const getHash = (value) => {
|
9645
9655
|
const items = value.indexOf('=') > 0 ? value.split(/[;,](?![^=;,]*(?:[;,]|$))/) : value.split(',');
|
9646
9656
|
return foldl(items, (output, item) => {
|
@@ -10422,7 +10432,7 @@
|
|
10422
10432
|
registerOption('placeholder', {
|
10423
10433
|
processor: 'string',
|
10424
10434
|
// Fallback to the original elements placeholder if not set in the settings
|
10425
|
-
default: DOM$
|
10435
|
+
default: DOM$d.getAttrib(editor.getElement(), 'placeholder')
|
10426
10436
|
});
|
10427
10437
|
});
|
10428
10438
|
registerOption('lists_indent_on_tab', {
|
@@ -10806,8 +10816,6 @@
|
|
10806
10816
|
const isElement$3 = isElement$7;
|
10807
10817
|
const isText$4 = isText$b;
|
10808
10818
|
const isCaretCandidate$1 = isCaretCandidate$3;
|
10809
|
-
const isForwards = (direction) => direction === 1 /* HDirection.Forwards */;
|
10810
|
-
const isBackwards = (direction) => direction === -1 /* HDirection.Backwards */;
|
10811
10819
|
const skipCaretContainers = (walk, shallow) => {
|
10812
10820
|
let node;
|
10813
10821
|
while ((node = walk(shallow))) {
|
@@ -11024,6 +11032,20 @@
|
|
11024
11032
|
return inSameBlock;
|
11025
11033
|
};
|
11026
11034
|
|
11035
|
+
/**
|
11036
|
+
* This module contains logic for moving around a virtual caret in logical order within a DOM element.
|
11037
|
+
*
|
11038
|
+
* It ignores the most obvious invalid caret locations such as within a script element or within a
|
11039
|
+
* contentEditable=false element but it will return locations that isn't possible to render visually.
|
11040
|
+
*
|
11041
|
+
* @private
|
11042
|
+
* @class tinymce.caret.CaretWalker
|
11043
|
+
* @example
|
11044
|
+
* const caretWalker = CaretWalker(rootElm);
|
11045
|
+
*
|
11046
|
+
* const prevLogicalCaretPosition = caretWalker.prev(CaretPosition.fromRangeStart(range));
|
11047
|
+
* const nextLogicalCaretPosition = caretWalker.next(CaretPosition.fromRangeEnd(range));
|
11048
|
+
*/
|
11027
11049
|
const isContentEditableFalse$5 = isContentEditableFalse$a;
|
11028
11050
|
const isText$3 = isText$b;
|
11029
11051
|
const isElement$2 = isElement$7;
|
@@ -11375,7 +11397,7 @@
|
|
11375
11397
|
return true;
|
11376
11398
|
};
|
11377
11399
|
const isValidTextNode = (node) => isText$b(node) && node.data.length > 0;
|
11378
|
-
const restoreEndPoint = (dom, suffix, bookmark) => {
|
11400
|
+
const restoreEndPoint$1 = (dom, suffix, bookmark) => {
|
11379
11401
|
const marker = dom.get(bookmark.id + '_' + suffix);
|
11380
11402
|
const markerParent = marker === null || marker === void 0 ? void 0 : marker.parentNode;
|
11381
11403
|
const keep = bookmark.keep;
|
@@ -11469,8 +11491,8 @@
|
|
11469
11491
|
}
|
11470
11492
|
};
|
11471
11493
|
const resolveId = (dom, bookmark) => {
|
11472
|
-
const startPos = restoreEndPoint(dom, 'start', bookmark);
|
11473
|
-
const endPos = restoreEndPoint(dom, 'end', bookmark);
|
11494
|
+
const startPos = restoreEndPoint$1(dom, 'start', bookmark);
|
11495
|
+
const endPos = restoreEndPoint$1(dom, 'end', bookmark);
|
11474
11496
|
return lift2(startPos, endPos.or(startPos), (spos, epos) => {
|
11475
11497
|
const range = dom.createRng();
|
11476
11498
|
range.setStart(addBogus(dom, spos.container()), spos.offset());
|
@@ -11505,8 +11527,8 @@
|
|
11505
11527
|
return Optional.none();
|
11506
11528
|
};
|
11507
11529
|
|
11508
|
-
const getBookmark$
|
11509
|
-
return getBookmark$
|
11530
|
+
const getBookmark$1 = (selection, type, normalized) => {
|
11531
|
+
return getBookmark$2(selection, type, normalized);
|
11510
11532
|
};
|
11511
11533
|
const moveToBookmark = (selection, bookmark) => {
|
11512
11534
|
resolve(selection, bookmark).each(({ range, forward }) => {
|
@@ -12428,7 +12450,7 @@
|
|
12428
12450
|
const selection = editor.selection;
|
12429
12451
|
const initialRng = selection.getRng();
|
12430
12452
|
const hasFakeSelection = getCellsFromEditor(editor).length > 0;
|
12431
|
-
const masterUid = generate
|
12453
|
+
const masterUid = generate('mce-annotation');
|
12432
12454
|
if (initialRng.collapsed && !hasFakeSelection) {
|
12433
12455
|
applyWordGrab(editor, initialRng);
|
12434
12456
|
}
|
@@ -12576,7 +12598,7 @@
|
|
12576
12598
|
* // Restore the selection bookmark
|
12577
12599
|
* tinymce.activeEditor.selection.moveToBookmark(bm);
|
12578
12600
|
*/
|
12579
|
-
getBookmark: curry(getBookmark$
|
12601
|
+
getBookmark: curry(getBookmark$1, selection),
|
12580
12602
|
/**
|
12581
12603
|
* Restores the selection to the specified bookmark.
|
12582
12604
|
*
|
@@ -12634,7 +12656,7 @@
|
|
12634
12656
|
const rng = !selection || selection.rangeCount === 0 ? Optional.none() : Optional.from(selection.getRangeAt(0));
|
12635
12657
|
return rng.map(nativeRangeToSelectionRange);
|
12636
12658
|
};
|
12637
|
-
const getBookmark
|
12659
|
+
const getBookmark = (root) => {
|
12638
12660
|
const win = defaultView(root);
|
12639
12661
|
return readRange(win.dom)
|
12640
12662
|
.filter(isRngInRoot(root));
|
@@ -12655,7 +12677,7 @@
|
|
12655
12677
|
}
|
12656
12678
|
};
|
12657
12679
|
const store = (editor) => {
|
12658
|
-
const newBookmark = shouldStore(editor) ? getBookmark
|
12680
|
+
const newBookmark = shouldStore(editor) ? getBookmark(SugarElement.fromDom(editor.getBody())) : Optional.none();
|
12659
12681
|
editor.bookmark = newBookmark.isSome() ? newBookmark : editor.bookmark;
|
12660
12682
|
};
|
12661
12683
|
const getRng = (editor) => {
|
@@ -12836,7 +12858,7 @@
|
|
12836
12858
|
};
|
12837
12859
|
|
12838
12860
|
let documentFocusInHandler;
|
12839
|
-
const DOM$
|
12861
|
+
const DOM$c = DOMUtils.DOM;
|
12840
12862
|
const isEditorUIElement = (elm) => {
|
12841
12863
|
// Since this can be overridden by third party we need to use the API reference here
|
12842
12864
|
return isElement$7(elm) && FocusManager.isEditorUIElement(elm);
|
@@ -12854,7 +12876,7 @@
|
|
12854
12876
|
};
|
12855
12877
|
const isUIElement = (editor, elm) => {
|
12856
12878
|
const customSelector = getCustomUiSelector(editor);
|
12857
|
-
const parent = DOM$
|
12879
|
+
const parent = DOM$c.getParent(elm, (elm) => {
|
12858
12880
|
return (isEditorUIElement(elm) ||
|
12859
12881
|
(customSelector ? editor.dom.is(elm, customSelector) : false));
|
12860
12882
|
});
|
@@ -12944,7 +12966,7 @@
|
|
12944
12966
|
});
|
12945
12967
|
}
|
12946
12968
|
};
|
12947
|
-
DOM$
|
12969
|
+
DOM$c.bind(document, 'focusin', documentFocusInHandler);
|
12948
12970
|
}
|
12949
12971
|
};
|
12950
12972
|
const unregisterDocumentEvents = (editorManager, e) => {
|
@@ -12952,7 +12974,7 @@
|
|
12952
12974
|
editorManager.focusedEditor = null;
|
12953
12975
|
}
|
12954
12976
|
if (!editorManager.activeEditor && documentFocusInHandler) {
|
12955
|
-
DOM$
|
12977
|
+
DOM$c.unbind(document, 'focusin', documentFocusInHandler);
|
12956
12978
|
documentFocusInHandler = null;
|
12957
12979
|
}
|
12958
12980
|
};
|
@@ -16067,90 +16089,90 @@
|
|
16067
16089
|
return outRng;
|
16068
16090
|
};
|
16069
16091
|
|
16070
|
-
|
16071
|
-
const DOM$
|
16072
|
-
|
16073
|
-
|
16074
|
-
|
16075
|
-
|
16076
|
-
|
16077
|
-
|
16078
|
-
* becomes: <p><b><span data-mce-type="bookmark">|</span></b><b data-mce-type="bookmark">|</span></b></p>
|
16079
|
-
*/
|
16080
|
-
const createBookmark$1 = (rng) => {
|
16081
|
-
const bookmark = {};
|
16082
|
-
const setupEndPoint = (start) => {
|
16083
|
-
let container = rng[start ? 'startContainer' : 'endContainer'];
|
16084
|
-
let offset = rng[start ? 'startOffset' : 'endOffset'];
|
16085
|
-
if (isElement$7(container)) {
|
16086
|
-
const offsetNode = DOM$c.create('span', { 'data-mce-type': 'bookmark' });
|
16087
|
-
if (container.hasChildNodes()) {
|
16088
|
-
if (offset === container.childNodes.length) {
|
16089
|
-
container.appendChild(offsetNode);
|
16090
|
-
}
|
16091
|
-
else {
|
16092
|
-
container.insertBefore(offsetNode, container.childNodes[offset]);
|
16093
|
-
}
|
16092
|
+
const DOM$b = DOMUtils.DOM;
|
16093
|
+
const defaultMarker = () => DOM$b.create('span', { 'data-mce-type': 'bookmark' });
|
16094
|
+
const setupEndPoint = (container, offset, createMarker) => {
|
16095
|
+
if (isElement$7(container)) {
|
16096
|
+
const offsetNode = createMarker();
|
16097
|
+
if (container.hasChildNodes()) {
|
16098
|
+
if (offset === container.childNodes.length) {
|
16099
|
+
container.appendChild(offsetNode);
|
16094
16100
|
}
|
16095
16101
|
else {
|
16096
|
-
container.
|
16102
|
+
container.insertBefore(offsetNode, container.childNodes[offset]);
|
16097
16103
|
}
|
16098
|
-
container = offsetNode;
|
16099
|
-
offset = 0;
|
16100
16104
|
}
|
16101
|
-
|
16102
|
-
|
16103
|
-
|
16104
|
-
|
16105
|
-
|
16106
|
-
|
16105
|
+
else {
|
16106
|
+
container.appendChild(offsetNode);
|
16107
|
+
}
|
16108
|
+
return { container: offsetNode, offset: 0 };
|
16109
|
+
}
|
16110
|
+
else {
|
16111
|
+
return { container, offset };
|
16107
16112
|
}
|
16108
|
-
return bookmark;
|
16109
16113
|
};
|
16110
|
-
const
|
16111
|
-
const
|
16112
|
-
|
16113
|
-
|
16114
|
-
|
16115
|
-
|
16116
|
-
|
16117
|
-
|
16118
|
-
return idx;
|
16119
|
-
}
|
16120
|
-
// Skip data-mce-type=bookmark nodes
|
16121
|
-
if (!isElement$7(node) || node.getAttribute('data-mce-type') !== 'bookmark') {
|
16122
|
-
idx++;
|
16123
|
-
}
|
16124
|
-
node = node.nextSibling;
|
16114
|
+
const restoreEndPoint = (container, offset) => {
|
16115
|
+
const nodeIndex = (container) => {
|
16116
|
+
var _a;
|
16117
|
+
let node = (_a = container.parentNode) === null || _a === void 0 ? void 0 : _a.firstChild;
|
16118
|
+
let idx = 0;
|
16119
|
+
while (node) {
|
16120
|
+
if (node === container) {
|
16121
|
+
return idx;
|
16125
16122
|
}
|
16126
|
-
|
16127
|
-
|
16128
|
-
|
16129
|
-
let offset = bookmark[start ? 'startOffset' : 'endOffset'];
|
16130
|
-
if (!container) {
|
16131
|
-
return;
|
16132
|
-
}
|
16133
|
-
if (isElement$7(container) && container.parentNode) {
|
16134
|
-
const node = container;
|
16135
|
-
offset = nodeIndex(container);
|
16136
|
-
container = container.parentNode;
|
16137
|
-
DOM$c.remove(node);
|
16138
|
-
if (!container.hasChildNodes() && DOM$c.isBlock(container)) {
|
16139
|
-
container.appendChild(DOM$c.create('br'));
|
16123
|
+
// Skip data-mce-type=bookmark nodes
|
16124
|
+
if (!isElement$7(node) || node.getAttribute('data-mce-type') !== 'bookmark') {
|
16125
|
+
idx++;
|
16140
16126
|
}
|
16127
|
+
node = node.nextSibling;
|
16141
16128
|
}
|
16142
|
-
|
16143
|
-
bookmark[start ? 'startOffset' : 'endOffset'] = offset;
|
16129
|
+
return -1;
|
16144
16130
|
};
|
16145
|
-
|
16146
|
-
|
16147
|
-
|
16148
|
-
|
16149
|
-
|
16150
|
-
|
16131
|
+
if (isElement$7(container) && isNonNullable(container.parentNode)) {
|
16132
|
+
const node = container;
|
16133
|
+
offset = nodeIndex(container);
|
16134
|
+
container = container.parentNode;
|
16135
|
+
DOM$b.remove(node);
|
16136
|
+
if (!container.hasChildNodes() && DOM$b.isBlock(container)) {
|
16137
|
+
container.appendChild(DOM$b.create('br'));
|
16138
|
+
}
|
16151
16139
|
}
|
16140
|
+
return { container, offset };
|
16141
|
+
};
|
16142
|
+
const createNormalizedRange = (startContainer, startOffset, endContainer, endOffset) => {
|
16143
|
+
const rng = DOM$b.createRng();
|
16144
|
+
rng.setStart(startContainer, startOffset);
|
16145
|
+
rng.setEnd(endContainer, endOffset);
|
16152
16146
|
return normalizeRange$1(rng);
|
16153
16147
|
};
|
16148
|
+
/**
|
16149
|
+
* Returns a range bookmark. This will convert indexed bookmarks into temporary span elements with
|
16150
|
+
* index 0 so that they can be restored properly after the DOM has been modified. Text bookmarks will not have spans
|
16151
|
+
* added to them since they can be restored after a dom operation.
|
16152
|
+
*
|
16153
|
+
* So this: <p><b>|</b><b>|</b></p>
|
16154
|
+
* becomes: <p><b><span data-mce-type="bookmark">|</span></b><b data-mce-type="bookmark">|</span></b></p>
|
16155
|
+
*/
|
16156
|
+
const createBookmark = (rng, createMarker = defaultMarker) => {
|
16157
|
+
const { container: startContainer, offset: startOffset } = setupEndPoint(rng.startContainer, rng.startOffset, createMarker);
|
16158
|
+
if (rng.collapsed) {
|
16159
|
+
return { startContainer, startOffset };
|
16160
|
+
}
|
16161
|
+
else {
|
16162
|
+
const { container: endContainer, offset: endOffset } = setupEndPoint(rng.endContainer, rng.endOffset, createMarker);
|
16163
|
+
return { startContainer, startOffset, endContainer, endOffset };
|
16164
|
+
}
|
16165
|
+
};
|
16166
|
+
const resolveBookmark = (bookmark) => {
|
16167
|
+
const { container: startContainer, offset: startOffset } = restoreEndPoint(bookmark.startContainer, bookmark.startOffset);
|
16168
|
+
if (!isUndefined(bookmark.endContainer) && !isUndefined(bookmark.endOffset)) {
|
16169
|
+
const { container: endContainer, offset: endOffset } = restoreEndPoint(bookmark.endContainer, bookmark.endOffset);
|
16170
|
+
return createNormalizedRange(startContainer, startOffset, endContainer, endOffset);
|
16171
|
+
}
|
16172
|
+
else {
|
16173
|
+
return createNormalizedRange(startContainer, startOffset, startContainer, startOffset);
|
16174
|
+
}
|
16175
|
+
};
|
16154
16176
|
|
16155
16177
|
const applyStyles = (dom, elm, format, vars) => {
|
16156
16178
|
Tools.each(format.styles, (value, name) => {
|
@@ -17398,9 +17420,9 @@
|
|
17398
17420
|
return Optional.some(el);
|
17399
17421
|
}
|
17400
17422
|
};
|
17401
|
-
const bookmark = createBookmark
|
17423
|
+
const bookmark = createBookmark(editor.selection.getRng());
|
17402
17424
|
normalizeFontSizeElementsInternal(editor.dom, fontSizeElements, hasFormat, createFormatElement, removeFormatFromElement);
|
17403
|
-
editor.selection.setRng(resolveBookmark
|
17425
|
+
editor.selection.setRng(resolveBookmark(bookmark));
|
17404
17426
|
};
|
17405
17427
|
const collectFontSizeElements = (formatter, wrappers) => bind$3(wrappers, (wrapper) => {
|
17406
17428
|
const fontSizeDescendants = descendants$1(wrapper, (el) => isFontSizeAlteringElement(formatter, el));
|
@@ -20056,7 +20078,7 @@
|
|
20056
20078
|
// Deliberately ban all tags and attributes by default, and then un-ban them on demand in hooks
|
20057
20079
|
// #comment and #cdata-section are always allowed as they aren't controlled via the schema
|
20058
20080
|
// body is also allowed due to the DOMPurify checking the root node before sanitizing
|
20059
|
-
ALLOWED_TAGS: ['#comment', '#cdata-section', 'body'],
|
20081
|
+
ALLOWED_TAGS: ['#comment', '#cdata-section', 'body', 'html'],
|
20060
20082
|
ALLOWED_ATTR: []
|
20061
20083
|
};
|
20062
20084
|
const config = { ...basePurifyConfig };
|
@@ -20393,6 +20415,7 @@
|
|
20393
20415
|
return name;
|
20394
20416
|
}
|
20395
20417
|
};
|
20418
|
+
const xhtmlAttribte = ' xmlns="http://www.w3.org/1999/xhtml"';
|
20396
20419
|
const DomParser = (settings = {}, schema = Schema()) => {
|
20397
20420
|
const nodeFilterRegistry = create$8();
|
20398
20421
|
const attributeFilterRegistry = create$8();
|
@@ -20406,25 +20429,28 @@
|
|
20406
20429
|
};
|
20407
20430
|
const parser = new DOMParser();
|
20408
20431
|
const sanitizer = getSanitizer(defaultedSettings, schema);
|
20409
|
-
const parseAndSanitizeWithContext = (html, rootName, format = 'html') => {
|
20410
|
-
const
|
20432
|
+
const parseAndSanitizeWithContext = (html, rootName, format = 'html', useDocumentNotBody = false) => {
|
20433
|
+
const isxhtml = format === 'xhtml';
|
20434
|
+
const mimeType = isxhtml ? 'application/xhtml+xml' : 'text/html';
|
20411
20435
|
// Determine the root element to wrap the HTML in when parsing. If we're dealing with a
|
20412
20436
|
// special element then we need to wrap it so the internal content is handled appropriately.
|
20413
20437
|
const isSpecialRoot = has$2(schema.getSpecialElements(), rootName.toLowerCase());
|
20414
20438
|
const content = isSpecialRoot ? `<${rootName}>${html}</${rootName}>` : html;
|
20415
20439
|
const makeWrap = () => {
|
20416
|
-
if (
|
20417
|
-
|
20418
|
-
return `<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>${content}</body></html>`;
|
20419
|
-
}
|
20420
|
-
else if (/^[\s]*<head/i.test(html) || /^[\s]*<html/i.test(html) || /^[\s]*<!DOCTYPE/i.test(html)) {
|
20421
|
-
return `<html>${content}</html>`;
|
20440
|
+
if (/^[\s]*<head/i.test(html) || /^[\s]*<html/i.test(html) || /^[\s]*<!DOCTYPE/i.test(html)) {
|
20441
|
+
return `<html${isxhtml ? xhtmlAttribte : ''}>${content}</html>`;
|
20422
20442
|
}
|
20423
20443
|
else {
|
20424
|
-
|
20444
|
+
if (isxhtml) {
|
20445
|
+
return `<html${xhtmlAttribte}><head></head><body>${content}</body></html>`;
|
20446
|
+
}
|
20447
|
+
else {
|
20448
|
+
return `<body>${content}</body>`;
|
20449
|
+
}
|
20425
20450
|
}
|
20426
20451
|
};
|
20427
|
-
const
|
20452
|
+
const document = parser.parseFromString(makeWrap(), mimeType);
|
20453
|
+
const body = useDocumentNotBody ? document.documentElement : document.body;
|
20428
20454
|
sanitizer.sanitizeHtmlElement(body, mimeType);
|
20429
20455
|
return isSpecialRoot ? body.firstChild : body;
|
20430
20456
|
};
|
@@ -20555,11 +20581,12 @@
|
|
20555
20581
|
* const rootNode = tinymce.html.DomParser({...}).parse('<b>text</b>');
|
20556
20582
|
*/
|
20557
20583
|
const parse = (html, args = {}) => {
|
20558
|
-
var _a;
|
20584
|
+
var _a, _b;
|
20559
20585
|
const validate = defaultedSettings.validate;
|
20560
|
-
const
|
20586
|
+
const preferFullDocument = ((_a = args.context) !== null && _a !== void 0 ? _a : defaultedSettings.root_name) === '#document';
|
20587
|
+
const rootName = (_b = args.context) !== null && _b !== void 0 ? _b : (preferFullDocument ? 'html' : defaultedSettings.root_name);
|
20561
20588
|
// Parse and sanitize the content
|
20562
|
-
const element = parseAndSanitizeWithContext(html, rootName, args.format);
|
20589
|
+
const element = parseAndSanitizeWithContext(html, rootName, args.format, preferFullDocument);
|
20563
20590
|
updateChildren(schema, element);
|
20564
20591
|
// Create the AST representation
|
20565
20592
|
const rootNode = new AstNode(rootName, 11);
|
@@ -20694,8 +20721,7 @@
|
|
20694
20721
|
'tab_focus,tabfocus_elements,table_responsive_width,text_block_elements,text_inline_elements,toolbar_drawer,types,validate,whitespace_elements,' +
|
20695
20722
|
'paste_enable_default_filters,paste_filter_drop,paste_word_valid_elements,paste_retain_style_properties,paste_convert_word_fake_lists,' +
|
20696
20723
|
'template_cdate_classes,template_mdate_classes,template_selected_content_classes,template_preview_replace_values,template_replace_values,templates,template_cdate_format,template_mdate_format').split(',');
|
20697
|
-
|
20698
|
-
const deprecatedOptions = [];
|
20724
|
+
const deprecatedOptions = ['content_css_cors'];
|
20699
20725
|
const removedPlugins = 'bbcode,colorpicker,contextmenu,fullpage,legacyoutput,spellchecker,template,textcolor,rtc'.split(',');
|
20700
20726
|
const deprecatedPlugins = [
|
20701
20727
|
{
|
@@ -23746,12 +23772,21 @@
|
|
23746
23772
|
const schema = editor && editor.schema ? editor.schema : Schema(defaultedSettings);
|
23747
23773
|
const htmlParser = DomParser(defaultedSettings, schema);
|
23748
23774
|
register$3(htmlParser, defaultedSettings, dom);
|
23749
|
-
const serialize = (node,
|
23750
|
-
const
|
23751
|
-
const
|
23752
|
-
const
|
23753
|
-
const
|
23754
|
-
|
23775
|
+
const serialize = (node, domSerializerArgs = {}) => {
|
23776
|
+
const { indent, entity_encoding, ...rest } = domSerializerArgs;
|
23777
|
+
const parserArgs = { format: 'html', ...rest };
|
23778
|
+
const targetNode = process$1(editor, node, parserArgs);
|
23779
|
+
const html = getHtmlFromNode(dom, targetNode, parserArgs);
|
23780
|
+
const rootNode = parseHtml(htmlParser, html, parserArgs);
|
23781
|
+
if (parserArgs.format === 'tree') {
|
23782
|
+
return rootNode;
|
23783
|
+
}
|
23784
|
+
const serializerSettings = {
|
23785
|
+
...defaultedSettings,
|
23786
|
+
...(isNonNullable(indent) ? { indent } : {}),
|
23787
|
+
...(isNonNullable(entity_encoding) ? { entity_encoding } : {}),
|
23788
|
+
};
|
23789
|
+
return toHtml(editor, serializerSettings, schema, rootNode, parserArgs);
|
23755
23790
|
};
|
23756
23791
|
return {
|
23757
23792
|
schema,
|
@@ -23921,9 +23956,9 @@
|
|
23921
23956
|
});
|
23922
23957
|
};
|
23923
23958
|
|
23924
|
-
const DOM$
|
23959
|
+
const DOM$a = DOMUtils.DOM;
|
23925
23960
|
const restoreOriginalStyles = (editor) => {
|
23926
|
-
DOM$
|
23961
|
+
DOM$a.setStyle(editor.id, 'display', editor.orgDisplay);
|
23927
23962
|
};
|
23928
23963
|
const safeDestroy = (x) => Optional.from(x).each((x) => x.destroy());
|
23929
23964
|
const clearDomReferences = (editor) => {
|
@@ -23944,7 +23979,7 @@
|
|
23944
23979
|
form.submit = form._mceOldSubmit;
|
23945
23980
|
delete form._mceOldSubmit;
|
23946
23981
|
}
|
23947
|
-
DOM$
|
23982
|
+
DOM$a.unbind(form, 'submit reset', editor.formEventDelegate);
|
23948
23983
|
}
|
23949
23984
|
};
|
23950
23985
|
const remove$1 = (editor) => {
|
@@ -23959,7 +23994,7 @@
|
|
23959
23994
|
editor.unbindAllNativeEvents();
|
23960
23995
|
// Remove any hidden input
|
23961
23996
|
if (editor.hasHiddenInput && isNonNullable(element === null || element === void 0 ? void 0 : element.nextSibling)) {
|
23962
|
-
DOM$
|
23997
|
+
DOM$a.remove(element.nextSibling);
|
23963
23998
|
}
|
23964
23999
|
fireRemove(editor);
|
23965
24000
|
editor.editorManager.remove(editor);
|
@@ -23967,7 +24002,7 @@
|
|
23967
24002
|
restoreOriginalStyles(editor);
|
23968
24003
|
}
|
23969
24004
|
fireDetach(editor);
|
23970
|
-
DOM$
|
24005
|
+
DOM$a.remove(editor.getContainer());
|
23971
24006
|
safeDestroy(_selectionOverrides);
|
23972
24007
|
safeDestroy(editorUpload);
|
23973
24008
|
editor.destroy();
|
@@ -26633,6 +26668,37 @@
|
|
26633
26668
|
};
|
26634
26669
|
const isChildOfBody = (dom, elm) => dom.isChildOf(elm, dom.getRoot());
|
26635
26670
|
|
26671
|
+
const DOM$9 = DOMUtils.DOM;
|
26672
|
+
const normalizeList = (dom, list) => {
|
26673
|
+
const parentNode = list.parentElement;
|
26674
|
+
// Move UL/OL to previous LI if it's the only child of a LI
|
26675
|
+
if (parentNode && parentNode.nodeName === 'LI' && parentNode.firstChild === list) {
|
26676
|
+
const sibling = parentNode.previousSibling;
|
26677
|
+
if (sibling && sibling.nodeName === 'LI') {
|
26678
|
+
sibling.appendChild(list);
|
26679
|
+
if (isEmpty$1(dom, parentNode)) {
|
26680
|
+
DOM$9.remove(parentNode);
|
26681
|
+
}
|
26682
|
+
}
|
26683
|
+
else {
|
26684
|
+
DOM$9.setStyle(parentNode, 'listStyleType', 'none');
|
26685
|
+
}
|
26686
|
+
}
|
26687
|
+
// Append OL/UL to previous LI if it's in a parent OL/UL i.e. old HTML4
|
26688
|
+
if (isListNode(parentNode)) {
|
26689
|
+
const sibling = parentNode.previousSibling;
|
26690
|
+
if (sibling && sibling.nodeName === 'LI') {
|
26691
|
+
sibling.appendChild(list);
|
26692
|
+
}
|
26693
|
+
}
|
26694
|
+
};
|
26695
|
+
const normalizeLists = (dom, element) => {
|
26696
|
+
const lists = Tools.grep(dom.select('ol,ul', element));
|
26697
|
+
Tools.each(lists, (list) => {
|
26698
|
+
normalizeList(dom, list);
|
26699
|
+
});
|
26700
|
+
};
|
26701
|
+
|
26636
26702
|
const getNormalizedPoint = (container, offset) => {
|
26637
26703
|
if (isTextNode$1(container)) {
|
26638
26704
|
return { container, offset };
|
@@ -26667,123 +26733,6 @@
|
|
26667
26733
|
return outRng;
|
26668
26734
|
};
|
26669
26735
|
|
26670
|
-
const DOM$a = DOMUtils.DOM;
|
26671
|
-
/**
|
26672
|
-
* Returns a range bookmark. This will convert indexed bookmarks into temporary span elements with
|
26673
|
-
* index 0 so that they can be restored properly after the DOM has been modified. Text bookmarks will not have spans
|
26674
|
-
* added to them since they can be restored after a dom operation.
|
26675
|
-
*
|
26676
|
-
* So this: <p><b>|</b><b>|</b></p>
|
26677
|
-
* becomes: <p><b><span data-mce-type="bookmark">|</span></b><b data-mce-type="bookmark">|</span></b></p>
|
26678
|
-
*
|
26679
|
-
*/
|
26680
|
-
const createBookmark = (rng) => {
|
26681
|
-
const bookmark = {};
|
26682
|
-
const setupEndPoint = (start) => {
|
26683
|
-
let container = rng[start ? 'startContainer' : 'endContainer'];
|
26684
|
-
let offset = rng[start ? 'startOffset' : 'endOffset'];
|
26685
|
-
if (isElement$1(container)) {
|
26686
|
-
const offsetNode = DOM$a.create('span', { 'data-mce-type': 'bookmark' });
|
26687
|
-
if (container.hasChildNodes()) {
|
26688
|
-
offset = Math.min(offset, container.childNodes.length - 1);
|
26689
|
-
if (start) {
|
26690
|
-
container.insertBefore(offsetNode, container.childNodes[offset]);
|
26691
|
-
}
|
26692
|
-
else {
|
26693
|
-
DOM$a.insertAfter(offsetNode, container.childNodes[offset]);
|
26694
|
-
}
|
26695
|
-
}
|
26696
|
-
else {
|
26697
|
-
container.appendChild(offsetNode);
|
26698
|
-
}
|
26699
|
-
container = offsetNode;
|
26700
|
-
offset = 0;
|
26701
|
-
}
|
26702
|
-
bookmark[start ? 'startContainer' : 'endContainer'] = container;
|
26703
|
-
bookmark[start ? 'startOffset' : 'endOffset'] = offset;
|
26704
|
-
};
|
26705
|
-
setupEndPoint(true);
|
26706
|
-
if (!rng.collapsed) {
|
26707
|
-
setupEndPoint();
|
26708
|
-
}
|
26709
|
-
return bookmark;
|
26710
|
-
};
|
26711
|
-
const resolveBookmark$1 = (bookmark) => {
|
26712
|
-
const restoreEndPoint = (start) => {
|
26713
|
-
const nodeIndex = (container) => {
|
26714
|
-
var _a;
|
26715
|
-
let node = (_a = container.parentNode) === null || _a === void 0 ? void 0 : _a.firstChild;
|
26716
|
-
let idx = 0;
|
26717
|
-
while (node) {
|
26718
|
-
if (node === container) {
|
26719
|
-
return idx;
|
26720
|
-
}
|
26721
|
-
// Skip data-mce-type=bookmark nodes
|
26722
|
-
if (!isElement$1(node) || node.getAttribute('data-mce-type') !== 'bookmark') {
|
26723
|
-
idx++;
|
26724
|
-
}
|
26725
|
-
node = node.nextSibling;
|
26726
|
-
}
|
26727
|
-
return -1;
|
26728
|
-
};
|
26729
|
-
let container = bookmark[start ? 'startContainer' : 'endContainer'];
|
26730
|
-
let offset = bookmark[start ? 'startOffset' : 'endOffset'];
|
26731
|
-
if (!container) {
|
26732
|
-
return;
|
26733
|
-
}
|
26734
|
-
if (isElement$1(container) && container.parentNode) {
|
26735
|
-
const node = container;
|
26736
|
-
offset = nodeIndex(container);
|
26737
|
-
container = container.parentNode;
|
26738
|
-
DOM$a.remove(node);
|
26739
|
-
if (!container.hasChildNodes() && DOM$a.isBlock(container)) {
|
26740
|
-
container.appendChild(DOM$a.create('br'));
|
26741
|
-
}
|
26742
|
-
}
|
26743
|
-
bookmark[start ? 'startContainer' : 'endContainer'] = container;
|
26744
|
-
bookmark[start ? 'startOffset' : 'endOffset'] = offset;
|
26745
|
-
};
|
26746
|
-
restoreEndPoint(true);
|
26747
|
-
restoreEndPoint();
|
26748
|
-
const rng = DOM$a.createRng();
|
26749
|
-
rng.setStart(bookmark.startContainer, bookmark.startOffset);
|
26750
|
-
if (bookmark.endContainer) {
|
26751
|
-
rng.setEnd(bookmark.endContainer, bookmark.endOffset);
|
26752
|
-
}
|
26753
|
-
return normalizeRange(rng);
|
26754
|
-
};
|
26755
|
-
|
26756
|
-
const DOM$9 = DOMUtils.DOM;
|
26757
|
-
const normalizeList = (dom, list) => {
|
26758
|
-
const parentNode = list.parentElement;
|
26759
|
-
// Move UL/OL to previous LI if it's the only child of a LI
|
26760
|
-
if (parentNode && parentNode.nodeName === 'LI' && parentNode.firstChild === list) {
|
26761
|
-
const sibling = parentNode.previousSibling;
|
26762
|
-
if (sibling && sibling.nodeName === 'LI') {
|
26763
|
-
sibling.appendChild(list);
|
26764
|
-
if (isEmpty$1(dom, parentNode)) {
|
26765
|
-
DOM$9.remove(parentNode);
|
26766
|
-
}
|
26767
|
-
}
|
26768
|
-
else {
|
26769
|
-
DOM$9.setStyle(parentNode, 'listStyleType', 'none');
|
26770
|
-
}
|
26771
|
-
}
|
26772
|
-
// Append OL/UL to previous LI if it's in a parent OL/UL i.e. old HTML4
|
26773
|
-
if (isListNode(parentNode)) {
|
26774
|
-
const sibling = parentNode.previousSibling;
|
26775
|
-
if (sibling && sibling.nodeName === 'LI') {
|
26776
|
-
sibling.appendChild(list);
|
26777
|
-
}
|
26778
|
-
}
|
26779
|
-
};
|
26780
|
-
const normalizeLists = (dom, element) => {
|
26781
|
-
const lists = Tools.grep(dom.select('ol,ul', element));
|
26782
|
-
Tools.each(lists, (list) => {
|
26783
|
-
normalizeList(dom, list);
|
26784
|
-
});
|
26785
|
-
};
|
26786
|
-
|
26787
26736
|
const listNames = ['OL', 'UL', 'DL'];
|
26788
26737
|
const listSelector = listNames.join(',');
|
26789
26738
|
const getParentList = (editor, node) => {
|
@@ -27492,7 +27441,7 @@
|
|
27492
27441
|
mergeWithAdjacentLists(editor.dom, listBlock);
|
27493
27442
|
}
|
27494
27443
|
});
|
27495
|
-
editor.selection.setRng(resolveBookmark
|
27444
|
+
editor.selection.setRng(resolveBookmark(bookmark));
|
27496
27445
|
};
|
27497
27446
|
const isValidLists = (list1, list2) => {
|
27498
27447
|
return isListNode(list1) && list1.nodeName === (list2 === null || list2 === void 0 ? void 0 : list2.nodeName);
|
@@ -27574,7 +27523,7 @@
|
|
27574
27523
|
Tools.each(allLists, (elm) => {
|
27575
27524
|
updateFunction(editor, elm, listName, detail);
|
27576
27525
|
});
|
27577
|
-
editor.selection.setRng(resolveBookmark
|
27526
|
+
editor.selection.setRng(resolveBookmark(bookmark));
|
27578
27527
|
}
|
27579
27528
|
};
|
27580
27529
|
const hasListStyleDetail = (detail) => {
|
@@ -27603,7 +27552,7 @@
|
|
27603
27552
|
updateListWithDetails(editor.dom, parentList, detail);
|
27604
27553
|
const newList = editor.dom.rename(parentList, listName);
|
27605
27554
|
mergeWithAdjacentLists(editor.dom, newList);
|
27606
|
-
editor.selection.setRng(resolveBookmark
|
27555
|
+
editor.selection.setRng(resolveBookmark(bookmark));
|
27607
27556
|
applyList(editor, listName, detail);
|
27608
27557
|
fireListEvent(editor, listToggleActionFromListName(listName), newList);
|
27609
27558
|
}
|
@@ -27729,13 +27678,13 @@
|
|
27729
27678
|
else {
|
27730
27679
|
const bookmark = createBookmark(rng);
|
27731
27680
|
mergeLiElements(dom, fromLi, toLi);
|
27732
|
-
editor.selection.setRng(resolveBookmark
|
27681
|
+
editor.selection.setRng(resolveBookmark(bookmark));
|
27733
27682
|
}
|
27734
27683
|
};
|
27735
27684
|
const mergeBackward = (editor, rng, fromLi, toLi) => {
|
27736
27685
|
const bookmark = createBookmark(rng);
|
27737
27686
|
mergeLiElements(editor.dom, fromLi, toLi);
|
27738
|
-
const resolvedBookmark = resolveBookmark
|
27687
|
+
const resolvedBookmark = resolveBookmark(bookmark);
|
27739
27688
|
editor.selection.setRng(resolvedBookmark);
|
27740
27689
|
};
|
27741
27690
|
const backspaceDeleteFromListToListCaret = (editor, isForward) => {
|
@@ -27776,7 +27725,7 @@
|
|
27776
27725
|
const bookmark = createBookmark(rng);
|
27777
27726
|
moveChildren(dom, commonAncestorParent, otherLi);
|
27778
27727
|
commonAncestorParent.remove();
|
27779
|
-
const resolvedBookmark = resolveBookmark
|
27728
|
+
const resolvedBookmark = resolveBookmark(bookmark);
|
27780
27729
|
editor.selection.setRng(resolvedBookmark);
|
27781
27730
|
});
|
27782
27731
|
return true;
|
@@ -28311,65 +28260,6 @@
|
|
28311
28260
|
}
|
28312
28261
|
};
|
28313
28262
|
|
28314
|
-
const isTextEndpoint = (endpoint) => endpoint.hasOwnProperty('text');
|
28315
|
-
const isElementEndpoint = (endpoint) => endpoint.hasOwnProperty('marker');
|
28316
|
-
const getBookmark = (range, createMarker) => {
|
28317
|
-
const getEndpoint = (container, offset) => {
|
28318
|
-
if (isText$b(container)) {
|
28319
|
-
return { text: container, offset };
|
28320
|
-
}
|
28321
|
-
else {
|
28322
|
-
const marker = createMarker();
|
28323
|
-
const children = container.childNodes;
|
28324
|
-
if (offset < children.length) {
|
28325
|
-
container.insertBefore(marker, children[offset]);
|
28326
|
-
return { marker, before: true };
|
28327
|
-
}
|
28328
|
-
else {
|
28329
|
-
container.appendChild(marker);
|
28330
|
-
return { marker, before: false };
|
28331
|
-
}
|
28332
|
-
}
|
28333
|
-
};
|
28334
|
-
const end = getEndpoint(range.endContainer, range.endOffset);
|
28335
|
-
const start = getEndpoint(range.startContainer, range.startOffset);
|
28336
|
-
return { start, end };
|
28337
|
-
};
|
28338
|
-
const resolveBookmark = (bm) => {
|
28339
|
-
var _a, _b;
|
28340
|
-
const { start, end } = bm;
|
28341
|
-
const rng = new window.Range();
|
28342
|
-
if (isTextEndpoint(start)) {
|
28343
|
-
rng.setStart(start.text, start.offset);
|
28344
|
-
}
|
28345
|
-
else {
|
28346
|
-
if (isElementEndpoint(start)) {
|
28347
|
-
if (start.before) {
|
28348
|
-
rng.setStartBefore(start.marker);
|
28349
|
-
}
|
28350
|
-
else {
|
28351
|
-
rng.setStartAfter(start.marker);
|
28352
|
-
}
|
28353
|
-
(_a = start.marker.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(start.marker);
|
28354
|
-
}
|
28355
|
-
}
|
28356
|
-
if (isTextEndpoint(end)) {
|
28357
|
-
rng.setEnd(end.text, end.offset);
|
28358
|
-
}
|
28359
|
-
else {
|
28360
|
-
if (isElementEndpoint(end)) {
|
28361
|
-
if (end.before) {
|
28362
|
-
rng.setEndBefore(end.marker);
|
28363
|
-
}
|
28364
|
-
else {
|
28365
|
-
rng.setEndAfter(end.marker);
|
28366
|
-
}
|
28367
|
-
(_b = end.marker.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(end.marker);
|
28368
|
-
}
|
28369
|
-
}
|
28370
|
-
return rng;
|
28371
|
-
};
|
28372
|
-
|
28373
28263
|
const backspaceDelete$7 = (editor, forward) => {
|
28374
28264
|
var _a;
|
28375
28265
|
const dom = editor.dom;
|
@@ -28389,7 +28279,7 @@
|
|
28389
28279
|
}
|
28390
28280
|
// Div was deleted by delete operation then lets restore it
|
28391
28281
|
if (body.firstChild !== startBlock) {
|
28392
|
-
const bookmark =
|
28282
|
+
const bookmark = createBookmark(editor.selection.getRng(), () => document.createElement('span'));
|
28393
28283
|
Array.from(body.childNodes).forEach((node) => wrapper.appendChild(node));
|
28394
28284
|
body.appendChild(wrapper);
|
28395
28285
|
editor.selection.setRng(resolveBookmark(bookmark));
|
@@ -28932,7 +28822,7 @@
|
|
28932
28822
|
}
|
28933
28823
|
return Optional.none();
|
28934
28824
|
};
|
28935
|
-
const moveVertically = (editor, direction, range, isBefore, isAfter, isElement) => {
|
28825
|
+
const moveVertically$1 = (editor, direction, range, isBefore, isAfter, isElement) => {
|
28936
28826
|
const caretPosition = getNormalizedRangeEndPoint(direction, editor.getBody(), range);
|
28937
28827
|
const caretClientRect = last(caretPosition.getClientRects());
|
28938
28828
|
const forwards = direction === VDirection.Down;
|
@@ -29595,7 +29485,7 @@
|
|
29595
29485
|
}
|
29596
29486
|
if (!rootBlockNode) {
|
29597
29487
|
if (!bm && editor.hasFocus()) {
|
29598
|
-
bm =
|
29488
|
+
bm = createBookmark(editor.selection.getRng(), () => document.createElement('span'));
|
29599
29489
|
}
|
29600
29490
|
// Firefox will remove the last BR element if you insert nodes next to it using DOM APIs like insertBefore
|
29601
29491
|
// so for that weird edge case we stop processing.
|
@@ -29762,7 +29652,7 @@
|
|
29762
29652
|
const moveToCeFalseVertically = (direction, editor, range) => {
|
29763
29653
|
const isBefore = (caretPosition) => isBeforeContentEditableFalse(caretPosition) || isBeforeTable(caretPosition);
|
29764
29654
|
const isAfter = (caretPosition) => isAfterContentEditableFalse(caretPosition) || isAfterTable(caretPosition);
|
29765
|
-
return moveVertically(editor, direction, range, isBefore, isAfter, isContentEditableFalse$3);
|
29655
|
+
return moveVertically$1(editor, direction, range, isBefore, isAfter, isContentEditableFalse$3);
|
29766
29656
|
};
|
29767
29657
|
const createTextBlock = (editor) => {
|
29768
29658
|
const textBlock = editor.dom.create(getForcedRootBlock(editor));
|
@@ -29815,7 +29705,7 @@
|
|
29815
29705
|
moveToRange(editor, newRange);
|
29816
29706
|
return true;
|
29817
29707
|
});
|
29818
|
-
const moveV$
|
29708
|
+
const moveV$5 = (editor, down) => getVerticalRange(editor, down).exists((newRange) => {
|
29819
29709
|
moveToRange(editor, newRange);
|
29820
29710
|
return true;
|
29821
29711
|
});
|
@@ -29840,6 +29730,39 @@
|
|
29840
29730
|
return true;
|
29841
29731
|
});
|
29842
29732
|
|
29733
|
+
const getClosestCetBlock = (position, root) => {
|
29734
|
+
const isRoot = (el) => eq(el, root);
|
29735
|
+
const isCet = (el) => isContentEditableTrue$3(el.dom);
|
29736
|
+
const startNode = SugarElement.fromDom(position.container());
|
29737
|
+
const closestCetBlock = closest$4(startNode, isCet, isRoot);
|
29738
|
+
return closestCetBlock.filter((b) => !isRoot(b));
|
29739
|
+
};
|
29740
|
+
const moveVertically = (editor, position, down) => {
|
29741
|
+
const getNextPosition = down ? getClosestPositionBelow : getClosestPositionAbove;
|
29742
|
+
return getNextPosition(editor.getBody(), position).map((nextPosition) => nextPosition.toRange());
|
29743
|
+
};
|
29744
|
+
const moveToNextOrPreviousLine = (editor, down) => {
|
29745
|
+
const startPosition = CaretPosition.fromRangeStart(editor.selection.getRng());
|
29746
|
+
const endPosition = CaretPosition.fromRangeEnd(editor.selection.getRng());
|
29747
|
+
const root = SugarElement.fromDom(editor.getBody());
|
29748
|
+
/* I wasn't able to find a way to create a selection between two different contenteditable elements.
|
29749
|
+
However I can't rule out that it is possible. So I am checking if both positions are in the same contenteditable element.
|
29750
|
+
This is a defensive check to ensure selection integrity.
|
29751
|
+
*/
|
29752
|
+
const closestCetBlock = flatten(lift2(getClosestCetBlock(startPosition, root), getClosestCetBlock(endPosition, root), (c1, c2) => eq(c1, c2) ? Optional.some(c1) : Optional.none()));
|
29753
|
+
return closestCetBlock.fold(never, (cetBlock) => {
|
29754
|
+
if ((down && isAtLastLine(cetBlock.dom, endPosition)) ||
|
29755
|
+
(!down && isAtFirstLine(cetBlock.dom, startPosition))) {
|
29756
|
+
return moveVertically(editor, down ? endPosition : startPosition, down).exists((newRange) => {
|
29757
|
+
moveToRange(editor, newRange);
|
29758
|
+
return true;
|
29759
|
+
});
|
29760
|
+
}
|
29761
|
+
return false;
|
29762
|
+
});
|
29763
|
+
};
|
29764
|
+
const moveV$4 = (editor, down) => moveToNextOrPreviousLine(editor, down);
|
29765
|
+
|
29843
29766
|
const isTarget = (node) => contains$2(['figcaption'], name(node));
|
29844
29767
|
const getClosestTargetBlock = (pos, root, schema) => {
|
29845
29768
|
const isRoot = curry(eq, root);
|
@@ -29945,7 +29868,7 @@
|
|
29945
29868
|
const moveV$1 = (editor, down) => {
|
29946
29869
|
const direction = down ? 1 : -1;
|
29947
29870
|
const range = editor.selection.getRng();
|
29948
|
-
return moveVertically(editor, direction, range, isBeforeMedia, isAfterMedia, isMedia$2).exists((newRange) => {
|
29871
|
+
return moveVertically$1(editor, direction, range, isBeforeMedia, isAfterMedia, isMedia$2).exists((newRange) => {
|
29949
29872
|
moveToRange(editor, newRange);
|
29950
29873
|
return true;
|
29951
29874
|
});
|
@@ -30230,7 +30153,7 @@
|
|
30230
30153
|
return toLeaf$2(universe, element, offset);
|
30231
30154
|
};
|
30232
30155
|
|
30233
|
-
const imageId = generate
|
30156
|
+
const imageId = generate('image');
|
30234
30157
|
const getDragImage = (transfer) => {
|
30235
30158
|
const dt = transfer;
|
30236
30159
|
return Optional.from(dt[imageId]);
|
@@ -30240,7 +30163,7 @@
|
|
30240
30163
|
dt[imageId] = imageData;
|
30241
30164
|
};
|
30242
30165
|
|
30243
|
-
const eventId = generate
|
30166
|
+
const eventId = generate('event');
|
30244
30167
|
const getEvent = (transfer) => {
|
30245
30168
|
const dt = transfer;
|
30246
30169
|
return Optional.from(dt[eventId]);
|
@@ -30264,7 +30187,7 @@
|
|
30264
30187
|
item: (_) => null
|
30265
30188
|
});
|
30266
30189
|
|
30267
|
-
const modeId = generate
|
30190
|
+
const modeId = generate('mode');
|
30268
30191
|
const getMode = (transfer) => {
|
30269
30192
|
const dt = transfer;
|
30270
30193
|
return Optional.from(dt[modeId]);
|
@@ -30580,11 +30503,12 @@
|
|
30580
30503
|
|
30581
30504
|
const executeKeydownOverride$4 = (editor, caret, evt) => {
|
30582
30505
|
const isMac = Env.os.isMacOS() || Env.os.isiOS();
|
30506
|
+
const isFirefox = Env.browser.isFirefox();
|
30583
30507
|
execute([
|
30584
30508
|
{ keyCode: VK.RIGHT, action: action(moveH$2, editor, true) },
|
30585
30509
|
{ keyCode: VK.LEFT, action: action(moveH$2, editor, false) },
|
30586
|
-
{ keyCode: VK.UP, action: action(moveV$
|
30587
|
-
{ keyCode: VK.DOWN, action: action(moveV$
|
30510
|
+
{ keyCode: VK.UP, action: action(moveV$5, editor, false) },
|
30511
|
+
{ keyCode: VK.DOWN, action: action(moveV$5, editor, true) },
|
30588
30512
|
...(isMac ? [
|
30589
30513
|
{ keyCode: VK.UP, action: action(selectToEndPoint, editor, false), metaKey: true, shiftKey: true },
|
30590
30514
|
{ keyCode: VK.DOWN, action: action(selectToEndPoint, editor, true), metaKey: true, shiftKey: true }
|
@@ -30605,7 +30529,11 @@
|
|
30605
30529
|
{ keyCode: VK.RIGHT, ctrlKey: !isMac, altKey: isMac, action: action(moveNextWord, editor, caret) },
|
30606
30530
|
{ keyCode: VK.LEFT, ctrlKey: !isMac, altKey: isMac, action: action(movePrevWord, editor, caret) },
|
30607
30531
|
{ keyCode: VK.UP, action: action(moveV$3, editor, false) },
|
30608
|
-
{ keyCode: VK.DOWN, action: action(moveV$3, editor, true) }
|
30532
|
+
{ keyCode: VK.DOWN, action: action(moveV$3, editor, true) },
|
30533
|
+
...(isFirefox ? [
|
30534
|
+
{ keyCode: VK.UP, action: action(moveV$4, editor, false) },
|
30535
|
+
{ keyCode: VK.DOWN, action: action(moveV$4, editor, true) }
|
30536
|
+
] : [])
|
30609
30537
|
], evt).each((_) => {
|
30610
30538
|
evt.preventDefault();
|
30611
30539
|
});
|
@@ -30968,7 +30896,7 @@
|
|
30968
30896
|
const mergeValues = (values, base) => {
|
30969
30897
|
return SimpleResult.svalue(deepMerge(base, merge$1.apply(undefined, values)));
|
30970
30898
|
};
|
30971
|
-
const mergeErrors = (errors) => compose(SimpleResult.serror, flatten)(errors);
|
30899
|
+
const mergeErrors = (errors) => compose(SimpleResult.serror, flatten$1)(errors);
|
30972
30900
|
const consolidateObj = (objects, base) => {
|
30973
30901
|
const partition = SimpleResult.partition(objects);
|
30974
30902
|
return partition.errors.length > 0 ? mergeErrors(partition.errors) : mergeValues(partition.values, base);
|
@@ -31569,7 +31497,7 @@
|
|
31569
31497
|
}
|
31570
31498
|
});
|
31571
31499
|
};
|
31572
|
-
const executeKeyupOverride = (editor, evt, isBackspaceKeydown) => execute([
|
31500
|
+
const executeKeyupOverride = (editor, evt, isBackspaceKeydown, formatNodes) => execute([
|
31573
31501
|
{ keyCode: VK.BACKSPACE, action: action(paddEmptyElement, editor) },
|
31574
31502
|
{ keyCode: VK.DELETE, action: action(paddEmptyElement, editor) },
|
31575
31503
|
...isMacOSOriOS ? [
|
@@ -31581,7 +31509,10 @@
|
|
31581
31509
|
...isBackspaceKeydown ? [{
|
31582
31510
|
// Firefox detects macOS Command key code as "Command" not "Meta"
|
31583
31511
|
keyCode: isFirefox ? 224 : 91,
|
31584
|
-
action: action(
|
31512
|
+
action: action(() => {
|
31513
|
+
updateCaretFormat(editor, formatNodes);
|
31514
|
+
return refreshCaret(editor);
|
31515
|
+
})
|
31585
31516
|
}] : []
|
31586
31517
|
] : [
|
31587
31518
|
{ keyCode: VK.BACKSPACE, ctrlKey: true, action: action(refreshCaret, editor) },
|
@@ -31591,15 +31522,18 @@
|
|
31591
31522
|
const setup$o = (editor, caret) => {
|
31592
31523
|
// track backspace keydown state for emulating Meta + Backspace keyup detection on macOS
|
31593
31524
|
let isBackspaceKeydown = false;
|
31525
|
+
let formatNodes = [];
|
31594
31526
|
editor.on('keydown', (evt) => {
|
31595
31527
|
isBackspaceKeydown = evt.keyCode === VK.BACKSPACE;
|
31528
|
+
formatNodes = getFormatNodesAtStart(editor);
|
31596
31529
|
if (!evt.isDefaultPrevented()) {
|
31597
31530
|
executeKeydownOverride$3(editor, caret, evt);
|
31598
31531
|
}
|
31599
31532
|
});
|
31600
31533
|
editor.on('keyup', (evt) => {
|
31601
31534
|
if (!evt.isDefaultPrevented()) {
|
31602
|
-
executeKeyupOverride(editor, evt, isBackspaceKeydown);
|
31535
|
+
executeKeyupOverride(editor, evt, isBackspaceKeydown, formatNodes);
|
31536
|
+
formatNodes.length = 0;
|
31603
31537
|
}
|
31604
31538
|
isBackspaceKeydown = false;
|
31605
31539
|
});
|
@@ -31647,7 +31581,7 @@
|
|
31647
31581
|
findFirstList(firstChild).fold(() => {
|
31648
31582
|
if (isEmpty(firstChild)) {
|
31649
31583
|
const element = toLeaf$1(firstChild, 0).element;
|
31650
|
-
if (!isBr$6(element)) {
|
31584
|
+
if (isElement$8(element) && !isBr$6(element)) {
|
31651
31585
|
append$1(element, SugarElement.fromText(nbsp));
|
31652
31586
|
}
|
31653
31587
|
}
|
@@ -34897,7 +34831,10 @@
|
|
34897
34831
|
});
|
34898
34832
|
editor.on('focusin', (e) => {
|
34899
34833
|
// for medias the selection is already managed in `MediaFocus.ts`
|
34900
|
-
if (
|
34834
|
+
if (isMedia$2(e.target)) {
|
34835
|
+
return;
|
34836
|
+
}
|
34837
|
+
if (editor.getBody().contains(e.target) && e.target !== editor.getBody() && !editor.dom.isEditable(e.target.parentNode)) {
|
34901
34838
|
if (fakeCaret.isShowing()) {
|
34902
34839
|
fakeCaret.hide();
|
34903
34840
|
}
|
@@ -35415,7 +35352,7 @@
|
|
35415
35352
|
applyPattern$2(editor, pattern, patternRange);
|
35416
35353
|
};
|
35417
35354
|
const addMarkers = (dom, matches) => {
|
35418
|
-
const markerPrefix = generate
|
35355
|
+
const markerPrefix = generate('mce_textpattern');
|
35419
35356
|
// Add end markers
|
35420
35357
|
const matchesWithEnds = foldr(matches, (acc, match) => {
|
35421
35358
|
const endMarker = createMarker(dom, markerPrefix + `_end${acc.length}`, match.endRng);
|
@@ -35832,10 +35769,15 @@
|
|
35832
35769
|
if (!editor.inline) {
|
35833
35770
|
// Needs to be both down/up due to weird rendering bug on Chrome Windows
|
35834
35771
|
dom.bind(editor.getDoc(), 'mousedown mouseup', (e) => {
|
35772
|
+
var _a;
|
35835
35773
|
let rng;
|
35836
35774
|
if (e.target === editor.getDoc().documentElement) {
|
35837
35775
|
rng = selection.getRng();
|
35838
|
-
editor
|
35776
|
+
// TINY-12245: this is needed to avoid the scroll back to the top when the content is scrolled, there is no selection and the user is clicking on a non selectable editor element
|
35777
|
+
// example content scrolled by browser search and user click on the horizontal scroll bar
|
35778
|
+
if (((_a = editor.getDoc().getSelection()) === null || _a === void 0 ? void 0 : _a.anchorNode) !== null) {
|
35779
|
+
editor.getBody().focus();
|
35780
|
+
}
|
35839
35781
|
if (e.type === 'mousedown') {
|
35840
35782
|
if (isCaretContainer$2(rng.startContainer)) {
|
35841
35783
|
return;
|
@@ -35933,9 +35875,10 @@
|
|
35933
35875
|
const isEditableImage = (node) => node.nodeName === 'IMG' && editor.dom.isEditable(node);
|
35934
35876
|
editor.on('mousedown', (e) => {
|
35935
35877
|
lift2(Optional.from(e.clientX), Optional.from(e.clientY), (clientX, clientY) => {
|
35878
|
+
var _a;
|
35936
35879
|
const caretPos = editor.getDoc().caretPositionFromPoint(clientX, clientY);
|
35937
|
-
const img = (caretPos === null || caretPos === void 0 ? void 0 : caretPos.offsetNode.childNodes[caretPos.offset - (caretPos.offset > 0 ? 1 : 0)]) || (caretPos === null || caretPos === void 0 ? void 0 : caretPos.offsetNode);
|
35938
|
-
if (img && isEditableImage(img)) {
|
35880
|
+
const img = ((_a = caretPos === null || caretPos === void 0 ? void 0 : caretPos.offsetNode) === null || _a === void 0 ? void 0 : _a.childNodes[caretPos.offset - (caretPos.offset > 0 ? 1 : 0)]) || (caretPos === null || caretPos === void 0 ? void 0 : caretPos.offsetNode);
|
35881
|
+
if (isNonNullable(img) && isEditableImage(img)) {
|
35939
35882
|
const rect = img.getBoundingClientRect();
|
35940
35883
|
e.preventDefault();
|
35941
35884
|
if (!editor.hasFocus()) {
|
@@ -36829,7 +36772,7 @@
|
|
36829
36772
|
id: id + '_ifr',
|
36830
36773
|
frameBorder: '0',
|
36831
36774
|
allowTransparency: 'true',
|
36832
|
-
title
|
36775
|
+
...Env.browser.isFirefox() ? { title } : {}
|
36833
36776
|
});
|
36834
36777
|
add$2(iframe, 'tox-edit-area__iframe');
|
36835
36778
|
return iframe;
|
@@ -36845,17 +36788,18 @@
|
|
36845
36788
|
const bodyId = getBodyId(editor);
|
36846
36789
|
const bodyClass = getBodyClass(editor);
|
36847
36790
|
const translatedAriaText = editor.translate(getIframeAriaText(editor));
|
36791
|
+
const iframeBodyAriaLabel = Env.browser.isFirefox() ? '' : `aria-label="${translatedAriaText}"`;
|
36848
36792
|
if (getContentSecurityPolicy(editor)) {
|
36849
36793
|
iframeHTML += '<meta http-equiv="Content-Security-Policy" content="' + getContentSecurityPolicy(editor) + '" />';
|
36850
36794
|
}
|
36851
36795
|
iframeHTML += '</head>' +
|
36852
|
-
`<body id="${bodyId}" class="mce-content-body ${bodyClass}" data-id="${editor.id}"
|
36796
|
+
`<body id="${bodyId}" class="mce-content-body ${bodyClass}" data-id="${editor.id}" ${iframeBodyAriaLabel}>` +
|
36853
36797
|
'<br>' +
|
36854
36798
|
'</body></html>';
|
36855
36799
|
return iframeHTML;
|
36856
36800
|
};
|
36857
36801
|
const createIframe = (editor, boxInfo) => {
|
36858
|
-
const iframeTitle =
|
36802
|
+
const iframeTitle = getIframeAriaText(editor);
|
36859
36803
|
const translatedTitle = editor.translate(iframeTitle);
|
36860
36804
|
const tabindex = getOpt(SugarElement.fromDom(editor.getElement()), 'tabindex').bind(toInt);
|
36861
36805
|
const ifr = createIframeElement(editor.id, translatedTitle, getIframeAttrs(editor), tabindex).dom;
|
@@ -37318,23 +37262,55 @@
|
|
37318
37262
|
return name.trim()[0];
|
37319
37263
|
}
|
37320
37264
|
};
|
37321
|
-
|
37322
|
-
|
37265
|
+
/* For a given string returns integer between 0 and maxValue (inclusive).
|
37266
|
+
This function is based on the djb2 hash algorithm reported by Dan Bernstein.
|
37267
|
+
You can find more informations here: http://www.cse.yorku.ca/~oz/hash.html
|
37268
|
+
The hashing algorithm is using bitwise operators to multiply by 32, and later to ensure a positive integer.
|
37269
|
+
The result is then reduced to the range of 0 to maxValue using modulo operation.
|
37270
|
+
*/
|
37271
|
+
const djb2Hash = (key, maxValue) => {
|
37272
|
+
let hash = 5381;
|
37273
|
+
for (let i = 0; i < key.length; i++) {
|
37274
|
+
// eslint-disable-next-line no-bitwise
|
37275
|
+
hash = ((hash << 5) + hash) + key.charCodeAt(i);
|
37276
|
+
}
|
37277
|
+
// eslint-disable-next-line no-bitwise
|
37278
|
+
return (hash >>> 0) % (maxValue + 1);
|
37279
|
+
};
|
37280
|
+
const getColor = (id) => {
|
37281
|
+
const colorIdx = djb2Hash(id !== null && id !== void 0 ? id : '', AvatarColors.length - 1);
|
37323
37282
|
return AvatarColors[colorIdx];
|
37324
37283
|
};
|
37325
|
-
const
|
37284
|
+
const generateAvatarSvg = (content, color, size) => {
|
37326
37285
|
const halfSize = size / 2;
|
37327
37286
|
return `<svg height="${size}" width="${size}" xmlns="http://www.w3.org/2000/svg">` +
|
37328
37287
|
`<circle cx="${halfSize}" cy="${halfSize}" r="${halfSize}" fill="${color}"/>` +
|
37329
37288
|
`<text x="50%" y="50%" text-anchor="middle" dominant-baseline="central" fill="#FFF" font-family="sans-serif" font-size="${halfSize}">` +
|
37330
|
-
|
37289
|
+
content +
|
37331
37290
|
`</text>` +
|
37332
37291
|
'</svg>';
|
37333
37292
|
};
|
37334
|
-
|
37335
|
-
|
37336
|
-
|
37337
|
-
|
37293
|
+
/**
|
37294
|
+
* Generates a data URL for an SVG avatar with the specified content, color, and size.
|
37295
|
+
*
|
37296
|
+
* @param content The text content to display in the avatar (typically a single character)
|
37297
|
+
* @param color The background color of the avatar (hex color string)
|
37298
|
+
* @param size The size of the avatar in pixels (width and height)
|
37299
|
+
* @returns A data URL string containing the encoded SVG avatar
|
37300
|
+
*/
|
37301
|
+
const generateAvatar = (content, color, size) => 'data:image/svg+xml,' + encodeURIComponent(generateAvatarSvg(content, color, size));
|
37302
|
+
/**
|
37303
|
+
* Generates a user avatar based on the user's name and ID.
|
37304
|
+
*
|
37305
|
+
* @param user User object containing id and name properties
|
37306
|
+
* @param user.id Unique identifier used to determine the avatar color
|
37307
|
+
* @param user.name User's name, first character will be displayed in the avatar
|
37308
|
+
* @param config Configuration object for the avatar
|
37309
|
+
* @param config.size The size of the avatar in pixels (defaults to 36)
|
37310
|
+
* @returns A data URL string containing the encoded SVG avatar
|
37311
|
+
*/
|
37312
|
+
const generateUserAvatar = (user, config = { size: 36 }) => generateAvatar(getFirstChar(user.name), getColor(user.id), config.size);
|
37313
|
+
|
37338
37314
|
const userSchema = objOf([
|
37339
37315
|
required('id'),
|
37340
37316
|
optionString('name'),
|
@@ -37366,7 +37342,7 @@
|
|
37366
37342
|
return {
|
37367
37343
|
id,
|
37368
37344
|
name: name.getOr(id),
|
37369
|
-
avatar: avatar.getOr(
|
37345
|
+
avatar: avatar.getOr(generateUserAvatar({ id, name: name.getOr(id) })),
|
37370
37346
|
...objectCat(rest),
|
37371
37347
|
};
|
37372
37348
|
});
|
@@ -37399,7 +37375,7 @@
|
|
37399
37375
|
return mapToObject(userIds, (userId) => Promise.resolve({
|
37400
37376
|
id: userId,
|
37401
37377
|
name: userId,
|
37402
|
-
avatar:
|
37378
|
+
avatar: generateUserAvatar({ id: userId, name: userId })
|
37403
37379
|
}));
|
37404
37380
|
}
|
37405
37381
|
const uncachedIds = unique$1(filter$5((userIds), (userId) => !lookup(userId).isSome()));
|
@@ -37431,7 +37407,7 @@
|
|
37431
37407
|
acc[userId] = lookup(userId).getOr(Promise.resolve({
|
37432
37408
|
id: userId,
|
37433
37409
|
name: userId,
|
37434
|
-
avatar:
|
37410
|
+
avatar: generateUserAvatar({ id: userId, name: userId })
|
37435
37411
|
}));
|
37436
37412
|
return acc;
|
37437
37413
|
}, {});
|
@@ -37946,7 +37922,7 @@
|
|
37946
37922
|
const anchor = editor.dom.getParent(editor.selection.getNode(), 'a');
|
37947
37923
|
if (isObject(linkDetails) && isString(linkDetails.href)) {
|
37948
37924
|
// Spaces are never valid in URLs and it's a very common mistake for people to make so we fix it here.
|
37949
|
-
linkDetails.href = linkDetails.href.replace(/ /g, '%20');
|
37925
|
+
linkDetails.href = linkDetails.href.replace(/ /g, '%20').replace(/&/g, '&');
|
37950
37926
|
// Remove existing links if there could be child links or that the href isn't specified
|
37951
37927
|
if (!anchor || !linkDetails.href) {
|
37952
37928
|
editor.formatter.remove('link');
|
@@ -40330,14 +40306,14 @@
|
|
40330
40306
|
* @property minorVersion
|
40331
40307
|
* @type String
|
40332
40308
|
*/
|
40333
|
-
minorVersion: '
|
40309
|
+
minorVersion: '1.1',
|
40334
40310
|
/**
|
40335
40311
|
* Release date of TinyMCE build.
|
40336
40312
|
*
|
40337
40313
|
* @property releaseDate
|
40338
40314
|
* @type String
|
40339
40315
|
*/
|
40340
|
-
releaseDate: '2025-
|
40316
|
+
releaseDate: '2025-09-17',
|
40341
40317
|
/**
|
40342
40318
|
* Collection of language pack data.
|
40343
40319
|
*
|