2019-12-07 16:10:32 +00:00
|
|
|
#!/usr/bin/env node
|
|
|
|
|
|
|
|
const fs = require('fs');
|
|
|
|
const argparse = require('argparse');
|
|
|
|
const markdownIt = require('markdown-it');
|
|
|
|
const markdownItTaskCheckbox = require('markdown-it-task-checkbox');
|
|
|
|
const markdownItEmoji = require('markdown-it-emoji');
|
|
|
|
const markdownItHeaderAnchors = require('./markdown-it-header-anchors');
|
2020-09-06 16:07:36 +00:00
|
|
|
const Prism = require('prismjs/components/prism-core');
|
2019-12-07 16:10:32 +00:00
|
|
|
const loadPrismLanguages = require('prismjs/components/');
|
2020-09-06 16:07:36 +00:00
|
|
|
const PRISM_COMPONENTS = require('prismjs/components.js');
|
2019-12-07 16:10:32 +00:00
|
|
|
|
2020-09-06 08:43:17 +00:00
|
|
|
// TODO: integrate <https://github.com/PrismJS/prism-themes>
|
|
|
|
const PRISM_THEMES = Object.keys(PRISM_COMPONENTS.themes).filter(
|
|
|
|
(k) => k !== 'meta',
|
|
|
|
);
|
|
|
|
|
2019-12-07 16:10:32 +00:00
|
|
|
let parser = new argparse.ArgumentParser();
|
2020-09-06 08:43:17 +00:00
|
|
|
|
|
|
|
parser.addArgument('INPUT_FILE', {
|
2019-12-07 16:10:32 +00:00
|
|
|
nargs: argparse.Const.OPTIONAL,
|
|
|
|
help: '(stdin by default)',
|
|
|
|
});
|
2020-09-06 08:43:17 +00:00
|
|
|
parser.addArgument('OUTPUT_FILE', {
|
2019-12-07 16:10:32 +00:00
|
|
|
nargs: argparse.Const.OPTIONAL,
|
|
|
|
help: '(stdout by default)',
|
|
|
|
});
|
2020-09-06 08:43:17 +00:00
|
|
|
|
|
|
|
parser.addArgument('--input-encoding', {
|
|
|
|
defaultValue: 'utf-8',
|
|
|
|
help: '(utf-8 by default)',
|
|
|
|
});
|
|
|
|
parser.addArgument('--output-encoding', {
|
|
|
|
defaultValue: 'utf-8',
|
|
|
|
help: '(utf-8 by default)',
|
|
|
|
});
|
|
|
|
|
|
|
|
parser.addArgument('--no-default-stylesheets', {
|
|
|
|
nargs: argparse.Const.SUPPRESS,
|
|
|
|
});
|
|
|
|
parser.addArgument('--syntax-theme', {
|
|
|
|
choices: PRISM_THEMES,
|
|
|
|
});
|
|
|
|
|
|
|
|
parser.addArgument('--stylesheet', {
|
|
|
|
nargs: argparse.Const.ZERO_OR_MORE,
|
|
|
|
});
|
|
|
|
parser.addArgument('--script', {
|
|
|
|
nargs: argparse.Const.ZERO_OR_MORE,
|
|
|
|
});
|
|
|
|
|
2019-12-07 16:10:32 +00:00
|
|
|
let args = parser.parseArgs();
|
|
|
|
|
|
|
|
let md = markdownIt({
|
|
|
|
html: true,
|
|
|
|
linkify: true,
|
2020-09-06 16:07:36 +00:00
|
|
|
highlight: (code, lang) => {
|
|
|
|
if (lang) {
|
2019-12-07 16:10:32 +00:00
|
|
|
loadPrismLanguages([lang]);
|
2019-12-11 21:03:10 +00:00
|
|
|
if (Object.prototype.hasOwnProperty.call(Prism.languages, lang)) {
|
2020-09-06 16:07:36 +00:00
|
|
|
return Prism.highlight(code, Prism.languages[lang], lang);
|
2019-12-11 21:03:10 +00:00
|
|
|
}
|
2019-12-07 16:10:32 +00:00
|
|
|
}
|
2020-09-06 16:07:36 +00:00
|
|
|
return null;
|
2019-12-07 16:10:32 +00:00
|
|
|
},
|
|
|
|
});
|
|
|
|
md.use(markdownItTaskCheckbox);
|
|
|
|
md.use(markdownItEmoji);
|
|
|
|
md.use(markdownItHeaderAnchors);
|
|
|
|
|
2020-09-06 08:43:17 +00:00
|
|
|
let markdownDocument = fs.readFileSync(
|
|
|
|
args.get('INPUT_FILE', 0),
|
|
|
|
args.get('input_encoding'),
|
2020-07-06 15:51:13 +00:00
|
|
|
);
|
2020-09-06 08:43:17 +00:00
|
|
|
let renderedMarkdown = md.render(markdownDocument);
|
|
|
|
|
|
|
|
let stylesheetsTexts = [];
|
|
|
|
let scriptsTexts = [];
|
|
|
|
let syntaxThemeName = null;
|
|
|
|
|
|
|
|
if (!args.get('no_default_stylesheets')) {
|
|
|
|
syntaxThemeName = 'prism';
|
|
|
|
stylesheetsTexts.push(
|
|
|
|
fs.readFileSync(
|
|
|
|
require.resolve('github-markdown-css/github-markdown.css'),
|
|
|
|
'utf-8',
|
|
|
|
),
|
|
|
|
fs.readFileSync(
|
|
|
|
require.resolve('./github-markdown-additions.css'),
|
|
|
|
'utf-8',
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
syntaxThemeName = args.get('syntax_theme') || syntaxThemeName;
|
|
|
|
if (syntaxThemeName) {
|
|
|
|
stylesheetsTexts.push(
|
|
|
|
fs.readFileSync(
|
|
|
|
require.resolve(`prismjs/themes/${syntaxThemeName}.css`),
|
|
|
|
'utf-8',
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (let stylesheetPath of args.get('stylesheet', [])) {
|
|
|
|
stylesheetsTexts.push(fs.readFileSync(stylesheetPath));
|
|
|
|
}
|
|
|
|
|
|
|
|
for (let scriptPath of args.get('script', [])) {
|
|
|
|
scriptsTexts.push(fs.readFileSync(scriptPath));
|
|
|
|
}
|
2019-12-07 16:10:32 +00:00
|
|
|
|
|
|
|
let renderedHtmlDocument = `
|
|
|
|
<!DOCTYPE html>
|
|
|
|
<html>
|
|
|
|
<head>
|
|
|
|
<meta charset="UTF-8">
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
2020-09-06 08:43:17 +00:00
|
|
|
${stylesheetsTexts.map((s) => `<style>\n${s}\n</style>`).join('\n')}
|
2019-12-07 16:10:32 +00:00
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<article class="markdown-body">
|
|
|
|
${renderedMarkdown}
|
|
|
|
</article>
|
2020-09-06 08:43:17 +00:00
|
|
|
${scriptsTexts.map((s) => `<script>\n${s}\n</script>`).join('\n')}
|
2019-12-07 16:10:32 +00:00
|
|
|
</body>
|
|
|
|
</html>
|
|
|
|
`;
|
|
|
|
|
2020-09-06 08:43:17 +00:00
|
|
|
fs.writeFileSync(
|
|
|
|
args.get('OUTPUT_FILE', 1),
|
|
|
|
renderedHtmlDocument,
|
|
|
|
args.get('output_encoding'),
|
|
|
|
);
|