UNPKG

@mui/internal-docs-infra

Version:

MUI Infra - internal documentation creation tools.

145 lines (137 loc) 6.02 kB
// MDX JSX types const META_LINK_TEXTS = ['See Demo', 'See Setup', 'See Types']; /** * Remark plugin that cleans up meta link patterns in markdown. * * Looks for patterns where a Demo/Types component is followed by a meta link * (e.g., "[See Demo]", "[See Setup]", "[See Types]") and optionally a horizontal * rule (---). When found, removes the link and any following horizontal rule. * * This is useful for markdown that will be converted to HTML where the link * and separator are distracting on the page. * * Pattern it matches: * ``` * <DemoSomething /> * * [See Demo](./demos/base/) * * --- (optional) * ``` * * Gets transformed to: * ``` * <DemoSomething /> * ``` * * Also matches: * ``` * <TypesSomething /> * * [See Types](./types.md#something) * * --- (optional) * ``` */ export const transformMarkdownMetaLinks = () => { return tree => { const parent = tree; const children = parent.children; for (let i = 0; i < children.length - 1; i += 1) { const current = children[i]; const next = children[i + 1]; const separator = children[i + 2]; // May not exist let hasDemo = false; // Check if current node is an HTML element containing a Demo component without .Title if (current?.type === 'html') { const htmlNode = current; hasDemo = htmlNode.value.includes('<Demo') && !htmlNode.value.includes('.Title'); } else if (current?.type === 'mdxJsxFlowElement') { // Check if current node is an MDX JSX element (for imported Demo components) const mdxNode = current; if (mdxNode.name && mdxNode.name.includes('Demo') && !mdxNode.name.includes('.Title')) { hasDemo = true; } } else if (current?.type === 'paragraph') { // Check if paragraph contains only a single HTML node with a Demo component const paragraphNode = current; if (paragraphNode.children.length === 1 && paragraphNode.children[0].type === 'html') { const htmlNode = paragraphNode.children[0]; hasDemo = htmlNode.value.includes('<Demo') && !htmlNode.value.includes('.Title'); } else if (paragraphNode.children.length >= 2 && paragraphNode.children[0].type === 'html' && paragraphNode.children[paragraphNode.children.length - 1].type === 'html') { // Check if this looks like a Demo component with opening and closing tags const openingTag = paragraphNode.children[0]; const closingTag = paragraphNode.children[paragraphNode.children.length - 1]; if (openingTag.value.includes('<Demo') && !openingTag.value.includes('.Title') && closingTag.value.includes('</Demo')) { hasDemo = true; } } else { // Check if paragraph contains any HTML nodes with Demo components (mixed content) hasDemo = paragraphNode.children.some(child => { return child.type === 'html' && child.value.includes('<Demo') && !child.value.includes('.Title'); }); } } // Also check for Types components (e.g., <TypesSomething />) if (!hasDemo) { if (current?.type === 'html') { const htmlNode = current; hasDemo = htmlNode.value.includes('<Types') && !htmlNode.value.includes('.Title'); } else if (current?.type === 'mdxJsxFlowElement') { const mdxNode = current; if (mdxNode.name && mdxNode.name.includes('Types') && !mdxNode.name.includes('.Title')) { hasDemo = true; } } else if (current?.type === 'paragraph') { const paragraphNode = current; if (paragraphNode.children.length === 1 && paragraphNode.children[0].type === 'html') { const htmlNode = paragraphNode.children[0]; hasDemo = htmlNode.value.includes('<Types') && !htmlNode.value.includes('.Title'); } else if (paragraphNode.children.length >= 2 && paragraphNode.children[0].type === 'html' && paragraphNode.children[paragraphNode.children.length - 1].type === 'html') { const openingTag = paragraphNode.children[0]; const closingTag = paragraphNode.children[paragraphNode.children.length - 1]; if (openingTag.value.includes('<Types') && !openingTag.value.includes('.Title') && closingTag.value.includes('</Types')) { hasDemo = true; } } else { hasDemo = paragraphNode.children.some(child => { return child.type === 'html' && child.value.includes('<Types') && !child.value.includes('.Title'); }); } } } if (!hasDemo) { continue; } let removedSomething = false; // Check if next node is a paragraph containing a meta link (See Demo, See Setup, See Types) if (next?.type === 'paragraph') { const hasMetaLink = next.children.some(child => { return child.type === 'link' && child.children.some(linkChild => linkChild.type === 'text' && META_LINK_TEXTS.includes(linkChild.value)); }); // Check if there's also a thematic break (---) after the paragraph const hasThematicBreak = separator?.type === 'thematicBreak'; if (hasMetaLink) { // Remove the meta link paragraph and any following thematic break if (hasThematicBreak) { // Remove both the meta link paragraph and the thematic break children.splice(i + 1, 2); removedSomething = true; } else { // Remove only the meta link paragraph children.splice(i + 1, 1); removedSomething = true; } } else if (hasThematicBreak) { // No meta link, but there's a thematic break after the paragraph - remove just the HR children.splice(i + 2, 1); removedSomething = true; } } // If we removed something, adjust the loop index to prevent skipping if (removedSomething) { i -= 1; } } }; };