diff --git a/src/generators/legacy-json/utils/__tests__/parseList.test.mjs b/src/generators/legacy-json/utils/__tests__/parseList.test.mjs index 1806cb84..11b2fee3 100644 --- a/src/generators/legacy-json/utils/__tests__/parseList.test.mjs +++ b/src/generators/legacy-json/utils/__tests__/parseList.test.mjs @@ -123,4 +123,50 @@ describe('parseList', () => { parseList(section, nodes); assert.ok(Array.isArray(section.params)); }); + + it('processes recursive lists', () => { + const section = { type: 'event' }; + const nodes = [ + { + type: 'list', + children: [ + { + children: [ + { + type: 'paragraph', + children: [ + { type: 'text', value: 'param1 {string} first parameter' }, + ], + }, + // This is a nested typed list + { + type: 'list', + children: [ + { + children: [ + { + type: 'paragraph', + children: [ + { type: 'inlineCode', value: 'option' }, // inline code + { type: 'text', value: ' ' }, // space + { + type: 'link', + children: [{ type: 'text', value: '' }], // link with < value + }, + { type: 'text', value: ' option description' }, + ], + }, + ], + }, + ], + }, + ], + }, + ], + }, + ]; + + parseList(section, nodes); + assert.equal(section.params[0].options.length, 1); + }); }); diff --git a/src/generators/legacy-json/utils/parseList.mjs b/src/generators/legacy-json/utils/parseList.mjs index bf8cafea..0d8a1c33 100644 --- a/src/generators/legacy-json/utils/parseList.mjs +++ b/src/generators/legacy-json/utils/parseList.mjs @@ -37,6 +37,30 @@ export const extractPattern = (text, pattern, key, current) => { return text.replace(pattern, ''); }; +/** + * Determines if the input List node is a typed list + * @param {import('@types/mdast').List} list + */ +export const isTypedList = list => { + if (list.type !== 'list') { + // Exit early if not a list + return false; + } + + const children = list?.children?.[0]?.children?.[0]?.children; + + return ( + // The first element must be a code block + children?.[0]?.type === 'inlineCode' && + // Followed by a space + children?.[1]?.value.trim() === '' && + // Followed by a link (type) + children?.[2]?.type === 'link' && + // Types start with `<` + children?.[2]?.children?.[0]?.value?.[0] === '<' + ); +}; + /** * Parses an individual list item node to extract its properties * @@ -46,9 +70,11 @@ export const extractPattern = (text, pattern, key, current) => { export function parseListItem(child) { const current = {}; + const subList = child.children.find(isTypedList); + // Extract and clean raw text from the node, excluding nested lists current.textRaw = transformTypeReferences( - transformNodesToString(child.children.filter(node => node.type !== 'list')) + transformNodesToString(child.children.filter(node => node !== subList)) .replace(/\s+/g, ' ') .replace(//gs, '') ); @@ -70,9 +96,8 @@ export function parseListItem(child) { current.desc = text.replace(LEADING_HYPHEN, '').trim() || undefined; // Parse nested lists (options) recursively if present - const optionsNode = child.children.find(node => node.type === 'list'); - if (optionsNode) { - current.options = optionsNode.children.map(parseListItem); + if (subList) { + current.options = subList.children.map(parseListItem); } return current;