From 7ca7c4cbc652a740cb9f0193b8699800ed6e927f Mon Sep 17 00:00:00 2001 From: Felipe Barso <77860630+aprendendofelipe@users.noreply.github.com> Date: Tue, 3 Jan 2023 08:30:53 -0300 Subject: [PATCH] Add support for regexes to allow property values Closes Gh-26. Reviewed-by: Titus Wormer --- lib/index.js | 22 ++++++++++++++-------- readme.md | 5 +++-- test.js | 24 ++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 10 deletions(-) diff --git a/lib/index.js b/lib/index.js index de375b3..6ed22f5 100644 --- a/lib/index.js +++ b/lib/index.js @@ -9,8 +9,8 @@ * Possible property values * @typedef {string|number|boolean} PrimitivePropertyValue * Possible primitive HTML attribute values - * @typedef {string|[string, ...Array]} AttributeValue - * @typedef {Record>} AttributeMap + * @typedef {string|[string, ...Array]} AttributeValue + * @typedef {Record>} AttributeMap * * @typedef Schema Sanitization configuration * @property {Record>} [attributes] @@ -236,7 +236,7 @@ function handleProperties(schema, properties, node, stack) { for (key in props) { if (own.call(props, key)) { let value = props[key] - /** @type {Array} */ + /** @type {Array} */ let definition if (own.call(allowed, key)) { @@ -281,9 +281,10 @@ function handleDoctypeName() { /** * Sanitize `tagName`. * - * @type {Handler} - * @param {unknown} tagName + * @param {Schema} schema + * @param {string} tagName * @param {Node} _ + * @param {Array} stack * @returns {string|false} */ function handleTagName(schema, tagName, _, stack) { @@ -354,7 +355,7 @@ function allow(_, value) { * @param {Schema} schema * @param {Array} values * @param {string} prop - * @param {Array} definition + * @param {Array} definition * @returns {Array} */ function handlePropertyValues(schema, values, prop, definition) { @@ -380,7 +381,7 @@ function handlePropertyValues(schema, values, prop, definition) { * @param {Schema} schema * @param {unknown} value * @param {string} prop - * @param {Array} definition + * @param {Array} definition * @returns {PropertyValue} */ function handlePropertyValue(schema, value, prop, definition) { @@ -389,7 +390,12 @@ function handlePropertyValue(schema, value, prop, definition) { typeof value === 'number' || typeof value === 'string') && safeProtocol(schema, value, prop) && - (definition.length === 0 || definition.includes(value)) + (definition.length === 0 || + definition.some((allowed) => + allowed && typeof allowed === 'object' && 'flags' in allowed + ? allowed.test(String(value)) + : allowed === value + )) ) { return schema.clobberPrefix && schema.clobber && diff --git a/readme.md b/readme.md index fa56d68..acfdd37 100644 --- a/readme.md +++ b/readme.md @@ -192,8 +192,9 @@ attributes: { Instead of a single string (such as `type`), which allows any [*property value*][value] of that [*property name*][name], it’s also possible to provide -an array (such as `['type', 'checkbox']`), where the first entry is the -*property name*, and all other entries allowed *property values*. +an array (such as `['type', 'checkbox']` or `['className', /^hljs-/]`), +where the first entry is the *property name*, and all other entries are +*property values* allowed (or regular expressions that are tested with values). This is how the default GitHub schema allows only disabled checkbox inputs: ```js diff --git a/test.js b/test.js index d189861..0d8807d 100644 --- a/test.js +++ b/test.js @@ -610,6 +610,30 @@ test('sanitize()', (t) => { 'should support a list of valid values on new attributes' ) + t.deepEqual( + sanitize( + h('div', [ + h('span', {className: 'a-one'}), + h('span', {className: 'a-two'}), + h('span', {className: 'b-one'}), + h('span', {className: 'b-two'}), + h('span', {className: 'a-one a-two b-one b-two'}) + ]), + deepmerge(defaultSchema, { + tagNames: ['span'], + attributes: {span: [['className', /^a-/, 'b-one']]} + }) + ), + h('div', [ + h('span', {className: 'a-one'}), + h('span', {className: 'a-two'}), + h('span', {className: 'b-one'}), + h('span', {className: []}), + h('span', {className: 'a-one a-two b-one'}) + ]), + 'should support RegExp in the list of valid values' + ) + t.deepEqual( sanitize( h('div', [