diff --git a/package-lock.json b/package-lock.json index 43d3a60b0c0b69..8d22b9d0c12965 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27803,9 +27803,10 @@ } }, "node_modules/hpq": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/hpq/-/hpq-1.3.0.tgz", - "integrity": "sha512-fvYTvdCFOWQupGxqkahrkA+ERBuMdzkxwtUdKrxR6rmMd4Pfl+iZ1QiQYoaZ0B/v0y59MOMnz3XFUWbT50/NWA==" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/hpq/-/hpq-1.4.0.tgz", + "integrity": "sha512-ycJQMRaRPBcfnoT1gS5I1XCvbbw9KO94Y0vkwksuOjcJMqNZtb03MF2tCItLI2mQbkZWSSeFinoRDPmjzv4tKg==", + "license": "MIT" }, "node_modules/html-dom-parser": { "version": "5.1.2", @@ -50794,7 +50795,7 @@ "change-case": "^4.1.2", "colord": "^2.9.3", "fast-deep-equal": "^3.1.3", - "hpq": "^1.3.0", + "hpq": "^1.4.0", "is-plain-object": "^5.0.0", "marked": "^18.0.3", "memize": "^2.1.1", diff --git a/packages/blocks/CHANGELOG.md b/packages/blocks/CHANGELOG.md index 57cac4bb3957d6..245fe4e041c63d 100644 --- a/packages/blocks/CHANGELOG.md +++ b/packages/blocks/CHANGELOG.md @@ -5,6 +5,7 @@ ### Internal - Update `memize` to 2.1.1 ([#80764](https://github.com/WordPress/gutenberg/pull/80764)). +- Update `hpq` to 1.4.0 for its bundled TypeScript types ([#81199](https://github.com/WordPress/gutenberg/pull/81199)). ## 15.24.0 (2026-07-14) diff --git a/packages/blocks/package.json b/packages/blocks/package.json index f9ea8ee3209ed5..6af94fed6eba7f 100644 --- a/packages/blocks/package.json +++ b/packages/blocks/package.json @@ -68,7 +68,7 @@ "change-case": "^4.1.2", "colord": "^2.9.3", "fast-deep-equal": "^3.1.3", - "hpq": "^1.3.0", + "hpq": "^1.4.0", "is-plain-object": "^5.0.0", "marked": "^18.0.3", "memize": "^2.1.1", diff --git a/packages/blocks/src/api/matchers.ts b/packages/blocks/src/api/matchers.ts index 9c588dbc285845..a0c6a97cee8039 100644 --- a/packages/blocks/src/api/matchers.ts +++ b/packages/blocks/src/api/matchers.ts @@ -1,7 +1,6 @@ /** * External dependencies */ -// @ts-expect-error `hpq` does not ship type declarations. export { attr, prop, text, query } from 'hpq'; /** diff --git a/packages/blocks/src/api/parser/get-block-attributes.ts b/packages/blocks/src/api/parser/get-block-attributes.ts index 33c5c74650471b..5032d76f6e0700 100644 --- a/packages/blocks/src/api/parser/get-block-attributes.ts +++ b/packages/blocks/src/api/parser/get-block-attributes.ts @@ -1,8 +1,8 @@ /** * External dependencies */ -// @ts-expect-error `hpq` does not ship type declarations. import { parse as hpqParse } from 'hpq'; +import type { MatcherObj } from 'hpq'; import memoize from 'memize'; /** @@ -39,9 +39,9 @@ import type { BlockAttribute, BlockType } from '../../types'; * @return Enhanced hpq matcher. */ export const toBooleanAttributeMatcher = - ( matcher: ( value: unknown ) => unknown ) => - ( value: unknown ): boolean => - matcher( value ) !== undefined; + ( matcher: ( domNode: Element ) => unknown ) => + ( domNode: Element ): boolean => + matcher( domNode ) !== undefined; /** * Returns true if value is of the given JSON schema type, or false otherwise. @@ -205,12 +205,12 @@ export const matcherFromSource = memoize( ): ( ( domNode: Element ) => unknown ) | undefined => { switch ( sourceConfig.source ) { case 'attribute': { - let matcher = attr( + const matcher = attr( sourceConfig.selector, - sourceConfig.attribute + sourceConfig.attribute! ); if ( sourceConfig.type === 'boolean' ) { - matcher = toBooleanAttributeMatcher( matcher ); + return toBooleanAttributeMatcher( matcher ); } return matcher; } @@ -228,6 +228,11 @@ export const matcherFromSource = memoize( case 'node': return node( sourceConfig.selector ); case 'query': + /* + * Sub-matchers may be undefined for unknown source types. hpq + * tolerates this and matches such keys as undefined, but its + * types don't allow for it. + */ const subMatchers = Object.fromEntries( Object.entries( sourceConfig.query! ).map( ( [ key, subSourceConfig ] ) => [ @@ -235,12 +240,12 @@ export const matcherFromSource = memoize( matcherFromSource( subSourceConfig ), ] ) - ); - return query( sourceConfig.selector, subMatchers ); + ) as MatcherObj; + return query( sourceConfig.selector!, subMatchers ); case 'tag': { const matcher = prop( sourceConfig.selector, 'nodeName' ); - return ( domNode: Node ) => - ( matcher( domNode ) as string )?.toLowerCase(); + return ( domNode: Element ) => + matcher( domNode )?.toLowerCase(); } default: // eslint-disable-next-line no-console @@ -259,8 +264,8 @@ export const matcherFromSource = memoize( * * @return Parsed DOM node. */ -function parseHtml( innerHTML: string | Node ): Node { - return hpqParse( innerHTML, ( h: Node ) => h ); +function parseHtml( innerHTML: string | Node ): Element { + return hpqParse( innerHTML as string | Element, ( h: Element ) => h ); } /**