tinymce-rails 8.5.1 → 8.6.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.
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* TinyMCE version 8.
|
|
2
|
+
* TinyMCE version 8.6.0 (2026-06-03)
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
(function () {
|
|
@@ -18492,24 +18492,65 @@
|
|
|
18492
18492
|
}
|
|
18493
18493
|
};
|
|
18494
18494
|
|
|
18495
|
-
/*! @license DOMPurify 3.
|
|
18496
|
-
|
|
18497
|
-
|
|
18498
|
-
|
|
18499
|
-
|
|
18500
|
-
|
|
18501
|
-
|
|
18502
|
-
|
|
18503
|
-
|
|
18504
|
-
|
|
18505
|
-
|
|
18506
|
-
|
|
18507
|
-
|
|
18508
|
-
|
|
18509
|
-
|
|
18510
|
-
|
|
18511
|
-
|
|
18512
|
-
|
|
18495
|
+
/*! @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 */
|
|
18496
|
+
|
|
18497
|
+
function _arrayLikeToArray(r, a) {
|
|
18498
|
+
(null == a || a > r.length) && (a = r.length);
|
|
18499
|
+
for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
|
|
18500
|
+
return n;
|
|
18501
|
+
}
|
|
18502
|
+
function _arrayWithHoles(r) {
|
|
18503
|
+
if (Array.isArray(r)) return r;
|
|
18504
|
+
}
|
|
18505
|
+
function _iterableToArrayLimit(r, l) {
|
|
18506
|
+
var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
|
|
18507
|
+
if (null != t) {
|
|
18508
|
+
var e,
|
|
18509
|
+
n,
|
|
18510
|
+
i,
|
|
18511
|
+
u,
|
|
18512
|
+
a = [],
|
|
18513
|
+
f = true,
|
|
18514
|
+
o = false;
|
|
18515
|
+
try {
|
|
18516
|
+
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);
|
|
18517
|
+
} catch (r) {
|
|
18518
|
+
o = true, n = r;
|
|
18519
|
+
} finally {
|
|
18520
|
+
try {
|
|
18521
|
+
if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
|
|
18522
|
+
} finally {
|
|
18523
|
+
if (o) throw n;
|
|
18524
|
+
}
|
|
18525
|
+
}
|
|
18526
|
+
return a;
|
|
18527
|
+
}
|
|
18528
|
+
}
|
|
18529
|
+
function _nonIterableRest() {
|
|
18530
|
+
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
18531
|
+
}
|
|
18532
|
+
function _slicedToArray(r, e) {
|
|
18533
|
+
return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
|
|
18534
|
+
}
|
|
18535
|
+
function _unsupportedIterableToArray(r, a) {
|
|
18536
|
+
if (r) {
|
|
18537
|
+
if ("string" == typeof r) return _arrayLikeToArray(r, a);
|
|
18538
|
+
var t = {}.toString.call(r).slice(8, -1);
|
|
18539
|
+
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;
|
|
18540
|
+
}
|
|
18541
|
+
}
|
|
18542
|
+
|
|
18543
|
+
const entries = Object.entries,
|
|
18544
|
+
setPrototypeOf = Object.setPrototypeOf,
|
|
18545
|
+
isFrozen = Object.isFrozen,
|
|
18546
|
+
getPrototypeOf = Object.getPrototypeOf,
|
|
18547
|
+
getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
|
|
18548
|
+
let freeze = Object.freeze,
|
|
18549
|
+
seal = Object.seal,
|
|
18550
|
+
create$7 = Object.create; // eslint-disable-line import/no-mutable-exports
|
|
18551
|
+
let _ref = typeof Reflect !== 'undefined' && Reflect,
|
|
18552
|
+
apply = _ref.apply,
|
|
18553
|
+
construct = _ref.construct;
|
|
18513
18554
|
if (!freeze) {
|
|
18514
18555
|
freeze = function freeze(x) {
|
|
18515
18556
|
return x;
|
|
@@ -18541,13 +18582,19 @@
|
|
|
18541
18582
|
const arrayPop = unapply(Array.prototype.pop);
|
|
18542
18583
|
const arrayPush = unapply(Array.prototype.push);
|
|
18543
18584
|
const arraySplice = unapply(Array.prototype.splice);
|
|
18585
|
+
const arrayIsArray = Array.isArray;
|
|
18544
18586
|
const stringToLowerCase = unapply(String.prototype.toLowerCase);
|
|
18545
18587
|
const stringToString = unapply(String.prototype.toString);
|
|
18546
18588
|
const stringMatch = unapply(String.prototype.match);
|
|
18547
18589
|
const stringReplace = unapply(String.prototype.replace);
|
|
18548
18590
|
const stringIndexOf = unapply(String.prototype.indexOf);
|
|
18549
18591
|
const stringTrim = unapply(String.prototype.trim);
|
|
18592
|
+
const numberToString = unapply(Number.prototype.toString);
|
|
18593
|
+
const booleanToString = unapply(Boolean.prototype.toString);
|
|
18594
|
+
const bigintToString = typeof BigInt === 'undefined' ? null : unapply(BigInt.prototype.toString);
|
|
18595
|
+
const symbolToString = typeof Symbol === 'undefined' ? null : unapply(Symbol.prototype.toString);
|
|
18550
18596
|
const objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);
|
|
18597
|
+
const objectToString = unapply(Object.prototype.toString);
|
|
18551
18598
|
const regExpTest = unapply(RegExp.prototype.test);
|
|
18552
18599
|
const typeErrorCreate = unconstruct(TypeError);
|
|
18553
18600
|
/**
|
|
@@ -18597,6 +18644,9 @@
|
|
|
18597
18644
|
// Prevent prototype setters from intercepting set as a this value.
|
|
18598
18645
|
setPrototypeOf(set, null);
|
|
18599
18646
|
}
|
|
18647
|
+
if (!arrayIsArray(array)) {
|
|
18648
|
+
return set;
|
|
18649
|
+
}
|
|
18600
18650
|
let l = array.length;
|
|
18601
18651
|
while (l--) {
|
|
18602
18652
|
let element = array[l];
|
|
@@ -18637,10 +18687,13 @@
|
|
|
18637
18687
|
*/
|
|
18638
18688
|
function clone(object) {
|
|
18639
18689
|
const newObject = create$7(null);
|
|
18640
|
-
for (const
|
|
18690
|
+
for (const _ref2 of entries(object)) {
|
|
18691
|
+
var _ref3 = _slicedToArray(_ref2, 2);
|
|
18692
|
+
const property = _ref3[0];
|
|
18693
|
+
const value = _ref3[1];
|
|
18641
18694
|
const isPropertyExist = objectHasOwnProperty(object, property);
|
|
18642
18695
|
if (isPropertyExist) {
|
|
18643
|
-
if (
|
|
18696
|
+
if (arrayIsArray(value)) {
|
|
18644
18697
|
newObject[property] = cleanArray(value);
|
|
18645
18698
|
} else if (value && typeof value === 'object' && value.constructor === Object) {
|
|
18646
18699
|
newObject[property] = clone(value);
|
|
@@ -18651,6 +18704,58 @@
|
|
|
18651
18704
|
}
|
|
18652
18705
|
return newObject;
|
|
18653
18706
|
}
|
|
18707
|
+
/**
|
|
18708
|
+
* Convert non-node values into strings without depending on direct property access.
|
|
18709
|
+
*
|
|
18710
|
+
* @param value - The value to stringify.
|
|
18711
|
+
* @returns A string representation of the provided value.
|
|
18712
|
+
*/
|
|
18713
|
+
function stringifyValue(value) {
|
|
18714
|
+
switch (typeof value) {
|
|
18715
|
+
case 'string':
|
|
18716
|
+
{
|
|
18717
|
+
return value;
|
|
18718
|
+
}
|
|
18719
|
+
case 'number':
|
|
18720
|
+
{
|
|
18721
|
+
return numberToString(value);
|
|
18722
|
+
}
|
|
18723
|
+
case 'boolean':
|
|
18724
|
+
{
|
|
18725
|
+
return booleanToString(value);
|
|
18726
|
+
}
|
|
18727
|
+
case 'bigint':
|
|
18728
|
+
{
|
|
18729
|
+
return bigintToString ? bigintToString(value) : '0';
|
|
18730
|
+
}
|
|
18731
|
+
case 'symbol':
|
|
18732
|
+
{
|
|
18733
|
+
return symbolToString ? symbolToString(value) : 'Symbol()';
|
|
18734
|
+
}
|
|
18735
|
+
case 'undefined':
|
|
18736
|
+
{
|
|
18737
|
+
return objectToString(value);
|
|
18738
|
+
}
|
|
18739
|
+
case 'function':
|
|
18740
|
+
case 'object':
|
|
18741
|
+
{
|
|
18742
|
+
if (value === null) {
|
|
18743
|
+
return objectToString(value);
|
|
18744
|
+
}
|
|
18745
|
+
const valueAsRecord = value;
|
|
18746
|
+
const valueToString = lookupGetter(valueAsRecord, 'toString');
|
|
18747
|
+
if (typeof valueToString === 'function') {
|
|
18748
|
+
const stringified = valueToString(valueAsRecord);
|
|
18749
|
+
return typeof stringified === 'string' ? stringified : objectToString(stringified);
|
|
18750
|
+
}
|
|
18751
|
+
return objectToString(value);
|
|
18752
|
+
}
|
|
18753
|
+
default:
|
|
18754
|
+
{
|
|
18755
|
+
return objectToString(value);
|
|
18756
|
+
}
|
|
18757
|
+
}
|
|
18758
|
+
}
|
|
18654
18759
|
/**
|
|
18655
18760
|
* This method automatically checks if the prop is function or getter and behaves accordingly.
|
|
18656
18761
|
*
|
|
@@ -18676,6 +18781,14 @@
|
|
|
18676
18781
|
}
|
|
18677
18782
|
return fallbackValue;
|
|
18678
18783
|
}
|
|
18784
|
+
function isRegex(value) {
|
|
18785
|
+
try {
|
|
18786
|
+
regExpTest(value, '');
|
|
18787
|
+
return true;
|
|
18788
|
+
} catch (_unused) {
|
|
18789
|
+
return false;
|
|
18790
|
+
}
|
|
18791
|
+
}
|
|
18679
18792
|
|
|
18680
18793
|
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
18794
|
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 +18804,14 @@
|
|
|
18691
18804
|
const mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);
|
|
18692
18805
|
const text = freeze(['#text']);
|
|
18693
18806
|
|
|
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'
|
|
18807
|
+
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
18808
|
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', '
|
|
18809
|
+
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
18810
|
const xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
|
|
18698
18811
|
|
|
18699
|
-
|
|
18700
|
-
const
|
|
18701
|
-
const
|
|
18702
|
-
const TMPLIT_EXPR = seal(/\$\{[\w\W]*/gm); // eslint-disable-line unicorn/better-regex
|
|
18812
|
+
const MUSTACHE_EXPR = seal(/{{[\w\W]*|^[\w\W]*}}/g);
|
|
18813
|
+
const ERB_EXPR = seal(/<%[\w\W]*|^[\w\W]*%>/g);
|
|
18814
|
+
const TMPLIT_EXPR = seal(/\${[\w\W]*/g);
|
|
18703
18815
|
const DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]+$/); // eslint-disable-line no-useless-escape
|
|
18704
18816
|
const ARIA_ATTR = seal(/^aria-[\-\w]+$/); // eslint-disable-line no-useless-escape
|
|
18705
18817
|
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 +18822,15 @@
|
|
|
18710
18822
|
const DOCTYPE_NAME = seal(/^html$/i);
|
|
18711
18823
|
const CUSTOM_ELEMENT = seal(/^[a-z][.\w]*(-[.\w]+)+$/i);
|
|
18712
18824
|
|
|
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
18825
|
/* eslint-disable @typescript-eslint/indent */
|
|
18728
18826
|
// https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
|
|
18729
18827
|
const NODE_TYPE = {
|
|
18730
18828
|
element: 1,
|
|
18731
|
-
attribute: 2,
|
|
18732
18829
|
text: 3,
|
|
18733
|
-
cdataSection: 4,
|
|
18734
|
-
entityReference: 5,
|
|
18735
|
-
// Deprecated
|
|
18736
|
-
entityNode: 6,
|
|
18737
18830
|
// Deprecated
|
|
18738
18831
|
progressingInstruction: 7,
|
|
18739
18832
|
comment: 8,
|
|
18740
|
-
document: 9
|
|
18741
|
-
documentType: 10,
|
|
18742
|
-
documentFragment: 11,
|
|
18743
|
-
notation: 12 // Deprecated
|
|
18744
|
-
};
|
|
18833
|
+
document: 9};
|
|
18745
18834
|
const getGlobal = function getGlobal() {
|
|
18746
18835
|
return typeof window === 'undefined' ? null : window;
|
|
18747
18836
|
};
|
|
@@ -18799,7 +18888,7 @@
|
|
|
18799
18888
|
function createDOMPurify() {
|
|
18800
18889
|
let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
|
|
18801
18890
|
const DOMPurify = root => createDOMPurify(root);
|
|
18802
|
-
DOMPurify.version = '3.
|
|
18891
|
+
DOMPurify.version = '3.4.5';
|
|
18803
18892
|
DOMPurify.removed = [];
|
|
18804
18893
|
if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document || !window.Element) {
|
|
18805
18894
|
// Not running in a browser, provide a factory function
|
|
@@ -18807,28 +18896,26 @@
|
|
|
18807
18896
|
DOMPurify.isSupported = false;
|
|
18808
18897
|
return DOMPurify;
|
|
18809
18898
|
}
|
|
18810
|
-
let
|
|
18811
|
-
document
|
|
18812
|
-
} = window;
|
|
18899
|
+
let document = window.document;
|
|
18813
18900
|
const originalDocument = document;
|
|
18814
18901
|
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;
|
|
18902
|
+
const DocumentFragment = window.DocumentFragment,
|
|
18903
|
+
HTMLTemplateElement = window.HTMLTemplateElement,
|
|
18904
|
+
Node = window.Node,
|
|
18905
|
+
Element = window.Element,
|
|
18906
|
+
NodeFilter = window.NodeFilter,
|
|
18907
|
+
_window$NamedNodeMap = window.NamedNodeMap,
|
|
18908
|
+
NamedNodeMap = _window$NamedNodeMap === void 0 ? window.NamedNodeMap || window.MozNamedAttrMap : _window$NamedNodeMap,
|
|
18909
|
+
HTMLFormElement = window.HTMLFormElement,
|
|
18910
|
+
DOMParser = window.DOMParser,
|
|
18911
|
+
trustedTypes = window.trustedTypes;
|
|
18826
18912
|
const ElementPrototype = Element.prototype;
|
|
18827
18913
|
const cloneNode = lookupGetter(ElementPrototype, 'cloneNode');
|
|
18828
18914
|
const remove = lookupGetter(ElementPrototype, 'remove');
|
|
18829
18915
|
const getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');
|
|
18830
18916
|
const getChildNodes = lookupGetter(ElementPrototype, 'childNodes');
|
|
18831
18917
|
const getParentNode = lookupGetter(ElementPrototype, 'parentNode');
|
|
18918
|
+
const getNodeType = Node && Node.prototype ? lookupGetter(Node.prototype, 'nodeType') : null;
|
|
18832
18919
|
// As per issue #47, the web-components registry is inherited by a
|
|
18833
18920
|
// new document created via createHTMLDocument. As per the spec
|
|
18834
18921
|
// (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)
|
|
@@ -18843,33 +18930,26 @@
|
|
|
18843
18930
|
}
|
|
18844
18931
|
let trustedTypesPolicy;
|
|
18845
18932
|
let emptyHTML = '';
|
|
18846
|
-
const
|
|
18847
|
-
implementation,
|
|
18848
|
-
createNodeIterator,
|
|
18849
|
-
createDocumentFragment,
|
|
18850
|
-
getElementsByTagName
|
|
18851
|
-
|
|
18852
|
-
const {
|
|
18853
|
-
importNode
|
|
18854
|
-
} = originalDocument;
|
|
18933
|
+
const _document = document,
|
|
18934
|
+
implementation = _document.implementation,
|
|
18935
|
+
createNodeIterator = _document.createNodeIterator,
|
|
18936
|
+
createDocumentFragment = _document.createDocumentFragment,
|
|
18937
|
+
getElementsByTagName = _document.getElementsByTagName;
|
|
18938
|
+
const importNode = originalDocument.importNode;
|
|
18855
18939
|
let hooks = _createHooksMap();
|
|
18856
18940
|
/**
|
|
18857
18941
|
* Expose whether this browser supports running the full DOMPurify.
|
|
18858
18942
|
*/
|
|
18859
18943
|
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;
|
|
18944
|
+
const MUSTACHE_EXPR$1 = MUSTACHE_EXPR,
|
|
18945
|
+
ERB_EXPR$1 = ERB_EXPR,
|
|
18946
|
+
TMPLIT_EXPR$1 = TMPLIT_EXPR,
|
|
18947
|
+
DATA_ATTR$1 = DATA_ATTR,
|
|
18948
|
+
ARIA_ATTR$1 = ARIA_ATTR,
|
|
18949
|
+
IS_SCRIPT_OR_DATA$1 = IS_SCRIPT_OR_DATA,
|
|
18950
|
+
ATTR_WHITESPACE$1 = ATTR_WHITESPACE,
|
|
18951
|
+
CUSTOM_ELEMENT$1 = CUSTOM_ELEMENT;
|
|
18952
|
+
let IS_ALLOWED_URI$1 = IS_ALLOWED_URI;
|
|
18873
18953
|
/**
|
|
18874
18954
|
* We consider the elements and attributes below to be safe. Ideally
|
|
18875
18955
|
* don't add any new ones but feel free to remove unwanted ones.
|
|
@@ -19047,15 +19127,15 @@
|
|
|
19047
19127
|
// HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.
|
|
19048
19128
|
transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? stringToString : stringToLowerCase;
|
|
19049
19129
|
/* 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;
|
|
19130
|
+
ALLOWED_TAGS = objectHasOwnProperty(cfg, 'ALLOWED_TAGS') && arrayIsArray(cfg.ALLOWED_TAGS) ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS;
|
|
19131
|
+
ALLOWED_ATTR = objectHasOwnProperty(cfg, 'ALLOWED_ATTR') && arrayIsArray(cfg.ALLOWED_ATTR) ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;
|
|
19132
|
+
ALLOWED_NAMESPACES = objectHasOwnProperty(cfg, 'ALLOWED_NAMESPACES') && arrayIsArray(cfg.ALLOWED_NAMESPACES) ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES;
|
|
19133
|
+
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;
|
|
19134
|
+
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;
|
|
19135
|
+
FORBID_CONTENTS = objectHasOwnProperty(cfg, 'FORBID_CONTENTS') && arrayIsArray(cfg.FORBID_CONTENTS) ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS;
|
|
19136
|
+
FORBID_TAGS = objectHasOwnProperty(cfg, 'FORBID_TAGS') && arrayIsArray(cfg.FORBID_TAGS) ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : clone({});
|
|
19137
|
+
FORBID_ATTR = objectHasOwnProperty(cfg, 'FORBID_ATTR') && arrayIsArray(cfg.FORBID_ATTR) ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : clone({});
|
|
19138
|
+
USE_PROFILES = objectHasOwnProperty(cfg, 'USE_PROFILES') ? cfg.USE_PROFILES && typeof cfg.USE_PROFILES === 'object' ? clone(cfg.USE_PROFILES) : cfg.USE_PROFILES : false;
|
|
19059
19139
|
ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true
|
|
19060
19140
|
ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true
|
|
19061
19141
|
ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false
|
|
@@ -19071,19 +19151,20 @@
|
|
|
19071
19151
|
SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false; // Default false
|
|
19072
19152
|
KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
|
|
19073
19153
|
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
|
-
|
|
19154
|
+
IS_ALLOWED_URI$1 = isRegex(cfg.ALLOWED_URI_REGEXP) ? cfg.ALLOWED_URI_REGEXP : IS_ALLOWED_URI; // Default regexp
|
|
19155
|
+
NAMESPACE = typeof cfg.NAMESPACE === 'string' ? cfg.NAMESPACE : HTML_NAMESPACE; // Default HTML namespace
|
|
19156
|
+
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
|
|
19157
|
+
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
|
|
19158
|
+
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);
|
|
19159
|
+
CUSTOM_ELEMENT_HANDLING = create$7(null);
|
|
19160
|
+
if (objectHasOwnProperty(customElementHandling, 'tagNameCheck') && isRegexOrFunction(customElementHandling.tagNameCheck)) {
|
|
19161
|
+
CUSTOM_ELEMENT_HANDLING.tagNameCheck = customElementHandling.tagNameCheck; // Default undefined
|
|
19081
19162
|
}
|
|
19082
|
-
if (
|
|
19083
|
-
CUSTOM_ELEMENT_HANDLING.attributeNameCheck =
|
|
19163
|
+
if (objectHasOwnProperty(customElementHandling, 'attributeNameCheck') && isRegexOrFunction(customElementHandling.attributeNameCheck)) {
|
|
19164
|
+
CUSTOM_ELEMENT_HANDLING.attributeNameCheck = customElementHandling.attributeNameCheck; // Default undefined
|
|
19084
19165
|
}
|
|
19085
|
-
if (
|
|
19086
|
-
CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements =
|
|
19166
|
+
if (objectHasOwnProperty(customElementHandling, 'allowCustomizedBuiltInElements') && typeof customElementHandling.allowCustomizedBuiltInElements === 'boolean') {
|
|
19167
|
+
CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = customElementHandling.allowCustomizedBuiltInElements; // Default undefined
|
|
19087
19168
|
}
|
|
19088
19169
|
if (SAFE_FOR_TEMPLATES) {
|
|
19089
19170
|
ALLOW_DATA_ATTR = false;
|
|
@@ -19115,44 +19196,41 @@
|
|
|
19115
19196
|
addToSet(ALLOWED_ATTR, xml);
|
|
19116
19197
|
}
|
|
19117
19198
|
}
|
|
19118
|
-
/*
|
|
19119
|
-
|
|
19120
|
-
|
|
19121
|
-
|
|
19122
|
-
if (!objectHasOwnProperty(cfg, 'ADD_ATTR')) {
|
|
19123
|
-
EXTRA_ELEMENT_HANDLING.attributeCheck = null;
|
|
19124
|
-
}
|
|
19199
|
+
/* Always reset function-based ADD_TAGS / ADD_ATTR checks to prevent
|
|
19200
|
+
* leaking across calls when switching from function to array config */
|
|
19201
|
+
EXTRA_ELEMENT_HANDLING.tagCheck = null;
|
|
19202
|
+
EXTRA_ELEMENT_HANDLING.attributeCheck = null;
|
|
19125
19203
|
/* Merge configuration parameters */
|
|
19126
|
-
if (cfg
|
|
19204
|
+
if (objectHasOwnProperty(cfg, 'ADD_TAGS')) {
|
|
19127
19205
|
if (typeof cfg.ADD_TAGS === 'function') {
|
|
19128
19206
|
EXTRA_ELEMENT_HANDLING.tagCheck = cfg.ADD_TAGS;
|
|
19129
|
-
} else {
|
|
19207
|
+
} else if (arrayIsArray(cfg.ADD_TAGS)) {
|
|
19130
19208
|
if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
|
|
19131
19209
|
ALLOWED_TAGS = clone(ALLOWED_TAGS);
|
|
19132
19210
|
}
|
|
19133
19211
|
addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);
|
|
19134
19212
|
}
|
|
19135
19213
|
}
|
|
19136
|
-
if (cfg
|
|
19214
|
+
if (objectHasOwnProperty(cfg, 'ADD_ATTR')) {
|
|
19137
19215
|
if (typeof cfg.ADD_ATTR === 'function') {
|
|
19138
19216
|
EXTRA_ELEMENT_HANDLING.attributeCheck = cfg.ADD_ATTR;
|
|
19139
|
-
} else {
|
|
19217
|
+
} else if (arrayIsArray(cfg.ADD_ATTR)) {
|
|
19140
19218
|
if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
|
|
19141
19219
|
ALLOWED_ATTR = clone(ALLOWED_ATTR);
|
|
19142
19220
|
}
|
|
19143
19221
|
addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);
|
|
19144
19222
|
}
|
|
19145
19223
|
}
|
|
19146
|
-
if (cfg.ADD_URI_SAFE_ATTR) {
|
|
19224
|
+
if (objectHasOwnProperty(cfg, 'ADD_URI_SAFE_ATTR') && arrayIsArray(cfg.ADD_URI_SAFE_ATTR)) {
|
|
19147
19225
|
addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);
|
|
19148
19226
|
}
|
|
19149
|
-
if (cfg.FORBID_CONTENTS) {
|
|
19227
|
+
if (objectHasOwnProperty(cfg, 'FORBID_CONTENTS') && arrayIsArray(cfg.FORBID_CONTENTS)) {
|
|
19150
19228
|
if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
|
|
19151
19229
|
FORBID_CONTENTS = clone(FORBID_CONTENTS);
|
|
19152
19230
|
}
|
|
19153
19231
|
addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);
|
|
19154
19232
|
}
|
|
19155
|
-
if (cfg.ADD_FORBID_CONTENTS) {
|
|
19233
|
+
if (objectHasOwnProperty(cfg, 'ADD_FORBID_CONTENTS') && arrayIsArray(cfg.ADD_FORBID_CONTENTS)) {
|
|
19156
19234
|
if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
|
|
19157
19235
|
FORBID_CONTENTS = clone(FORBID_CONTENTS);
|
|
19158
19236
|
}
|
|
@@ -19391,6 +19469,40 @@
|
|
|
19391
19469
|
// eslint-disable-next-line no-bitwise
|
|
19392
19470
|
NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT | NodeFilter.SHOW_PROCESSING_INSTRUCTION | NodeFilter.SHOW_CDATA_SECTION, null);
|
|
19393
19471
|
};
|
|
19472
|
+
/**
|
|
19473
|
+
* Strip template-engine expressions ({{...}}, ${...}, <%...%>) from the
|
|
19474
|
+
* character data of an element subtree. Used as the final safety net for
|
|
19475
|
+
* SAFE_FOR_TEMPLATES on every DOM-returning code path so that expressions
|
|
19476
|
+
* which only form after text-node normalization (e.g. fragments split across
|
|
19477
|
+
* stripped elements) cannot survive into a template-evaluating framework.
|
|
19478
|
+
*
|
|
19479
|
+
* Walks text/comment/CDATA/processing-instruction nodes and mutates `.data`
|
|
19480
|
+
* in place rather than round-tripping through innerHTML. This preserves
|
|
19481
|
+
* descendant node references (important for IN_PLACE callers), avoids a
|
|
19482
|
+
* serialize/reparse cycle, and reads literal character data — which means
|
|
19483
|
+
* `<%...%>` in text content matches the ERB regex against its real bytes
|
|
19484
|
+
* instead of the HTML-entity-escaped form innerHTML would produce.
|
|
19485
|
+
*
|
|
19486
|
+
* Attribute values are not visited here; SAFE_FOR_TEMPLATES handling for
|
|
19487
|
+
* attributes is performed during the per-node `_sanitizeAttributes` pass.
|
|
19488
|
+
*
|
|
19489
|
+
* @param node The root element whose character data should be scrubbed.
|
|
19490
|
+
*/
|
|
19491
|
+
const _scrubTemplateExpressions = function _scrubTemplateExpressions(node) {
|
|
19492
|
+
node.normalize();
|
|
19493
|
+
const walker = createNodeIterator.call(node.ownerDocument || node, node,
|
|
19494
|
+
// eslint-disable-next-line no-bitwise
|
|
19495
|
+
NodeFilter.SHOW_TEXT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_CDATA_SECTION | NodeFilter.SHOW_PROCESSING_INSTRUCTION, null);
|
|
19496
|
+
let currentNode = walker.nextNode();
|
|
19497
|
+
while (currentNode) {
|
|
19498
|
+
let data = currentNode.data;
|
|
19499
|
+
arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], expr => {
|
|
19500
|
+
data = stringReplace(data, expr, ' ');
|
|
19501
|
+
});
|
|
19502
|
+
currentNode.data = data;
|
|
19503
|
+
currentNode = walker.nextNode();
|
|
19504
|
+
}
|
|
19505
|
+
};
|
|
19394
19506
|
/**
|
|
19395
19507
|
* _isClobbered
|
|
19396
19508
|
*
|
|
@@ -19401,13 +19513,31 @@
|
|
|
19401
19513
|
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
19514
|
};
|
|
19403
19515
|
/**
|
|
19404
|
-
* Checks whether the given object is a DOM node
|
|
19516
|
+
* Checks whether the given object is a DOM node, including nodes that
|
|
19517
|
+
* originate from a different window/realm (e.g. an iframe's
|
|
19518
|
+
* contentDocument). The previous `value instanceof Node` check was
|
|
19519
|
+
* realm-bound: nodes from a different window failed it, causing
|
|
19520
|
+
* sanitize() to silently stringify them and reset IN_PLACE to false,
|
|
19521
|
+
* returning the original node unsanitized. See GHSA-4w3q-35jp-p934.
|
|
19522
|
+
*
|
|
19523
|
+
* Implementation: call the cached `nodeType` getter from Node.prototype
|
|
19524
|
+
* directly on the value. This bypasses any clobbered instance property
|
|
19525
|
+
* (e.g. a child element named "nodeType") and works across realms
|
|
19526
|
+
* because the WebIDL `nodeType` getter reads an internal slot that
|
|
19527
|
+
* every real Node has, regardless of which window minted it.
|
|
19405
19528
|
*
|
|
19406
19529
|
* @param value object to check whether it's a DOM node
|
|
19407
|
-
* @return true
|
|
19530
|
+
* @return true if value is a DOM node from any realm
|
|
19408
19531
|
*/
|
|
19409
19532
|
const _isNode = function _isNode(value) {
|
|
19410
|
-
|
|
19533
|
+
if (!getNodeType || typeof value !== 'object' || value === null) {
|
|
19534
|
+
return false;
|
|
19535
|
+
}
|
|
19536
|
+
try {
|
|
19537
|
+
return typeof getNodeType(value) === 'number';
|
|
19538
|
+
} catch (_) {
|
|
19539
|
+
return false;
|
|
19540
|
+
}
|
|
19411
19541
|
};
|
|
19412
19542
|
function _executeHooks(hooks, currentNode, data) {
|
|
19413
19543
|
arrayForEach(hooks, hook => {
|
|
@@ -19444,6 +19574,11 @@
|
|
|
19444
19574
|
_forceRemove(currentNode);
|
|
19445
19575
|
return true;
|
|
19446
19576
|
}
|
|
19577
|
+
/* Remove risky CSS construction leading to mXSS */
|
|
19578
|
+
if (SAFE_FOR_XML && currentNode.namespaceURI === HTML_NAMESPACE && tagName === 'style' && _isNode(currentNode.firstElementChild)) {
|
|
19579
|
+
_forceRemove(currentNode);
|
|
19580
|
+
return true;
|
|
19581
|
+
}
|
|
19447
19582
|
/* Remove any occurrence of processing instructions */
|
|
19448
19583
|
if (currentNode.nodeType === NODE_TYPE.progressingInstruction) {
|
|
19449
19584
|
_forceRemove(currentNode);
|
|
@@ -19455,7 +19590,7 @@
|
|
|
19455
19590
|
return true;
|
|
19456
19591
|
}
|
|
19457
19592
|
/* Remove element if anything forbids its presence */
|
|
19458
|
-
if (!(EXTRA_ELEMENT_HANDLING.tagCheck instanceof Function && EXTRA_ELEMENT_HANDLING.tagCheck(tagName)) &&
|
|
19593
|
+
if (FORBID_TAGS[tagName] || !(EXTRA_ELEMENT_HANDLING.tagCheck instanceof Function && EXTRA_ELEMENT_HANDLING.tagCheck(tagName)) && !ALLOWED_TAGS[tagName]) {
|
|
19459
19594
|
/* Check if we have a custom element to handle */
|
|
19460
19595
|
if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName)) {
|
|
19461
19596
|
if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) {
|
|
@@ -19473,7 +19608,6 @@
|
|
|
19473
19608
|
const childCount = childNodes.length;
|
|
19474
19609
|
for (let i = childCount - 1; i >= 0; --i) {
|
|
19475
19610
|
const childClone = cloneNode(childNodes[i], true);
|
|
19476
|
-
childClone.__removalCount = (currentNode.__removalCount || 0) + 1;
|
|
19477
19611
|
parentNode.insertBefore(childClone, getNextSibling(currentNode));
|
|
19478
19612
|
}
|
|
19479
19613
|
}
|
|
@@ -19495,7 +19629,7 @@
|
|
|
19495
19629
|
if (SAFE_FOR_TEMPLATES && currentNode.nodeType === NODE_TYPE.text) {
|
|
19496
19630
|
/* Get the element's text content */
|
|
19497
19631
|
content = currentNode.textContent;
|
|
19498
|
-
arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
|
|
19632
|
+
arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], expr => {
|
|
19499
19633
|
content = stringReplace(content, expr, ' ');
|
|
19500
19634
|
});
|
|
19501
19635
|
if (currentNode.textContent !== content) {
|
|
@@ -19527,11 +19661,12 @@
|
|
|
19527
19661
|
if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
|
|
19528
19662
|
return false;
|
|
19529
19663
|
}
|
|
19664
|
+
const nameIsPermitted = ALLOWED_ATTR[lcName] || EXTRA_ELEMENT_HANDLING.attributeCheck instanceof Function && EXTRA_ELEMENT_HANDLING.attributeCheck(lcName, lcTag);
|
|
19530
19665
|
/* Allow valid data-* attributes: At least one character after "-"
|
|
19531
19666
|
(https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
|
|
19532
19667
|
XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
|
|
19533
19668
|
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 (
|
|
19669
|
+
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
19670
|
if (
|
|
19536
19671
|
// First condition does a very basic check if a) it's basically a valid custom element tagname AND
|
|
19537
19672
|
// b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
|
|
@@ -19543,11 +19678,15 @@
|
|
|
19543
19678
|
return false;
|
|
19544
19679
|
}
|
|
19545
19680
|
/* 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) {
|
|
19681
|
+
} 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
19682
|
return false;
|
|
19548
19683
|
} else ;
|
|
19549
19684
|
return true;
|
|
19550
19685
|
};
|
|
19686
|
+
/* Names the HTML spec reserves from valid-custom-element-name; these must
|
|
19687
|
+
* never be treated as basic custom elements even when a permissive
|
|
19688
|
+
* CUSTOM_ELEMENT_HANDLING.tagNameCheck is configured. */
|
|
19689
|
+
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
19690
|
/**
|
|
19552
19691
|
* _isBasicCustomElement
|
|
19553
19692
|
* checks if at least one dash is included in tagName, and it's not the first char
|
|
@@ -19557,7 +19696,7 @@
|
|
|
19557
19696
|
* @returns Returns true if the tag name meets the basic criteria for a custom element, otherwise false.
|
|
19558
19697
|
*/
|
|
19559
19698
|
const _isBasicCustomElement = function _isBasicCustomElement(tagName) {
|
|
19560
|
-
return tagName
|
|
19699
|
+
return !RESERVED_CUSTOM_ELEMENT_NAMES[stringToLowerCase(tagName)] && regExpTest(CUSTOM_ELEMENT$1, tagName);
|
|
19561
19700
|
};
|
|
19562
19701
|
/**
|
|
19563
19702
|
* _sanitizeAttributes
|
|
@@ -19572,9 +19711,7 @@
|
|
|
19572
19711
|
const _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
|
|
19573
19712
|
/* Execute a hook if present */
|
|
19574
19713
|
_executeHooks(hooks.beforeSanitizeAttributes, currentNode, null);
|
|
19575
|
-
const
|
|
19576
|
-
attributes
|
|
19577
|
-
} = currentNode;
|
|
19714
|
+
const attributes = currentNode.attributes;
|
|
19578
19715
|
/* Check if we have attributes; if not we might have a text node */
|
|
19579
19716
|
if (!attributes || _isClobbered(currentNode)) {
|
|
19580
19717
|
return;
|
|
@@ -19590,11 +19727,9 @@
|
|
|
19590
19727
|
/* Go backwards over all attributes; safely remove bad ones */
|
|
19591
19728
|
while (l--) {
|
|
19592
19729
|
const attr = attributes[l];
|
|
19593
|
-
const
|
|
19594
|
-
|
|
19595
|
-
|
|
19596
|
-
value: attrValue
|
|
19597
|
-
} = attr;
|
|
19730
|
+
const name = attr.name,
|
|
19731
|
+
namespaceURI = attr.namespaceURI,
|
|
19732
|
+
attrValue = attr.value;
|
|
19598
19733
|
const lcName = transformCaseFunc(name);
|
|
19599
19734
|
const initValue = attrValue;
|
|
19600
19735
|
let value = name === 'value' ? initValue : stringTrim(initValue);
|
|
@@ -19608,12 +19743,14 @@
|
|
|
19608
19743
|
/* Full DOM Clobbering protection via namespace isolation,
|
|
19609
19744
|
* Prefix id and name attributes with `user-content-`
|
|
19610
19745
|
*/
|
|
19611
|
-
if (SANITIZE_NAMED_PROPS && (lcName === 'id' || lcName === 'name')) {
|
|
19746
|
+
if (SANITIZE_NAMED_PROPS && (lcName === 'id' || lcName === 'name') && stringIndexOf(value, SANITIZE_NAMED_PROPS_PREFIX) !== 0) {
|
|
19612
19747
|
// Remove the attribute with this value
|
|
19613
19748
|
_removeAttribute(name, currentNode);
|
|
19614
19749
|
// Prefix the value and later re-create the attribute with the sanitized value
|
|
19615
19750
|
value = SANITIZE_NAMED_PROPS_PREFIX + value;
|
|
19616
19751
|
}
|
|
19752
|
+
// Else: already prefixed, leave the attribute alone — the prefix is
|
|
19753
|
+
// itself the clobbering protection, and re-applying it is incorrect.
|
|
19617
19754
|
/* Work around a security issue with comments inside attributes */
|
|
19618
19755
|
if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|script|title|xmp|textarea|noscript|iframe|noembed|noframes)/i, value)) {
|
|
19619
19756
|
_removeAttribute(name, currentNode);
|
|
@@ -19640,7 +19777,7 @@
|
|
|
19640
19777
|
}
|
|
19641
19778
|
/* Sanitize attribute content to be template-safe */
|
|
19642
19779
|
if (SAFE_FOR_TEMPLATES) {
|
|
19643
|
-
arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
|
|
19780
|
+
arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], expr => {
|
|
19644
19781
|
value = stringReplace(value, expr, ' ');
|
|
19645
19782
|
});
|
|
19646
19783
|
}
|
|
@@ -19694,7 +19831,7 @@
|
|
|
19694
19831
|
*
|
|
19695
19832
|
* @param fragment to iterate over recursively
|
|
19696
19833
|
*/
|
|
19697
|
-
const
|
|
19834
|
+
const _sanitizeShadowDOM2 = function _sanitizeShadowDOM(fragment) {
|
|
19698
19835
|
let shadowNode = null;
|
|
19699
19836
|
const shadowIterator = _createNodeIterator(fragment);
|
|
19700
19837
|
/* Execute a hook if present */
|
|
@@ -19708,12 +19845,55 @@
|
|
|
19708
19845
|
_sanitizeAttributes(shadowNode);
|
|
19709
19846
|
/* Deep shadow DOM detected */
|
|
19710
19847
|
if (shadowNode.content instanceof DocumentFragment) {
|
|
19711
|
-
|
|
19848
|
+
_sanitizeShadowDOM2(shadowNode.content);
|
|
19712
19849
|
}
|
|
19713
19850
|
}
|
|
19714
19851
|
/* Execute a hook if present */
|
|
19715
19852
|
_executeHooks(hooks.afterSanitizeShadowDOM, fragment, null);
|
|
19716
19853
|
};
|
|
19854
|
+
/**
|
|
19855
|
+
* _sanitizeAttachedShadowRoots
|
|
19856
|
+
*
|
|
19857
|
+
* Walks `root` and feeds every attached shadow root we encounter into
|
|
19858
|
+
* the existing _sanitizeShadowDOM pipeline. The default node iterator
|
|
19859
|
+
* does not descend into shadow trees, so nodes inside an attached
|
|
19860
|
+
* shadow root would otherwise be skipped entirely.
|
|
19861
|
+
*
|
|
19862
|
+
* Two real input paths put attached shadow roots in front of us:
|
|
19863
|
+
* 1. IN_PLACE on a DOM node that already has shadow roots attached.
|
|
19864
|
+
* 2. DOM-node input where importNode(dirty, true) deep-clones the
|
|
19865
|
+
* shadow root because it was created with `clonable: true`.
|
|
19866
|
+
*
|
|
19867
|
+
* This pass runs once, up front, so the main iteration loop (and the
|
|
19868
|
+
* existing _sanitizeShadowDOM template-content recursion) stay
|
|
19869
|
+
* untouched — string-input paths are not affected.
|
|
19870
|
+
*
|
|
19871
|
+
* @param root the subtree root to walk for attached shadow roots
|
|
19872
|
+
*/
|
|
19873
|
+
const _sanitizeAttachedShadowRoots2 = function _sanitizeAttachedShadowRoots(root) {
|
|
19874
|
+
if (root.nodeType === NODE_TYPE.element && root.shadowRoot instanceof DocumentFragment) {
|
|
19875
|
+
const sr = root.shadowRoot;
|
|
19876
|
+
// Recurse first so that nested shadow roots are reached even if
|
|
19877
|
+
// _sanitizeShadowDOM removes hosts at this level.
|
|
19878
|
+
_sanitizeAttachedShadowRoots2(sr);
|
|
19879
|
+
_sanitizeShadowDOM2(sr);
|
|
19880
|
+
}
|
|
19881
|
+
// Snapshot children before recursing. Sanitization of one subtree
|
|
19882
|
+
// (e.g. via an uponSanitizeShadowNode hook) may detach siblings,
|
|
19883
|
+
// and naive nextSibling traversal would silently skip the rest of
|
|
19884
|
+
// the list once a node is detached.
|
|
19885
|
+
const childNodes = root.childNodes;
|
|
19886
|
+
if (!childNodes) {
|
|
19887
|
+
return;
|
|
19888
|
+
}
|
|
19889
|
+
const snapshot = [];
|
|
19890
|
+
arrayForEach(childNodes, child => {
|
|
19891
|
+
arrayPush(snapshot, child);
|
|
19892
|
+
});
|
|
19893
|
+
for (const child of snapshot) {
|
|
19894
|
+
_sanitizeAttachedShadowRoots2(child);
|
|
19895
|
+
}
|
|
19896
|
+
};
|
|
19717
19897
|
// eslint-disable-next-line complexity
|
|
19718
19898
|
DOMPurify.sanitize = function (dirty) {
|
|
19719
19899
|
let cfg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
@@ -19730,13 +19910,9 @@
|
|
|
19730
19910
|
}
|
|
19731
19911
|
/* Stringify, in case dirty is an object */
|
|
19732
19912
|
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');
|
|
19913
|
+
dirty = stringifyValue(dirty);
|
|
19914
|
+
if (typeof dirty !== 'string') {
|
|
19915
|
+
throw typeErrorCreate('dirty is not a string, aborting');
|
|
19740
19916
|
}
|
|
19741
19917
|
}
|
|
19742
19918
|
/* Return dirty HTML if DOMPurify cannot run */
|
|
@@ -19755,13 +19931,17 @@
|
|
|
19755
19931
|
}
|
|
19756
19932
|
if (IN_PLACE) {
|
|
19757
19933
|
/* Do some early pre-sanitization to avoid unsafe root nodes */
|
|
19758
|
-
|
|
19759
|
-
|
|
19934
|
+
const nn = dirty.nodeName;
|
|
19935
|
+
if (typeof nn === 'string') {
|
|
19936
|
+
const tagName = transformCaseFunc(nn);
|
|
19760
19937
|
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
|
|
19761
19938
|
throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');
|
|
19762
19939
|
}
|
|
19763
19940
|
}
|
|
19764
|
-
|
|
19941
|
+
/* Sanitize attached shadow roots before the main iterator runs.
|
|
19942
|
+
The iterator does not descend into shadow trees. */
|
|
19943
|
+
_sanitizeAttachedShadowRoots2(dirty);
|
|
19944
|
+
} else if (_isNode(dirty)) {
|
|
19765
19945
|
/* If dirty is a DOM element, append to an empty document to avoid
|
|
19766
19946
|
elements being stripped by the parser */
|
|
19767
19947
|
body = _initDocument('<!---->');
|
|
@@ -19775,6 +19955,10 @@
|
|
|
19775
19955
|
// eslint-disable-next-line unicorn/prefer-dom-node-append
|
|
19776
19956
|
body.appendChild(importedNode);
|
|
19777
19957
|
}
|
|
19958
|
+
/* Clonable shadow roots are deep-cloned by importNode(); sanitize
|
|
19959
|
+
them before the main iterator runs, since the iterator does not
|
|
19960
|
+
descend into shadow trees. */
|
|
19961
|
+
_sanitizeAttachedShadowRoots2(importedNode);
|
|
19778
19962
|
} else {
|
|
19779
19963
|
/* Exit directly if we have nothing to do */
|
|
19780
19964
|
if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT &&
|
|
@@ -19803,15 +19987,21 @@
|
|
|
19803
19987
|
_sanitizeAttributes(currentNode);
|
|
19804
19988
|
/* Shadow DOM detected, sanitize it */
|
|
19805
19989
|
if (currentNode.content instanceof DocumentFragment) {
|
|
19806
|
-
|
|
19990
|
+
_sanitizeShadowDOM2(currentNode.content);
|
|
19807
19991
|
}
|
|
19808
19992
|
}
|
|
19809
19993
|
/* If we sanitized `dirty` in-place, return it. */
|
|
19810
19994
|
if (IN_PLACE) {
|
|
19995
|
+
if (SAFE_FOR_TEMPLATES) {
|
|
19996
|
+
_scrubTemplateExpressions(dirty);
|
|
19997
|
+
}
|
|
19811
19998
|
return dirty;
|
|
19812
19999
|
}
|
|
19813
20000
|
/* Return sanitized string or DOM */
|
|
19814
20001
|
if (RETURN_DOM) {
|
|
20002
|
+
if (SAFE_FOR_TEMPLATES) {
|
|
20003
|
+
_scrubTemplateExpressions(body);
|
|
20004
|
+
}
|
|
19815
20005
|
if (RETURN_DOM_FRAGMENT) {
|
|
19816
20006
|
returnNode = createDocumentFragment.call(body.ownerDocument);
|
|
19817
20007
|
while (body.firstChild) {
|
|
@@ -19840,7 +20030,7 @@
|
|
|
19840
20030
|
}
|
|
19841
20031
|
/* Sanitize final string template-safe */
|
|
19842
20032
|
if (SAFE_FOR_TEMPLATES) {
|
|
19843
|
-
arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
|
|
20033
|
+
arrayForEach([MUSTACHE_EXPR$1, ERB_EXPR$1, TMPLIT_EXPR$1], expr => {
|
|
19844
20034
|
serializedHTML = stringReplace(serializedHTML, expr, ' ');
|
|
19845
20035
|
});
|
|
19846
20036
|
}
|
|
@@ -40777,14 +40967,14 @@
|
|
|
40777
40967
|
* @property minorVersion
|
|
40778
40968
|
* @type String
|
|
40779
40969
|
*/
|
|
40780
|
-
minorVersion: '
|
|
40970
|
+
minorVersion: '6.0',
|
|
40781
40971
|
/**
|
|
40782
40972
|
* Release date of TinyMCE build.
|
|
40783
40973
|
*
|
|
40784
40974
|
* @property releaseDate
|
|
40785
40975
|
* @type String
|
|
40786
40976
|
*/
|
|
40787
|
-
releaseDate: '2026-
|
|
40977
|
+
releaseDate: '2026-06-03',
|
|
40788
40978
|
/**
|
|
40789
40979
|
* Collection of language pack data.
|
|
40790
40980
|
*
|