tinymce-rails 8.5.1 → 8.7.0
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/app/assets/source/tinymce/tinymce.js +613 -204
- data/lib/tinymce/rails/version.rb +2 -2
- data/vendor/assets/javascripts/tinymce/icons/default/icons.js +1 -1
- data/vendor/assets/javascripts/tinymce/plugins/autolink/plugin.js +1 -1
- data/vendor/assets/javascripts/tinymce/plugins/autosave/plugin.js +1 -1
- data/vendor/assets/javascripts/tinymce/plugins/codesample/plugin.js +2 -2
- data/vendor/assets/javascripts/tinymce/plugins/emoticons/plugin.js +1 -1
- data/vendor/assets/javascripts/tinymce/plugins/help/plugin.js +1 -1
- data/vendor/assets/javascripts/tinymce/plugins/image/plugin.js +1 -1
- data/vendor/assets/javascripts/tinymce/plugins/preview/plugin.js +1 -1
- data/vendor/assets/javascripts/tinymce/plugins/table/plugin.js +1 -1
- data/vendor/assets/javascripts/tinymce/skins/content/dark/content.css +1 -1
- data/vendor/assets/javascripts/tinymce/skins/content/dark/content.js +1 -1
- data/vendor/assets/javascripts/tinymce/skins/content/dark/content.min.css +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 +3 -1
- data/vendor/assets/javascripts/tinymce/tinymce.d.ts +11 -1
- data/vendor/assets/javascripts/tinymce/tinymce.js +4 -2
- metadata +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* TinyMCE version 8.
|
|
2
|
+
* TinyMCE version 8.7.0 (2026-07-01)
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
(function () {
|
|
@@ -573,14 +573,16 @@
|
|
|
573
573
|
}
|
|
574
574
|
return Optional.none();
|
|
575
575
|
};
|
|
576
|
-
const
|
|
576
|
+
const findLastByPredicate = (arr, pred) => {
|
|
577
577
|
for (let i = arr.length - 1; i >= 0; i--) {
|
|
578
578
|
if (pred(arr[i], i)) {
|
|
579
|
-
return Optional.some(i);
|
|
579
|
+
return Optional.some({ v: arr[i], i });
|
|
580
580
|
}
|
|
581
581
|
}
|
|
582
582
|
return Optional.none();
|
|
583
583
|
};
|
|
584
|
+
const findLast = (arr, pred) => findLastByPredicate(arr, pred).map((r) => r.v);
|
|
585
|
+
const findLastIndex = (arr, pred) => findLastByPredicate(arr, pred).map((r) => r.i);
|
|
584
586
|
const flatten$1 = (xs) => {
|
|
585
587
|
// Note, this is possible because push supports multiple arguments:
|
|
586
588
|
// http://jsperf.com/concat-push/6
|
|
@@ -2198,14 +2200,14 @@
|
|
|
2198
2200
|
const siblings = (element) => {
|
|
2199
2201
|
// TODO: Refactor out children so we can just not add self instead of filtering afterwards
|
|
2200
2202
|
const filterSelf = (elements) => filter$5(elements, (x) => !eq(element, x));
|
|
2201
|
-
return parent(element).map(children$
|
|
2203
|
+
return parent(element).map(children$2).map(filterSelf).getOr([]);
|
|
2202
2204
|
};
|
|
2203
2205
|
const prevSibling = (element) => Optional.from(element.dom.previousSibling).map(SugarElement.fromDom);
|
|
2204
2206
|
const nextSibling = (element) => Optional.from(element.dom.nextSibling).map(SugarElement.fromDom);
|
|
2205
2207
|
// This one needs to be reversed, so they're still in DOM order
|
|
2206
2208
|
const prevSiblings = (element) => reverse(toArray(element, prevSibling));
|
|
2207
2209
|
const nextSiblings = (element) => toArray(element, nextSibling);
|
|
2208
|
-
const children$
|
|
2210
|
+
const children$2 = (element) => map$3(element.dom.childNodes, SugarElement.fromDom);
|
|
2209
2211
|
const child$1 = (element, index) => {
|
|
2210
2212
|
const cs = element.dom.childNodes;
|
|
2211
2213
|
return Optional.from(cs[index]).map(SugarElement.fromDom);
|
|
@@ -2442,7 +2444,7 @@
|
|
|
2442
2444
|
// than removing every child node manually.
|
|
2443
2445
|
// The following is (probably) safe for performance as 99.9% of the time the trick works and
|
|
2444
2446
|
// Traverse.children will return an empty array.
|
|
2445
|
-
each$e(children$
|
|
2447
|
+
each$e(children$2(element), (rogue) => {
|
|
2446
2448
|
remove$8(rogue);
|
|
2447
2449
|
});
|
|
2448
2450
|
};
|
|
@@ -2453,7 +2455,7 @@
|
|
|
2453
2455
|
}
|
|
2454
2456
|
};
|
|
2455
2457
|
const unwrap = (wrapper) => {
|
|
2456
|
-
const children = children$
|
|
2458
|
+
const children = children$2(wrapper);
|
|
2457
2459
|
if (children.length > 0) {
|
|
2458
2460
|
after$3(wrapper, children);
|
|
2459
2461
|
}
|
|
@@ -2476,7 +2478,7 @@
|
|
|
2476
2478
|
const mutate = (original, tag) => {
|
|
2477
2479
|
const nu = shallowAs(original, tag);
|
|
2478
2480
|
after$4(original, nu);
|
|
2479
|
-
const children = children$
|
|
2481
|
+
const children = children$2(original);
|
|
2480
2482
|
append(nu, children);
|
|
2481
2483
|
remove$8(original);
|
|
2482
2484
|
return nu;
|
|
@@ -2486,7 +2488,7 @@
|
|
|
2486
2488
|
const doc = scope || document;
|
|
2487
2489
|
const div = doc.createElement('div');
|
|
2488
2490
|
div.innerHTML = html;
|
|
2489
|
-
return children$
|
|
2491
|
+
return children$2(SugarElement.fromDom(div));
|
|
2490
2492
|
};
|
|
2491
2493
|
const fromDom$1 = (nodes) => map$3(nodes, SugarElement.fromDom);
|
|
2492
2494
|
|
|
@@ -2526,6 +2528,14 @@
|
|
|
2526
2528
|
const doc = dom.ownerDocument;
|
|
2527
2529
|
return getShadowRoot(SugarElement.fromDom(dom)).fold(() => doc.body.contains(dom), compose1(inBody, getShadowHost));
|
|
2528
2530
|
};
|
|
2531
|
+
const body = () => getBody(SugarElement.fromDom(document));
|
|
2532
|
+
const getBody = (doc) => {
|
|
2533
|
+
const b = doc.dom.body;
|
|
2534
|
+
if (b === null || b === undefined) {
|
|
2535
|
+
throw new Error('Body is not available yet');
|
|
2536
|
+
}
|
|
2537
|
+
return SugarElement.fromDom(b);
|
|
2538
|
+
};
|
|
2529
2539
|
|
|
2530
2540
|
const internalSet = (dom, property, value) => {
|
|
2531
2541
|
// This is going to hurt. Apologies.
|
|
@@ -2999,11 +3009,11 @@
|
|
|
2999
3009
|
};
|
|
3000
3010
|
|
|
3001
3011
|
const ancestors$1 = (scope, predicate, isRoot) => filter$5(parents$1(scope, isRoot), predicate);
|
|
3002
|
-
const children = (scope, predicate) => filter$5(children$
|
|
3012
|
+
const children$1 = (scope, predicate) => filter$5(children$2(scope), predicate);
|
|
3003
3013
|
const descendants$1 = (scope, predicate) => {
|
|
3004
3014
|
let result = [];
|
|
3005
3015
|
// Recurse.toArray() might help here
|
|
3006
|
-
each$e(children$
|
|
3016
|
+
each$e(children$2(scope), (x) => {
|
|
3007
3017
|
if (predicate(x)) {
|
|
3008
3018
|
result = result.concat([x]);
|
|
3009
3019
|
}
|
|
@@ -3021,6 +3031,10 @@
|
|
|
3021
3031
|
// It may surprise you to learn this is exactly what JQuery does
|
|
3022
3032
|
// TODO: Avoid all this wrapping and unwrapping
|
|
3023
3033
|
ancestors$1(scope, (e) => is$2(e, selector), isRoot);
|
|
3034
|
+
const children = (scope, selector) =>
|
|
3035
|
+
// It may surprise you to learn this is exactly what JQuery does
|
|
3036
|
+
// TODO: Avoid all the wrapping and unwrapping
|
|
3037
|
+
children$1(scope, (e) => is$2(e, selector));
|
|
3024
3038
|
const descendants = (scope, selector) => all(selector, scope);
|
|
3025
3039
|
|
|
3026
3040
|
const ancestor$3 = (scope, predicate, isRoot) => ancestor$5(scope, predicate, isRoot).isSome();
|
|
@@ -3205,6 +3219,20 @@
|
|
|
3205
3219
|
};
|
|
3206
3220
|
const getAtPoint = (win, x, y) => fromPoint$1(win, x, y);
|
|
3207
3221
|
|
|
3222
|
+
const getImageSize = (url) => new Promise((resolve, reject) => {
|
|
3223
|
+
const img = document.createElement('img');
|
|
3224
|
+
img.addEventListener('load', () => {
|
|
3225
|
+
resolve({
|
|
3226
|
+
width: img.naturalWidth,
|
|
3227
|
+
height: img.naturalHeight
|
|
3228
|
+
});
|
|
3229
|
+
});
|
|
3230
|
+
img.addEventListener('error', () => {
|
|
3231
|
+
reject(`Failed to get image dimensions for: ${url}`);
|
|
3232
|
+
});
|
|
3233
|
+
img.src = url;
|
|
3234
|
+
});
|
|
3235
|
+
|
|
3208
3236
|
const get$2 = (_win) => {
|
|
3209
3237
|
const win = _win === undefined ? window : _win;
|
|
3210
3238
|
if (detect$1().browser.isFirefox()) {
|
|
@@ -3660,7 +3688,7 @@
|
|
|
3660
3688
|
const isRoot = (el) => eq(el, rootNode);
|
|
3661
3689
|
each$e(fromDom$1(transparentBlocks), (transparentBlock) => {
|
|
3662
3690
|
ancestor$5(transparentBlock, isBlock, isRoot).each((parentBlock) => {
|
|
3663
|
-
const invalidChildren = children(transparentBlock, (el) => isBlock(el) && !schema.isValidChild(name(parentBlock), name(el)));
|
|
3691
|
+
const invalidChildren = children$1(transparentBlock, (el) => isBlock(el) && !schema.isValidChild(name(parentBlock), name(el)));
|
|
3664
3692
|
if (invalidChildren.length > 0) {
|
|
3665
3693
|
const stateScope = parentElement(parentBlock);
|
|
3666
3694
|
each$e(invalidChildren, (child) => {
|
|
@@ -3711,7 +3739,7 @@
|
|
|
3711
3739
|
// this tries to compensate for that by detecting if that offsets are incorrect and then remove the height
|
|
3712
3740
|
const getTableCaptionDeltaY = (elm) => {
|
|
3713
3741
|
if (browser$2.isFirefox() && name(elm) === 'table') {
|
|
3714
|
-
return firstElement(children$
|
|
3742
|
+
return firstElement(children$2(elm)).filter((elm) => {
|
|
3715
3743
|
return name(elm) === 'caption';
|
|
3716
3744
|
}).bind((caption) => {
|
|
3717
3745
|
return firstElement(nextSiblings(caption)).map((body) => {
|
|
@@ -5594,12 +5622,16 @@
|
|
|
5594
5622
|
let matches;
|
|
5595
5623
|
while ((matches = styleRegExp.exec(css))) {
|
|
5596
5624
|
styleRegExp.lastIndex = matches.index + matches[0].length;
|
|
5597
|
-
let name = matches[1].replace(trimRightRegExp, '')
|
|
5625
|
+
let name = matches[1].replace(trimRightRegExp, '');
|
|
5598
5626
|
let value = matches[2].replace(trimRightRegExp, '');
|
|
5599
5627
|
if (name && value) {
|
|
5600
5628
|
// Decode escaped sequences like \65 -> e
|
|
5601
5629
|
name = decodeHexSequences(name);
|
|
5602
5630
|
value = decodeHexSequences(value);
|
|
5631
|
+
// Custom properties (--*) keep user case; standard names normalize to lowercase
|
|
5632
|
+
if (!name.startsWith('--')) {
|
|
5633
|
+
name = name.toLowerCase();
|
|
5634
|
+
}
|
|
5603
5635
|
// Skip properties with double quotes and sequences like \" \' in their names
|
|
5604
5636
|
// See 'mXSS Attacks: Attacking well-secured Web-Applications by using innerHTML Mutations'
|
|
5605
5637
|
// https://cure53.de/fp170.pdf
|
|
@@ -5614,9 +5646,6 @@
|
|
|
5614
5646
|
if (name === 'font-weight' && value === '700') {
|
|
5615
5647
|
value = 'bold';
|
|
5616
5648
|
}
|
|
5617
|
-
else if (name === 'color' || name === 'background-color') { // Lowercase colors like RED
|
|
5618
|
-
value = value.toLowerCase();
|
|
5619
|
-
}
|
|
5620
5649
|
// Convert RGB colors to HEX
|
|
5621
5650
|
if (getColorFormat(value) === 'rgb') {
|
|
5622
5651
|
fromString(value).each((rgba) => {
|
|
@@ -6591,7 +6620,7 @@
|
|
|
6591
6620
|
const $node = SugarElement.fromDom(n);
|
|
6592
6621
|
if (keepChildren) {
|
|
6593
6622
|
// Unwrap but don't keep any empty text nodes
|
|
6594
|
-
each$e(children$
|
|
6623
|
+
each$e(children$2($node), (child) => {
|
|
6595
6624
|
if (isText$c(child) && child.dom.length === 0) {
|
|
6596
6625
|
remove$8(child);
|
|
6597
6626
|
}
|
|
@@ -12736,7 +12765,7 @@
|
|
|
12736
12765
|
switch (ctx) {
|
|
12737
12766
|
case "invalid-child" /* ChildContext.InvalidChild */: {
|
|
12738
12767
|
finishWrapper();
|
|
12739
|
-
const children = children$
|
|
12768
|
+
const children = children$2(elem);
|
|
12740
12769
|
processElements(children);
|
|
12741
12770
|
finishWrapper();
|
|
12742
12771
|
break;
|
|
@@ -12890,6 +12919,113 @@
|
|
|
12890
12919
|
};
|
|
12891
12920
|
};
|
|
12892
12921
|
|
|
12922
|
+
const announcerContainerId = generate('tiny-aria-announcer');
|
|
12923
|
+
const POLITE_MESSAGE_TTL_MS = 600000; // 10 minutes
|
|
12924
|
+
const CREATE_DELAY_MS = 100; // Delay before creating announcer regions to avoid interfering with screen readers initial announcements.
|
|
12925
|
+
const politeTimestampAttr = 'data-mce-announced-at';
|
|
12926
|
+
const OFFSCREEN_STYLES = {
|
|
12927
|
+
position: 'absolute',
|
|
12928
|
+
left: '-9999px',
|
|
12929
|
+
width: '1px',
|
|
12930
|
+
height: '1px',
|
|
12931
|
+
overflow: 'hidden'
|
|
12932
|
+
};
|
|
12933
|
+
const createRegion = (live) => {
|
|
12934
|
+
const region = SugarElement.fromTag('div');
|
|
12935
|
+
setAll$1(region, {
|
|
12936
|
+
'aria-live': live,
|
|
12937
|
+
'aria-atomic': 'false',
|
|
12938
|
+
'aria-relevant': 'additions'
|
|
12939
|
+
});
|
|
12940
|
+
return region;
|
|
12941
|
+
};
|
|
12942
|
+
const isConnected = (element) => element.dom.isConnected;
|
|
12943
|
+
const createNewState = () => {
|
|
12944
|
+
const container = SugarElement.fromTag('div');
|
|
12945
|
+
const politeRegion = createRegion('polite');
|
|
12946
|
+
const assertiveRegion = createRegion('assertive');
|
|
12947
|
+
set$5(container, 'id', announcerContainerId);
|
|
12948
|
+
setAll(container, OFFSCREEN_STYLES);
|
|
12949
|
+
append$1(container, politeRegion);
|
|
12950
|
+
append$1(container, assertiveRegion);
|
|
12951
|
+
append$1(body(), container);
|
|
12952
|
+
return { container, politeRegion, assertiveRegion };
|
|
12953
|
+
};
|
|
12954
|
+
const cleanupExpiredMessages = (polite, now) => {
|
|
12955
|
+
each$e(children(polite, `div[${politeTimestampAttr}]`), (messageDiv) => {
|
|
12956
|
+
getOpt(messageDiv, politeTimestampAttr)
|
|
12957
|
+
.bind((value) => toInt(value))
|
|
12958
|
+
.filter((announcedAt) => now - announcedAt > POLITE_MESSAGE_TTL_MS)
|
|
12959
|
+
.each(() => remove$8(messageDiv));
|
|
12960
|
+
});
|
|
12961
|
+
};
|
|
12962
|
+
const createAnnouncer = () => {
|
|
12963
|
+
const state = value$1();
|
|
12964
|
+
const mountRegions = async () => {
|
|
12965
|
+
const createNewPendingState = async () => {
|
|
12966
|
+
const promise = new Promise((resolve) => {
|
|
12967
|
+
const newState = createNewState();
|
|
12968
|
+
setTimeout(() => resolve(newState), CREATE_DELAY_MS);
|
|
12969
|
+
});
|
|
12970
|
+
state.set(promise);
|
|
12971
|
+
return promise;
|
|
12972
|
+
};
|
|
12973
|
+
return state.get().fold(createNewPendingState, async (existingPromise) => {
|
|
12974
|
+
const { container } = await existingPromise;
|
|
12975
|
+
if (isConnected(container)) {
|
|
12976
|
+
return existingPromise;
|
|
12977
|
+
}
|
|
12978
|
+
else {
|
|
12979
|
+
// A concurrent caller may have already replaced the stale state while we awaited.
|
|
12980
|
+
// The block after the await runs atomically, so reuse that state if present and
|
|
12981
|
+
// only create a fresh one when the state is still the stale promise we observed.
|
|
12982
|
+
return state.get().filter((current) => current !== existingPromise).getOrThunk(createNewPendingState);
|
|
12983
|
+
}
|
|
12984
|
+
});
|
|
12985
|
+
};
|
|
12986
|
+
const addMessage = (region, message) => {
|
|
12987
|
+
const now = Date.now();
|
|
12988
|
+
cleanupExpiredMessages(region, now);
|
|
12989
|
+
const messageDiv = SugarElement.fromTag('div');
|
|
12990
|
+
set$5(messageDiv, politeTimestampAttr, String(now));
|
|
12991
|
+
append$1(messageDiv, SugarElement.fromText(message));
|
|
12992
|
+
append$1(region, messageDiv);
|
|
12993
|
+
};
|
|
12994
|
+
const polite = async (message) => {
|
|
12995
|
+
const { politeRegion } = await mountRegions();
|
|
12996
|
+
addMessage(politeRegion, message);
|
|
12997
|
+
};
|
|
12998
|
+
const assertive = async (message) => {
|
|
12999
|
+
const { assertiveRegion } = await mountRegions();
|
|
13000
|
+
addMessage(assertiveRegion, message);
|
|
13001
|
+
};
|
|
13002
|
+
return { polite, assertive };
|
|
13003
|
+
};
|
|
13004
|
+
|
|
13005
|
+
const announcer = createAnnouncer();
|
|
13006
|
+
/**
|
|
13007
|
+
* Announces a message to screen readers via an aria-live region, without shifting focus.
|
|
13008
|
+
*
|
|
13009
|
+
* @method announce
|
|
13010
|
+
* @param {String} message The message to announce to screen readers.
|
|
13011
|
+
* @param {Object} options Optional settings.
|
|
13012
|
+
* @param {Boolean} options.assertive If true, uses aria-live="assertive" instead of polite.
|
|
13013
|
+
* @example
|
|
13014
|
+
* tinymce.dom.AriaAnnouncer.announce('Bold on');
|
|
13015
|
+
* tinymce.dom.AriaAnnouncer.announce('Error occurred', { assertive: true });
|
|
13016
|
+
*/
|
|
13017
|
+
const announce = (message, options) => {
|
|
13018
|
+
if (options?.assertive === true) {
|
|
13019
|
+
announcer.assertive(message).catch(noop);
|
|
13020
|
+
}
|
|
13021
|
+
else {
|
|
13022
|
+
announcer.polite(message).catch(noop);
|
|
13023
|
+
}
|
|
13024
|
+
};
|
|
13025
|
+
const AriaAnnouncer = {
|
|
13026
|
+
announce
|
|
13027
|
+
};
|
|
13028
|
+
|
|
12893
13029
|
/**
|
|
12894
13030
|
* Constructs a new BookmarkManager instance for a specific selection instance.
|
|
12895
13031
|
*
|
|
@@ -12954,7 +13090,7 @@
|
|
|
12954
13090
|
};
|
|
12955
13091
|
|
|
12956
13092
|
const clamp$1 = (offset, element) => {
|
|
12957
|
-
const max = isText$c(element) ? get$5(element).length : children$
|
|
13093
|
+
const max = isText$c(element) ? get$5(element).length : children$2(element).length + 1;
|
|
12958
13094
|
if (offset > max) {
|
|
12959
13095
|
return max;
|
|
12960
13096
|
}
|
|
@@ -14226,7 +14362,7 @@
|
|
|
14226
14362
|
editor.dispatch('AfterScrollIntoView', data);
|
|
14227
14363
|
};
|
|
14228
14364
|
const descend = (element, offset) => {
|
|
14229
|
-
const children = children$
|
|
14365
|
+
const children = children$2(element);
|
|
14230
14366
|
if (children.length === 0 || excludeFromDescend(element)) {
|
|
14231
14367
|
return { element, offset };
|
|
14232
14368
|
}
|
|
@@ -14246,7 +14382,7 @@
|
|
|
14246
14382
|
return { element: last, offset: get$5(last).length };
|
|
14247
14383
|
}
|
|
14248
14384
|
else {
|
|
14249
|
-
return { element: last, offset: children$
|
|
14385
|
+
return { element: last, offset: children$2(last).length };
|
|
14250
14386
|
}
|
|
14251
14387
|
}
|
|
14252
14388
|
}
|
|
@@ -15750,7 +15886,7 @@
|
|
|
15750
15886
|
const br = SugarElement.fromHtml('<br data-mce-bogus="1">');
|
|
15751
15887
|
// Remove all bogus elements except caret
|
|
15752
15888
|
if (preserveEmptyCaret) {
|
|
15753
|
-
each$e(children$
|
|
15889
|
+
each$e(children$2(elm), (node) => {
|
|
15754
15890
|
if (!isEmptyCaretFormatElement(node)) {
|
|
15755
15891
|
remove$8(node);
|
|
15756
15892
|
}
|
|
@@ -15922,7 +16058,7 @@
|
|
|
15922
16058
|
// Clean up any additional leftover nodes. If the last block wasn't a direct child, then we also need to clean up siblings
|
|
15923
16059
|
if (!eq(root, lastBlock)) {
|
|
15924
16060
|
const additionalCleanupNodes = is$4(parent(lastBlock), root) ? [] : siblings(lastBlock);
|
|
15925
|
-
each$e(additionalCleanupNodes.concat(children$
|
|
16061
|
+
each$e(additionalCleanupNodes.concat(children$2(root)), (node) => {
|
|
15926
16062
|
if (!eq(node, lastBlock) && !contains(node, lastBlock) && isEmpty$4(editor.schema, node)) {
|
|
15927
16063
|
remove$8(node);
|
|
15928
16064
|
}
|
|
@@ -17695,14 +17831,14 @@
|
|
|
17695
17831
|
});
|
|
17696
17832
|
};
|
|
17697
17833
|
const wrapChildrenInInnerWrapper = (target, wrapper, hasFormat, removeFormatFromElement) => {
|
|
17698
|
-
each$e(children$
|
|
17834
|
+
each$e(children$2(target), (child) => {
|
|
17699
17835
|
if (isElement$8(child) && hasFormat(child)) {
|
|
17700
17836
|
if (removeFormatFromElement(child).isNone()) {
|
|
17701
17837
|
unwrap(child);
|
|
17702
17838
|
}
|
|
17703
17839
|
}
|
|
17704
17840
|
});
|
|
17705
|
-
each$e(children$
|
|
17841
|
+
each$e(children$2(target), (child) => append$1(wrapper, child));
|
|
17706
17842
|
prepend(target, wrapper);
|
|
17707
17843
|
};
|
|
17708
17844
|
const wrapInOuterWrappers = (target, wrappers) => {
|
|
@@ -18492,24 +18628,65 @@
|
|
|
18492
18628
|
}
|
|
18493
18629
|
};
|
|
18494
18630
|
|
|
18495
|
-
/*! @license DOMPurify 3.
|
|
18496
|
-
|
|
18497
|
-
|
|
18498
|
-
|
|
18499
|
-
|
|
18500
|
-
|
|
18501
|
-
|
|
18502
|
-
|
|
18503
|
-
|
|
18504
|
-
|
|
18505
|
-
|
|
18506
|
-
|
|
18507
|
-
|
|
18508
|
-
|
|
18509
|
-
|
|
18510
|
-
|
|
18511
|
-
|
|
18512
|
-
|
|
18631
|
+
/*! @license DOMPurify 3.4.5 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.4.5/LICENSE */
|
|
18632
|
+
|
|
18633
|
+
function _arrayLikeToArray(r, a) {
|
|
18634
|
+
(null == a || a > r.length) && (a = r.length);
|
|
18635
|
+
for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
|
|
18636
|
+
return n;
|
|
18637
|
+
}
|
|
18638
|
+
function _arrayWithHoles(r) {
|
|
18639
|
+
if (Array.isArray(r)) return r;
|
|
18640
|
+
}
|
|
18641
|
+
function _iterableToArrayLimit(r, l) {
|
|
18642
|
+
var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
|
|
18643
|
+
if (null != t) {
|
|
18644
|
+
var e,
|
|
18645
|
+
n,
|
|
18646
|
+
i,
|
|
18647
|
+
u,
|
|
18648
|
+
a = [],
|
|
18649
|
+
f = true,
|
|
18650
|
+
o = false;
|
|
18651
|
+
try {
|
|
18652
|
+
if (i = (t = t.call(r)).next, 0 === l) ; else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
|
|
18653
|
+
} catch (r) {
|
|
18654
|
+
o = true, n = r;
|
|
18655
|
+
} finally {
|
|
18656
|
+
try {
|
|
18657
|
+
if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
|
|
18658
|
+
} finally {
|
|
18659
|
+
if (o) throw n;
|
|
18660
|
+
}
|
|
18661
|
+
}
|
|
18662
|
+
return a;
|
|
18663
|
+
}
|
|
18664
|
+
}
|
|
18665
|
+
function _nonIterableRest() {
|
|
18666
|
+
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
18667
|
+
}
|
|
18668
|
+
function _slicedToArray(r, e) {
|
|
18669
|
+
return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
|
|
18670
|
+
}
|
|
18671
|
+
function _unsupportedIterableToArray(r, a) {
|
|
18672
|
+
if (r) {
|
|
18673
|
+
if ("string" == typeof r) return _arrayLikeToArray(r, a);
|
|
18674
|
+
var t = {}.toString.call(r).slice(8, -1);
|
|
18675
|
+
return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
|
|
18676
|
+
}
|
|
18677
|
+
}
|
|
18678
|
+
|
|
18679
|
+
const entries = Object.entries,
|
|
18680
|
+
setPrototypeOf = Object.setPrototypeOf,
|
|
18681
|
+
isFrozen = Object.isFrozen,
|
|
18682
|
+
getPrototypeOf = Object.getPrototypeOf,
|
|
18683
|
+
getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
|
|
18684
|
+
let freeze = Object.freeze,
|
|
18685
|
+
seal = Object.seal,
|
|
18686
|
+
create$7 = Object.create; // eslint-disable-line import/no-mutable-exports
|
|
18687
|
+
let _ref = typeof Reflect !== 'undefined' && Reflect,
|
|
18688
|
+
apply = _ref.apply,
|
|
18689
|
+
construct = _ref.construct;
|
|
18513
18690
|
if (!freeze) {
|
|
18514
18691
|
freeze = function freeze(x) {
|
|
18515
18692
|
return x;
|
|
@@ -18541,13 +18718,19 @@
|
|
|
18541
18718
|
const arrayPop = unapply(Array.prototype.pop);
|
|
18542
18719
|
const arrayPush = unapply(Array.prototype.push);
|
|
18543
18720
|
const arraySplice = unapply(Array.prototype.splice);
|
|
18721
|
+
const arrayIsArray = Array.isArray;
|
|
18544
18722
|
const stringToLowerCase = unapply(String.prototype.toLowerCase);
|
|
18545
18723
|
const stringToString = unapply(String.prototype.toString);
|
|
18546
18724
|
const stringMatch = unapply(String.prototype.match);
|
|
18547
18725
|
const stringReplace = unapply(String.prototype.replace);
|
|
18548
18726
|
const stringIndexOf = unapply(String.prototype.indexOf);
|
|
18549
18727
|
const stringTrim = unapply(String.prototype.trim);
|
|
18728
|
+
const numberToString = unapply(Number.prototype.toString);
|
|
18729
|
+
const booleanToString = unapply(Boolean.prototype.toString);
|
|
18730
|
+
const bigintToString = typeof BigInt === 'undefined' ? null : unapply(BigInt.prototype.toString);
|
|
18731
|
+
const symbolToString = typeof Symbol === 'undefined' ? null : unapply(Symbol.prototype.toString);
|
|
18550
18732
|
const objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);
|
|
18733
|
+
const objectToString = unapply(Object.prototype.toString);
|
|
18551
18734
|
const regExpTest = unapply(RegExp.prototype.test);
|
|
18552
18735
|
const typeErrorCreate = unconstruct(TypeError);
|
|
18553
18736
|
/**
|
|
@@ -18597,6 +18780,9 @@
|
|
|
18597
18780
|
// Prevent prototype setters from intercepting set as a this value.
|
|
18598
18781
|
setPrototypeOf(set, null);
|
|
18599
18782
|
}
|
|
18783
|
+
if (!arrayIsArray(array)) {
|
|
18784
|
+
return set;
|
|
18785
|
+
}
|
|
18600
18786
|
let l = array.length;
|
|
18601
18787
|
while (l--) {
|
|
18602
18788
|
let element = array[l];
|
|
@@ -18637,10 +18823,13 @@
|
|
|
18637
18823
|
*/
|
|
18638
18824
|
function clone(object) {
|
|
18639
18825
|
const newObject = create$7(null);
|
|
18640
|
-
for (const
|
|
18826
|
+
for (const _ref2 of entries(object)) {
|
|
18827
|
+
var _ref3 = _slicedToArray(_ref2, 2);
|
|
18828
|
+
const property = _ref3[0];
|
|
18829
|
+
const value = _ref3[1];
|
|
18641
18830
|
const isPropertyExist = objectHasOwnProperty(object, property);
|
|
18642
18831
|
if (isPropertyExist) {
|
|
18643
|
-
if (
|
|
18832
|
+
if (arrayIsArray(value)) {
|
|
18644
18833
|
newObject[property] = cleanArray(value);
|
|
18645
18834
|
} else if (value && typeof value === 'object' && value.constructor === Object) {
|
|
18646
18835
|
newObject[property] = clone(value);
|
|
@@ -18651,6 +18840,58 @@
|
|
|
18651
18840
|
}
|
|
18652
18841
|
return newObject;
|
|
18653
18842
|
}
|
|
18843
|
+
/**
|
|
18844
|
+
* Convert non-node values into strings without depending on direct property access.
|
|
18845
|
+
*
|
|
18846
|
+
* @param value - The value to stringify.
|
|
18847
|
+
* @returns A string representation of the provided value.
|
|
18848
|
+
*/
|
|
18849
|
+
function stringifyValue(value) {
|
|
18850
|
+
switch (typeof value) {
|
|
18851
|
+
case 'string':
|
|
18852
|
+
{
|
|
18853
|
+
return value;
|
|
18854
|
+
}
|
|
18855
|
+
case 'number':
|
|
18856
|
+
{
|
|
18857
|
+
return numberToString(value);
|
|
18858
|
+
}
|
|
18859
|
+
case 'boolean':
|
|
18860
|
+
{
|
|
18861
|
+
return booleanToString(value);
|
|
18862
|
+
}
|
|
18863
|
+
case 'bigint':
|
|
18864
|
+
{
|
|
18865
|
+
return bigintToString ? bigintToString(value) : '0';
|
|
18866
|
+
}
|
|
18867
|
+
case 'symbol':
|
|
18868
|
+
{
|
|
18869
|
+
return symbolToString ? symbolToString(value) : 'Symbol()';
|
|
18870
|
+
}
|
|
18871
|
+
case 'undefined':
|
|
18872
|
+
{
|
|
18873
|
+
return objectToString(value);
|
|
18874
|
+
}
|
|
18875
|
+
case 'function':
|
|
18876
|
+
case 'object':
|
|
18877
|
+
{
|
|
18878
|
+
if (value === null) {
|
|
18879
|
+
return objectToString(value);
|
|
18880
|
+
}
|
|
18881
|
+
const valueAsRecord = value;
|
|
18882
|
+
const valueToString = lookupGetter(valueAsRecord, 'toString');
|
|
18883
|
+
if (typeof valueToString === 'function') {
|
|
18884
|
+
const stringified = valueToString(valueAsRecord);
|
|
18885
|
+
return typeof stringified === 'string' ? stringified : objectToString(stringified);
|
|
18886
|
+
}
|
|
18887
|
+
return objectToString(value);
|
|
18888
|
+
}
|
|
18889
|
+
default:
|
|
18890
|
+
{
|
|
18891
|
+
return objectToString(value);
|
|
18892
|
+
}
|
|
18893
|
+
}
|
|
18894
|
+
}
|
|
18654
18895
|
/**
|
|
18655
18896
|
* This method automatically checks if the prop is function or getter and behaves accordingly.
|
|
18656
18897
|
*
|
|
@@ -18676,6 +18917,14 @@
|
|
|
18676
18917
|
}
|
|
18677
18918
|
return fallbackValue;
|
|
18678
18919
|
}
|
|
18920
|
+
function isRegex(value) {
|
|
18921
|
+
try {
|
|
18922
|
+
regExpTest(value, '');
|
|
18923
|
+
return true;
|
|
18924
|
+
} catch (_unused) {
|
|
18925
|
+
return false;
|
|
18926
|
+
}
|
|
18927
|
+
}
|
|
18679
18928
|
|
|
18680
18929
|
const html$1 = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'search', 'section', 'select', 'shadow', 'slot', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']);
|
|
18681
18930
|
const svg$1 = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'enterkeyhint', 'exportparts', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'inputmode', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'part', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'view', 'vkern']);
|
|
@@ -18691,15 +18940,14 @@
|
|
|
18691
18940
|
const mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);
|
|
18692
18941
|
const text = freeze(['#text']);
|
|
18693
18942
|
|
|
18694
|
-
const html = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', 'exportparts', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inert', 'inputmode', 'integrity', 'ismap', 'kind', 'label', 'lang', 'list', 'loading', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'muted', 'name', 'nonce', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'part', 'pattern', 'placeholder', 'playsinline', 'popover', 'popovertarget', 'popovertargetaction', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'slot', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'wrap', 'xmlns'
|
|
18943
|
+
const html = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'command', 'commandfor', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', 'exportparts', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inert', 'inputmode', 'integrity', 'ismap', 'kind', 'label', 'lang', 'list', 'loading', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'muted', 'name', 'nonce', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'part', 'pattern', 'placeholder', 'playsinline', 'popover', 'popovertarget', 'popovertargetaction', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'slot', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'wrap', 'xmlns']);
|
|
18695
18944
|
const svg = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'amplitude', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clippathunits', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'exponent', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'filterunits', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'intercept', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'mask-type', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'primitiveunits', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'slope', 'specularconstant', 'specularexponent', 'spreadmethod', 'startoffset', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'systemlanguage', 'tabindex', 'tablevalues', 'targetx', 'targety', 'transform', 'transform-origin', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']);
|
|
18696
|
-
const mathMl = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', '
|
|
18945
|
+
const mathMl = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnalign', 'columnlines', 'columnspacing', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'encoding', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lquote', 'lspace', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']);
|
|
18697
18946
|
const xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
|
|
18698
18947
|
|
|
18699
|
-
|
|
18700
|
-
const
|
|
18701
|
-
const
|
|
18702
|
-
const TMPLIT_EXPR = seal(/\$\{[\w\W]*/gm); // eslint-disable-line unicorn/better-regex
|
|
18948
|
+
const MUSTACHE_EXPR = seal(/{{[\w\W]*|^[\w\W]*}}/g);
|
|
18949
|
+
const ERB_EXPR = seal(/<%[\w\W]*|^[\w\W]*%>/g);
|
|
18950
|
+
const TMPLIT_EXPR = seal(/\${[\w\W]*/g);
|
|
18703
18951
|
const DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]+$/); // eslint-disable-line no-useless-escape
|
|
18704
18952
|
const ARIA_ATTR = seal(/^aria-[\-\w]+$/); // eslint-disable-line no-useless-escape
|
|
18705
18953
|
const IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i // eslint-disable-line no-useless-escape
|
|
@@ -18710,38 +18958,15 @@
|
|
|
18710
18958
|
const DOCTYPE_NAME = seal(/^html$/i);
|
|
18711
18959
|
const CUSTOM_ELEMENT = seal(/^[a-z][.\w]*(-[.\w]+)+$/i);
|
|
18712
18960
|
|
|
18713
|
-
var EXPRESSIONS = /*#__PURE__*/Object.freeze({
|
|
18714
|
-
__proto__: null,
|
|
18715
|
-
ARIA_ATTR: ARIA_ATTR,
|
|
18716
|
-
ATTR_WHITESPACE: ATTR_WHITESPACE,
|
|
18717
|
-
CUSTOM_ELEMENT: CUSTOM_ELEMENT,
|
|
18718
|
-
DATA_ATTR: DATA_ATTR,
|
|
18719
|
-
DOCTYPE_NAME: DOCTYPE_NAME,
|
|
18720
|
-
ERB_EXPR: ERB_EXPR,
|
|
18721
|
-
IS_ALLOWED_URI: IS_ALLOWED_URI,
|
|
18722
|
-
IS_SCRIPT_OR_DATA: IS_SCRIPT_OR_DATA,
|
|
18723
|
-
MUSTACHE_EXPR: MUSTACHE_EXPR,
|
|
18724
|
-
TMPLIT_EXPR: TMPLIT_EXPR
|
|
18725
|
-
});
|
|
18726
|
-
|
|
18727
18961
|
/* eslint-disable @typescript-eslint/indent */
|
|
18728
18962
|
// https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
|
|
18729
18963
|
const NODE_TYPE = {
|
|
18730
18964
|
element: 1,
|
|
18731
|
-
attribute: 2,
|
|
18732
18965
|
text: 3,
|
|
18733
|
-
cdataSection: 4,
|
|
18734
|
-
entityReference: 5,
|
|
18735
|
-
// Deprecated
|
|
18736
|
-
entityNode: 6,
|
|
18737
18966
|
// Deprecated
|
|
18738
18967
|
progressingInstruction: 7,
|
|
18739
18968
|
comment: 8,
|
|
18740
|
-
document: 9
|
|
18741
|
-
documentType: 10,
|
|
18742
|
-
documentFragment: 11,
|
|
18743
|
-
notation: 12 // Deprecated
|
|
18744
|
-
};
|
|
18969
|
+
document: 9};
|
|
18745
18970
|
const getGlobal = function getGlobal() {
|
|
18746
18971
|
return typeof window === 'undefined' ? null : window;
|
|
18747
18972
|
};
|
|
@@ -18799,7 +19024,7 @@
|
|
|
18799
19024
|
function createDOMPurify() {
|
|
18800
19025
|
let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
|
|
18801
19026
|
const DOMPurify = root => createDOMPurify(root);
|
|
18802
|
-
DOMPurify.version = '3.
|
|
19027
|
+
DOMPurify.version = '3.4.5';
|
|
18803
19028
|
DOMPurify.removed = [];
|
|
18804
19029
|
if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document || !window.Element) {
|
|
18805
19030
|
// Not running in a browser, provide a factory function
|
|
@@ -18807,28 +19032,26 @@
|
|
|
18807
19032
|
DOMPurify.isSupported = false;
|
|
18808
19033
|
return DOMPurify;
|
|
18809
19034
|
}
|
|
18810
|
-
let
|
|
18811
|
-
document
|
|
18812
|
-
} = window;
|
|
19035
|
+
let document = window.document;
|
|
18813
19036
|
const originalDocument = document;
|
|
18814
19037
|
const currentScript = originalDocument.currentScript;
|
|
18815
|
-
const
|
|
18816
|
-
|
|
18817
|
-
|
|
18818
|
-
|
|
18819
|
-
|
|
18820
|
-
|
|
18821
|
-
NamedNodeMap = window.NamedNodeMap || window.MozNamedAttrMap,
|
|
18822
|
-
HTMLFormElement,
|
|
18823
|
-
DOMParser,
|
|
18824
|
-
trustedTypes
|
|
18825
|
-
} = window;
|
|
19038
|
+
const DocumentFragment = window.DocumentFragment,
|
|
19039
|
+
HTMLTemplateElement = window.HTMLTemplateElement,
|
|
19040
|
+
Node = window.Node,
|
|
19041
|
+
Element = window.Element,
|
|
19042
|
+
NodeFilter = window.NodeFilter,
|
|
19043
|
+
_window$NamedNodeMap = window.NamedNodeMap,
|
|
19044
|
+
NamedNodeMap = _window$NamedNodeMap === void 0 ? window.NamedNodeMap || window.MozNamedAttrMap : _window$NamedNodeMap,
|
|
19045
|
+
HTMLFormElement = window.HTMLFormElement,
|
|
19046
|
+
DOMParser = window.DOMParser,
|
|
19047
|
+
trustedTypes = window.trustedTypes;
|
|
18826
19048
|
const ElementPrototype = Element.prototype;
|
|
18827
19049
|
const cloneNode = lookupGetter(ElementPrototype, 'cloneNode');
|
|
18828
19050
|
const remove = lookupGetter(ElementPrototype, 'remove');
|
|
18829
19051
|
const getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');
|
|
18830
19052
|
const getChildNodes = lookupGetter(ElementPrototype, 'childNodes');
|
|
18831
19053
|
const getParentNode = lookupGetter(ElementPrototype, 'parentNode');
|
|
19054
|
+
const getNodeType = Node && Node.prototype ? lookupGetter(Node.prototype, 'nodeType') : null;
|
|
18832
19055
|
// As per issue #47, the web-components registry is inherited by a
|
|
18833
19056
|
// new document created via createHTMLDocument. As per the spec
|
|
18834
19057
|
// (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)
|
|
@@ -18843,33 +19066,26 @@
|
|
|
18843
19066
|
}
|
|
18844
19067
|
let trustedTypesPolicy;
|
|
18845
19068
|
let emptyHTML = '';
|
|
18846
|
-
const
|
|
18847
|
-
implementation,
|
|
18848
|
-
createNodeIterator,
|
|
18849
|
-
createDocumentFragment,
|
|
18850
|
-
getElementsByTagName
|
|
18851
|
-
|
|
18852
|
-
const {
|
|
18853
|
-
importNode
|
|
18854
|
-
} = originalDocument;
|
|
19069
|
+
const _document = document,
|
|
19070
|
+
implementation = _document.implementation,
|
|
19071
|
+
createNodeIterator = _document.createNodeIterator,
|
|
19072
|
+
createDocumentFragment = _document.createDocumentFragment,
|
|
19073
|
+
getElementsByTagName = _document.getElementsByTagName;
|
|
19074
|
+
const importNode = originalDocument.importNode;
|
|
18855
19075
|
let hooks = _createHooksMap();
|
|
18856
19076
|
/**
|
|
18857
19077
|
* Expose whether this browser supports running the full DOMPurify.
|
|
18858
19078
|
*/
|
|
18859
19079
|
DOMPurify.isSupported = typeof entries === 'function' && typeof getParentNode === 'function' && implementation && implementation.createHTMLDocument !== undefined;
|
|
18860
|
-
const
|
|
18861
|
-
|
|
18862
|
-
|
|
18863
|
-
|
|
18864
|
-
|
|
18865
|
-
|
|
18866
|
-
|
|
18867
|
-
|
|
18868
|
-
|
|
18869
|
-
} = EXPRESSIONS;
|
|
18870
|
-
let {
|
|
18871
|
-
IS_ALLOWED_URI: IS_ALLOWED_URI$1
|
|
18872
|
-
} = EXPRESSIONS;
|
|
19080
|
+
const MUSTACHE_EXPR$1 = MUSTACHE_EXPR,
|
|
19081
|
+
ERB_EXPR$1 = ERB_EXPR,
|
|
19082
|
+
TMPLIT_EXPR$1 = TMPLIT_EXPR,
|
|
19083
|
+
DATA_ATTR$1 = DATA_ATTR,
|
|
19084
|
+
ARIA_ATTR$1 = ARIA_ATTR,
|
|
19085
|
+
IS_SCRIPT_OR_DATA$1 = IS_SCRIPT_OR_DATA,
|
|
19086
|
+
ATTR_WHITESPACE$1 = ATTR_WHITESPACE,
|
|
19087
|
+
CUSTOM_ELEMENT$1 = CUSTOM_ELEMENT;
|
|
19088
|
+
let IS_ALLOWED_URI$1 = IS_ALLOWED_URI;
|
|
18873
19089
|
/**
|
|
18874
19090
|
* We consider the elements and attributes below to be safe. Ideally
|
|
18875
19091
|
* don't add any new ones but feel free to remove unwanted ones.
|
|
@@ -19047,15 +19263,15 @@
|
|
|
19047
19263
|
// HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.
|
|
19048
19264
|
transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? stringToString : stringToLowerCase;
|
|
19049
19265
|
/* Set configuration parameters */
|
|
19050
|
-
ALLOWED_TAGS = objectHasOwnProperty(cfg, 'ALLOWED_TAGS') ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS;
|
|
19051
|
-
ALLOWED_ATTR = objectHasOwnProperty(cfg, 'ALLOWED_ATTR') ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;
|
|
19052
|
-
ALLOWED_NAMESPACES = objectHasOwnProperty(cfg, 'ALLOWED_NAMESPACES') ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES;
|
|
19053
|
-
URI_SAFE_ATTRIBUTES = objectHasOwnProperty(cfg, 'ADD_URI_SAFE_ATTR') ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR, transformCaseFunc) : DEFAULT_URI_SAFE_ATTRIBUTES;
|
|
19054
|
-
DATA_URI_TAGS = objectHasOwnProperty(cfg, 'ADD_DATA_URI_TAGS') ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS, transformCaseFunc) : DEFAULT_DATA_URI_TAGS;
|
|
19055
|
-
FORBID_CONTENTS = objectHasOwnProperty(cfg, 'FORBID_CONTENTS') ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS;
|
|
19056
|
-
FORBID_TAGS = objectHasOwnProperty(cfg, 'FORBID_TAGS') ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : clone({});
|
|
19057
|
-
FORBID_ATTR = objectHasOwnProperty(cfg, 'FORBID_ATTR') ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : clone({});
|
|
19058
|
-
USE_PROFILES = objectHasOwnProperty(cfg, 'USE_PROFILES') ? cfg.USE_PROFILES : false;
|
|
19266
|
+
ALLOWED_TAGS = objectHasOwnProperty(cfg, 'ALLOWED_TAGS') && arrayIsArray(cfg.ALLOWED_TAGS) ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS;
|
|
19267
|
+
ALLOWED_ATTR = objectHasOwnProperty(cfg, 'ALLOWED_ATTR') && arrayIsArray(cfg.ALLOWED_ATTR) ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;
|
|
19268
|
+
ALLOWED_NAMESPACES = objectHasOwnProperty(cfg, 'ALLOWED_NAMESPACES') && arrayIsArray(cfg.ALLOWED_NAMESPACES) ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES;
|
|
19269
|
+
URI_SAFE_ATTRIBUTES = objectHasOwnProperty(cfg, 'ADD_URI_SAFE_ATTR') && arrayIsArray(cfg.ADD_URI_SAFE_ATTR) ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR, transformCaseFunc) : DEFAULT_URI_SAFE_ATTRIBUTES;
|
|
19270
|
+
DATA_URI_TAGS = objectHasOwnProperty(cfg, 'ADD_DATA_URI_TAGS') && arrayIsArray(cfg.ADD_DATA_URI_TAGS) ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS, transformCaseFunc) : DEFAULT_DATA_URI_TAGS;
|
|
19271
|
+
FORBID_CONTENTS = objectHasOwnProperty(cfg, 'FORBID_CONTENTS') && arrayIsArray(cfg.FORBID_CONTENTS) ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS;
|
|
19272
|
+
FORBID_TAGS = objectHasOwnProperty(cfg, 'FORBID_TAGS') && arrayIsArray(cfg.FORBID_TAGS) ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : clone({});
|
|
19273
|
+
FORBID_ATTR = objectHasOwnProperty(cfg, 'FORBID_ATTR') && arrayIsArray(cfg.FORBID_ATTR) ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : clone({});
|
|
19274
|
+
USE_PROFILES = objectHasOwnProperty(cfg, 'USE_PROFILES') ? cfg.USE_PROFILES && typeof cfg.USE_PROFILES === 'object' ? clone(cfg.USE_PROFILES) : cfg.USE_PROFILES : false;
|
|
19059
19275
|
ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true
|
|
19060
19276
|
ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true
|
|
19061
19277
|
ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false
|
|
@@ -19071,19 +19287,20 @@
|
|
|
19071
19287
|
SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false; // Default false
|
|
19072
19288
|
KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
|
|
19073
19289
|
IN_PLACE = cfg.IN_PLACE || false; // Default false
|
|
19074
|
-
IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP
|
|
19075
|
-
NAMESPACE = cfg.NAMESPACE
|
|
19076
|
-
MATHML_TEXT_INTEGRATION_POINTS = cfg.MATHML_TEXT_INTEGRATION_POINTS
|
|
19077
|
-
HTML_INTEGRATION_POINTS = cfg.HTML_INTEGRATION_POINTS
|
|
19078
|
-
|
|
19079
|
-
|
|
19080
|
-
|
|
19290
|
+
IS_ALLOWED_URI$1 = isRegex(cfg.ALLOWED_URI_REGEXP) ? cfg.ALLOWED_URI_REGEXP : IS_ALLOWED_URI; // Default regexp
|
|
19291
|
+
NAMESPACE = typeof cfg.NAMESPACE === 'string' ? cfg.NAMESPACE : HTML_NAMESPACE; // Default HTML namespace
|
|
19292
|
+
MATHML_TEXT_INTEGRATION_POINTS = objectHasOwnProperty(cfg, 'MATHML_TEXT_INTEGRATION_POINTS') && cfg.MATHML_TEXT_INTEGRATION_POINTS && typeof cfg.MATHML_TEXT_INTEGRATION_POINTS === 'object' ? clone(cfg.MATHML_TEXT_INTEGRATION_POINTS) : addToSet({}, ['mi', 'mo', 'mn', 'ms', 'mtext']); // Default built-in map
|
|
19293
|
+
HTML_INTEGRATION_POINTS = objectHasOwnProperty(cfg, 'HTML_INTEGRATION_POINTS') && cfg.HTML_INTEGRATION_POINTS && typeof cfg.HTML_INTEGRATION_POINTS === 'object' ? clone(cfg.HTML_INTEGRATION_POINTS) : addToSet({}, ['annotation-xml']); // Default built-in map
|
|
19294
|
+
const customElementHandling = objectHasOwnProperty(cfg, 'CUSTOM_ELEMENT_HANDLING') && cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING === 'object' ? clone(cfg.CUSTOM_ELEMENT_HANDLING) : create$7(null);
|
|
19295
|
+
CUSTOM_ELEMENT_HANDLING = create$7(null);
|
|
19296
|
+
if (objectHasOwnProperty(customElementHandling, 'tagNameCheck') && isRegexOrFunction(customElementHandling.tagNameCheck)) {
|
|
19297
|
+
CUSTOM_ELEMENT_HANDLING.tagNameCheck = customElementHandling.tagNameCheck; // Default undefined
|
|
19081
19298
|
}
|
|
19082
|
-
if (
|
|
19083
|
-
CUSTOM_ELEMENT_HANDLING.attributeNameCheck =
|
|
19299
|
+
if (objectHasOwnProperty(customElementHandling, 'attributeNameCheck') && isRegexOrFunction(customElementHandling.attributeNameCheck)) {
|
|
19300
|
+
CUSTOM_ELEMENT_HANDLING.attributeNameCheck = customElementHandling.attributeNameCheck; // Default undefined
|
|
19084
19301
|
}
|
|
19085
|
-
if (
|
|
19086
|
-
CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements =
|
|
19302
|
+
if (objectHasOwnProperty(customElementHandling, 'allowCustomizedBuiltInElements') && typeof customElementHandling.allowCustomizedBuiltInElements === 'boolean') {
|
|
19303
|
+
CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = customElementHandling.allowCustomizedBuiltInElements; // Default undefined
|
|
19087
19304
|
}
|
|
19088
19305
|
if (SAFE_FOR_TEMPLATES) {
|
|
19089
19306
|
ALLOW_DATA_ATTR = false;
|
|
@@ -19115,44 +19332,41 @@
|
|
|
19115
19332
|
addToSet(ALLOWED_ATTR, xml);
|
|
19116
19333
|
}
|
|
19117
19334
|
}
|
|
19118
|
-
/*
|
|
19119
|
-
|
|
19120
|
-
|
|
19121
|
-
|
|
19122
|
-
if (!objectHasOwnProperty(cfg, 'ADD_ATTR')) {
|
|
19123
|
-
EXTRA_ELEMENT_HANDLING.attributeCheck = null;
|
|
19124
|
-
}
|
|
19335
|
+
/* Always reset function-based ADD_TAGS / ADD_ATTR checks to prevent
|
|
19336
|
+
* leaking across calls when switching from function to array config */
|
|
19337
|
+
EXTRA_ELEMENT_HANDLING.tagCheck = null;
|
|
19338
|
+
EXTRA_ELEMENT_HANDLING.attributeCheck = null;
|
|
19125
19339
|
/* Merge configuration parameters */
|
|
19126
|
-
if (cfg
|
|
19340
|
+
if (objectHasOwnProperty(cfg, 'ADD_TAGS')) {
|
|
19127
19341
|
if (typeof cfg.ADD_TAGS === 'function') {
|
|
19128
19342
|
EXTRA_ELEMENT_HANDLING.tagCheck = cfg.ADD_TAGS;
|
|
19129
|
-
} else {
|
|
19343
|
+
} else if (arrayIsArray(cfg.ADD_TAGS)) {
|
|
19130
19344
|
if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
|
|
19131
19345
|
ALLOWED_TAGS = clone(ALLOWED_TAGS);
|
|
19132
19346
|
}
|
|
19133
19347
|
addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);
|
|
19134
19348
|
}
|
|
19135
19349
|
}
|
|
19136
|
-
if (cfg
|
|
19350
|
+
if (objectHasOwnProperty(cfg, 'ADD_ATTR')) {
|
|
19137
19351
|
if (typeof cfg.ADD_ATTR === 'function') {
|
|
19138
19352
|
EXTRA_ELEMENT_HANDLING.attributeCheck = cfg.ADD_ATTR;
|
|
19139
|
-
} else {
|
|
19353
|
+
} else if (arrayIsArray(cfg.ADD_ATTR)) {
|
|
19140
19354
|
if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
|
|
19141
19355
|
ALLOWED_ATTR = clone(ALLOWED_ATTR);
|
|
19142
19356
|
}
|
|
19143
19357
|
addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);
|
|
19144
19358
|
}
|
|
19145
19359
|
}
|
|
19146
|
-
if (cfg.ADD_URI_SAFE_ATTR) {
|
|
19360
|
+
if (objectHasOwnProperty(cfg, 'ADD_URI_SAFE_ATTR') && arrayIsArray(cfg.ADD_URI_SAFE_ATTR)) {
|
|
19147
19361
|
addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);
|
|
19148
19362
|
}
|
|
19149
|
-
if (cfg.FORBID_CONTENTS) {
|
|
19363
|
+
if (objectHasOwnProperty(cfg, 'FORBID_CONTENTS') && arrayIsArray(cfg.FORBID_CONTENTS)) {
|
|
19150
19364
|
if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
|
|
19151
19365
|
FORBID_CONTENTS = clone(FORBID_CONTENTS);
|
|
19152
19366
|
}
|
|
19153
19367
|
addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);
|
|
19154
19368
|
}
|
|
19155
|
-
if (cfg.ADD_FORBID_CONTENTS) {
|
|
19369
|
+
if (objectHasOwnProperty(cfg, 'ADD_FORBID_CONTENTS') && arrayIsArray(cfg.ADD_FORBID_CONTENTS)) {
|
|
19156
19370
|
if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
|
|
19157
19371
|
FORBID_CONTENTS = clone(FORBID_CONTENTS);
|
|
19158
19372
|
}
|
|
@@ -19391,6 +19605,40 @@
|
|
|
19391
19605
|
// eslint-disable-next-line no-bitwise
|
|
19392
19606
|
NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT | NodeFilter.SHOW_PROCESSING_INSTRUCTION | NodeFilter.SHOW_CDATA_SECTION, null);
|
|
19393
19607
|
};
|
|
19608
|
+
/**
|
|
19609
|
+
* Strip template-engine expressions ({{...}}, ${...}, <%...%>) from the
|
|
19610
|
+
* character data of an element subtree. Used as the final safety net for
|
|
19611
|
+
* SAFE_FOR_TEMPLATES on every DOM-returning code path so that expressions
|
|
19612
|
+
* which only form after text-node normalization (e.g. fragments split across
|
|
19613
|
+
* stripped elements) cannot survive into a template-evaluating framework.
|
|
19614
|
+
*
|
|
19615
|
+
* Walks text/comment/CDATA/processing-instruction nodes and mutates `.data`
|
|
19616
|
+
* in place rather than round-tripping through innerHTML. This preserves
|
|
19617
|
+
* descendant node references (important for IN_PLACE callers), avoids a
|
|
19618
|
+
* serialize/reparse cycle, and reads literal character data — which means
|
|
19619
|
+
* `<%...%>` in text content matches the ERB regex against its real bytes
|
|
19620
|
+
* instead of the HTML-entity-escaped form innerHTML would produce.
|
|
19621
|
+
*
|
|
19622
|
+
* Attribute values are not visited here; SAFE_FOR_TEMPLATES handling for
|
|
19623
|
+
* attributes is performed during the per-node `_sanitizeAttributes` pass.
|
|
19624
|
+
*
|
|
19625
|
+
* @param node The root element whose character data should be scrubbed.
|
|
19626
|
+
*/
|
|
19627
|
+
const _scrubTemplateExpressions = function _scrubTemplateExpressions(node) {
|
|
19628
|
+
node.normalize();
|
|
19629
|
+
const walker = createNodeIterator.call(node.ownerDocument || node, node,
|
|
19630
|
+
// eslint-disable-next-line no-bitwise
|
|
19631
|
+
NodeFilter.SHOW_TEXT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_CDATA_SECTION | NodeFilter.SHOW_PROCESSING_INSTRUCTION, null);
|
|
19632
|
+
let currentNode = walker.nextNode();
|
|
19633
|
+
while (currentNode) {
|
|
19634
|
+
let data = currentNode.data;
|
|
19635
|
+
arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], expr => {
|
|
19636
|
+
data = stringReplace(data, expr, ' ');
|
|
19637
|
+
});
|
|
19638
|
+
currentNode.data = data;
|
|
19639
|
+
currentNode = walker.nextNode();
|
|
19640
|
+
}
|
|
19641
|
+
};
|
|
19394
19642
|
/**
|
|
19395
19643
|
* _isClobbered
|
|
19396
19644
|
*
|
|
@@ -19401,13 +19649,31 @@
|
|
|
19401
19649
|
return element instanceof HTMLFormElement && (typeof element.nodeName !== 'string' || typeof element.textContent !== 'string' || typeof element.removeChild !== 'function' || !(element.attributes instanceof NamedNodeMap) || typeof element.removeAttribute !== 'function' || typeof element.setAttribute !== 'function' || typeof element.namespaceURI !== 'string' || typeof element.insertBefore !== 'function' || typeof element.hasChildNodes !== 'function');
|
|
19402
19650
|
};
|
|
19403
19651
|
/**
|
|
19404
|
-
* Checks whether the given object is a DOM node
|
|
19652
|
+
* Checks whether the given object is a DOM node, including nodes that
|
|
19653
|
+
* originate from a different window/realm (e.g. an iframe's
|
|
19654
|
+
* contentDocument). The previous `value instanceof Node` check was
|
|
19655
|
+
* realm-bound: nodes from a different window failed it, causing
|
|
19656
|
+
* sanitize() to silently stringify them and reset IN_PLACE to false,
|
|
19657
|
+
* returning the original node unsanitized. See GHSA-4w3q-35jp-p934.
|
|
19658
|
+
*
|
|
19659
|
+
* Implementation: call the cached `nodeType` getter from Node.prototype
|
|
19660
|
+
* directly on the value. This bypasses any clobbered instance property
|
|
19661
|
+
* (e.g. a child element named "nodeType") and works across realms
|
|
19662
|
+
* because the WebIDL `nodeType` getter reads an internal slot that
|
|
19663
|
+
* every real Node has, regardless of which window minted it.
|
|
19405
19664
|
*
|
|
19406
19665
|
* @param value object to check whether it's a DOM node
|
|
19407
|
-
* @return true
|
|
19666
|
+
* @return true if value is a DOM node from any realm
|
|
19408
19667
|
*/
|
|
19409
19668
|
const _isNode = function _isNode(value) {
|
|
19410
|
-
|
|
19669
|
+
if (!getNodeType || typeof value !== 'object' || value === null) {
|
|
19670
|
+
return false;
|
|
19671
|
+
}
|
|
19672
|
+
try {
|
|
19673
|
+
return typeof getNodeType(value) === 'number';
|
|
19674
|
+
} catch (_) {
|
|
19675
|
+
return false;
|
|
19676
|
+
}
|
|
19411
19677
|
};
|
|
19412
19678
|
function _executeHooks(hooks, currentNode, data) {
|
|
19413
19679
|
arrayForEach(hooks, hook => {
|
|
@@ -19444,6 +19710,11 @@
|
|
|
19444
19710
|
_forceRemove(currentNode);
|
|
19445
19711
|
return true;
|
|
19446
19712
|
}
|
|
19713
|
+
/* Remove risky CSS construction leading to mXSS */
|
|
19714
|
+
if (SAFE_FOR_XML && currentNode.namespaceURI === HTML_NAMESPACE && tagName === 'style' && _isNode(currentNode.firstElementChild)) {
|
|
19715
|
+
_forceRemove(currentNode);
|
|
19716
|
+
return true;
|
|
19717
|
+
}
|
|
19447
19718
|
/* Remove any occurrence of processing instructions */
|
|
19448
19719
|
if (currentNode.nodeType === NODE_TYPE.progressingInstruction) {
|
|
19449
19720
|
_forceRemove(currentNode);
|
|
@@ -19455,7 +19726,7 @@
|
|
|
19455
19726
|
return true;
|
|
19456
19727
|
}
|
|
19457
19728
|
/* Remove element if anything forbids its presence */
|
|
19458
|
-
if (!(EXTRA_ELEMENT_HANDLING.tagCheck instanceof Function && EXTRA_ELEMENT_HANDLING.tagCheck(tagName)) &&
|
|
19729
|
+
if (FORBID_TAGS[tagName] || !(EXTRA_ELEMENT_HANDLING.tagCheck instanceof Function && EXTRA_ELEMENT_HANDLING.tagCheck(tagName)) && !ALLOWED_TAGS[tagName]) {
|
|
19459
19730
|
/* Check if we have a custom element to handle */
|
|
19460
19731
|
if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName)) {
|
|
19461
19732
|
if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) {
|
|
@@ -19473,7 +19744,6 @@
|
|
|
19473
19744
|
const childCount = childNodes.length;
|
|
19474
19745
|
for (let i = childCount - 1; i >= 0; --i) {
|
|
19475
19746
|
const childClone = cloneNode(childNodes[i], true);
|
|
19476
|
-
childClone.__removalCount = (currentNode.__removalCount || 0) + 1;
|
|
19477
19747
|
parentNode.insertBefore(childClone, getNextSibling(currentNode));
|
|
19478
19748
|
}
|
|
19479
19749
|
}
|
|
@@ -19495,7 +19765,7 @@
|
|
|
19495
19765
|
if (SAFE_FOR_TEMPLATES && currentNode.nodeType === NODE_TYPE.text) {
|
|
19496
19766
|
/* Get the element's text content */
|
|
19497
19767
|
content = currentNode.textContent;
|
|
19498
|
-
arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
|
|
19768
|
+
arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], expr => {
|
|
19499
19769
|
content = stringReplace(content, expr, ' ');
|
|
19500
19770
|
});
|
|
19501
19771
|
if (currentNode.textContent !== content) {
|
|
@@ -19527,11 +19797,12 @@
|
|
|
19527
19797
|
if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
|
|
19528
19798
|
return false;
|
|
19529
19799
|
}
|
|
19800
|
+
const nameIsPermitted = ALLOWED_ATTR[lcName] || EXTRA_ELEMENT_HANDLING.attributeCheck instanceof Function && EXTRA_ELEMENT_HANDLING.attributeCheck(lcName, lcTag);
|
|
19530
19801
|
/* Allow valid data-* attributes: At least one character after "-"
|
|
19531
19802
|
(https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
|
|
19532
19803
|
XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
|
|
19533
19804
|
We don't need to check the value; it's always URI safe. */
|
|
19534
|
-
if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR, lcName)) ; else if (
|
|
19805
|
+
if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR$1, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$1, lcName)) ; else if (!nameIsPermitted || FORBID_ATTR[lcName]) {
|
|
19535
19806
|
if (
|
|
19536
19807
|
// First condition does a very basic check if a) it's basically a valid custom element tagname AND
|
|
19537
19808
|
// b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
|
|
@@ -19543,11 +19814,15 @@
|
|
|
19543
19814
|
return false;
|
|
19544
19815
|
}
|
|
19545
19816
|
/* Check value is safe. First, is attr inert? If so, is safe */
|
|
19546
|
-
} else if (URI_SAFE_ATTRIBUTES[lcName]) ; else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE, ''))) ; else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) ; else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA, stringReplace(value, ATTR_WHITESPACE, ''))) ; else if (value) {
|
|
19817
|
+
} else if (URI_SAFE_ATTRIBUTES[lcName]) ; else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE$1, ''))) ; else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) ; else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$1, stringReplace(value, ATTR_WHITESPACE$1, ''))) ; else if (value) {
|
|
19547
19818
|
return false;
|
|
19548
19819
|
} else ;
|
|
19549
19820
|
return true;
|
|
19550
19821
|
};
|
|
19822
|
+
/* Names the HTML spec reserves from valid-custom-element-name; these must
|
|
19823
|
+
* never be treated as basic custom elements even when a permissive
|
|
19824
|
+
* CUSTOM_ELEMENT_HANDLING.tagNameCheck is configured. */
|
|
19825
|
+
const RESERVED_CUSTOM_ELEMENT_NAMES = addToSet({}, ['annotation-xml', 'color-profile', 'font-face', 'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri', 'missing-glyph']);
|
|
19551
19826
|
/**
|
|
19552
19827
|
* _isBasicCustomElement
|
|
19553
19828
|
* checks if at least one dash is included in tagName, and it's not the first char
|
|
@@ -19557,7 +19832,7 @@
|
|
|
19557
19832
|
* @returns Returns true if the tag name meets the basic criteria for a custom element, otherwise false.
|
|
19558
19833
|
*/
|
|
19559
19834
|
const _isBasicCustomElement = function _isBasicCustomElement(tagName) {
|
|
19560
|
-
return tagName
|
|
19835
|
+
return !RESERVED_CUSTOM_ELEMENT_NAMES[stringToLowerCase(tagName)] && regExpTest(CUSTOM_ELEMENT$1, tagName);
|
|
19561
19836
|
};
|
|
19562
19837
|
/**
|
|
19563
19838
|
* _sanitizeAttributes
|
|
@@ -19572,9 +19847,7 @@
|
|
|
19572
19847
|
const _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
|
|
19573
19848
|
/* Execute a hook if present */
|
|
19574
19849
|
_executeHooks(hooks.beforeSanitizeAttributes, currentNode, null);
|
|
19575
|
-
const
|
|
19576
|
-
attributes
|
|
19577
|
-
} = currentNode;
|
|
19850
|
+
const attributes = currentNode.attributes;
|
|
19578
19851
|
/* Check if we have attributes; if not we might have a text node */
|
|
19579
19852
|
if (!attributes || _isClobbered(currentNode)) {
|
|
19580
19853
|
return;
|
|
@@ -19590,11 +19863,9 @@
|
|
|
19590
19863
|
/* Go backwards over all attributes; safely remove bad ones */
|
|
19591
19864
|
while (l--) {
|
|
19592
19865
|
const attr = attributes[l];
|
|
19593
|
-
const
|
|
19594
|
-
|
|
19595
|
-
|
|
19596
|
-
value: attrValue
|
|
19597
|
-
} = attr;
|
|
19866
|
+
const name = attr.name,
|
|
19867
|
+
namespaceURI = attr.namespaceURI,
|
|
19868
|
+
attrValue = attr.value;
|
|
19598
19869
|
const lcName = transformCaseFunc(name);
|
|
19599
19870
|
const initValue = attrValue;
|
|
19600
19871
|
let value = name === 'value' ? initValue : stringTrim(initValue);
|
|
@@ -19608,12 +19879,14 @@
|
|
|
19608
19879
|
/* Full DOM Clobbering protection via namespace isolation,
|
|
19609
19880
|
* Prefix id and name attributes with `user-content-`
|
|
19610
19881
|
*/
|
|
19611
|
-
if (SANITIZE_NAMED_PROPS && (lcName === 'id' || lcName === 'name')) {
|
|
19882
|
+
if (SANITIZE_NAMED_PROPS && (lcName === 'id' || lcName === 'name') && stringIndexOf(value, SANITIZE_NAMED_PROPS_PREFIX) !== 0) {
|
|
19612
19883
|
// Remove the attribute with this value
|
|
19613
19884
|
_removeAttribute(name, currentNode);
|
|
19614
19885
|
// Prefix the value and later re-create the attribute with the sanitized value
|
|
19615
19886
|
value = SANITIZE_NAMED_PROPS_PREFIX + value;
|
|
19616
19887
|
}
|
|
19888
|
+
// Else: already prefixed, leave the attribute alone — the prefix is
|
|
19889
|
+
// itself the clobbering protection, and re-applying it is incorrect.
|
|
19617
19890
|
/* Work around a security issue with comments inside attributes */
|
|
19618
19891
|
if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|script|title|xmp|textarea|noscript|iframe|noembed|noframes)/i, value)) {
|
|
19619
19892
|
_removeAttribute(name, currentNode);
|
|
@@ -19640,7 +19913,7 @@
|
|
|
19640
19913
|
}
|
|
19641
19914
|
/* Sanitize attribute content to be template-safe */
|
|
19642
19915
|
if (SAFE_FOR_TEMPLATES) {
|
|
19643
|
-
arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
|
|
19916
|
+
arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], expr => {
|
|
19644
19917
|
value = stringReplace(value, expr, ' ');
|
|
19645
19918
|
});
|
|
19646
19919
|
}
|
|
@@ -19694,7 +19967,7 @@
|
|
|
19694
19967
|
*
|
|
19695
19968
|
* @param fragment to iterate over recursively
|
|
19696
19969
|
*/
|
|
19697
|
-
const
|
|
19970
|
+
const _sanitizeShadowDOM2 = function _sanitizeShadowDOM(fragment) {
|
|
19698
19971
|
let shadowNode = null;
|
|
19699
19972
|
const shadowIterator = _createNodeIterator(fragment);
|
|
19700
19973
|
/* Execute a hook if present */
|
|
@@ -19708,12 +19981,55 @@
|
|
|
19708
19981
|
_sanitizeAttributes(shadowNode);
|
|
19709
19982
|
/* Deep shadow DOM detected */
|
|
19710
19983
|
if (shadowNode.content instanceof DocumentFragment) {
|
|
19711
|
-
|
|
19984
|
+
_sanitizeShadowDOM2(shadowNode.content);
|
|
19712
19985
|
}
|
|
19713
19986
|
}
|
|
19714
19987
|
/* Execute a hook if present */
|
|
19715
19988
|
_executeHooks(hooks.afterSanitizeShadowDOM, fragment, null);
|
|
19716
19989
|
};
|
|
19990
|
+
/**
|
|
19991
|
+
* _sanitizeAttachedShadowRoots
|
|
19992
|
+
*
|
|
19993
|
+
* Walks `root` and feeds every attached shadow root we encounter into
|
|
19994
|
+
* the existing _sanitizeShadowDOM pipeline. The default node iterator
|
|
19995
|
+
* does not descend into shadow trees, so nodes inside an attached
|
|
19996
|
+
* shadow root would otherwise be skipped entirely.
|
|
19997
|
+
*
|
|
19998
|
+
* Two real input paths put attached shadow roots in front of us:
|
|
19999
|
+
* 1. IN_PLACE on a DOM node that already has shadow roots attached.
|
|
20000
|
+
* 2. DOM-node input where importNode(dirty, true) deep-clones the
|
|
20001
|
+
* shadow root because it was created with `clonable: true`.
|
|
20002
|
+
*
|
|
20003
|
+
* This pass runs once, up front, so the main iteration loop (and the
|
|
20004
|
+
* existing _sanitizeShadowDOM template-content recursion) stay
|
|
20005
|
+
* untouched — string-input paths are not affected.
|
|
20006
|
+
*
|
|
20007
|
+
* @param root the subtree root to walk for attached shadow roots
|
|
20008
|
+
*/
|
|
20009
|
+
const _sanitizeAttachedShadowRoots2 = function _sanitizeAttachedShadowRoots(root) {
|
|
20010
|
+
if (root.nodeType === NODE_TYPE.element && root.shadowRoot instanceof DocumentFragment) {
|
|
20011
|
+
const sr = root.shadowRoot;
|
|
20012
|
+
// Recurse first so that nested shadow roots are reached even if
|
|
20013
|
+
// _sanitizeShadowDOM removes hosts at this level.
|
|
20014
|
+
_sanitizeAttachedShadowRoots2(sr);
|
|
20015
|
+
_sanitizeShadowDOM2(sr);
|
|
20016
|
+
}
|
|
20017
|
+
// Snapshot children before recursing. Sanitization of one subtree
|
|
20018
|
+
// (e.g. via an uponSanitizeShadowNode hook) may detach siblings,
|
|
20019
|
+
// and naive nextSibling traversal would silently skip the rest of
|
|
20020
|
+
// the list once a node is detached.
|
|
20021
|
+
const childNodes = root.childNodes;
|
|
20022
|
+
if (!childNodes) {
|
|
20023
|
+
return;
|
|
20024
|
+
}
|
|
20025
|
+
const snapshot = [];
|
|
20026
|
+
arrayForEach(childNodes, child => {
|
|
20027
|
+
arrayPush(snapshot, child);
|
|
20028
|
+
});
|
|
20029
|
+
for (const child of snapshot) {
|
|
20030
|
+
_sanitizeAttachedShadowRoots2(child);
|
|
20031
|
+
}
|
|
20032
|
+
};
|
|
19717
20033
|
// eslint-disable-next-line complexity
|
|
19718
20034
|
DOMPurify.sanitize = function (dirty) {
|
|
19719
20035
|
let cfg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
@@ -19730,13 +20046,9 @@
|
|
|
19730
20046
|
}
|
|
19731
20047
|
/* Stringify, in case dirty is an object */
|
|
19732
20048
|
if (typeof dirty !== 'string' && !_isNode(dirty)) {
|
|
19733
|
-
|
|
19734
|
-
|
|
19735
|
-
|
|
19736
|
-
throw typeErrorCreate('dirty is not a string, aborting');
|
|
19737
|
-
}
|
|
19738
|
-
} else {
|
|
19739
|
-
throw typeErrorCreate('toString is not a function');
|
|
20049
|
+
dirty = stringifyValue(dirty);
|
|
20050
|
+
if (typeof dirty !== 'string') {
|
|
20051
|
+
throw typeErrorCreate('dirty is not a string, aborting');
|
|
19740
20052
|
}
|
|
19741
20053
|
}
|
|
19742
20054
|
/* Return dirty HTML if DOMPurify cannot run */
|
|
@@ -19755,13 +20067,17 @@
|
|
|
19755
20067
|
}
|
|
19756
20068
|
if (IN_PLACE) {
|
|
19757
20069
|
/* Do some early pre-sanitization to avoid unsafe root nodes */
|
|
19758
|
-
|
|
19759
|
-
|
|
20070
|
+
const nn = dirty.nodeName;
|
|
20071
|
+
if (typeof nn === 'string') {
|
|
20072
|
+
const tagName = transformCaseFunc(nn);
|
|
19760
20073
|
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
|
|
19761
20074
|
throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');
|
|
19762
20075
|
}
|
|
19763
20076
|
}
|
|
19764
|
-
|
|
20077
|
+
/* Sanitize attached shadow roots before the main iterator runs.
|
|
20078
|
+
The iterator does not descend into shadow trees. */
|
|
20079
|
+
_sanitizeAttachedShadowRoots2(dirty);
|
|
20080
|
+
} else if (_isNode(dirty)) {
|
|
19765
20081
|
/* If dirty is a DOM element, append to an empty document to avoid
|
|
19766
20082
|
elements being stripped by the parser */
|
|
19767
20083
|
body = _initDocument('<!---->');
|
|
@@ -19775,6 +20091,10 @@
|
|
|
19775
20091
|
// eslint-disable-next-line unicorn/prefer-dom-node-append
|
|
19776
20092
|
body.appendChild(importedNode);
|
|
19777
20093
|
}
|
|
20094
|
+
/* Clonable shadow roots are deep-cloned by importNode(); sanitize
|
|
20095
|
+
them before the main iterator runs, since the iterator does not
|
|
20096
|
+
descend into shadow trees. */
|
|
20097
|
+
_sanitizeAttachedShadowRoots2(importedNode);
|
|
19778
20098
|
} else {
|
|
19779
20099
|
/* Exit directly if we have nothing to do */
|
|
19780
20100
|
if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT &&
|
|
@@ -19803,15 +20123,21 @@
|
|
|
19803
20123
|
_sanitizeAttributes(currentNode);
|
|
19804
20124
|
/* Shadow DOM detected, sanitize it */
|
|
19805
20125
|
if (currentNode.content instanceof DocumentFragment) {
|
|
19806
|
-
|
|
20126
|
+
_sanitizeShadowDOM2(currentNode.content);
|
|
19807
20127
|
}
|
|
19808
20128
|
}
|
|
19809
20129
|
/* If we sanitized `dirty` in-place, return it. */
|
|
19810
20130
|
if (IN_PLACE) {
|
|
20131
|
+
if (SAFE_FOR_TEMPLATES) {
|
|
20132
|
+
_scrubTemplateExpressions(dirty);
|
|
20133
|
+
}
|
|
19811
20134
|
return dirty;
|
|
19812
20135
|
}
|
|
19813
20136
|
/* Return sanitized string or DOM */
|
|
19814
20137
|
if (RETURN_DOM) {
|
|
20138
|
+
if (SAFE_FOR_TEMPLATES) {
|
|
20139
|
+
_scrubTemplateExpressions(body);
|
|
20140
|
+
}
|
|
19815
20141
|
if (RETURN_DOM_FRAGMENT) {
|
|
19816
20142
|
returnNode = createDocumentFragment.call(body.ownerDocument);
|
|
19817
20143
|
while (body.firstChild) {
|
|
@@ -19840,7 +20166,7 @@
|
|
|
19840
20166
|
}
|
|
19841
20167
|
/* Sanitize final string template-safe */
|
|
19842
20168
|
if (SAFE_FOR_TEMPLATES) {
|
|
19843
|
-
arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
|
|
20169
|
+
arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], expr => {
|
|
19844
20170
|
serializedHTML = stringReplace(serializedHTML, expr, ' ');
|
|
19845
20171
|
});
|
|
19846
20172
|
}
|
|
@@ -21878,7 +22204,7 @@
|
|
|
21878
22204
|
append(SugarElement.fromDom(pre1), [
|
|
21879
22205
|
SugarElement.fromTag('br', doc),
|
|
21880
22206
|
SugarElement.fromTag('br', doc),
|
|
21881
|
-
...children$
|
|
22207
|
+
...children$2(sPre2)
|
|
21882
22208
|
]);
|
|
21883
22209
|
};
|
|
21884
22210
|
if (!rng.collapsed) {
|
|
@@ -22025,10 +22351,12 @@
|
|
|
22025
22351
|
const wrapName = format.inline || format.block;
|
|
22026
22352
|
const wrapElm = createWrapElement(wrapName);
|
|
22027
22353
|
const isMatchingWrappingBlock = (node) => isWrappingBlockFormat(format) && matchNode$1(ed, node, name, vars);
|
|
22354
|
+
const canRenameChildBlocks = (node) => forall(node.childNodes, (child) => !isTextBlock$2(ed.schema, child) || isValid(ed, wrapName, child.nodeName.toLowerCase()));
|
|
22028
22355
|
const canRenameBlock = (node, parentName, isEditableDescendant) => {
|
|
22029
22356
|
const isValidBlockFormatForNode = isNonWrappingBlockFormat(format) &&
|
|
22030
22357
|
isTextBlock$2(ed.schema, node) &&
|
|
22031
|
-
isValid(ed, parentName, wrapName)
|
|
22358
|
+
isValid(ed, parentName, wrapName) &&
|
|
22359
|
+
canRenameChildBlocks(node);
|
|
22032
22360
|
return isEditableDescendant && isValidBlockFormatForNode;
|
|
22033
22361
|
};
|
|
22034
22362
|
const canWrapNode = (node, parentName, isEditableDescendant, isWrappableNoneditableElm) => {
|
|
@@ -22185,6 +22513,19 @@
|
|
|
22185
22513
|
// node variable is used by other functions above in the same scope so need to set it here
|
|
22186
22514
|
node = targetNode;
|
|
22187
22515
|
applyNodeStyle(formatList, node);
|
|
22516
|
+
if (isBlockFormat(format) && !dom.isBlock(targetNode)) {
|
|
22517
|
+
const parentBlock = dom.getParent(targetNode, dom.isBlock);
|
|
22518
|
+
if (dom.isEditable(parentBlock)) {
|
|
22519
|
+
const wrapperElementName = format.block;
|
|
22520
|
+
if (parentBlock.nodeName.toLowerCase() === wrapperElementName.toLowerCase()) {
|
|
22521
|
+
setElementFormat(ed, parentBlock, format, vars, node);
|
|
22522
|
+
}
|
|
22523
|
+
else if (!isWrappingBlockFormat(format)) {
|
|
22524
|
+
const elm = dom.rename(parentBlock, wrapperElementName);
|
|
22525
|
+
setElementFormat(ed, elm, format, vars, node);
|
|
22526
|
+
}
|
|
22527
|
+
}
|
|
22528
|
+
}
|
|
22188
22529
|
fireFormatApply(ed, name, node, vars);
|
|
22189
22530
|
return;
|
|
22190
22531
|
}
|
|
@@ -25974,7 +26315,7 @@
|
|
|
25974
26315
|
preview: 'font-family font-size'
|
|
25975
26316
|
},
|
|
25976
26317
|
{
|
|
25977
|
-
selector: '.mce-preview-object,[data-ephox-embed-iri]',
|
|
26318
|
+
selector: '.mce-preview-object,[data-ephox-embed-iri],.tiny-pageembed',
|
|
25978
26319
|
ceFalseOverride: true,
|
|
25979
26320
|
styles: {
|
|
25980
26321
|
float: 'left'
|
|
@@ -26026,7 +26367,7 @@
|
|
|
26026
26367
|
preview: 'font-family font-size'
|
|
26027
26368
|
},
|
|
26028
26369
|
{
|
|
26029
|
-
selector: '.mce-preview-object',
|
|
26370
|
+
selector: '.mce-preview-object,.tiny-pageembed',
|
|
26030
26371
|
ceFalseOverride: true,
|
|
26031
26372
|
styles: {
|
|
26032
26373
|
display: 'table', // Needs to be `table` to properly render while editing
|
|
@@ -26090,7 +26431,7 @@
|
|
|
26090
26431
|
preview: 'font-family font-size'
|
|
26091
26432
|
},
|
|
26092
26433
|
{
|
|
26093
|
-
selector: '.mce-preview-object,[data-ephox-embed-iri]',
|
|
26434
|
+
selector: '.mce-preview-object,[data-ephox-embed-iri],.tiny-pageembed',
|
|
26094
26435
|
ceFalseOverride: true,
|
|
26095
26436
|
styles: {
|
|
26096
26437
|
float: 'right'
|
|
@@ -26777,8 +27118,8 @@
|
|
|
26777
27118
|
isFirstTypedCharacter.set(true);
|
|
26778
27119
|
return;
|
|
26779
27120
|
}
|
|
26780
|
-
const
|
|
26781
|
-
if (
|
|
27121
|
+
const hasMetaOrCtrlModifier = Env.os.isMacOS() ? e.metaKey : e.ctrlKey && !e.altKey;
|
|
27122
|
+
if (hasMetaOrCtrlModifier && (e.key === 'Backspace' || e.key === 'Delete')) {
|
|
26782
27123
|
undoManager.beforeChange();
|
|
26783
27124
|
}
|
|
26784
27125
|
});
|
|
@@ -27343,7 +27684,7 @@
|
|
|
27343
27684
|
const isIndented = (entry) => entry.depth > 0;
|
|
27344
27685
|
const isSelected = (entry) => entry.isSelected;
|
|
27345
27686
|
const cloneItemContent = (li) => {
|
|
27346
|
-
const children = children$
|
|
27687
|
+
const children = children$2(li);
|
|
27347
27688
|
const content = hasLastChildList(li) ? children.slice(0, -1) : children;
|
|
27348
27689
|
return map$3(content, deep);
|
|
27349
27690
|
};
|
|
@@ -27541,7 +27882,7 @@
|
|
|
27541
27882
|
return currentItemEntry.toArray().concat(childListEntries);
|
|
27542
27883
|
};
|
|
27543
27884
|
const parseItem = (depth, itemSelection, selectionState, item) => firstChild(item).filter(isList).fold(() => parseSingleItem(depth, itemSelection, selectionState, item), (list) => {
|
|
27544
|
-
const parsedSiblings = foldl(children$
|
|
27885
|
+
const parsedSiblings = foldl(children$2(item), (acc, liChild, i) => {
|
|
27545
27886
|
if (i === 0) {
|
|
27546
27887
|
return acc;
|
|
27547
27888
|
}
|
|
@@ -27564,7 +27905,7 @@
|
|
|
27564
27905
|
}, []);
|
|
27565
27906
|
return parseList(depth, itemSelection, selectionState, list).concat(parsedSiblings);
|
|
27566
27907
|
});
|
|
27567
|
-
const parseList = (depth, itemSelection, selectionState, list) => bind$3(children$
|
|
27908
|
+
const parseList = (depth, itemSelection, selectionState, list) => bind$3(children$2(list), (element) => {
|
|
27568
27909
|
const parser = isList(element) ? parseList : parseItem;
|
|
27569
27910
|
const newDepth = depth + 1;
|
|
27570
27911
|
return parser(newDepth, itemSelection, selectionState, element);
|
|
@@ -28227,7 +28568,7 @@
|
|
|
28227
28568
|
const rng = normalizeRange(editor.selection.getRng());
|
|
28228
28569
|
const nextCaretContainer = findNextCaretContainer(editor, rng, isForward, root);
|
|
28229
28570
|
const otherLi = dom.getParent(nextCaretContainer, 'LI', root);
|
|
28230
|
-
if (nextCaretContainer && otherLi) {
|
|
28571
|
+
if (nextCaretContainer && otherLi && (isForward || !dom.isChildOf(nextCaretContainer, block))) {
|
|
28231
28572
|
const findValidElement = (element) => contains$2(['td', 'th', 'caption'], name(element));
|
|
28232
28573
|
const findRoot = (node) => node.dom === root;
|
|
28233
28574
|
const otherLiCell = closest$5(SugarElement.fromDom(otherLi), findValidElement, findRoot);
|
|
@@ -28325,7 +28666,7 @@
|
|
|
28325
28666
|
const read$1 = (schema, rootNode, forward, rng) => rng.collapsed ? readFromRange(schema, rootNode, forward, rng) : Optional.none();
|
|
28326
28667
|
|
|
28327
28668
|
const getChildrenUntilBlockBoundary = (block, schema) => {
|
|
28328
|
-
const children = children$
|
|
28669
|
+
const children = children$2(block);
|
|
28329
28670
|
return findIndex$2(children, (el) => schema.isBlock(name(el))).fold(constant(children), (index) => children.slice(0, index));
|
|
28330
28671
|
};
|
|
28331
28672
|
const extractChildren = (block, schema) => {
|
|
@@ -29720,7 +30061,11 @@
|
|
|
29720
30061
|
const canIndent = (editor) => !editor.mode.isReadOnly() && canIndent$1(editor);
|
|
29721
30062
|
const isListComponent = (el) => isList$1(el) || isListItem$2(el);
|
|
29722
30063
|
const parentIsListComponent = (el) => parent(el).exists(isListComponent);
|
|
29723
|
-
const getBlocksToIndent = (editor) =>
|
|
30064
|
+
const getBlocksToIndent = (editor) => {
|
|
30065
|
+
const selectedCells = getCellsFromEditor(editor);
|
|
30066
|
+
return selectedCells.length === 0 ?
|
|
30067
|
+
filter$5(fromDom$1(editor.selection.getSelectedBlocks()), (el) => !isListComponent(el) && !parentIsListComponent(el) && isEditable(el)) : selectedCells;
|
|
30068
|
+
};
|
|
29724
30069
|
const handle = (editor, command) => {
|
|
29725
30070
|
if (editor.mode.isReadOnly()) {
|
|
29726
30071
|
return;
|
|
@@ -30395,7 +30740,7 @@
|
|
|
30395
30740
|
return filterFirstLayer(scope, selector, always);
|
|
30396
30741
|
};
|
|
30397
30742
|
const filterFirstLayer = (scope, selector, predicate) => {
|
|
30398
|
-
return bind$3(children$
|
|
30743
|
+
return bind$3(children$2(scope), (x) => {
|
|
30399
30744
|
if (is$2(x, selector)) {
|
|
30400
30745
|
return predicate(x) ? [x] : [];
|
|
30401
30746
|
}
|
|
@@ -30605,7 +30950,7 @@
|
|
|
30605
30950
|
nextSibling: nextSibling
|
|
30606
30951
|
}),
|
|
30607
30952
|
property: constant({
|
|
30608
|
-
children: children$
|
|
30953
|
+
children: children$2,
|
|
30609
30954
|
name: name,
|
|
30610
30955
|
parent: parent,
|
|
30611
30956
|
document,
|
|
@@ -33712,15 +34057,20 @@
|
|
|
33712
34057
|
blobCache.add(blobInfo);
|
|
33713
34058
|
return blobInfo;
|
|
33714
34059
|
};
|
|
33715
|
-
const pasteImage = (editor, imageItem) => {
|
|
33716
|
-
parseDataUri(imageItem.uri).
|
|
34060
|
+
const pasteImage = async (editor, imageItem) => {
|
|
34061
|
+
return parseDataUri(imageItem.uri).fold(() => Promise.resolve(), ({ data, type, base64Encoded }) => {
|
|
33717
34062
|
const base64 = base64Encoded ? data : btoa(data);
|
|
33718
34063
|
const file = imageItem.file;
|
|
33719
34064
|
// TODO: Move the bulk of the cache logic to EditorUpload
|
|
33720
34065
|
const blobCache = editor.editorUpload.blobCache;
|
|
33721
34066
|
const existingBlobInfo = blobCache.getByData(base64, type);
|
|
33722
34067
|
const blobInfo = existingBlobInfo ?? createBlobInfo(editor, blobCache, file, base64);
|
|
33723
|
-
|
|
34068
|
+
const imgUrl = blobInfo.blobUri();
|
|
34069
|
+
return getImageSize(imgUrl).then(({ width, height }) => {
|
|
34070
|
+
pasteHtml(editor, `<img width="${width}" height="${height}" src="${imgUrl}">`, false, true);
|
|
34071
|
+
}).catch(() => {
|
|
34072
|
+
pasteHtml(editor, `<img src="${imgUrl}">`, false, true);
|
|
34073
|
+
});
|
|
33724
34074
|
});
|
|
33725
34075
|
};
|
|
33726
34076
|
const isClipboardEvent = (event) => event.type === 'paste';
|
|
@@ -33751,13 +34101,13 @@
|
|
|
33751
34101
|
if (images.length > 0) {
|
|
33752
34102
|
e.preventDefault();
|
|
33753
34103
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
33754
|
-
readFilesAsDataUris(images).then((fileResults) => {
|
|
34104
|
+
readFilesAsDataUris(images).then(async (fileResults) => {
|
|
33755
34105
|
if (rng) {
|
|
33756
34106
|
editor.selection.setRng(rng);
|
|
33757
34107
|
}
|
|
33758
|
-
|
|
33759
|
-
pasteImage(editor, result);
|
|
33760
|
-
}
|
|
34108
|
+
for (const result of fileResults) {
|
|
34109
|
+
await pasteImage(editor, result);
|
|
34110
|
+
}
|
|
33761
34111
|
});
|
|
33762
34112
|
return true;
|
|
33763
34113
|
}
|
|
@@ -35905,6 +36255,7 @@
|
|
|
35905
36255
|
const browser = Env.browser;
|
|
35906
36256
|
const isGecko = browser.isFirefox();
|
|
35907
36257
|
const isWebKit = browser.isChromium() || browser.isSafari();
|
|
36258
|
+
const isSafari = browser.isSafari();
|
|
35908
36259
|
const isiOS = Env.deviceType.isiPhone() || Env.deviceType.isiPad();
|
|
35909
36260
|
const isMac = Env.os.isMacOS() || Env.os.isiOS();
|
|
35910
36261
|
/**
|
|
@@ -36511,6 +36862,45 @@
|
|
|
36511
36862
|
}
|
|
36512
36863
|
});
|
|
36513
36864
|
};
|
|
36865
|
+
/**
|
|
36866
|
+
* this is needed to manage the difference between
|
|
36867
|
+
* ```
|
|
36868
|
+
* <li><span class="fake">a</span><div>b</div></li>
|
|
36869
|
+
* ```
|
|
36870
|
+
* and
|
|
36871
|
+
* ```
|
|
36872
|
+
* <li><span class="fake">a</span> <div>b</div></li>
|
|
36873
|
+
* ```
|
|
36874
|
+
* since if the indentation of the HTML has a new line it creates a fake child in the `li` that is an empty text
|
|
36875
|
+
* it's check it trying to get the rects and if it can't it means that it's the false unwanted new line
|
|
36876
|
+
**/
|
|
36877
|
+
const isValidSibling = (el) => getClientRects([el.dom]).length > 0;
|
|
36878
|
+
const firstBlockChildOrNewLine = (target) => child(target, (child) => isBr$6(child) || isElement$8(child) && get$8(child, 'display') === 'block');
|
|
36879
|
+
const clickAfterEl = (clientX, clientY, rect) => clientX >= rect.right && clientY >= rect.top && clientY <= rect.bottom;
|
|
36880
|
+
/**
|
|
36881
|
+
* In Chrome in a `LI` that contains a block element and where the first child is an inline element
|
|
36882
|
+
* clicking on the right side of the first child the carret goes at the start of the element instead that in the end of it
|
|
36883
|
+
* issue: https://issues.chromium.org/issues/40767343
|
|
36884
|
+
**/
|
|
36885
|
+
const fixInLISelection = () => {
|
|
36886
|
+
editor.on('mousedown', (e) => {
|
|
36887
|
+
const target = SugarElement.fromDom(e.target);
|
|
36888
|
+
if (isListItem$2(target)) {
|
|
36889
|
+
firstBlockChildOrNewLine(target).each((firstBlock) => {
|
|
36890
|
+
const prevSiblings$1 = prevSiblings(firstBlock);
|
|
36891
|
+
findLast(prevSiblings$1, isValidSibling).each((lastInlineBeforeBlock) => {
|
|
36892
|
+
if (get$c(getClientRects([lastInlineBeforeBlock.dom]), 0).exists((rect) => clickAfterEl(e.clientX, e.clientY, rect))) {
|
|
36893
|
+
prevPosition(target.dom, CaretPosition(firstBlock.dom, 0)).each((pos) => {
|
|
36894
|
+
e.preventDefault();
|
|
36895
|
+
editor.focus();
|
|
36896
|
+
editor.selection.setRng(pos.toRange());
|
|
36897
|
+
});
|
|
36898
|
+
}
|
|
36899
|
+
});
|
|
36900
|
+
});
|
|
36901
|
+
}
|
|
36902
|
+
});
|
|
36903
|
+
};
|
|
36514
36904
|
// No-op since Mozilla seems to have fixed the caret repaint issues
|
|
36515
36905
|
const refreshContentEditable = noop;
|
|
36516
36906
|
const isHidden = () => {
|
|
@@ -36557,6 +36947,9 @@
|
|
|
36557
36947
|
blockFormSubmitInsideEditor();
|
|
36558
36948
|
disableBackspaceIntoATable();
|
|
36559
36949
|
removeAppleInterchangeBrs();
|
|
36950
|
+
if (!isSafari) {
|
|
36951
|
+
fixInLISelection();
|
|
36952
|
+
}
|
|
36560
36953
|
// touchClickEvent();
|
|
36561
36954
|
// iOS
|
|
36562
36955
|
if (isiOS) {
|
|
@@ -40653,6 +41046,21 @@
|
|
|
40653
41046
|
hasEditableRoot() {
|
|
40654
41047
|
return hasEditableRoot(this);
|
|
40655
41048
|
}
|
|
41049
|
+
/**
|
|
41050
|
+
* Announces a message to screen readers via the page-wide aria-live region, without shifting focus.
|
|
41051
|
+
* Delegates to {@link tinymce.dom.AriaAnnouncer#announce}.
|
|
41052
|
+
*
|
|
41053
|
+
* @method announce
|
|
41054
|
+
* @param {String} message The message to announce to screen readers.
|
|
41055
|
+
* @param {Object} options Optional settings.
|
|
41056
|
+
* @param {Boolean} options.assertive If true, uses aria-live="assertive" (role="alert") instead of polite.
|
|
41057
|
+
* @example
|
|
41058
|
+
* tinymce.activeEditor.announce('Bold on');
|
|
41059
|
+
* tinymce.activeEditor.announce('Error occurred', { assertive: true });
|
|
41060
|
+
*/
|
|
41061
|
+
announce(message, options) {
|
|
41062
|
+
AriaAnnouncer.announce(message, options);
|
|
41063
|
+
}
|
|
40656
41064
|
/**
|
|
40657
41065
|
* Removes the editor from the dom and tinymce collection.
|
|
40658
41066
|
*
|
|
@@ -40777,14 +41185,14 @@
|
|
|
40777
41185
|
* @property minorVersion
|
|
40778
41186
|
* @type String
|
|
40779
41187
|
*/
|
|
40780
|
-
minorVersion: '
|
|
41188
|
+
minorVersion: '7.0',
|
|
40781
41189
|
/**
|
|
40782
41190
|
* Release date of TinyMCE build.
|
|
40783
41191
|
*
|
|
40784
41192
|
* @property releaseDate
|
|
40785
41193
|
* @type String
|
|
40786
41194
|
*/
|
|
40787
|
-
releaseDate: '2026-
|
|
41195
|
+
releaseDate: '2026-07-01',
|
|
40788
41196
|
/**
|
|
40789
41197
|
* Collection of language pack data.
|
|
40790
41198
|
*
|
|
@@ -41642,6 +42050,7 @@
|
|
|
41642
42050
|
ControlSelection,
|
|
41643
42051
|
BookmarkManager,
|
|
41644
42052
|
Selection: EditorSelection,
|
|
42053
|
+
AriaAnnouncer,
|
|
41645
42054
|
Event: EventUtils.Event
|
|
41646
42055
|
},
|
|
41647
42056
|
html: {
|