You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

52 lines
1.9 KiB

const path = require('path');
const remark = require('remark');
const flatMap = require('unist-util-flatmap');
const { readSync } = require('to-vfile');
module.exports = function includeMarkdownPlugin({ resolveFrom } = {}) {
return function transformer(tree, file) {
return flatMap(tree, node => {
if (node.type !== 'paragraph') return [node];
// detect an `@include` statement
const includeMatch =
node.children[0].value && node.children[0].value.match(/^@include\s['"](.*)['"]$/);
if (!includeMatch) return [node];
// read the file contents
const includePath = path.join(resolveFrom || file.dirname, includeMatch[1]);
let includeContents;
try {
includeContents = readSync(includePath, 'utf8');
} catch (err) {
console.log(err);
throw new Error(
`The @include file path at ${includePath} was not found.\n\nInclude Location: ${file.path}:${node.position.start.line}:${node.position.start.column}`
);
}
// if we are including a ".md" or ".mdx" file, we add the contents as processed markdown
// if any other file type, they are embedded into a code block
if (includePath.match(/\.md(?:x)?$/)) {
// return the file contents in place of the @include
// this takes a couple steps because we allow recursive includes
const processor = remark().use(includeMarkdownPlugin, { resolveFrom });
const ast = processor.parse(includeContents);
return processor.runSync(ast, includeContents).children;
} else {
// trim trailing newline
includeContents.contents = includeContents.contents.trim();
// return contents wrapped inside a "code" node
return [
{
type: 'code',
lang: includePath.match(/\.(\w+)$/)[1],
value: includeContents,
},
];
}
});
};
};