Skip to content
Open
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
191 changes: 189 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@node-core/doc-kit",
"type": "module",
"version": "1.3.10",
"version": "1.4.0",
"repository": {
"type": "git",
"url": "git+https://github.com/nodejs/doc-kit.git"
Expand Down Expand Up @@ -74,6 +74,7 @@
"rehype-recma": "^1.0.0",
"rehype-stringify": "^10.0.1",
"remark-gfm": "^4.0.1",
"remark-mdx": "^3.1.1",
"remark-parse": "^11.0.0",
"remark-rehype": "^11.1.2",
"remark-stringify": "^11.0.0",
Expand Down
82 changes: 68 additions & 14 deletions src/generators/ast/generate.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,41 @@ import { relative, sep } from 'node:path/posix';

import globParent from 'glob-parent';
import { globSync } from 'tinyglobby';
import { parse as parseYaml } from 'yaml';

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 as remark } from '../../utils/remark.mjs';
import { getRemark as remark, getRemarkMdx } from '../../utils/remark.mjs';

/**
* Determines whether a file should be parsed as MDX. A `.mdx` extension opts in
* by default, but an explicit `mdx` boolean in the file's `---` frontmatter
* always takes precedence (so a `.md` file can opt in, or a `.mdx` file out).
*
* @param {string} path - Absolute file path
* @param {string} content - Raw file contents
* @returns {boolean}
*/
const isMdxFile = (path, content) => {
const frontmatter = QUERIES.standardYamlFrontmatter.exec(content);

if (frontmatter) {
try {
const { mdx } = parseYaml(frontmatter[1]) ?? {};

if (typeof mdx === 'boolean') {
return mdx;
}
} catch {
// Node.js core docs use a non-standard frontmatter dialect that may fail
// to parse here; fall back to the extension check below.
}
}

return path.endsWith('.mdx');
};

/**
* Process a chunk of markdown files in a worker thread.
Expand All @@ -25,23 +54,48 @@ export async function processChunk(inputSlice, itemIndices) {

for (const [path, parent] of filePaths) {
const content = await readFile(path, 'utf-8');
const value = content
.replace(

const mdx = isMdxFile(path, content);

// Stability indexes become links in both modes.
const withStabilityLinks = content.replace(
QUERIES.stabilityIndexPrefix,
match => `[${match}](${STABILITY_INDEX_URL})`
);

// The path is the relative path minus the extension
const relativePath = sep + withExt(relative(parent, path));

let tree;

if (mdx) {
// A `<!-- -->` HTML comment is invalid MDX, so the frontmatter can't be
// rewritten in-source. Strip it, parse as MDX, then re-attach it as the
// YAML `html` node the metadata stage expects.
const frontmatter = QUERIES.standardYamlFrontmatter.exec(content);
const source = withStabilityLinks.replace(
QUERIES.standardYamlFrontmatter,
(_, yaml) => '<!-- YAML\n' + yaml + '\n-->\n'
)
.replace(
QUERIES.stabilityIndexPrefix,
match => `[${match}](${STABILITY_INDEX_URL})`
''
);

const relativePath = sep + withExt(relative(parent, path));
tree = getRemarkMdx().parse(source);

if (frontmatter) {
tree.children.unshift({
type: 'html',
value: `<!-- YAML\n${frontmatter[1]}\n-->`,
});
}
} else {
const value = withStabilityLinks.replace(
QUERIES.standardYamlFrontmatter,
(_, yaml) => `<!-- YAML\n${yaml}\n-->`
);

tree = remark().parse(value);
}

results.push({
tree: remark().parse(value),
// The path is the relative path minus the extension
path: relativePath,
});
results.push({ tree, path: relativePath, mdx });
}

return results;
Expand Down
Loading
Loading