Files
noodl-docs/plugins/import-markdown.js
Eric Tuvesson 656e5fc8d2 chore: Upgrade Docusaurus from v2 to v3 (#52)
* chore: Upgrade Docusaurus from v2 to v3

* chore: Update "Test build" GH workflow

* fix: build

All markdown is processed as MDX

* fix: Broken links
2024-01-12 16:53:22 +01:00

104 lines
3.2 KiB
JavaScript

/**
* Inspired by https://github.com/hashicorp/web-platform-packages/tree/9723b25a054674f9c2bebc12928377c35957508f/packages/remark-plugins/plugins/include-markdown
*
* Problem with that page is that it is not ES6,
* which Docusaurus doesn't support yet.
*/
const path = require('path')
const { remark } = require('remark')
const remarkMdx = require('remark-mdx')
const { _parseNoodlMarkupPlugin } = require('./markdown-syntax')
const readFileSync = require('fs').readFileSync
function flatMap(ast, fn) {
return transform(ast, 0, null)[0]
function transform(node, index, parent) {
if (node.children) {
var out = []
for (var i = 0, n = node.children.length; i < n; i++) {
var xs = transform(node.children[i], i, node)
if (xs) {
for (var j = 0, m = xs.length; j < m; j++) {
out.push(xs[j])
}
}
}
node.children = out
}
return fn(node, index, parent)
}
}
function includeMarkdownPlugin({
resolveFrom,
resolveMdx,
} = {}) {
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) {
//if (JSON.stringify(node).includes('.md'))
// console.log('NO MATCH', node)
return [node]
}
//console.log('MATCH', node)
// read the file contents
const includePath = path.join(
resolveFrom || file.dirname,
includeMatch[1]
)
let includeContents
try {
includeContents = readFileSync(includePath, {
encoding: 'utf8'
})
} catch (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
// (takes a couple steps because we're processing includes with remark)
const processor = remark().use(_parseNoodlMarkupPlugin)
// NOTE: Use our _parseNoodlMarkupPlugin plugin
// use remark-mdx to process the include contents
processor.use(remarkMdx)
// use the includeMarkdown plugin to allow recursive includes
processor.use(includeMarkdownPlugin, {
resolveFrom,
resolveMdx
})
// Process the file contents, then return them
const ast = processor.parse(includeContents)
const res = processor.runSync(ast, includeContents)
return res.children
} else {
// trim trailing newline
includeContents.value = includeContents.value.trim()
// return contents wrapped inside a "code" node
return [{
type: 'code',
lang: includePath.match(/\.(\w+)$/)[1],
value: includeContents,
}, ]
}
})
}
}
module.exports = includeMarkdownPlugin