diff --git a/lib/handle/comment.js b/lib/handle/comment.js index 5049ef0..80184f9 100644 --- a/lib/handle/comment.js +++ b/lib/handle/comment.js @@ -1,6 +1,6 @@ /** * @typedef {import('../types.js').Comment} Comment - * @typedef {import('../types.js').Parent} Parent + * @typedef {import('../types.js').Parents} Parents * @typedef {import('../types.js').State} State */ @@ -13,7 +13,7 @@ import {stringifyEntities} from 'stringify-entities' * Node to handle. * @param {number | undefined} _1 * Index of `node` in `parent. - * @param {Parent | undefined} _2 + * @param {Parents | undefined} _2 * Parent of `node`. * @param {State} state * Info passed around about the current state. diff --git a/lib/handle/doctype.js b/lib/handle/doctype.js index f7737a4..3d6185e 100644 --- a/lib/handle/doctype.js +++ b/lib/handle/doctype.js @@ -1,6 +1,6 @@ /** * @typedef {import('../types.js').DocType} DocType - * @typedef {import('../types.js').Parent} Parent + * @typedef {import('../types.js').Parents} Parents * @typedef {import('../types.js').State} State */ @@ -11,7 +11,7 @@ * Node to handle. * @param {number | undefined} _2 * Index of `node` in `parent. - * @param {Parent | undefined} _3 + * @param {Parents | undefined} _3 * Parent of `node`. * @param {State} state * Info passed around about the current state. diff --git a/lib/handle/element.js b/lib/handle/element.js index 14ba7cd..9aefb32 100644 --- a/lib/handle/element.js +++ b/lib/handle/element.js @@ -1,6 +1,6 @@ /** * @typedef {import('../types.js').State} State - * @typedef {import('../types.js').Parent} Parent + * @typedef {import('../types.js').Parents} Parents * @typedef {import('../types.js').Element} Element * @typedef {import('../types.js').Properties} Properties * @typedef {import('../types.js').PropertyValue} PropertyValue @@ -53,7 +53,7 @@ const constants = { * Node to handle. * @param {number | undefined} index * Index of `node` in `parent. - * @param {Parent | undefined} parent + * @param {Parents | undefined} parent * Parent of `node`. * @param {State} state * Info passed around about the current state. @@ -89,6 +89,8 @@ export function element(node, index, parent, state) { // categorisation. // This enables for example `menuitem`s, which are void in W3C HTML but not // void in WHATWG HTML, to be stringified properly. + // Note: `menuitem` has since been removed from the HTML spec, and so is no + // longer void. if (content) selfClosing = false if (attrs || !omit || !opening(node, index, parent)) { diff --git a/lib/handle/index.js b/lib/handle/index.js index 9783345..d6c5ab3 100644 --- a/lib/handle/index.js +++ b/lib/handle/index.js @@ -1,7 +1,7 @@ /** * @typedef {import('../types.js').State} State - * @typedef {import('../types.js').Node} Node - * @typedef {import('../types.js').Parent} Parent + * @typedef {import('../types.js').Nodes} Nodes + * @typedef {import('../types.js').Parents} Parents */ import {zwitch} from 'zwitch' @@ -13,7 +13,7 @@ import {root} from './root.js' import {text} from './text.js' /** - * @type {(node: Node, index: number | undefined, parent: Parent | undefined, state: State) => string} + * @type {(node: Nodes, index: number | undefined, parent: Parents | undefined, state: State) => string} */ export const handle = zwitch('type', { invalid, diff --git a/lib/handle/raw.js b/lib/handle/raw.js index d32555c..eda9e83 100644 --- a/lib/handle/raw.js +++ b/lib/handle/raw.js @@ -1,6 +1,6 @@ /** * @typedef {import('../types.js').State} State - * @typedef {import('../types.js').Parent} Parent + * @typedef {import('../types.js').Parents} Parents * @typedef {import('../types.js').Raw} Raw */ @@ -13,7 +13,7 @@ import {text} from './text.js' * Node to handle. * @param {number | undefined} index * Index of `node` in `parent. - * @param {Parent | undefined} parent + * @param {Parents | undefined} parent * Parent of `node`. * @param {State} state * Info passed around about the current state. diff --git a/lib/handle/root.js b/lib/handle/root.js index 974d2cc..06ec1a1 100644 --- a/lib/handle/root.js +++ b/lib/handle/root.js @@ -1,6 +1,6 @@ /** * @typedef {import('../types.js').Root} Root - * @typedef {import('../types.js').Parent} Parent + * @typedef {import('../types.js').Parents} Parents * @typedef {import('../types.js').State} State */ @@ -11,7 +11,7 @@ * Node to handle. * @param {number | undefined} _1 * Index of `node` in `parent. - * @param {Parent | undefined} _2 + * @param {Parents | undefined} _2 * Parent of `node`. * @param {State} state * Info passed around about the current state. diff --git a/lib/handle/text.js b/lib/handle/text.js index 58d03d4..9dccda6 100644 --- a/lib/handle/text.js +++ b/lib/handle/text.js @@ -1,6 +1,6 @@ /** * @typedef {import('../types.js').State} State - * @typedef {import('../types.js').Parent} Parent + * @typedef {import('../types.js').Parents} Parents * @typedef {import('../types.js').Raw} Raw * @typedef {import('../types.js').Text} Text */ @@ -14,7 +14,7 @@ import {stringifyEntities} from 'stringify-entities' * Node to handle. * @param {number | undefined} _ * Index of `node` in `parent. - * @param {Parent | undefined} parent + * @param {Parents | undefined} parent * Parent of `node`. * @param {State} state * Info passed around about the current state. diff --git a/lib/index.js b/lib/index.js index 812dca7..6263c41 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,7 +1,7 @@ /** - * @typedef {import('./types.js').Node} Node - * @typedef {import('./types.js').Parent} Parent - * @typedef {import('./types.js').Content} Content + * @typedef {import('./types.js').Nodes} Nodes + * @typedef {import('./types.js').Parents} Parents + * @typedef {import('./types.js').RootContent} RootContent * @typedef {import('./types.js').Options} Options * @typedef {import('./types.js').State} State */ @@ -13,7 +13,7 @@ import {handle} from './handle/index.js' /** * Serialize hast as HTML. * - * @param {Node | Array} tree + * @param {Nodes | Array} tree * Tree to serialize. * @param {Options | null | undefined} [options] * Configuration. @@ -71,11 +71,11 @@ export function toHtml(tree, options) { * * @this {State} * Info passed around about the current state. - * @param {Node} node + * @param {Nodes} node * Node to handle. * @param {number | undefined} index * Index of `node` in `parent. - * @param {Parent | undefined} parent + * @param {Parents | undefined} parent * Parent of `node`. * @returns {string} * Serialized node. @@ -89,7 +89,7 @@ function one(node, index, parent) { * * @this {State} * Info passed around about the current state. - * @param {Parent | undefined} parent + * @param {Parents | undefined} parent * Parent whose children to serialize. * @returns {string} */ diff --git a/lib/omission/closing.js b/lib/omission/closing.js index f295d58..83a3c93 100644 --- a/lib/omission/closing.js +++ b/lib/omission/closing.js @@ -1,6 +1,6 @@ /** * @typedef {import('../types.js').Element} Element - * @typedef {import('../types.js').Parent} Parent + * @typedef {import('../types.js').Parents} Parents */ import {whitespace} from 'hast-util-whitespace' @@ -19,7 +19,6 @@ export const closing = omission({ rp: rubyElement, optgroup, option, - menuitem, colgroup: headOrColgroupOrCaption, caption: headOrColgroupOrCaption, thead, @@ -37,7 +36,7 @@ export const closing = omission({ * Element. * @param {number | undefined} index * Index of element in parent. - * @param {Parent | undefined} parent + * @param {Parents | undefined} parent * Parent of element. * @returns {boolean} * Whether the closing tag can be omitted. @@ -58,7 +57,7 @@ function headOrColgroupOrCaption(_, index, parent) { * Element. * @param {number | undefined} index * Index of element in parent. - * @param {Parent | undefined} parent + * @param {Parents | undefined} parent * Parent of element. * @returns {boolean} * Whether the closing tag can be omitted. @@ -75,7 +74,7 @@ function html(_, index, parent) { * Element. * @param {number | undefined} index * Index of element in parent. - * @param {Parent | undefined} parent + * @param {Parents | undefined} parent * Parent of element. * @returns {boolean} * Whether the closing tag can be omitted. @@ -92,7 +91,7 @@ function body(_, index, parent) { * Element. * @param {number | undefined} index * Index of element in parent. - * @param {Parent | undefined} parent + * @param {Parents | undefined} parent * Parent of element. * @returns {boolean} * Whether the closing tag can be omitted. @@ -153,7 +152,7 @@ function p(_, index, parent) { * Element. * @param {number | undefined} index * Index of element in parent. - * @param {Parent | undefined} parent + * @param {Parents | undefined} parent * Parent of element. * @returns {boolean} * Whether the closing tag can be omitted. @@ -170,7 +169,7 @@ function li(_, index, parent) { * Element. * @param {number | undefined} index * Index of element in parent. - * @param {Parent | undefined} parent + * @param {Parents | undefined} parent * Parent of element. * @returns {boolean} * Whether the closing tag can be omitted. @@ -191,7 +190,7 @@ function dt(_, index, parent) { * Element. * @param {number | undefined} index * Index of element in parent. - * @param {Parent | undefined} parent + * @param {Parents | undefined} parent * Parent of element. * @returns {boolean} * Whether the closing tag can be omitted. @@ -212,7 +211,7 @@ function dd(_, index, parent) { * Element. * @param {number | undefined} index * Index of element in parent. - * @param {Parent | undefined} parent + * @param {Parents | undefined} parent * Parent of element. * @returns {boolean} * Whether the closing tag can be omitted. @@ -233,7 +232,7 @@ function rubyElement(_, index, parent) { * Element. * @param {number | undefined} index * Index of element in parent. - * @param {Parent | undefined} parent + * @param {Parents | undefined} parent * Parent of element. * @returns {boolean} * Whether the closing tag can be omitted. @@ -250,7 +249,7 @@ function optgroup(_, index, parent) { * Element. * @param {number | undefined} index * Index of element in parent. - * @param {Parent | undefined} parent + * @param {Parents | undefined} parent * Parent of element. * @returns {boolean} * Whether the closing tag can be omitted. @@ -264,29 +263,6 @@ function option(_, index, parent) { ) } -/** - * Whether to omit ``. - * - * @param {Element} _ - * Element. - * @param {number | undefined} index - * Index of element in parent. - * @param {Parent | undefined} parent - * Parent of element. - * @returns {boolean} - * Whether the closing tag can be omitted. - */ -function menuitem(_, index, parent) { - const next = siblingAfter(parent, index) - return ( - !next || - (next.type === 'element' && - (next.tagName === 'menuitem' || - next.tagName === 'hr' || - next.tagName === 'menu')) - ) -} - /** * Whether to omit ``. * @@ -294,7 +270,7 @@ function menuitem(_, index, parent) { * Element. * @param {number | undefined} index * Index of element in parent. - * @param {Parent | undefined} parent + * @param {Parents | undefined} parent * Parent of element. * @returns {boolean} * Whether the closing tag can be omitted. @@ -315,7 +291,7 @@ function thead(_, index, parent) { * Element. * @param {number | undefined} index * Index of element in parent. - * @param {Parent | undefined} parent + * @param {Parents | undefined} parent * Parent of element. * @returns {boolean} * Whether the closing tag can be omitted. @@ -336,7 +312,7 @@ function tbody(_, index, parent) { * Element. * @param {number | undefined} index * Index of element in parent. - * @param {Parent | undefined} parent + * @param {Parents | undefined} parent * Parent of element. * @returns {boolean} * Whether the closing tag can be omitted. @@ -352,7 +328,7 @@ function tfoot(_, index, parent) { * Element. * @param {number | undefined} index * Index of element in parent. - * @param {Parent | undefined} parent + * @param {Parents | undefined} parent * Parent of element. * @returns {boolean} * Whether the closing tag can be omitted. @@ -369,7 +345,7 @@ function tr(_, index, parent) { * Element. * @param {number | undefined} index * Index of element in parent. - * @param {Parent | undefined} parent + * @param {Parents | undefined} parent * Parent of element. * @returns {boolean} * Whether the closing tag can be omitted. diff --git a/lib/omission/opening.js b/lib/omission/opening.js index 1f0077d..3c3d75f 100644 --- a/lib/omission/opening.js +++ b/lib/omission/opening.js @@ -1,7 +1,7 @@ /** * @typedef {import('../types.js').Element} Element - * @typedef {import('../types.js').Parent} Parent - * @typedef {import('../types.js').Content} Content + * @typedef {import('../types.js').Parents} Parents + * @typedef {import('../types.js').RootContent} RootContent */ import {whitespace} from 'hast-util-whitespace' @@ -94,7 +94,7 @@ function body(node) { * Element. * @param {number | undefined} index * Index of element in parent. - * @param {Parent | undefined} parent + * @param {Parents | undefined} parent * Parent of element. * @returns {boolean} * Whether the opening tag can be omitted. @@ -124,7 +124,7 @@ function colgroup(node, index, parent) { * Element. * @param {number | undefined} index * Index of element in parent. - * @param {Parent | undefined} parent + * @param {Parents | undefined} parent * Parent of element. * @returns {boolean} * Whether the opening tag can be omitted. diff --git a/lib/omission/util/siblings.js b/lib/omission/util/siblings.js index f0d9909..a5c28ac 100644 --- a/lib/omission/util/siblings.js +++ b/lib/omission/util/siblings.js @@ -1,6 +1,6 @@ /** - * @typedef {import('../../types.js').Parent} Parent - * @typedef {import('../../types.js').Content} Content + * @typedef {import('../../types.js').Parents} Parents + * @typedef {import('../../types.js').RootContent} RootContent */ import {whitespace} from 'hast-util-whitespace' @@ -19,10 +19,10 @@ function siblings(increment) { /** * Find applicable siblings in a direction. * - * @param {Parent | null | undefined} parent + * @param {Parents | null | undefined} parent * @param {number | null | undefined} index * @param {boolean | null | undefined} [includeWhitespace=false] - * @returns {Content} + * @returns {RootContent} */ function sibling(parent, index, includeWhitespace) { const siblings = parent ? parent.children : [] diff --git a/lib/types.js b/lib/types.js index 7c20bed..1109836 100644 --- a/lib/types.js +++ b/lib/types.js @@ -3,19 +3,19 @@ * @typedef {import('unist').Literal} UnistLiteral * @typedef {import('hast').Root} Root * @typedef {import('hast').Comment} Comment - * @typedef {import('hast').DocType} DocType + * @typedef {import('hast').Doctype} DocType * @typedef {import('hast').Element} Element * @typedef {import('hast').Text} Text - * @typedef {import('hast').Content} Content + * @typedef {import('hast').Nodes} Nodes + * @typedef {import('hast').RootContent} RootContent * @typedef {import('hast').Properties} Properties - * @typedef {import('hast-util-raw/complex-types.js').Raw} Raw + * @typedef {import('hast').Parents} Parents + * @typedef {import('mdast-util-to-hast').Raw} Raw * @typedef {import('stringify-entities').Options} StringifyEntitiesOptions * @typedef {import('property-information').Schema} Schema */ /** - * @typedef {Content | Root} Node - * @typedef {Extract} Parent * @typedef {Properties[keyof Properties]} PropertyValue * * @callback OmitHandle @@ -24,7 +24,7 @@ * Element to check. * @param {number | undefined} index * Index of element in parent. - * @param {Parent | undefined} parent + * @param {Parents | undefined} parent * Parent of element. * @returns {boolean} * Whether to omit a tag. @@ -158,9 +158,9 @@ * * @typedef State * Info passed around about the current state. - * @property {(node: Node, index: number | undefined, parent: Parent | undefined) => string} one + * @property {(node: Nodes, index: number | undefined, parent: Parents | undefined) => string} one * Serialize one node. - * @property {(node: Parent | undefined) => string} all + * @property {(node: Parents | undefined) => string} all * Serialize the children of a parent node. * @property {Settings} settings * User configuration. diff --git a/package.json b/package.json index fcc13dd..2d18f72 100644 --- a/package.json +++ b/package.json @@ -34,13 +34,14 @@ "index.js" ], "dependencies": { - "@types/hast": "^2.0.0", - "@types/unist": "^2.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", "ccount": "^2.0.0", "comma-separated-tokens": "^2.0.0", - "hast-util-raw": "^7.0.0", - "hast-util-whitespace": "^2.0.0", - "html-void-elements": "^2.0.0", + "hast-util-raw": "^9.0.0", + "hast-util-whitespace": "^3.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", "property-information": "^6.0.0", "space-separated-tokens": "^2.0.0", "stringify-entities": "^4.0.0", @@ -49,13 +50,13 @@ "devDependencies": { "@types/node": "^20.0.0", "c8": "^8.0.0", - "hastscript": "^7.0.0", + "hastscript": "^8.0.0", "prettier": "^3.0.0", "remark-cli": "^11.0.0", "remark-preset-wooorm": "^9.0.0", "type-coverage": "^2.0.0", "typescript": "^5.0.0", - "unist-builder": "^3.0.0", + "unist-builder": "^4.0.0", "xo": "^0.55.0" }, "scripts": { diff --git a/test/doctype.js b/test/doctype.js index 6e26220..96fbba3 100644 --- a/test/doctype.js +++ b/test/doctype.js @@ -5,21 +5,18 @@ import {toHtml} from '../index.js' test('`doctype`', () => { assert.deepEqual( - // @ts-expect-error hast types out of date. toHtml(u('doctype')), '', 'should serialize doctypes' ) assert.deepEqual( - // @ts-expect-error hast types out of date. toHtml(u('doctype'), {tightDoctype: true}), '', 'should serialize doctypes tightly in `tightDoctype` mode' ) assert.deepEqual( - // @ts-expect-error hast types out of date. toHtml(u('doctype'), {upperDoctype: true}), '', 'should serialize uppercase doctypes in `upperDoctype` mode' diff --git a/test/omission-closing-menuitem.js b/test/omission-closing-menuitem.js index 8df1a41..160acf7 100644 --- a/test/omission-closing-menuitem.js +++ b/test/omission-closing-menuitem.js @@ -6,19 +6,19 @@ import {toHtml} from '../index.js' test('`menuitem` (closing)', () => { assert.deepEqual( toHtml(h('menuitem', 'alpha'), {omitOptionalTags: true}), - 'alpha', + 'alpha', 'should omit tag without parent' ) assert.deepEqual( toHtml(h('menu', [h('menuitem', 'alpha')]), {omitOptionalTags: true}), - 'alpha', + 'alpha', 'should omit tag without following' ) assert.deepEqual( toHtml(h('menu', [h('menuitem'), h('menuitem')]), {omitOptionalTags: true}), - '', + '', 'should omit tag followed by `menuitem`' ) @@ -26,7 +26,7 @@ test('`menuitem` (closing)', () => { toHtml(h('menu', [h('menuitem', 'alpha'), h('hr')]), { omitOptionalTags: true }), - 'alpha
', + 'alpha
', 'should omit tag followed by `hr`' ) @@ -34,7 +34,7 @@ test('`menuitem` (closing)', () => { toHtml(h('menu', [h('menuitem', 'alpha'), h('menu')]), { omitOptionalTags: true }), - 'alpha', + 'alpha', 'should omit tag followed by `menu`' ) @@ -50,7 +50,7 @@ test('`menuitem` (closing)', () => { // in WHATWG HTML, but not in W3C HTML, here do not have children. assert.deepEqual( toHtml(h('menu', [h('menuitem'), h('p')]), {omitOptionalTags: true}), - '

', + '

', 'should omit tag when without children' ) })