Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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