action_text-trix 2.1.16 → 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 +209 -74
- 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,6 +1,6 @@
|
|
|
1
1
|
/*
|
|
2
|
-
Trix 2.1.
|
|
3
|
-
Copyright ©
|
|
2
|
+
Trix 2.1.19
|
|
3
|
+
Copyright © 2026 37signals, LLC
|
|
4
4
|
*/
|
|
5
5
|
(function (global, factory) {
|
|
6
6
|
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
|
@@ -9,7 +9,7 @@ Copyright © 2025 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";
|
|
@@ -43,22 +43,22 @@ Copyright © 2025 37signals, LLC
|
|
|
43
43
|
"@rollup/plugin-json": "^4.1.0",
|
|
44
44
|
"@rollup/plugin-node-resolve": "^13.3.0",
|
|
45
45
|
"@web/dev-server": "^0.1.34",
|
|
46
|
+
"@web/test-runner": "^0.20.2",
|
|
47
|
+
"@web/test-runner-playwright": "^0.11.1",
|
|
48
|
+
"@web/test-runner-webdriver": "^0.9.0",
|
|
46
49
|
"babel-eslint": "^10.1.0",
|
|
47
50
|
chokidar: "^4.0.2",
|
|
48
51
|
concurrently: "^7.4.0",
|
|
49
52
|
eslint: "^7.32.0",
|
|
50
53
|
esm: "^3.2.25",
|
|
51
54
|
idiomorph: "^0.7.3",
|
|
52
|
-
karma: "6.4.1",
|
|
53
|
-
"karma-chrome-launcher": "3.2.0",
|
|
54
|
-
"karma-qunit": "^4.1.2",
|
|
55
|
-
"karma-sauce-launcher": "^4.3.6",
|
|
56
55
|
qunit: "2.19.1",
|
|
57
56
|
rangy: "^1.3.0",
|
|
58
57
|
rollup: "^2.56.3",
|
|
59
58
|
"rollup-plugin-includepaths": "^0.2.4",
|
|
60
59
|
"rollup-plugin-terser": "^7.0.2",
|
|
61
60
|
sass: "^1.83.0",
|
|
61
|
+
"source-map": "^0.7.6",
|
|
62
62
|
svgo: "^2.8.0",
|
|
63
63
|
webdriverio: "^7.19.5"
|
|
64
64
|
};
|
|
@@ -74,7 +74,8 @@ Copyright © 2025 37signals, LLC
|
|
|
74
74
|
watch: "rollup -c -w",
|
|
75
75
|
lint: "eslint .",
|
|
76
76
|
pretest: "yarn run lint && yarn run build",
|
|
77
|
-
test: "
|
|
77
|
+
test: "web-test-runner",
|
|
78
|
+
"test:watch": "web-test-runner --watch",
|
|
78
79
|
version: "yarn build && git add action_text-trix",
|
|
79
80
|
prerelease: "yarn version && yarn test",
|
|
80
81
|
"release-npm": "npm adduser && npm publish",
|
|
@@ -1764,7 +1765,7 @@ $\
|
|
|
1764
1765
|
}
|
|
1765
1766
|
}
|
|
1766
1767
|
|
|
1767
|
-
/*! @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 */
|
|
1768
1769
|
|
|
1769
1770
|
const {
|
|
1770
1771
|
entries,
|
|
@@ -1813,13 +1814,19 @@ $\
|
|
|
1813
1814
|
const arrayPop = unapply(Array.prototype.pop);
|
|
1814
1815
|
const arrayPush = unapply(Array.prototype.push);
|
|
1815
1816
|
const arraySplice = unapply(Array.prototype.splice);
|
|
1817
|
+
const arrayIsArray = Array.isArray;
|
|
1816
1818
|
const stringToLowerCase = unapply(String.prototype.toLowerCase);
|
|
1817
1819
|
const stringToString = unapply(String.prototype.toString);
|
|
1818
1820
|
const stringMatch = unapply(String.prototype.match);
|
|
1819
1821
|
const stringReplace = unapply(String.prototype.replace);
|
|
1820
1822
|
const stringIndexOf = unapply(String.prototype.indexOf);
|
|
1821
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);
|
|
1822
1828
|
const objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);
|
|
1829
|
+
const objectToString = unapply(Object.prototype.toString);
|
|
1823
1830
|
const regExpTest = unapply(RegExp.prototype.test);
|
|
1824
1831
|
const typeErrorCreate = unconstruct(TypeError);
|
|
1825
1832
|
/**
|
|
@@ -1869,6 +1876,9 @@ $\
|
|
|
1869
1876
|
// Prevent prototype setters from intercepting set as a this value.
|
|
1870
1877
|
setPrototypeOf(set, null);
|
|
1871
1878
|
}
|
|
1879
|
+
if (!arrayIsArray(array)) {
|
|
1880
|
+
return set;
|
|
1881
|
+
}
|
|
1872
1882
|
let l = array.length;
|
|
1873
1883
|
while (l--) {
|
|
1874
1884
|
let element = array[l];
|
|
@@ -1912,7 +1922,7 @@ $\
|
|
|
1912
1922
|
for (const [property, value] of entries(object)) {
|
|
1913
1923
|
const isPropertyExist = objectHasOwnProperty(object, property);
|
|
1914
1924
|
if (isPropertyExist) {
|
|
1915
|
-
if (
|
|
1925
|
+
if (arrayIsArray(value)) {
|
|
1916
1926
|
newObject[property] = cleanArray(value);
|
|
1917
1927
|
} else if (value && typeof value === 'object' && value.constructor === Object) {
|
|
1918
1928
|
newObject[property] = clone(value);
|
|
@@ -1923,6 +1933,58 @@ $\
|
|
|
1923
1933
|
}
|
|
1924
1934
|
return newObject;
|
|
1925
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
|
+
}
|
|
1926
1988
|
/**
|
|
1927
1989
|
* This method automatically checks if the prop is function or getter and behaves accordingly.
|
|
1928
1990
|
*
|
|
@@ -1948,8 +2010,16 @@ $\
|
|
|
1948
2010
|
}
|
|
1949
2011
|
return fallbackValue;
|
|
1950
2012
|
}
|
|
2013
|
+
function isRegex(value) {
|
|
2014
|
+
try {
|
|
2015
|
+
regExpTest(value, '');
|
|
2016
|
+
return true;
|
|
2017
|
+
} catch (_unused) {
|
|
2018
|
+
return false;
|
|
2019
|
+
}
|
|
2020
|
+
}
|
|
1951
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']);
|
|
1952
|
-
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']);
|
|
1953
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']);
|
|
1954
2024
|
// List of SVG elements that are disallowed by default.
|
|
1955
2025
|
// We still need to know them so that we can do namespace
|
|
@@ -1961,9 +2031,9 @@ $\
|
|
|
1961
2031
|
// even those that we disallow by default.
|
|
1962
2032
|
const mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);
|
|
1963
2033
|
const text = freeze(['#text']);
|
|
1964
|
-
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'
|
|
1965
|
-
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']);
|
|
1966
|
-
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']);
|
|
1967
2037
|
const xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
|
|
1968
2038
|
|
|
1969
2039
|
// eslint-disable-next-line unicorn/better-regex
|
|
@@ -1997,19 +2067,11 @@ $\
|
|
|
1997
2067
|
// https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
|
|
1998
2068
|
const NODE_TYPE = {
|
|
1999
2069
|
element: 1,
|
|
2000
|
-
attribute: 2,
|
|
2001
2070
|
text: 3,
|
|
2002
|
-
cdataSection: 4,
|
|
2003
|
-
entityReference: 5,
|
|
2004
|
-
// Deprecated
|
|
2005
|
-
entityNode: 6,
|
|
2006
2071
|
// Deprecated
|
|
2007
2072
|
progressingInstruction: 7,
|
|
2008
2073
|
comment: 8,
|
|
2009
|
-
document: 9
|
|
2010
|
-
documentType: 10,
|
|
2011
|
-
documentFragment: 11,
|
|
2012
|
-
notation: 12 // Deprecated
|
|
2074
|
+
document: 9
|
|
2013
2075
|
};
|
|
2014
2076
|
const getGlobal = function getGlobal() {
|
|
2015
2077
|
return typeof window === 'undefined' ? null : window;
|
|
@@ -2068,7 +2130,7 @@ $\
|
|
|
2068
2130
|
function createDOMPurify() {
|
|
2069
2131
|
let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
|
|
2070
2132
|
const DOMPurify = root => createDOMPurify(root);
|
|
2071
|
-
DOMPurify.version = '3.2
|
|
2133
|
+
DOMPurify.version = '3.4.2';
|
|
2072
2134
|
DOMPurify.removed = [];
|
|
2073
2135
|
if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document || !window.Element) {
|
|
2074
2136
|
// Not running in a browser, provide a factory function
|
|
@@ -2179,6 +2241,21 @@ $\
|
|
|
2179
2241
|
let FORBID_TAGS = null;
|
|
2180
2242
|
/* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */
|
|
2181
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
|
+
}));
|
|
2182
2259
|
/* Decide if ARIA attributes are okay */
|
|
2183
2260
|
let ALLOW_ARIA_ATTR = true;
|
|
2184
2261
|
/* Decide if custom data attributes are okay */
|
|
@@ -2301,15 +2378,15 @@ $\
|
|
|
2301
2378
|
// HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.
|
|
2302
2379
|
transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? stringToString : stringToLowerCase;
|
|
2303
2380
|
/* Set configuration parameters */
|
|
2304
|
-
ALLOWED_TAGS = objectHasOwnProperty(cfg, 'ALLOWED_TAGS') ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS;
|
|
2305
|
-
ALLOWED_ATTR = objectHasOwnProperty(cfg, 'ALLOWED_ATTR') ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;
|
|
2306
|
-
ALLOWED_NAMESPACES = objectHasOwnProperty(cfg, 'ALLOWED_NAMESPACES') ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES;
|
|
2307
|
-
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;
|
|
2308
|
-
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;
|
|
2309
|
-
FORBID_CONTENTS = objectHasOwnProperty(cfg, 'FORBID_CONTENTS') ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS;
|
|
2310
|
-
FORBID_TAGS = objectHasOwnProperty(cfg, 'FORBID_TAGS') ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : clone({});
|
|
2311
|
-
FORBID_ATTR = objectHasOwnProperty(cfg, 'FORBID_ATTR') ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : clone({});
|
|
2312
|
-
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;
|
|
2313
2390
|
ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true
|
|
2314
2391
|
ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true
|
|
2315
2392
|
ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false
|
|
@@ -2325,19 +2402,20 @@ $\
|
|
|
2325
2402
|
SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false; // Default false
|
|
2326
2403
|
KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
|
|
2327
2404
|
IN_PLACE = cfg.IN_PLACE || false; // Default false
|
|
2328
|
-
IS_ALLOWED_URI$1 = cfg.ALLOWED_URI_REGEXP
|
|
2329
|
-
NAMESPACE = cfg.NAMESPACE
|
|
2330
|
-
MATHML_TEXT_INTEGRATION_POINTS = cfg.MATHML_TEXT_INTEGRATION_POINTS
|
|
2331
|
-
HTML_INTEGRATION_POINTS = cfg.HTML_INTEGRATION_POINTS
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
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
|
|
2335
2413
|
}
|
|
2336
|
-
if (
|
|
2337
|
-
CUSTOM_ELEMENT_HANDLING.attributeNameCheck =
|
|
2414
|
+
if (objectHasOwnProperty(customElementHandling, 'attributeNameCheck') && isRegexOrFunction(customElementHandling.attributeNameCheck)) {
|
|
2415
|
+
CUSTOM_ELEMENT_HANDLING.attributeNameCheck = customElementHandling.attributeNameCheck; // Default undefined
|
|
2338
2416
|
}
|
|
2339
|
-
if (
|
|
2340
|
-
CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements =
|
|
2417
|
+
if (objectHasOwnProperty(customElementHandling, 'allowCustomizedBuiltInElements') && typeof customElementHandling.allowCustomizedBuiltInElements === 'boolean') {
|
|
2418
|
+
CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = customElementHandling.allowCustomizedBuiltInElements; // Default undefined
|
|
2341
2419
|
}
|
|
2342
2420
|
if (SAFE_FOR_TEMPLATES) {
|
|
2343
2421
|
ALLOW_DATA_ATTR = false;
|
|
@@ -2348,7 +2426,7 @@ $\
|
|
|
2348
2426
|
/* Parse profile info */
|
|
2349
2427
|
if (USE_PROFILES) {
|
|
2350
2428
|
ALLOWED_TAGS = addToSet({}, text);
|
|
2351
|
-
ALLOWED_ATTR =
|
|
2429
|
+
ALLOWED_ATTR = create(null);
|
|
2352
2430
|
if (USE_PROFILES.html === true) {
|
|
2353
2431
|
addToSet(ALLOWED_TAGS, html$1);
|
|
2354
2432
|
addToSet(ALLOWED_ATTR, html);
|
|
@@ -2369,28 +2447,46 @@ $\
|
|
|
2369
2447
|
addToSet(ALLOWED_ATTR, xml);
|
|
2370
2448
|
}
|
|
2371
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;
|
|
2372
2454
|
/* Merge configuration parameters */
|
|
2373
|
-
if (cfg
|
|
2374
|
-
if (
|
|
2375
|
-
|
|
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);
|
|
2376
2463
|
}
|
|
2377
|
-
addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);
|
|
2378
2464
|
}
|
|
2379
|
-
if (cfg
|
|
2380
|
-
if (
|
|
2381
|
-
|
|
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);
|
|
2382
2473
|
}
|
|
2383
|
-
addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);
|
|
2384
2474
|
}
|
|
2385
|
-
if (cfg.ADD_URI_SAFE_ATTR) {
|
|
2475
|
+
if (objectHasOwnProperty(cfg, 'ADD_URI_SAFE_ATTR') && arrayIsArray(cfg.ADD_URI_SAFE_ATTR)) {
|
|
2386
2476
|
addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);
|
|
2387
2477
|
}
|
|
2388
|
-
if (cfg.FORBID_CONTENTS) {
|
|
2478
|
+
if (objectHasOwnProperty(cfg, 'FORBID_CONTENTS') && arrayIsArray(cfg.FORBID_CONTENTS)) {
|
|
2389
2479
|
if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
|
|
2390
2480
|
FORBID_CONTENTS = clone(FORBID_CONTENTS);
|
|
2391
2481
|
}
|
|
2392
2482
|
addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);
|
|
2393
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
|
+
}
|
|
2394
2490
|
/* Add #text in case KEEP_CONTENT is set to true */
|
|
2395
2491
|
if (KEEP_CONTENT) {
|
|
2396
2492
|
ALLOWED_TAGS['#text'] = true;
|
|
@@ -2677,6 +2773,11 @@ $\
|
|
|
2677
2773
|
_forceRemove(currentNode);
|
|
2678
2774
|
return true;
|
|
2679
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
|
+
}
|
|
2680
2781
|
/* Remove any occurrence of processing instructions */
|
|
2681
2782
|
if (currentNode.nodeType === NODE_TYPE.progressingInstruction) {
|
|
2682
2783
|
_forceRemove(currentNode);
|
|
@@ -2688,7 +2789,7 @@ $\
|
|
|
2688
2789
|
return true;
|
|
2689
2790
|
}
|
|
2690
2791
|
/* Remove element if anything forbids its presence */
|
|
2691
|
-
if (
|
|
2792
|
+
if (FORBID_TAGS[tagName] || !(EXTRA_ELEMENT_HANDLING.tagCheck instanceof Function && EXTRA_ELEMENT_HANDLING.tagCheck(tagName)) && !ALLOWED_TAGS[tagName]) {
|
|
2692
2793
|
/* Check if we have a custom element to handle */
|
|
2693
2794
|
if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName)) {
|
|
2694
2795
|
if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) {
|
|
@@ -2706,7 +2807,6 @@ $\
|
|
|
2706
2807
|
const childCount = childNodes.length;
|
|
2707
2808
|
for (let i = childCount - 1; i >= 0; --i) {
|
|
2708
2809
|
const childClone = cloneNode(childNodes[i], true);
|
|
2709
|
-
childClone.__removalCount = (currentNode.__removalCount || 0) + 1;
|
|
2710
2810
|
parentNode.insertBefore(childClone, getNextSibling(currentNode));
|
|
2711
2811
|
}
|
|
2712
2812
|
}
|
|
@@ -2752,15 +2852,20 @@ $\
|
|
|
2752
2852
|
*/
|
|
2753
2853
|
// eslint-disable-next-line complexity
|
|
2754
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
|
+
}
|
|
2755
2859
|
/* Make sure attribute cannot clobber */
|
|
2756
2860
|
if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
|
|
2757
2861
|
return false;
|
|
2758
2862
|
}
|
|
2863
|
+
const nameIsPermitted = ALLOWED_ATTR[lcName] || EXTRA_ELEMENT_HANDLING.attributeCheck instanceof Function && EXTRA_ELEMENT_HANDLING.attributeCheck(lcName, lcTag);
|
|
2759
2864
|
/* Allow valid data-* attributes: At least one character after "-"
|
|
2760
2865
|
(https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
|
|
2761
2866
|
XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
|
|
2762
2867
|
We don't need to check the value; it's always URI safe. */
|
|
2763
|
-
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]) {
|
|
2764
2869
|
if (
|
|
2765
2870
|
// First condition does a very basic check if a) it's basically a valid custom element tagname AND
|
|
2766
2871
|
// b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
|
|
@@ -2777,6 +2882,10 @@ $\
|
|
|
2777
2882
|
} else ;
|
|
2778
2883
|
return true;
|
|
2779
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']);
|
|
2780
2889
|
/**
|
|
2781
2890
|
* _isBasicCustomElement
|
|
2782
2891
|
* checks if at least one dash is included in tagName, and it's not the first char
|
|
@@ -2786,7 +2895,7 @@ $\
|
|
|
2786
2895
|
* @returns Returns true if the tag name meets the basic criteria for a custom element, otherwise false.
|
|
2787
2896
|
*/
|
|
2788
2897
|
const _isBasicCustomElement = function _isBasicCustomElement(tagName) {
|
|
2789
|
-
return tagName
|
|
2898
|
+
return !RESERVED_CUSTOM_ELEMENT_NAMES[stringToLowerCase(tagName)] && regExpTest(CUSTOM_ELEMENT, tagName);
|
|
2790
2899
|
};
|
|
2791
2900
|
/**
|
|
2792
2901
|
* _sanitizeAttributes
|
|
@@ -2837,14 +2946,16 @@ $\
|
|
|
2837
2946
|
/* Full DOM Clobbering protection via namespace isolation,
|
|
2838
2947
|
* Prefix id and name attributes with `user-content-`
|
|
2839
2948
|
*/
|
|
2840
|
-
if (SANITIZE_NAMED_PROPS && (lcName === 'id' || lcName === 'name')) {
|
|
2949
|
+
if (SANITIZE_NAMED_PROPS && (lcName === 'id' || lcName === 'name') && stringIndexOf(value, SANITIZE_NAMED_PROPS_PREFIX) !== 0) {
|
|
2841
2950
|
// Remove the attribute with this value
|
|
2842
2951
|
_removeAttribute(name, currentNode);
|
|
2843
2952
|
// Prefix the value and later re-create the attribute with the sanitized value
|
|
2844
2953
|
value = SANITIZE_NAMED_PROPS_PREFIX + value;
|
|
2845
2954
|
}
|
|
2955
|
+
// Else: already prefixed, leave the attribute alone — the prefix is
|
|
2956
|
+
// itself the clobbering protection, and re-applying it is incorrect.
|
|
2846
2957
|
/* Work around a security issue with comments inside attributes */
|
|
2847
|
-
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)) {
|
|
2848
2959
|
_removeAttribute(name, currentNode);
|
|
2849
2960
|
continue;
|
|
2850
2961
|
}
|
|
@@ -2923,7 +3034,7 @@ $\
|
|
|
2923
3034
|
*
|
|
2924
3035
|
* @param fragment to iterate over recursively
|
|
2925
3036
|
*/
|
|
2926
|
-
const
|
|
3037
|
+
const _sanitizeShadowDOM2 = function _sanitizeShadowDOM(fragment) {
|
|
2927
3038
|
let shadowNode = null;
|
|
2928
3039
|
const shadowIterator = _createNodeIterator(fragment);
|
|
2929
3040
|
/* Execute a hook if present */
|
|
@@ -2937,7 +3048,7 @@ $\
|
|
|
2937
3048
|
_sanitizeAttributes(shadowNode);
|
|
2938
3049
|
/* Deep shadow DOM detected */
|
|
2939
3050
|
if (shadowNode.content instanceof DocumentFragment) {
|
|
2940
|
-
|
|
3051
|
+
_sanitizeShadowDOM2(shadowNode.content);
|
|
2941
3052
|
}
|
|
2942
3053
|
}
|
|
2943
3054
|
/* Execute a hook if present */
|
|
@@ -2959,13 +3070,9 @@ $\
|
|
|
2959
3070
|
}
|
|
2960
3071
|
/* Stringify, in case dirty is an object */
|
|
2961
3072
|
if (typeof dirty !== 'string' && !_isNode(dirty)) {
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
throw typeErrorCreate('dirty is not a string, aborting');
|
|
2966
|
-
}
|
|
2967
|
-
} else {
|
|
2968
|
-
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');
|
|
2969
3076
|
}
|
|
2970
3077
|
}
|
|
2971
3078
|
/* Return dirty HTML if DOMPurify cannot run */
|
|
@@ -2984,8 +3091,9 @@ $\
|
|
|
2984
3091
|
}
|
|
2985
3092
|
if (IN_PLACE) {
|
|
2986
3093
|
/* Do some early pre-sanitization to avoid unsafe root nodes */
|
|
2987
|
-
|
|
2988
|
-
|
|
3094
|
+
const nn = dirty.nodeName;
|
|
3095
|
+
if (typeof nn === 'string') {
|
|
3096
|
+
const tagName = transformCaseFunc(nn);
|
|
2989
3097
|
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
|
|
2990
3098
|
throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');
|
|
2991
3099
|
}
|
|
@@ -3032,7 +3140,7 @@ $\
|
|
|
3032
3140
|
_sanitizeAttributes(currentNode);
|
|
3033
3141
|
/* Shadow DOM detected, sanitize it */
|
|
3034
3142
|
if (currentNode.content instanceof DocumentFragment) {
|
|
3035
|
-
|
|
3143
|
+
_sanitizeShadowDOM2(currentNode.content);
|
|
3036
3144
|
}
|
|
3037
3145
|
}
|
|
3038
3146
|
/* If we sanitized `dirty` in-place, return it. */
|
|
@@ -3041,6 +3149,14 @@ $\
|
|
|
3041
3149
|
}
|
|
3042
3150
|
/* Return sanitized string or DOM */
|
|
3043
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
|
+
}
|
|
3044
3160
|
if (RETURN_DOM_FRAGMENT) {
|
|
3045
3161
|
returnNode = createDocumentFragment.call(body.ownerDocument);
|
|
3046
3162
|
while (body.firstChild) {
|
|
@@ -3117,6 +3233,10 @@ $\
|
|
|
3117
3233
|
var purify = createDOMPurify();
|
|
3118
3234
|
|
|
3119
3235
|
purify.addHook("uponSanitizeAttribute", function (node, data) {
|
|
3236
|
+
if (data.attrName === "data-trix-serialized-attributes") {
|
|
3237
|
+
data.keepAttr = false;
|
|
3238
|
+
return;
|
|
3239
|
+
}
|
|
3120
3240
|
const allowedAttributePattern = /^data-trix-/;
|
|
3121
3241
|
if (allowedAttributePattern.test(data.attrName)) {
|
|
3122
3242
|
data.forceKeepAttr = true;
|
|
@@ -6857,7 +6977,13 @@ $\
|
|
|
6857
6977
|
|
|
6858
6978
|
class StringPiece extends Piece {
|
|
6859
6979
|
static fromJSON(pieceJSON) {
|
|
6860
|
-
|
|
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);
|
|
6861
6987
|
}
|
|
6862
6988
|
constructor(string) {
|
|
6863
6989
|
super(...arguments);
|
|
@@ -10043,6 +10169,15 @@ $\
|
|
|
10043
10169
|
} else {
|
|
10044
10170
|
if (node.parentNode === container) {
|
|
10045
10171
|
if (childIndex++ === offset) {
|
|
10172
|
+
if (!strict && nodeIsBlockStart(node, {
|
|
10173
|
+
strict
|
|
10174
|
+
})) {
|
|
10175
|
+
if (foundBlock) {
|
|
10176
|
+
location.index++;
|
|
10177
|
+
}
|
|
10178
|
+
location.offset = 0;
|
|
10179
|
+
foundBlock = true;
|
|
10180
|
+
}
|
|
10046
10181
|
break;
|
|
10047
10182
|
}
|
|
10048
10183
|
} else if (!elementContainsNode(container, node)) {
|
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: []
|