2222 * @property {boolean } [allowComments] Whether to allow comments
2323 * @property {boolean } [allowDoctypes] Whether to allow doctypes
2424 *
25- * @typedef {(schema: Schema, value: unknown , node: Node , stack: Array.<string>) => unknown } Handler
25+ * @typedef {(schema: Schema, value: any , node: any , stack: Array.<string>) => unknown } Handler
2626 * @typedef {Object.<string, Handler> } NodeDefinition
27- * @typedef {((schema: Schema, node: Node) => NodeDefinition) } NodeDefinitionGetter
27+ * @typedef {((schema: Schema, node: Node) => NodeDefinition|undefined ) } NodeDefinitionGetter
2828 * @typedef {Object.<string, NodeDefinition|NodeDefinitionGetter> } NodeSchema
2929 */
3030
@@ -68,7 +68,7 @@ export function sanitize(node, schema) {
6868 if ( replace . length === 1 ) {
6969 ctx = replace [ 0 ]
7070 } else {
71- // @ts -ignore Assume `root` is not a child.
71+ // @ts -expect-error Assume `root` is not a child.
7272 ctx . children = replace
7373 }
7474 } else {
@@ -86,17 +86,18 @@ export function sanitize(node, schema) {
8686 * @param {Schema } schema
8787 * @param {Node } node
8888 * @param {Array.<string> } stack
89- * @returns {Node|Array.<Node>|null }
89+ * @returns {Node|Array.<Node>|undefined }
9090 */
9191function one ( schema , node , stack ) {
9292 const type = node && node . type
9393 /** @type {Node } */
94- // @ts -ignore rest of props added later.
94+ // @ts -expect-error rest of props added later.
9595 const replacement = { type : node . type }
96- /** @type {boolean } */
96+ /** @type {boolean|undefined } */
9797 let replace
9898
9999 if ( own . call ( nodeSchema , type ) ) {
100+ /** @type {NodeDefinition|NodeDefinitionGetter|undefined } */
100101 let definition = nodeSchema [ type ]
101102
102103 if ( typeof definition === 'function' ) {
@@ -112,14 +113,20 @@ function one(schema, node, stack) {
112113
113114 for ( key in allowed ) {
114115 if ( own . call ( allowed , key ) ) {
116+ // @ts -expect-error: fine.
117+ // type-coverage:ignore-next-line
115118 const result = allowed [ key ] ( schema , node [ key ] , node , stack )
116119
117120 // eslint-disable-next-line max-depth
118121 if ( result === false ) {
119- replace = null
122+ replace = undefined
120123 // Set the non-safe value.
124+ // @ts -expect-error: fine.
125+ // type-coverage:ignore-next-line
121126 replacement [ key ] = node [ key ]
122127 } else if ( result !== undefined && result !== null ) {
128+ // @ts -expect-error: fine.
129+ // type-coverage:ignore-next-line
123130 replacement [ key ] = result
124131 }
125132 }
@@ -132,16 +139,18 @@ function one(schema, node, stack) {
132139 }
133140
134141 return replacement . type === 'element' &&
142+ schema . strip &&
135143 ! schema . strip . includes ( replacement . tagName )
136144 ? replacement . children
137- : null
145+ : undefined
138146}
139147
140148/**
141149 * Sanitize `children`.
142150 *
143151 * @type {Handler }
144152 * @param {Array.<Node> } children
153+ * @param {Node } node
145154 * @returns {Array.<Node> }
146155 */
147156function all ( schema , children , node , stack ) {
@@ -177,12 +186,12 @@ function all(schema, children, node, stack) {
177186
178187/** @type {NodeDefinitionGetter } */
179188function handleDoctype ( schema ) {
180- return schema . allowDoctypes ? { name : handleDoctypeName } : null
189+ return schema . allowDoctypes ? { name : handleDoctypeName } : undefined
181190}
182191
183192/** @type {NodeDefinitionGetter } */
184193function handleComment ( schema ) {
185- return schema . allowComments ? { value : handleCommentValue } : null
194+ return schema . allowComments ? { value : handleCommentValue } : undefined
186195}
187196
188197/**
@@ -196,14 +205,14 @@ function handleComment(schema) {
196205function handleProperties ( schema , properties , node , stack ) {
197206 const name = handleTagName ( schema , node . tagName , node , stack )
198207 /* c8 ignore next */
208+ const attrs = schema . attributes || { }
209+ /* c8 ignore next */
199210 const reqs = schema . required || { }
200211 const props = properties || { }
201212 const allowed = Object . assign (
202213 { } ,
203- toPropertyValueMap ( schema . attributes [ '*' ] ) ,
204- toPropertyValueMap (
205- name && own . call ( schema . attributes , name ) ? schema . attributes [ name ] : [ ]
206- )
214+ toPropertyValueMap ( attrs [ '*' ] ) ,
215+ toPropertyValueMap ( name && own . call ( attrs , name ) ? attrs [ name ] : [ ] )
207216 )
208217 /** @type {Properties } */
209218 const result = { }
@@ -259,19 +268,25 @@ function handleDoctypeName() {
259268 * Sanitize `tagName`.
260269 *
261270 * @type {Handler }
271+ * @param {unknown } tagName
272+ * @param {Node } _
262273 * @returns {string|false }
263274 */
264275function handleTagName ( schema , tagName , _ , stack ) {
265276 const name = typeof tagName === 'string' ? tagName : ''
266277 let index = - 1
267278
268- if ( ! name || name === '*' || ! schema . tagNames . includes ( name ) ) {
279+ if (
280+ ! name ||
281+ name === '*' ||
282+ ( schema . tagNames && ! schema . tagNames . includes ( name ) )
283+ ) {
269284 return false
270285 }
271286
272287 // Some nodes can break out of their context if they don’t have a certain
273288 // ancestor.
274- if ( own . call ( schema . ancestors , name ) ) {
289+ if ( schema . ancestors && own . call ( schema . ancestors , name ) ) {
275290 while ( ++ index < schema . ancestors [ name ] . length ) {
276291 if ( stack . includes ( schema . ancestors [ name ] [ index ] ) ) {
277292 return name
@@ -288,6 +303,7 @@ function handleTagName(schema, tagName, _, stack) {
288303 * See <https://html.spec.whatwg.org/multipage/parsing.html#serialising-html-fragments>
289304 *
290305 * @type {Handler }
306+ * @param {unknown } value
291307 * @returns {string }
292308 */
293309function handleCommentValue ( _ , value ) {
@@ -301,6 +317,7 @@ function handleCommentValue(_, value) {
301317 * Sanitize `value`.
302318 *
303319 * @type {Handler }
320+ * @param {unknown } value
304321 * @returns {string }
305322 */
306323function handleValue ( _ , value ) {
@@ -311,6 +328,7 @@ function handleValue(_, value) {
311328 * Allow `value`.
312329 *
313330 * @type {Handler }
331+ * @param {unknown } value
314332 */
315333function allow ( _ , value ) {
316334 return value
@@ -334,7 +352,7 @@ function handlePropertyValues(schema, values, prop, definition) {
334352 const value = handlePropertyValue ( schema , values [ index ] , prop , definition )
335353
336354 if ( value !== undefined && value !== null ) {
337- // @ts -ignore Assume no booleans were in arrays.
355+ // @ts -expect-error Assume no booleans were in arrays.
338356 result . push ( value )
339357 }
340358 }
@@ -359,7 +377,11 @@ function handlePropertyValue(schema, value, prop, definition) {
359377 safeProtocol ( schema , value , prop ) &&
360378 ( definition . length === 0 || definition . includes ( value ) )
361379 ) {
362- return schema . clobber . includes ( prop ) ? schema . clobberPrefix + value : value
380+ return schema . clobberPrefix &&
381+ schema . clobber &&
382+ schema . clobber . includes ( prop )
383+ ? schema . clobberPrefix + value
384+ : value
363385 }
364386}
365387
@@ -377,9 +399,10 @@ function safeProtocol(schema, value, prop) {
377399 const questionMark = url . indexOf ( '?' )
378400 const numberSign = url . indexOf ( '#' )
379401 const slash = url . indexOf ( '/' )
380- const protocols = own . call ( schema . protocols , prop )
381- ? schema . protocols [ prop ] . concat ( )
382- : [ ]
402+ const protocols =
403+ schema . protocols && own . call ( schema . protocols , prop )
404+ ? schema . protocols [ prop ] . concat ( )
405+ : [ ]
383406 let index = - 1
384407
385408 if (
0 commit comments