Skip to content

Commit

Permalink
Add support for regexes to allow property values
Browse files Browse the repository at this point in the history
Closes Gh-26.

Reviewed-by: Titus Wormer <tituswormer@gmail.com>
  • Loading branch information
aprendendofelipe committed Jan 3, 2023
1 parent ee07ff2 commit 7ca7c4c
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 10 deletions.
22 changes: 14 additions & 8 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
* Possible property values
* @typedef {string|number|boolean} PrimitivePropertyValue
* Possible primitive HTML attribute values
* @typedef {string|[string, ...Array<PrimitivePropertyValue>]} AttributeValue
* @typedef {Record<string, Array<PrimitivePropertyValue>>} AttributeMap
* @typedef {string|[string, ...Array<PrimitivePropertyValue|RegExp>]} AttributeValue
* @typedef {Record<string, Array<PrimitivePropertyValue|RegExp>>} AttributeMap
*
* @typedef Schema Sanitization configuration
* @property {Record<string, Array<AttributeValue>>} [attributes]
Expand Down Expand Up @@ -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<PrimitivePropertyValue>} */
/** @type {Array<PrimitivePropertyValue|RegExp>} */
let definition

if (own.call(allowed, key)) {
Expand Down Expand Up @@ -281,9 +281,10 @@ function handleDoctypeName() {
/**
* Sanitize `tagName`.
*
* @type {Handler}
* @param {unknown} tagName
* @param {Schema} schema
* @param {string} tagName
* @param {Node} _
* @param {Array<string>} stack
* @returns {string|false}
*/
function handleTagName(schema, tagName, _, stack) {
Expand Down Expand Up @@ -354,7 +355,7 @@ function allow(_, value) {
* @param {Schema} schema
* @param {Array<unknown>} values
* @param {string} prop
* @param {Array<PrimitivePropertyValue>} definition
* @param {Array<PrimitivePropertyValue|RegExp>} definition
* @returns {Array<string|number>}
*/
function handlePropertyValues(schema, values, prop, definition) {
Expand All @@ -380,7 +381,7 @@ function handlePropertyValues(schema, values, prop, definition) {
* @param {Schema} schema
* @param {unknown} value
* @param {string} prop
* @param {Array<PropertyValue>} definition
* @param {Array<PropertyValue|RegExp>} definition
* @returns {PropertyValue}
*/
function handlePropertyValue(schema, value, prop, definition) {
Expand All @@ -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 &&
Expand Down
5 changes: 3 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
24 changes: 24 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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', [
Expand Down

0 comments on commit 7ca7c4c

Please sign in to comment.