From fcef3a5ba1900b2f99fe0b9add2cc83d431bb278 Mon Sep 17 00:00:00 2001 From: avivkeller Date: Tue, 19 Aug 2025 17:03:34 -0400 Subject: [PATCH 1/3] fix(isTypedList): validate property syntax --- src/utils/queries/constants.mjs | 2 ++ src/utils/queries/index.mjs | 18 +++++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/utils/queries/constants.mjs b/src/utils/queries/constants.mjs index 4e6a22b9..6219ce4b 100644 --- a/src/utils/queries/constants.mjs +++ b/src/utils/queries/constants.mjs @@ -3,3 +3,5 @@ // This is the perma-link within the API docs that reference the Stability Index export const DOC_API_STABILITY_SECTION_REF_URL = 'documentation.html#stability-index'; + +export const VALID_JAVASCRIPT_PROPERTY = /^[a-z0-9$_]+$/i; diff --git a/src/utils/queries/index.mjs b/src/utils/queries/index.mjs index 76810097..0e1c8461 100644 --- a/src/utils/queries/index.mjs +++ b/src/utils/queries/index.mjs @@ -3,7 +3,10 @@ import { u as createTree } from 'unist-builder'; import { SKIP } from 'unist-util-visit'; -import { DOC_API_STABILITY_SECTION_REF_URL } from './constants.mjs'; +import { + DOC_API_STABILITY_SECTION_REF_URL, + VALID_JAVASCRIPT_PROPERTY, +} from './constants.mjs'; import { extractYamlContent, parseHeadingIntoMetadata, @@ -278,15 +281,15 @@ createQueries.UNIST = { const [node, ...contentNodes] = list?.children?.[0]?.children?.[0]?.children ?? []; - // Exit if no content nodes - if (!node) { + const possibleProperty = node?.value?.trimStart(); + + // Exit if no content in node (or if no node exists) + if (!possibleProperty) { return false; } // Check for other starters - if ( - node.value?.trimStart().match(createQueries.QUERIES.typedListStarters) - ) { + if (possibleProperty.match(createQueries.QUERIES.typedListStarters)) { return true; } @@ -298,7 +301,8 @@ createQueries.UNIST = { // Check for inline code + space + type link pattern if ( node.type === 'inlineCode' && - contentNodes[0]?.value.trim() === '' && + possibleProperty.match(VALID_JAVASCRIPT_PROPERTY) && + contentNodes[0]?.value?.trim() === '' && contentNodes[1]?.type === 'link' && contentNodes[1]?.children?.[0]?.value?.[0] === '<' ) { From 3db7a7a19e66ad56df934ab27df17c37dd1e402d Mon Sep 17 00:00:00 2001 From: avivkeller Date: Wed, 20 Aug 2025 16:41:47 -0400 Subject: [PATCH 2/3] add tests, fix edge case --- src/utils/queries/__tests__/index.test.mjs | 110 +++++++++++++++++++++ src/utils/queries/index.mjs | 12 +-- 2 files changed, 116 insertions(+), 6 deletions(-) diff --git a/src/utils/queries/__tests__/index.test.mjs b/src/utils/queries/__tests__/index.test.mjs index 36f0b1a1..e04a5d5c 100644 --- a/src/utils/queries/__tests__/index.test.mjs +++ b/src/utils/queries/__tests__/index.test.mjs @@ -110,4 +110,114 @@ describe('createQueries', () => { }; queries.addStabilityMetadata(node, apiEntryMetadata); }); + + describe('UNIST', () => { + describe('isTypedList', () => { + it('returns false for non-list nodes', () => { + strictEqual( + createQueries.UNIST.isTypedList({ type: 'paragraph', children: [] }), + false + ); + }); + + it('returns false for empty lists', () => { + strictEqual( + createQueries.UNIST.isTypedList({ type: 'list', children: [] }), + false + ); + }); + + const cases = [ + { + name: 'typedListStarters pattern match', + node: { + type: 'list', + children: [ + { + children: [ + { + children: [{ type: 'text', value: 'Returns: foo' }], + }, + ], + }, + ], + }, + expected: true, + }, + { + name: 'direct type link pattern', + node: { + type: 'list', + children: [ + { + children: [ + { + children: [ + { + type: 'link', + children: [{ type: 'inlineCode', value: '' }], + }, + ], + }, + ], + }, + ], + }, + expected: true, + }, + { + name: 'inlineCode + space + type link pattern', + node: { + type: 'list', + children: [ + { + children: [ + { + children: [ + { type: 'inlineCode', value: 'foo' }, + { type: 'text', value: ' ' }, + { + type: 'link', + children: [{ type: 'text', value: '' }], + }, + ], + }, + ], + }, + ], + }, + expected: true, + }, + { + name: 'non-matching content', + node: { + type: 'list', + children: [ + { + children: [ + { + children: [ + { type: 'inlineCode', value: 'not a valid prop' }, + { type: 'text', value: ' ' }, + { + type: 'link', + children: [{ type: 'text', value: '' }], + }, + ], + }, + ], + }, + ], + }, + expected: false, + }, + ]; + + cases.forEach(({ name, node, expected }) => { + it(`returns ${expected} for ${name}`, () => { + strictEqual(createQueries.UNIST.isTypedList(node), expected); + }); + }); + }); + }); }); diff --git a/src/utils/queries/index.mjs b/src/utils/queries/index.mjs index 0e1c8461..b6300d9a 100644 --- a/src/utils/queries/index.mjs +++ b/src/utils/queries/index.mjs @@ -281,15 +281,15 @@ createQueries.UNIST = { const [node, ...contentNodes] = list?.children?.[0]?.children?.[0]?.children ?? []; - const possibleProperty = node?.value?.trimStart(); - - // Exit if no content in node (or if no node exists) - if (!possibleProperty) { + // Exit if no node + if (!node) { return false; } + const possibleProperty = node?.value?.trimStart(); + // Check for other starters - if (possibleProperty.match(createQueries.QUERIES.typedListStarters)) { + if (possibleProperty?.match(createQueries.QUERIES.typedListStarters)) { return true; } @@ -301,7 +301,7 @@ createQueries.UNIST = { // Check for inline code + space + type link pattern if ( node.type === 'inlineCode' && - possibleProperty.match(VALID_JAVASCRIPT_PROPERTY) && + possibleProperty?.match(VALID_JAVASCRIPT_PROPERTY) && contentNodes[0]?.value?.trim() === '' && contentNodes[1]?.type === 'link' && contentNodes[1]?.children?.[0]?.value?.[0] === '<' From a71661d9039554ef7a0a93b70b76055185fec7ab Mon Sep 17 00:00:00 2001 From: avivkeller Date: Fri, 22 Aug 2025 19:22:55 -0400 Subject: [PATCH 3/3] add . --- src/utils/queries/constants.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/queries/constants.mjs b/src/utils/queries/constants.mjs index 6219ce4b..88537e2f 100644 --- a/src/utils/queries/constants.mjs +++ b/src/utils/queries/constants.mjs @@ -4,4 +4,4 @@ export const DOC_API_STABILITY_SECTION_REF_URL = 'documentation.html#stability-index'; -export const VALID_JAVASCRIPT_PROPERTY = /^[a-z0-9$_]+$/i; +export const VALID_JAVASCRIPT_PROPERTY = /^[.a-z0-9$_]+$/i;