Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: validate that the docs can be parsed by mdx #2711

Merged
merged 1 commit into from Feb 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
43 changes: 36 additions & 7 deletions docs/dockhand.js
Expand Up @@ -4,6 +4,7 @@ const path = require('path');
const fs = require('fs');
const yaml = require('yaml');
const cmark = require('cmark-gfm');
const mdx = require('@mdx-js/mdx');
const mkdirp = require('mkdirp');
const jsdom = require('jsdom');
const npm = require('../lib/npm.js')
Expand All @@ -16,25 +17,35 @@ const outputRoot = path.join(docsRoot, 'output');

const template = fs.readFileSync('template.html').toString();

walk(inputRoot);
const run = async function() {
try {
await walk(inputRoot);
}
catch (error) {
console.error(error);
}
}

function walk(root, dirRelative) {
run();

async function walk(root, dirRelative) {
const dirPath = dirRelative ? path.join(root, dirRelative) : root;
const children = fs.readdirSync(dirPath);

fs.readdirSync(dirPath).forEach((childFilename) => {
for (const childFilename of children) {
const childRelative = dirRelative ? path.join(dirRelative, childFilename) : childFilename;
const childPath = path.join(root, childRelative);

if (fs.lstatSync(childPath).isDirectory()) {
walk(root, childRelative);
await walk(root, childRelative);
}
else {
translate(childRelative);
await translate(childRelative);
}
});
}
}

function translate(childPath) {
async function translate(childPath) {
const inputPath = path.join(inputRoot, childPath);

if (!inputPath.match(/\.md$/)) {
Expand Down Expand Up @@ -70,6 +81,16 @@ function translate(childPath) {
}
});

// Test that mdx can parse this markdown file. We don't actually
// use the output, it's just to ensure that the upstream docs
// site (docs.npmjs.com) can parse it when this file gets there.
try {
await mdx(md, { skipExport: true });
}
catch (error) {
throw new MarkdownError(childPath, error);
}

// Inject this data into the template, using a mustache-like
// replacement scheme.
const html = template.replace(/\{\{\s*([\w\.]+)\s*\}\}/g, (token, key) => {
Expand Down Expand Up @@ -225,3 +246,11 @@ function headerLevel(node) {
function debug(str) {
console.log(str);
}

class MarkdownError extends Error {
constructor(file, inner) {
super(`failed to parse ${file}`);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we care about the original error being eaten here?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a great use case for the error cause proposal, but lacking that, you could make MarkdownError extend AggregateError instead, and preserve the original error that way?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ljharb @wraithgar I don't think we care that much about this until we actually run into a problem making the docs pass/build. We can backlog some work to improve this & feel free to add changes.

this.file = file;
this.inner = inner;
}
}
83 changes: 83 additions & 0 deletions node_modules/.gitignore

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