action_text-trix 2.1.17 → 2.1.19
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/javascripts/trix.js +189 -68
- data/lib/action_text/trix/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 14985d71593b521f0ddc7c0488ad00483db8a3423b58f1dac7fd19c5568e2d78
|
|
4
|
+
data.tar.gz: 6d2fc6d9de5e0b992b66e1a17d77c572e1b695c084fedf3bc79aaf6cd5b56107
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6a48e8c1dcdf076d11a930df88d45180fef46c42584522ddb01a58ecf5e4d2afa767e2985363ceae427779373237d7196760d150f93ea26485b3661d00a3fe29
|
|
7
|
+
data.tar.gz: 0f4305effe253c9a6f7aaf3c68324a477fbd3e7451d3f4479ca1f13f7777e1af9e93c2304e3120b48f70e703f73731cc2c7b6c8ef42541e87a0106f2f7c6f31e
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
Trix 2.1.
|
|
2
|
+
Trix 2.1.19
|
|
3
3
|
Copyright © 2026 37signals, LLC
|
|
4
4
|
*/
|
|
5
5
|
(function (global, factory) {
|
|
@@ -9,7 +9,7 @@ Copyright © 2026 37signals, LLC
|
|
|
9
9
|
})(this, (function () { 'use strict';
|
|
10
10
|
|
|
11
11
|
var name = "trix";
|
|
12
|
-
var version = "2.1.
|
|
12
|
+
var version = "2.1.19";
|
|
13
13
|
var description = "A rich text editor for everyday writing";
|
|
14
14
|
var main = "dist/trix.umd.min.js";
|
|
15
15
|
var module = "dist/trix.esm.min.js";
|
|
@@ -1765,7 +1765,7 @@ $\
|
|
|
1765
1765
|
}
|
|
1766
1766
|
}
|
|
1767
1767
|
|
|
1768
|
-
/*! @license DOMPurify 3.2
|
|
1768
|
+
/*! @license DOMPurify 3.4.2 | (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.2/LICENSE */
|
|
1769
1769
|
|
|
1770
1770
|
const {
|
|
1771
1771
|
entries,
|
|
@@ -1814,13 +1814,19 @@ $\
|
|
|
1814
1814
|
const arrayPop = unapply(Array.prototype.pop);
|
|
1815
1815
|
const arrayPush = unapply(Array.prototype.push);
|
|
1816
1816
|
const arraySplice = unapply(Array.prototype.splice);
|
|
1817
|
+
const arrayIsArray = Array.isArray;
|
|
1817
1818
|
const stringToLowerCase = unapply(String.prototype.toLowerCase);
|
|
1818
1819
|
const stringToString = unapply(String.prototype.toString);
|
|
1819
1820
|
const stringMatch = unapply(String.prototype.match);
|
|
1820
1821
|
const stringReplace = unapply(String.prototype.replace);
|
|
1821
1822
|
const stringIndexOf = unapply(String.prototype.indexOf);
|
|
1822
1823
|
const stringTrim = unapply(String.prototype.trim);
|
|
1824
|
+
const numberToString = unapply(Number.prototype.toString);
|
|
1825
|
+
const booleanToString = unapply(Boolean.prototype.toString);
|
|
1826
|
+
const bigintToString = typeof BigInt === 'undefined' ? null : unapply(BigInt.prototype.toString);
|
|
1827
|
+
const symbolToString = typeof Symbol === 'undefined' ? null : unapply(Symbol.prototype.toString);
|
|
1823
1828
|
const objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);
|
|
1829
|
+
const objectToString = unapply(Object.prototype.toString);
|
|
1824
1830
|
const regExpTest = unapply(RegExp.prototype.test);
|
|
1825
1831
|
const typeErrorCreate = unconstruct(TypeError);
|
|
1826
1832
|
/**
|
|
@@ -1870,6 +1876,9 @@ $\
|
|
|
1870
1876
|
// Prevent prototype setters from intercepting set as a this value.
|
|
1871
1877
|
setPrototypeOf(set, null);
|
|
1872
1878
|
}
|
|
1879
|
+
if (!arrayIsArray(array)) {
|
|
1880
|
+
return set;
|
|
1881
|
+
}
|
|
1873
1882
|
let l = array.length;
|
|
1874
1883
|
while (l--) {
|
|
1875
1884
|
let element = array[l];
|
|
@@ -1913,7 +1922,7 @@ $\
|
|
|
1913
1922
|
for (const [property, value] of entries(object)) {
|
|
1914
1923
|
const isPropertyExist = objectHasOwnProperty(object, property);
|
|
1915
1924
|
if (isPropertyExist) {
|
|
1916
|
-
if (
|
|
1925
|
+
if (arrayIsArray(value)) {
|
|
1917
1926
|
newObject[property] = cleanArray(value);
|
|
1918
1927
|
} else if (value && typeof value === 'object' && value.constructor === Object) {
|
|
1919
1928
|
newObject[property] = clone(value);
|
|
@@ -1924,6 +1933,58 @@ $\
|
|
|
1924
1933
|
}
|
|
1925
1934
|
return newObject;
|
|
1926
1935
|
}
|
|
1936
|
+
/**
|
|
1937
|
+
* Convert non-node values into strings without depending on direct property access.
|
|
1938
|
+
*
|
|
1939
|
+
* @param value - The value to stringify.
|
|
1940
|
+
* @returns A string representation of the provided value.
|
|
1941
|
+
*/
|
|
1942
|
+
function stringifyValue(value) {
|
|
1943
|
+
switch (typeof value) {
|
|
1944
|
+
case 'string':
|
|
1945
|
+
{
|
|
1946
|
+
return value;
|
|
1947
|
+
}
|
|
1948
|
+
case 'number':
|
|
1949
|
+
{
|
|
1950
|
+
return numberToString(value);
|
|
1951
|
+
}
|
|
1952
|
+
case 'boolean':
|
|
1953
|
+
{
|
|
1954
|
+
return booleanToString(value);
|
|
1955
|
+
}
|
|
1956
|
+
case 'bigint':
|
|
1957
|
+
{
|
|
1958
|
+
return bigintToString ? bigintToString(value) : '0';
|
|
1959
|
+
}
|
|
1960
|
+
case 'symbol':
|
|
1961
|
+
{
|
|
1962
|
+
return symbolToString ? symbolToString(value) : 'Symbol()';
|
|
1963
|
+
}
|
|
1964
|
+
case 'undefined':
|
|
1965
|
+
{
|
|
1966
|
+
return objectToString(value);
|
|
1967
|
+
}
|
|
1968
|
+
case 'function':
|
|
1969
|
+
case 'object':
|
|
1970
|
+
{
|
|
1971
|
+
if (value === null) {
|
|
1972
|
+
return objectToString(value);
|
|
1973
|
+
}
|
|
1974
|
+
const valueAsRecord = value;
|
|
1975
|
+
const valueToString = lookupGetter(valueAsRecord, 'toString');
|
|
1976
|
+
if (typeof valueToString === 'function') {
|
|
1977
|
+
const stringified = valueToString(valueAsRecord);
|
|
1978
|
+
return typeof stringified === 'string' ? stringified : objectToString(stringified);
|
|
1979
|
+
}
|
|
1980
|
+
return objectToString(value);
|
|
1981
|
+
}
|
|
1982
|
+
default:
|
|
1983
|
+
{
|
|
1984
|
+
return objectToString(value);
|
|
1985
|
+
}
|
|
1986
|
+
}
|
|
1987
|
+
}
|
|
1927
1988
|
/**
|
|
1928
1989
|
* This method automatically checks if the prop is function or getter and behaves accordingly.
|
|
1929
1990
|
*
|
|
@@ -1949,8 +2010,16 @@ $\
|
|
|
1949
2010
|
}
|
|
1950
2011
|
return fallbackValue;
|
|
1951
2012
|
}
|
|
2013
|
+
function isRegex(value) {
|
|
2014
|
+
try {
|
|
2015
|
+
regExpTest(value, '');
|
|
2016
|
+
return true;
|
|
2017
|
+
} catch (_unused) {
|
|
2018
|
+
return false;
|
|
2019
|
+
}
|
|
2020
|
+
}
|
|
1952
2021
|
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']);
|
|
1953
|
-
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', '
|
|
2022
|
+
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']);
|
|
1954
2023
|
const svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feDropShadow', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);
|
|
1955
2024
|
// List of SVG elements that are disallowed by default.
|
|
1956
2025
|
// We still need to know them so that we can do namespace
|
|
@@ -1962,9 +2031,9 @@ $\
|
|
|
1962
2031
|
// even those that we disallow by default.
|
|
1963
2032
|
const mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);
|
|
1964
2033
|
const text = freeze(['#text']);
|
|
1965
|
-
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'
|
|
1966
|
-
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', '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']);
|
|
1967
|
-
const mathMl = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', '
|
|
2034
|
+
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']);
|
|
2035
|
+
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']);
|
|
2036
|
+
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']);
|
|
1968
2037
|
const xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
|
|
1969
2038
|
|
|
1970
2039
|
// eslint-disable-next-line unicorn/better-regex
|
|
@@ -1998,19 +2067,11 @@ $\
|
|
|
1998
2067
|
// https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
|
|
1999
2068
|
const NODE_TYPE = {
|
|
2000
2069
|
element: 1,
|
|
2001
|
-
attribute: 2,
|
|
2002
2070
|
text: 3,
|
|
2003
|
-
cdataSection: 4,
|
|
2004
|
-
entityReference: 5,
|
|
2005
|
-
// Deprecated
|
|
2006
|
-
entityNode: 6,
|
|
2007
2071
|
// Deprecated
|
|
2008
2072
|
progressingInstruction: 7,
|
|
2009
2073
|
comment: 8,
|
|
2010
|
-
document: 9
|
|
2011
|
-
documentType: 10,
|
|
2012
|
-
documentFragment: 11,
|
|
2013
|
-
notation: 12 // Deprecated
|
|
2074
|
+
document: 9
|
|
2014
2075
|
};
|
|
2015
2076
|
const getGlobal = function getGlobal() {
|
|
2016
2077
|
return typeof window === 'undefined' ? null : window;
|
|
@@ -2069,7 +2130,7 @@ $\
|
|
|
2069
2130
|
function createDOMPurify() {
|
|
2070
2131
|
let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
|
|
2071
2132
|
const DOMPurify = root => createDOMPurify(root);
|
|
2072
|
-
DOMPurify.version = '3.2
|
|
2133
|
+
DOMPurify.version = '3.4.2';
|
|
2073
2134
|
DOMPurify.removed = [];
|
|
2074
2135
|
if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document || !window.Element) {
|
|
2075
2136
|
// Not running in a browser, provide a factory function
|
|
@@ -2180,6 +2241,21 @@ $\
|
|
|
2180
2241
|
let FORBID_TAGS = null;
|
|
2181
2242
|
/* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */
|
|
2182
2243
|
let FORBID_ATTR = null;
|
|
2244
|
+
/* Config object to store ADD_TAGS/ADD_ATTR functions (when used as functions) */
|
|
2245
|
+
const EXTRA_ELEMENT_HANDLING = Object.seal(create(null, {
|
|
2246
|
+
tagCheck: {
|
|
2247
|
+
writable: true,
|
|
2248
|
+
configurable: false,
|
|
2249
|
+
enumerable: true,
|
|
2250
|
+
value: null
|
|
2251
|
+
},
|
|
2252
|
+
attributeCheck: {
|
|
2253
|
+
writable: true,
|
|
2254
|
+
configurable: false,
|
|
2255
|
+
enumerable: true,
|
|
2256
|
+
value: null
|
|
2257
|
+
}
|
|
2258
|
+
}));
|
|
2183
2259
|
/* Decide if ARIA attributes are okay */
|
|
2184
2260
|
let ALLOW_ARIA_ATTR = true;
|
|
2185
2261
|
/* Decide if custom data attributes are okay */
|
|
@@ -2302,15 +2378,15 @@ $\
|
|
|
2302
2378
|
// HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.
|
|
2303
2379
|
transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? stringToString : stringToLowerCase;
|
|
2304
2380
|
/* Set configuration parameters */
|
|
2305
|
-
ALLOWED_TAGS = objectHasOwnProperty(cfg, 'ALLOWED_TAGS') ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS;
|
|
2306
|
-
ALLOWED_ATTR = objectHasOwnProperty(cfg, 'ALLOWED_ATTR') ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;
|
|
2307
|
-
ALLOWED_NAMESPACES = objectHasOwnProperty(cfg, 'ALLOWED_NAMESPACES') ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES;
|
|
2308
|
-
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;
|
|
2309
|
-
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;
|
|
2310
|
-
FORBID_CONTENTS = objectHasOwnProperty(cfg, 'FORBID_CONTENTS') ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS;
|
|
2311
|
-
FORBID_TAGS = objectHasOwnProperty(cfg, 'FORBID_TAGS') ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : clone({});
|
|
2312
|
-
FORBID_ATTR = objectHasOwnProperty(cfg, 'FORBID_ATTR') ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : clone({});
|
|
2313
|
-
USE_PROFILES = objectHasOwnProperty(cfg, 'USE_PROFILES') ? cfg.USE_PROFILES : false;
|
|
2381
|
+
ALLOWED_TAGS = objectHasOwnProperty(cfg, 'ALLOWED_TAGS') && arrayIsArray(cfg.ALLOWED_TAGS) ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS;
|
|
2382
|
+
ALLOWED_ATTR = objectHasOwnProperty(cfg, 'ALLOWED_ATTR') && arrayIsArray(cfg.ALLOWED_ATTR) ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;
|
|
2383
|
+
ALLOWED_NAMESPACES = objectHasOwnProperty(cfg, 'ALLOWED_NAMESPACES') && arrayIsArray(cfg.ALLOWED_NAMESPACES) ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES;
|
|
2384
|
+
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;
|
|
2385
|
+
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;
|
|
2386
|
+
FORBID_CONTENTS = objectHasOwnProperty(cfg, 'FORBID_CONTENTS') && arrayIsArray(cfg.FORBID_CONTENTS) ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS;
|
|
2387
|
+
FORBID_TAGS = objectHasOwnProperty(cfg, 'FORBID_TAGS') && arrayIsArray(cfg.FORBID_TAGS) ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : clone({});
|
|
2388
|
+
FORBID_ATTR = objectHasOwnProperty(cfg, 'FORBID_ATTR') && arrayIsArray(cfg.FORBID_ATTR) ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : clone({});
|
|
2389
|
+
USE_PROFILES = objectHasOwnProperty(cfg, 'USE_PROFILES') ? cfg.USE_PROFILES && typeof cfg.USE_PROFILES === 'object' ? clone(cfg.USE_PROFILES) : cfg.USE_PROFILES : false;
|
|
2314
2390
|
ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true
|
|
2315
2391
|
ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true
|
|
2316
2392
|
ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false
|
|
@@ -2326,19 +2402,20 @@ $\
|
|
|
2326
2402
|
SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false; // Default false
|
|
2327
2403
|
KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
|
|
2328
2404
|
IN_PLACE = cfg.IN_PLACE || false; // Default false
|
|
2329
|
-
IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP
|
|
2330
|
-
NAMESPACE = cfg.NAMESPACE
|
|
2331
|
-
MATHML_TEXT_INTEGRATION_POINTS = cfg.MATHML_TEXT_INTEGRATION_POINTS
|
|
2332
|
-
HTML_INTEGRATION_POINTS = cfg.HTML_INTEGRATION_POINTS
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2405
|
+
IS_ALLOWED_URI$1 = isRegex(cfg.ALLOWED_URI_REGEXP) ? cfg.ALLOWED_URI_REGEXP : IS_ALLOWED_URI; // Default regexp
|
|
2406
|
+
NAMESPACE = typeof cfg.NAMESPACE === 'string' ? cfg.NAMESPACE : HTML_NAMESPACE; // Default HTML namespace
|
|
2407
|
+
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
|
|
2408
|
+
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
|
|
2409
|
+
const customElementHandling = objectHasOwnProperty(cfg, 'CUSTOM_ELEMENT_HANDLING') && cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING === 'object' ? clone(cfg.CUSTOM_ELEMENT_HANDLING) : create(null);
|
|
2410
|
+
CUSTOM_ELEMENT_HANDLING = create(null);
|
|
2411
|
+
if (objectHasOwnProperty(customElementHandling, 'tagNameCheck') && isRegexOrFunction(customElementHandling.tagNameCheck)) {
|
|
2412
|
+
CUSTOM_ELEMENT_HANDLING.tagNameCheck = customElementHandling.tagNameCheck; // Default undefined
|
|
2336
2413
|
}
|
|
2337
|
-
if (
|
|
2338
|
-
CUSTOM_ELEMENT_HANDLING.attributeNameCheck =
|
|
2414
|
+
if (objectHasOwnProperty(customElementHandling, 'attributeNameCheck') && isRegexOrFunction(customElementHandling.attributeNameCheck)) {
|
|
2415
|
+
CUSTOM_ELEMENT_HANDLING.attributeNameCheck = customElementHandling.attributeNameCheck; // Default undefined
|
|
2339
2416
|
}
|
|
2340
|
-
if (
|
|
2341
|
-
CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements =
|
|
2417
|
+
if (objectHasOwnProperty(customElementHandling, 'allowCustomizedBuiltInElements') && typeof customElementHandling.allowCustomizedBuiltInElements === 'boolean') {
|
|
2418
|
+
CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = customElementHandling.allowCustomizedBuiltInElements; // Default undefined
|
|
2342
2419
|
}
|
|
2343
2420
|
if (SAFE_FOR_TEMPLATES) {
|
|
2344
2421
|
ALLOW_DATA_ATTR = false;
|
|
@@ -2349,7 +2426,7 @@ $\
|
|
|
2349
2426
|
/* Parse profile info */
|
|
2350
2427
|
if (USE_PROFILES) {
|
|
2351
2428
|
ALLOWED_TAGS = addToSet({}, text);
|
|
2352
|
-
ALLOWED_ATTR =
|
|
2429
|
+
ALLOWED_ATTR = create(null);
|
|
2353
2430
|
if (USE_PROFILES.html === true) {
|
|
2354
2431
|
addToSet(ALLOWED_TAGS, html$1);
|
|
2355
2432
|
addToSet(ALLOWED_ATTR, html);
|
|
@@ -2370,28 +2447,46 @@ $\
|
|
|
2370
2447
|
addToSet(ALLOWED_ATTR, xml);
|
|
2371
2448
|
}
|
|
2372
2449
|
}
|
|
2450
|
+
/* Always reset function-based ADD_TAGS / ADD_ATTR checks to prevent
|
|
2451
|
+
* leaking across calls when switching from function to array config */
|
|
2452
|
+
EXTRA_ELEMENT_HANDLING.tagCheck = null;
|
|
2453
|
+
EXTRA_ELEMENT_HANDLING.attributeCheck = null;
|
|
2373
2454
|
/* Merge configuration parameters */
|
|
2374
|
-
if (cfg
|
|
2375
|
-
if (
|
|
2376
|
-
|
|
2455
|
+
if (objectHasOwnProperty(cfg, 'ADD_TAGS')) {
|
|
2456
|
+
if (typeof cfg.ADD_TAGS === 'function') {
|
|
2457
|
+
EXTRA_ELEMENT_HANDLING.tagCheck = cfg.ADD_TAGS;
|
|
2458
|
+
} else if (arrayIsArray(cfg.ADD_TAGS)) {
|
|
2459
|
+
if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
|
|
2460
|
+
ALLOWED_TAGS = clone(ALLOWED_TAGS);
|
|
2461
|
+
}
|
|
2462
|
+
addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);
|
|
2377
2463
|
}
|
|
2378
|
-
addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);
|
|
2379
2464
|
}
|
|
2380
|
-
if (cfg
|
|
2381
|
-
if (
|
|
2382
|
-
|
|
2465
|
+
if (objectHasOwnProperty(cfg, 'ADD_ATTR')) {
|
|
2466
|
+
if (typeof cfg.ADD_ATTR === 'function') {
|
|
2467
|
+
EXTRA_ELEMENT_HANDLING.attributeCheck = cfg.ADD_ATTR;
|
|
2468
|
+
} else if (arrayIsArray(cfg.ADD_ATTR)) {
|
|
2469
|
+
if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
|
|
2470
|
+
ALLOWED_ATTR = clone(ALLOWED_ATTR);
|
|
2471
|
+
}
|
|
2472
|
+
addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);
|
|
2383
2473
|
}
|
|
2384
|
-
addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);
|
|
2385
2474
|
}
|
|
2386
|
-
if (cfg.ADD_URI_SAFE_ATTR) {
|
|
2475
|
+
if (objectHasOwnProperty(cfg, 'ADD_URI_SAFE_ATTR') && arrayIsArray(cfg.ADD_URI_SAFE_ATTR)) {
|
|
2387
2476
|
addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);
|
|
2388
2477
|
}
|
|
2389
|
-
if (cfg.FORBID_CONTENTS) {
|
|
2478
|
+
if (objectHasOwnProperty(cfg, 'FORBID_CONTENTS') && arrayIsArray(cfg.FORBID_CONTENTS)) {
|
|
2390
2479
|
if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
|
|
2391
2480
|
FORBID_CONTENTS = clone(FORBID_CONTENTS);
|
|
2392
2481
|
}
|
|
2393
2482
|
addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);
|
|
2394
2483
|
}
|
|
2484
|
+
if (objectHasOwnProperty(cfg, 'ADD_FORBID_CONTENTS') && arrayIsArray(cfg.ADD_FORBID_CONTENTS)) {
|
|
2485
|
+
if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
|
|
2486
|
+
FORBID_CONTENTS = clone(FORBID_CONTENTS);
|
|
2487
|
+
}
|
|
2488
|
+
addToSet(FORBID_CONTENTS, cfg.ADD_FORBID_CONTENTS, transformCaseFunc);
|
|
2489
|
+
}
|
|
2395
2490
|
/* Add #text in case KEEP_CONTENT is set to true */
|
|
2396
2491
|
if (KEEP_CONTENT) {
|
|
2397
2492
|
ALLOWED_TAGS['#text'] = true;
|
|
@@ -2678,6 +2773,11 @@ $\
|
|
|
2678
2773
|
_forceRemove(currentNode);
|
|
2679
2774
|
return true;
|
|
2680
2775
|
}
|
|
2776
|
+
/* Remove risky CSS construction leading to mXSS */
|
|
2777
|
+
if (SAFE_FOR_XML && currentNode.namespaceURI === HTML_NAMESPACE && tagName === 'style' && _isNode(currentNode.firstElementChild)) {
|
|
2778
|
+
_forceRemove(currentNode);
|
|
2779
|
+
return true;
|
|
2780
|
+
}
|
|
2681
2781
|
/* Remove any occurrence of processing instructions */
|
|
2682
2782
|
if (currentNode.nodeType === NODE_TYPE.progressingInstruction) {
|
|
2683
2783
|
_forceRemove(currentNode);
|
|
@@ -2689,7 +2789,7 @@ $\
|
|
|
2689
2789
|
return true;
|
|
2690
2790
|
}
|
|
2691
2791
|
/* Remove element if anything forbids its presence */
|
|
2692
|
-
if (
|
|
2792
|
+
if (FORBID_TAGS[tagName] || !(EXTRA_ELEMENT_HANDLING.tagCheck instanceof Function && EXTRA_ELEMENT_HANDLING.tagCheck(tagName)) && !ALLOWED_TAGS[tagName]) {
|
|
2693
2793
|
/* Check if we have a custom element to handle */
|
|
2694
2794
|
if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName)) {
|
|
2695
2795
|
if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) {
|
|
@@ -2707,7 +2807,6 @@ $\
|
|
|
2707
2807
|
const childCount = childNodes.length;
|
|
2708
2808
|
for (let i = childCount - 1; i >= 0; --i) {
|
|
2709
2809
|
const childClone = cloneNode(childNodes[i], true);
|
|
2710
|
-
childClone.__removalCount = (currentNode.__removalCount || 0) + 1;
|
|
2711
2810
|
parentNode.insertBefore(childClone, getNextSibling(currentNode));
|
|
2712
2811
|
}
|
|
2713
2812
|
}
|
|
@@ -2753,15 +2852,20 @@ $\
|
|
|
2753
2852
|
*/
|
|
2754
2853
|
// eslint-disable-next-line complexity
|
|
2755
2854
|
const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
|
|
2855
|
+
/* FORBID_ATTR must always win, even if ADD_ATTR predicate would allow it */
|
|
2856
|
+
if (FORBID_ATTR[lcName]) {
|
|
2857
|
+
return false;
|
|
2858
|
+
}
|
|
2756
2859
|
/* Make sure attribute cannot clobber */
|
|
2757
2860
|
if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
|
|
2758
2861
|
return false;
|
|
2759
2862
|
}
|
|
2863
|
+
const nameIsPermitted = ALLOWED_ATTR[lcName] || EXTRA_ELEMENT_HANDLING.attributeCheck instanceof Function && EXTRA_ELEMENT_HANDLING.attributeCheck(lcName, lcTag);
|
|
2760
2864
|
/* Allow valid data-* attributes: At least one character after "-"
|
|
2761
2865
|
(https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
|
|
2762
2866
|
XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
|
|
2763
2867
|
We don't need to check the value; it's always URI safe. */
|
|
2764
|
-
if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR, lcName)) ;else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR, lcName)) ;else if (!
|
|
2868
|
+
if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR, lcName)) ;else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR, lcName)) ;else if (!nameIsPermitted || FORBID_ATTR[lcName]) {
|
|
2765
2869
|
if (
|
|
2766
2870
|
// First condition does a very basic check if a) it's basically a valid custom element tagname AND
|
|
2767
2871
|
// b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
|
|
@@ -2778,6 +2882,10 @@ $\
|
|
|
2778
2882
|
} else ;
|
|
2779
2883
|
return true;
|
|
2780
2884
|
};
|
|
2885
|
+
/* Names the HTML spec reserves from valid-custom-element-name; these must
|
|
2886
|
+
* never be treated as basic custom elements even when a permissive
|
|
2887
|
+
* CUSTOM_ELEMENT_HANDLING.tagNameCheck is configured. */
|
|
2888
|
+
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']);
|
|
2781
2889
|
/**
|
|
2782
2890
|
* _isBasicCustomElement
|
|
2783
2891
|
* checks if at least one dash is included in tagName, and it's not the first char
|
|
@@ -2787,7 +2895,7 @@ $\
|
|
|
2787
2895
|
* @returns Returns true if the tag name meets the basic criteria for a custom element, otherwise false.
|
|
2788
2896
|
*/
|
|
2789
2897
|
const _isBasicCustomElement = function _isBasicCustomElement(tagName) {
|
|
2790
|
-
return tagName
|
|
2898
|
+
return !RESERVED_CUSTOM_ELEMENT_NAMES[stringToLowerCase(tagName)] && regExpTest(CUSTOM_ELEMENT, tagName);
|
|
2791
2899
|
};
|
|
2792
2900
|
/**
|
|
2793
2901
|
* _sanitizeAttributes
|
|
@@ -2838,14 +2946,16 @@ $\
|
|
|
2838
2946
|
/* Full DOM Clobbering protection via namespace isolation,
|
|
2839
2947
|
* Prefix id and name attributes with `user-content-`
|
|
2840
2948
|
*/
|
|
2841
|
-
if (SANITIZE_NAMED_PROPS && (lcName === 'id' || lcName === 'name')) {
|
|
2949
|
+
if (SANITIZE_NAMED_PROPS && (lcName === 'id' || lcName === 'name') && stringIndexOf(value, SANITIZE_NAMED_PROPS_PREFIX) !== 0) {
|
|
2842
2950
|
// Remove the attribute with this value
|
|
2843
2951
|
_removeAttribute(name, currentNode);
|
|
2844
2952
|
// Prefix the value and later re-create the attribute with the sanitized value
|
|
2845
2953
|
value = SANITIZE_NAMED_PROPS_PREFIX + value;
|
|
2846
2954
|
}
|
|
2955
|
+
// Else: already prefixed, leave the attribute alone — the prefix is
|
|
2956
|
+
// itself the clobbering protection, and re-applying it is incorrect.
|
|
2847
2957
|
/* Work around a security issue with comments inside attributes */
|
|
2848
|
-
if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|title|textarea)/i, value)) {
|
|
2958
|
+
if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|script|title|xmp|textarea|noscript|iframe|noembed|noframes)/i, value)) {
|
|
2849
2959
|
_removeAttribute(name, currentNode);
|
|
2850
2960
|
continue;
|
|
2851
2961
|
}
|
|
@@ -2924,7 +3034,7 @@ $\
|
|
|
2924
3034
|
*
|
|
2925
3035
|
* @param fragment to iterate over recursively
|
|
2926
3036
|
*/
|
|
2927
|
-
const
|
|
3037
|
+
const _sanitizeShadowDOM2 = function _sanitizeShadowDOM(fragment) {
|
|
2928
3038
|
let shadowNode = null;
|
|
2929
3039
|
const shadowIterator = _createNodeIterator(fragment);
|
|
2930
3040
|
/* Execute a hook if present */
|
|
@@ -2938,7 +3048,7 @@ $\
|
|
|
2938
3048
|
_sanitizeAttributes(shadowNode);
|
|
2939
3049
|
/* Deep shadow DOM detected */
|
|
2940
3050
|
if (shadowNode.content instanceof DocumentFragment) {
|
|
2941
|
-
|
|
3051
|
+
_sanitizeShadowDOM2(shadowNode.content);
|
|
2942
3052
|
}
|
|
2943
3053
|
}
|
|
2944
3054
|
/* Execute a hook if present */
|
|
@@ -2960,13 +3070,9 @@ $\
|
|
|
2960
3070
|
}
|
|
2961
3071
|
/* Stringify, in case dirty is an object */
|
|
2962
3072
|
if (typeof dirty !== 'string' && !_isNode(dirty)) {
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
throw typeErrorCreate('dirty is not a string, aborting');
|
|
2967
|
-
}
|
|
2968
|
-
} else {
|
|
2969
|
-
throw typeErrorCreate('toString is not a function');
|
|
3073
|
+
dirty = stringifyValue(dirty);
|
|
3074
|
+
if (typeof dirty !== 'string') {
|
|
3075
|
+
throw typeErrorCreate('dirty is not a string, aborting');
|
|
2970
3076
|
}
|
|
2971
3077
|
}
|
|
2972
3078
|
/* Return dirty HTML if DOMPurify cannot run */
|
|
@@ -2985,8 +3091,9 @@ $\
|
|
|
2985
3091
|
}
|
|
2986
3092
|
if (IN_PLACE) {
|
|
2987
3093
|
/* Do some early pre-sanitization to avoid unsafe root nodes */
|
|
2988
|
-
|
|
2989
|
-
|
|
3094
|
+
const nn = dirty.nodeName;
|
|
3095
|
+
if (typeof nn === 'string') {
|
|
3096
|
+
const tagName = transformCaseFunc(nn);
|
|
2990
3097
|
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
|
|
2991
3098
|
throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');
|
|
2992
3099
|
}
|
|
@@ -3033,7 +3140,7 @@ $\
|
|
|
3033
3140
|
_sanitizeAttributes(currentNode);
|
|
3034
3141
|
/* Shadow DOM detected, sanitize it */
|
|
3035
3142
|
if (currentNode.content instanceof DocumentFragment) {
|
|
3036
|
-
|
|
3143
|
+
_sanitizeShadowDOM2(currentNode.content);
|
|
3037
3144
|
}
|
|
3038
3145
|
}
|
|
3039
3146
|
/* If we sanitized `dirty` in-place, return it. */
|
|
@@ -3042,6 +3149,14 @@ $\
|
|
|
3042
3149
|
}
|
|
3043
3150
|
/* Return sanitized string or DOM */
|
|
3044
3151
|
if (RETURN_DOM) {
|
|
3152
|
+
if (SAFE_FOR_TEMPLATES) {
|
|
3153
|
+
body.normalize();
|
|
3154
|
+
let html = body.innerHTML;
|
|
3155
|
+
arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr => {
|
|
3156
|
+
html = stringReplace(html, expr, ' ');
|
|
3157
|
+
});
|
|
3158
|
+
body.innerHTML = html;
|
|
3159
|
+
}
|
|
3045
3160
|
if (RETURN_DOM_FRAGMENT) {
|
|
3046
3161
|
returnNode = createDocumentFragment.call(body.ownerDocument);
|
|
3047
3162
|
while (body.firstChild) {
|
|
@@ -6862,7 +6977,13 @@ $\
|
|
|
6862
6977
|
|
|
6863
6978
|
class StringPiece extends Piece {
|
|
6864
6979
|
static fromJSON(pieceJSON) {
|
|
6865
|
-
|
|
6980
|
+
const attributes = {
|
|
6981
|
+
...pieceJSON.attributes
|
|
6982
|
+
};
|
|
6983
|
+
if (attributes.href && !purify.isValidAttribute("a", "href", attributes.href)) {
|
|
6984
|
+
delete attributes.href;
|
|
6985
|
+
}
|
|
6986
|
+
return new this(pieceJSON.string, attributes);
|
|
6866
6987
|
}
|
|
6867
6988
|
constructor(string) {
|
|
6868
6989
|
super(...arguments);
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: action_text-trix
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.1.
|
|
4
|
+
version: 2.1.19
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- 37signals, LLC
|
|
@@ -55,7 +55,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
55
55
|
- !ruby/object:Gem::Version
|
|
56
56
|
version: '0'
|
|
57
57
|
requirements: []
|
|
58
|
-
rubygems_version: 4.0.
|
|
58
|
+
rubygems_version: 4.0.6
|
|
59
59
|
specification_version: 4
|
|
60
60
|
summary: A rich text editor for everyday writing
|
|
61
61
|
test_files: []
|