From e8b5058b6d09fc8de3c060e3505e0b55311bb949 Mon Sep 17 00:00:00 2001 From: Sujal Goel Date: Mon, 30 Mar 2026 04:44:27 +0530 Subject: [PATCH 1/2] metadata: support intersection types in transformTypeToReferenceLink splitByOuterUnion only split on |, so intersection types like {A&B} were treated as a single unresolvable piece instead of having each component individually linked. Rename the function to splitByOuterSeparator and extend it to also split on & at depth 0. It now returns both the pieces and the separator string (' | ' or ' & ') so the join at the call site uses the correct separator rather than a hardcoded ' | '. --- .../utils/__tests__/transformers.test.mjs | 14 ++++++++++ .../metadata/utils/transformers.mjs | 27 +++++++++++-------- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/src/generators/metadata/utils/__tests__/transformers.test.mjs b/src/generators/metadata/utils/__tests__/transformers.test.mjs index 79f25ac5..ef625d4c 100644 --- a/src/generators/metadata/utils/__tests__/transformers.test.mjs +++ b/src/generators/metadata/utils/__tests__/transformers.test.mjs @@ -61,4 +61,18 @@ describe('transformTypeToReferenceLink', () => { '[``](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)<[``](https://developer.mozilla.org/docs/Web/JavaScript/Data_structures#string_type) | [``](https://developer.mozilla.org/docs/Web/JavaScript/Data_structures#number_type)> | [``](https://developer.mozilla.org/docs/Web/JavaScript/Data_structures#boolean_type)' ); }); + + it('should transform an intersection type joined with & into linked parts', () => { + strictEqual( + transformTypeToReferenceLink('{string&boolean}', {}), + '[``](https://developer.mozilla.org/docs/Web/JavaScript/Data_structures#string_type) & [``](https://developer.mozilla.org/docs/Web/JavaScript/Data_structures#boolean_type)' + ); + }); + + it('should handle an intersection with generics like {Map&Array}', () => { + strictEqual( + transformTypeToReferenceLink('{Map&Array}', {}), + '[``](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Map)<[``](https://developer.mozilla.org/docs/Web/JavaScript/Data_structures#string_type), [``](https://developer.mozilla.org/docs/Web/JavaScript/Data_structures#number_type)> & [``](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[``](https://developer.mozilla.org/docs/Web/JavaScript/Data_structures#string_type)>' + ); + }); }); diff --git a/src/generators/metadata/utils/transformers.mjs b/src/generators/metadata/utils/transformers.mjs index 8b8e51a3..50aa5edd 100644 --- a/src/generators/metadata/utils/transformers.mjs +++ b/src/generators/metadata/utils/transformers.mjs @@ -23,31 +23,34 @@ export const transformUnixManualToLink = ( return `[\`${text}\`](${DOC_MAN_BASE_URL}${sectionNumber}/${command}.${sectionNumber}${sectionLetter}.html)`; }; /** - * Safely splits the string by `|`, ignoring pipes that are inside `< >` + * Safely splits the string by `|` or `&` at the top level (ignoring those + * inside `< >`), and returns both the pieces and the separator used. * * @param {string} str The type string to split - * @returns {string[]} An array of type pieces + * @returns {{ pieces: string[], separator: string }} The split pieces and the separator string used to join them (` | ` or ` & `) */ -const splitByOuterUnion = str => { - const result = []; +const splitByOuterSeparator = str => { + const pieces = []; let current = ''; let depth = 0; + let separator = ' | '; for (const char of str) { if (char === '<') { depth++; } else if (char === '>') { depth--; - } else if (char === '|' && depth === 0) { - result.push(current); + } else if ((char === '|' || char === '&') && depth === 0) { + pieces.push(current); current = ''; + separator = char === '&' ? ' & ' : ' | '; continue; } current += char; } - result.push(current); - return result; + pieces.push(current); + return { pieces, separator }; }; /** @@ -147,7 +150,9 @@ export const transformTypeToReferenceLink = (type, record) => { return ''; }; - const typePieces = splitByOuterUnion(typeInput).map(piece => { + const { pieces: outerPieces, separator } = splitByOuterSeparator(typeInput); + + const typePieces = outerPieces.map(piece => { // This is the content to render as the text of the Markdown link const trimmedPiece = piece.trim(); @@ -169,8 +174,8 @@ export const transformTypeToReferenceLink = (type, record) => { }); // Filter out pieces that we failed to map and then join the valid ones - // into different links separated by a ` | ` - const markdownLinks = typePieces.filter(Boolean).join(' | '); + // using the same separator that appeared in the original type string + const markdownLinks = typePieces.filter(Boolean).join(separator); // Return the replaced links or the original content if they all failed to be replaced // Note that if some failed to get replaced, only the valid ones will be returned From fe467a6cdf4b3bc2e9d2c505949226832d66bba2 Mon Sep 17 00:00:00 2001 From: Sujal Goel Date: Mon, 30 Mar 2026 05:18:12 +0530 Subject: [PATCH 2/2] address review: use nullish assignment and derive separator from char --- src/generators/metadata/utils/transformers.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/generators/metadata/utils/transformers.mjs b/src/generators/metadata/utils/transformers.mjs index 50aa5edd..7fac4e85 100644 --- a/src/generators/metadata/utils/transformers.mjs +++ b/src/generators/metadata/utils/transformers.mjs @@ -33,7 +33,7 @@ const splitByOuterSeparator = str => { const pieces = []; let current = ''; let depth = 0; - let separator = ' | '; + let separator; for (const char of str) { if (char === '<') { @@ -43,7 +43,7 @@ const splitByOuterSeparator = str => { } else if ((char === '|' || char === '&') && depth === 0) { pieces.push(current); current = ''; - separator = char === '&' ? ' & ' : ' | '; + separator ??= ` ${char} `; continue; } current += char;