mirror of https://github.com/lukechilds/docs.git
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.
70 lines
1.9 KiB
70 lines
1.9 KiB
const { getOptions } = require('loader-utils');
|
|
const mdx = require('@mdx-js/mdx');
|
|
const fm = require('gray-matter');
|
|
const remark = require('remark');
|
|
const strip = require('strip-markdown');
|
|
const readingTime = require('reading-time');
|
|
|
|
const DEFAULT_RENDERER = `
|
|
import React from 'react'
|
|
import { mdx } from '@mdx-js/react'
|
|
`;
|
|
|
|
const getReadingTime = mdxContent => readingTime(mdxContent);
|
|
|
|
const getHeadings = mdxContent => {
|
|
const regex = /\n(#+)(.*)/gm;
|
|
const found = mdxContent.match(regex);
|
|
const getLevel = string => string.split('#');
|
|
const headings =
|
|
found && found.length
|
|
? found.map(f => {
|
|
const md = f.split('# ')[1];
|
|
let content = md;
|
|
remark()
|
|
.use(strip)
|
|
.process(md, (err, file) => {
|
|
if (err) throw err;
|
|
content = file.contents.toString().trim();
|
|
});
|
|
const level = getLevel(f).length;
|
|
return { content, level };
|
|
})
|
|
: [];
|
|
return headings;
|
|
};
|
|
|
|
const layoutPropsString = `const layoutProps = {`;
|
|
const newLayoutPropsString = frontmatter => `const layoutProps = {
|
|
frontmatter: ${frontmatter},\n`;
|
|
|
|
const withFrontmatter = (code, frontmatter) =>
|
|
code.replace(layoutPropsString, newLayoutPropsString(frontmatter));
|
|
|
|
const loader = async function (src) {
|
|
const callback = this.async();
|
|
const options = Object.assign({}, getOptions(this), {
|
|
filepath: this.resourcePath,
|
|
});
|
|
|
|
const { content, data } = fm(src);
|
|
const headings = getHeadings(content);
|
|
const duration = getReadingTime(content).text;
|
|
const frontmatter = JSON.stringify({ duration, ...data, headings });
|
|
|
|
let result;
|
|
|
|
try {
|
|
result = await mdx(content, options);
|
|
} catch (err) {
|
|
return callback(err);
|
|
}
|
|
|
|
const { renderer = DEFAULT_RENDERER } = options;
|
|
|
|
const code = withFrontmatter(`${renderer}\n${result}`, frontmatter);
|
|
|
|
return callback(null, code);
|
|
};
|
|
|
|
module.exports = loader;
|
|
|