myst-parser
Version:
Markdown parser for MyST markdown in JavaScript
73 lines (72 loc) • 2.84 kB
JavaScript
import { RuleId, fileError, fileWarn } from 'myst-common';
import { selectAll } from 'unist-util-select';
import { contentFromNode } from './utils.js';
import { parseOptions } from './inlineAttributes.js';
export function applyRoles(tree, specs, vfile) {
const specLookup = {};
specs.forEach((spec) => {
const names = [spec.name];
if (spec.alias) {
names.push(...(typeof spec.alias === 'string' ? [spec.alias] : spec.alias));
}
names.forEach((name) => {
if (specLookup[name]) {
fileWarn(vfile, `duplicate roles registered with name: ${name}`, {
ruleId: RuleId.roleRegistered,
});
}
else {
specLookup[name] = spec;
}
});
});
const nodes = selectAll('mystRole[processed=false]', tree);
nodes.forEach((node) => {
var _a;
delete node.processed; // Indicate that the role has been processed
const { name } = node;
const spec = specLookup[name];
if (!spec) {
fileError(vfile, `unknown role: ${name}`, { node, ruleId: RuleId.roleKnown });
// We probably want to do something better than just delete the children
delete node.children;
return;
}
const { body, options: optionsSpec, validate, run } = spec;
let data = { name, node: node, options: {} };
const { valid: validOptions, options } = parseOptions(name, node, vfile, optionsSpec);
let validationError = validOptions;
data.options = options;
// Only look to the direct children
const bodyNode = (_a = node.children) === null || _a === void 0 ? void 0 : _a.find((n) => n.type === 'mystRoleBody');
if (body) {
if (body.required && !bodyNode) {
fileError(vfile, `required body not provided for role: ${name}`, {
node,
ruleId: RuleId.roleBodyCorrect,
});
node.type = 'mystRoleError';
delete node.children;
validationError = true;
}
else {
data.body = contentFromNode(bodyNode, body, vfile, `body of role: ${name}`, RuleId.roleBodyCorrect);
if (body.required && data.body == null) {
validationError = true;
}
}
}
else if (bodyNode) {
fileWarn(vfile, `unexpected body provided for role: ${name}`, {
node: bodyNode,
ruleId: RuleId.roleBodyCorrect,
});
}
if (validationError)
return;
if (validate) {
data = validate(data, vfile);
}
node.children = run(data, vfile);
});
}