Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions src/generators/ast/generate.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ import { STABILITY_INDEX_URL } from './constants.mjs';
import getConfig from '../../utils/configuration/index.mjs';
import { withExt } from '../../utils/file.mjs';
import { QUERIES } from '../../utils/queries/index.mjs';
import { getRemark } from '../../utils/remark.mjs';

const remarkProcessor = getRemark();
import { getRemark as remark } from '../../utils/remark.mjs';

/**
* Process a chunk of markdown files in a worker thread.
Expand Down Expand Up @@ -40,7 +38,7 @@ export async function processChunk(inputSlice, itemIndices) {
const relativePath = sep + withExt(relative(parent, path));

results.push({
tree: remarkProcessor.parse(value),
tree: remark().parse(value),
// The path is the relative path minus the extension
path: relativePath,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ describe('transformHeadingNode (deprecation Type -> AlertBox level)', () => {
const parent = makeParent('Documentation');
const node = parent.children[0];

transformHeadingNode(entry, {}, node, 0, parent);
transformHeadingNode(entry, node, 0, parent);

const alert = parent.children[1];
const levelAttr = alert.attributes.find(a => a.name === 'level');
Expand All @@ -43,7 +43,7 @@ describe('transformHeadingNode (deprecation Type -> AlertBox level)', () => {
const parent = makeParent('Runtime');
const node = parent.children[0];

transformHeadingNode(entry, {}, node, 0, parent);
transformHeadingNode(entry, node, 0, parent);

const alert = parent.children[1];
const levelAttr = alert.attributes.find(a => a.name === 'level');
Expand All @@ -57,7 +57,7 @@ describe('transformHeadingNode (deprecation Type -> AlertBox level)', () => {
const parent = makeParent('SomeOtherThing');
const node = parent.children[0];

transformHeadingNode(entry, {}, node, 0, parent);
transformHeadingNode(entry, node, 0, parent);

const alert = parent.children[1];
const levelAttr = alert.attributes.find(a => a.name === 'level');
Expand Down
58 changes: 31 additions & 27 deletions src/generators/jsx-ast/utils/__tests__/types.test.mjs
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
import assert from 'node:assert/strict';
import { describe, it } from 'node:test';
import { describe, it, mock } from 'node:test';

// Mock remark
mock.module('../../../../utils/remark.mjs', {
namedExports: {
getRemarkRecma: () => ({
runSync: () => ({
body: [{ expression: 'mock-expression' }],
}),
}),
},
});

import {
const {
classifyTypeNode,
extractPropertyName,
extractTypeAnnotations,
parseListIntoProperties,
} from '../types.mjs';

// Mock remark processor for tests
const remark = {
runSync: () => ({
body: [{ expression: 'mock-expression' }],
}),
};
} = await import('../types.mjs');

describe('classifyTypeNode', () => {
it('returns 2 for union separator text node', () => {
Expand Down Expand Up @@ -183,7 +187,7 @@ describe('extractTypeAnnotations', () => {
{ type: 'text', value: ' description follows' },
];

const result = extractTypeAnnotations(nodes, remark);
const result = extractTypeAnnotations(nodes);

assert.strictEqual(result, 'mock-expression');
assert.strictEqual(nodes.length, 1);
Expand All @@ -204,7 +208,7 @@ describe('extractTypeAnnotations', () => {
{ type: 'text', value: ' description' },
];

const result = extractTypeAnnotations(nodes, remark);
const result = extractTypeAnnotations(nodes);

assert.strictEqual(result, 'mock-expression');
assert.strictEqual(nodes.length, 1);
Expand All @@ -220,7 +224,7 @@ describe('extractTypeAnnotations', () => {
{ type: 'text', value: ' | ' },
];

const result = extractTypeAnnotations(nodes, remark);
const result = extractTypeAnnotations(nodes);

assert.strictEqual(result, 'mock-expression');
assert.strictEqual(nodes.length, 0);
Expand All @@ -232,7 +236,7 @@ describe('extractTypeAnnotations', () => {
{ type: 'emphasis', children: [{ type: 'text', value: 'emphasized' }] },
];

const result = extractTypeAnnotations(nodes, remark);
const result = extractTypeAnnotations(nodes);

assert.strictEqual(result, undefined);
assert.strictEqual(nodes.length, 2);
Expand All @@ -248,7 +252,7 @@ describe('extractTypeAnnotations', () => {
{ type: 'text', value: ' | ' }, // This shouldn't be consumed
];

const result = extractTypeAnnotations(nodes, remark);
const result = extractTypeAnnotations(nodes);

assert.strictEqual(result, 'mock-expression');
assert.strictEqual(nodes.length, 2);
Expand All @@ -259,7 +263,7 @@ describe('extractTypeAnnotations', () => {
it('handles empty nodes array', () => {
const nodes = [];

const result = extractTypeAnnotations(nodes, remark);
const result = extractTypeAnnotations(nodes);

assert.strictEqual(result, undefined);
assert.strictEqual(nodes.length, 0);
Expand All @@ -275,7 +279,7 @@ describe('extractTypeAnnotations', () => {
{ type: 'text', value: ' description' },
];

const result = extractTypeAnnotations(nodes, remark);
const result = extractTypeAnnotations(nodes);

assert.strictEqual(result, 'mock-expression');
assert.strictEqual(nodes.length, 1);
Expand All @@ -300,7 +304,7 @@ describe('parseListIntoProperties', () => {
],
};

const result = parseListIntoProperties(node, remark);
const result = parseListIntoProperties(node);

assert.deepStrictEqual(result, [
{
Expand Down Expand Up @@ -333,7 +337,7 @@ describe('parseListIntoProperties', () => {
],
};

const result = parseListIntoProperties(node, remark);
const result = parseListIntoProperties(node);

assert.deepStrictEqual(result, [
{
Expand Down Expand Up @@ -362,7 +366,7 @@ describe('parseListIntoProperties', () => {
],
};

const result = parseListIntoProperties(node, remark);
const result = parseListIntoProperties(node);

assert.deepStrictEqual(result, [
{
Expand All @@ -388,7 +392,7 @@ describe('parseListIntoProperties', () => {
],
};

const result = parseListIntoProperties(node, remark);
const result = parseListIntoProperties(node);

assert.deepStrictEqual(result, [
{
Expand Down Expand Up @@ -416,7 +420,7 @@ describe('parseListIntoProperties', () => {
],
};

const result = parseListIntoProperties(node, remark);
const result = parseListIntoProperties(node);

assert.deepStrictEqual(result, [
{
Expand Down Expand Up @@ -460,7 +464,7 @@ describe('parseListIntoProperties', () => {
],
};

const result = parseListIntoProperties(node, remark);
const result = parseListIntoProperties(node);

assert.deepStrictEqual(result, [
{
Expand Down Expand Up @@ -507,7 +511,7 @@ describe('parseListIntoProperties', () => {
],
};

const result = parseListIntoProperties(node, remark);
const result = parseListIntoProperties(node);

assert.deepStrictEqual(result, [
{
Expand Down Expand Up @@ -542,7 +546,7 @@ describe('parseListIntoProperties', () => {
],
};

const result = parseListIntoProperties(node, remark);
const result = parseListIntoProperties(node);

assert.deepStrictEqual(result, [
{
Expand All @@ -561,7 +565,7 @@ describe('parseListIntoProperties', () => {
children: [],
};

const result = parseListIntoProperties(node, remark);
const result = parseListIntoProperties(node);

assert.deepStrictEqual(result, []);
});
Expand Down Expand Up @@ -605,7 +609,7 @@ describe('parseListIntoProperties', () => {
],
};

const result = parseListIntoProperties(node, remark);
const result = parseListIntoProperties(node);
assert.deepStrictEqual(result, [
{
children: [
Expand Down
49 changes: 16 additions & 33 deletions src/generators/jsx-ast/utils/buildContent.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ import {
populate,
} from '../../../utils/configuration/templates.mjs';
import { UNIST } from '../../../utils/queries/index.mjs';
import { getRemarkRecma as remark } from '../../../utils/remark.mjs';

/**
* Processes lifecycle and change history data into a sorted array of change entries.
* @param {import('../../metadata/types').MetadataEntry} entry - The metadata entry
* @param {import('unified').Processor} remark - The remark processor
*/
export const gatherChangeEntries = (entry, remark) => {
export const gatherChangeEntries = entry => {
// Lifecycle changes (e.g., added, deprecated)
const lifecycleChanges = Object.entries(LIFECYCLE_LABELS)
.filter(([field]) => entry[field])
Expand All @@ -48,7 +48,8 @@ export const gatherChangeEntries = (entry, remark) => {
// Explicit changes with parsed JSX labels
const explicitChanges = (entry.changes || []).map(change => ({
versions: enforceArray(change.version),
label: remark.runSync(remark.parse(change.description)).body[0].expression,
label: remark().runSync(remark().parse(change.description)).body[0]
.expression,
url: change['pr-url'],
}));

Expand All @@ -58,10 +59,9 @@ export const gatherChangeEntries = (entry, remark) => {
/**
* Creates a JSX ChangeHistory element or returns null if no changes.
* @param {import('../../metadata/types').MetadataEntry} entry - The metadata entry
* @param {import('unified').Processor} remark - The remark processor
*/
export const createChangeElement = (entry, remark) => {
const changes = gatherChangeEntries(entry, remark);
export const createChangeElement = entry => {
const changes = gatherChangeEntries(entry);

if (!changes.length) {
return null;
Expand Down Expand Up @@ -197,22 +197,15 @@ const getLevelFromDeprecationType = typeText => {
/**
* Transforms a heading node by injecting metadata, source links, and signatures.
* @param {import('../../metadata/types').MetadataEntry} entry - The API metadata entry
* @param {import('unified').Processor} remark - The remark processor
* @param {import('../../metadata/types').HeadingNode} node - The heading node to transform
* @param {number} index - The index of the node in its parent's children array
* @param {import('unist').Parent} parent - The parent node containing the heading
*/
export const transformHeadingNode = async (
entry,
remark,
node,
index,
parent
) => {
export const transformHeadingNode = async (entry, node, index, parent) => {
// Replace heading node with our enhanced heading element
parent.children[index] = createHeadingElement(
node,
createChangeElement(entry, remark)
createChangeElement(entry)
);

if (entry.api === 'deprecations' && node.depth === 3) {
Expand Down Expand Up @@ -254,9 +247,8 @@ export const transformHeadingNode = async (
/**
* Processes a single API documentation entry's content
* @param {import('../../metadata/types').MetadataEntry} entry - The API metadata entry to process
* @param {import('unified').Processor} remark - The remark processor
*/
export const processEntry = (entry, remark) => {
export const processEntry = entry => {
// Deep copy content to avoid mutations on original
const content = structuredClone(entry.content);

Expand All @@ -265,15 +257,14 @@ export const processEntry = (entry, remark) => {

// Visit and transform headings with metadata and links
visit(content, UNIST.isHeading, (...args) =>
transformHeadingNode(entry, remark, ...args)
transformHeadingNode(entry, ...args)
);

// Transform typed lists into property tables
visit(
content,
UNIST.isStronglyTypedList,
(node, idx, parent) =>
(parent.children[idx] = createSignatureTable(node, remark))
(node, idx, parent) => (parent.children[idx] = createSignatureTable(node))
);

return content;
Expand All @@ -284,19 +275,13 @@ export const processEntry = (entry, remark) => {
* @param {Array<import('../../metadata/types').MetadataEntry>} entries - API documentation metadata entries
* @param {ReturnType<import('./buildBarProps.mjs').buildSideBarProps>} sideBarProps - Props for the sidebar component
* @param {ReturnType<buildMetaBarProps>} metaBarProps - Props for the meta bar component
* @param {import('unified').Processor} remark - The remark processor
*/
export const createDocumentLayout = (
entries,
sideBarProps,
metaBarProps,
remark
) =>
export const createDocumentLayout = (entries, sideBarProps, metaBarProps) =>
createTree('root', [
createJSXElement(JSX_IMPORTS.Layout.name, {
sideBarProps,
metaBarProps,
children: entries.map(entry => processEntry(entry, remark)),
children: entries.map(processEntry),
}),
]);

Expand All @@ -307,23 +292,21 @@ export const createDocumentLayout = (
* @param {Array<import('../../metadata/types').MetadataEntry>} metadataEntries - API documentation metadata entries
* @param {import('../../metadata/types').MetadataEntry} head - Main API metadata entry with version information
* @param {Object} sideBarProps - Props for the sidebar component
* @param {import('unified').Processor} remark - Remark processor instance for markdown processing
* @returns {Promise<JSXContent>}
*/
const buildContent = async (metadataEntries, head, sideBarProps, remark) => {
const buildContent = async (metadataEntries, head, sideBarProps) => {
// Build props for the MetaBar from head and entries
const metaBarProps = buildMetaBarProps(head, metadataEntries);

// Create root document AST with all layout components and processed content
const root = createDocumentLayout(
metadataEntries,
sideBarProps,
metaBarProps,
remark
metaBarProps
);

// Run remark processor to transform AST (parse markdown, plugins, etc.)
const ast = await remark.run(root);
const ast = await remark().run(root);

// The final MDX content is the expression in the Program's first body node
return { ...ast.body[0].expression, data: head };
Expand Down
5 changes: 2 additions & 3 deletions src/generators/jsx-ast/utils/signature.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,9 @@ export const insertSignatureCodeBlock = ({ children }, { data }, idx) => {
* Renders a table of properties based on parsed metadata from a Markdown list.
*
* @param {import('mdast').List} node
* @param {import('unified').Processor} remark - The remark processor
*/
export const createSignatureTable = (node, remark) => {
const items = parseListIntoProperties(node, remark);
export const createSignatureTable = node => {
const items = parseListIntoProperties(node);

return createJSXElement(JSX_IMPORTS.FunctionSignature.name, {
title: items.length === 1 && 'kind' in items[0] ? null : 'Attributes',
Expand Down
Loading
Loading