2023-09-09 17:51:42 -06:00
|
|
|
/* global marked */
|
|
|
|
import '../marked.min.js';
|
2021-11-02 07:32:17 -07:00
|
|
|
import { promises } from 'fs';
|
|
|
|
import { join, dirname, parse, format } from 'path';
|
2024-11-24 15:31:41 -05:00
|
|
|
import { fileURLToPath } from 'url';
|
2023-08-10 21:25:40 -06:00
|
|
|
import { markedHighlight } from 'marked-highlight';
|
2021-11-02 07:32:17 -07:00
|
|
|
import { HighlightJS } from 'highlight.js';
|
|
|
|
import titleize from 'titleize';
|
2024-11-24 15:31:41 -05:00
|
|
|
import { getTests } from '@markedjs/testutils';
|
2022-03-30 17:42:54 +02:00
|
|
|
|
2021-11-02 07:32:17 -07:00
|
|
|
const { mkdir, rm, readdir, stat, readFile, writeFile, copyFile } = promises;
|
|
|
|
const { highlight, highlightAuto } = HighlightJS;
|
2020-08-15 19:05:08 -04:00
|
|
|
const cwd = process.cwd();
|
2024-11-24 15:31:41 -05:00
|
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
|
|
const __dirname = dirname(__filename);
|
2020-08-15 19:05:08 -04:00
|
|
|
const inputDir = join(cwd, 'docs');
|
|
|
|
const outputDir = join(cwd, 'public');
|
2020-08-15 19:20:00 -04:00
|
|
|
const templateFile = join(inputDir, '_document.html');
|
2020-08-16 22:28:55 -04:00
|
|
|
const isUppercase = str => /[A-Z_]+/.test(str);
|
2020-08-16 23:34:13 -04:00
|
|
|
const getTitle = str => str === 'INDEX' ? '' : titleize(str.replace(/_/g, ' ')) + ' - ';
|
2024-11-24 15:31:41 -05:00
|
|
|
function convertTestsToTable(name, tests) {
|
|
|
|
let total = 0;
|
|
|
|
let passing = 0;
|
|
|
|
let table = '\n| Section | Passing | Percent |\n';
|
|
|
|
table += '|:--------|:--------|--------:|\n';
|
|
|
|
for (const [key, value] of Object.entries(tests)) {
|
|
|
|
total += value.total;
|
|
|
|
passing += value.pass;
|
|
|
|
table += ` | ${key}`;
|
|
|
|
table += ` | ${(value.pass)} of ${(value.total)}`;
|
|
|
|
table += ` | ${((value.pass) / value.total * 100).toFixed()}%`;
|
|
|
|
table += ' |\n';
|
|
|
|
}
|
|
|
|
return `\n<details name="markdown-spec">
|
|
|
|
<summary>${name} (${(passing / total * 100).toFixed()}%)</summary>
|
|
|
|
${table}
|
|
|
|
</details>\n`;
|
|
|
|
}
|
|
|
|
|
2023-09-09 17:51:42 -06:00
|
|
|
const markedInstance = new marked.Marked(markedHighlight((code, language) => {
|
2023-08-10 21:25:40 -06:00
|
|
|
if (!language) {
|
|
|
|
return highlightAuto(code).value;
|
|
|
|
}
|
|
|
|
return highlight(code, { language }).value;
|
|
|
|
}));
|
2020-08-15 19:05:08 -04:00
|
|
|
|
|
|
|
async function init() {
|
|
|
|
console.log('Cleaning up output directory ' + outputDir);
|
2021-11-02 07:32:17 -07:00
|
|
|
await rm(outputDir, { force: true, recursive: true });
|
2020-08-15 19:05:08 -04:00
|
|
|
await mkdir(outputDir);
|
2023-09-09 17:51:42 -06:00
|
|
|
console.log(`Copying file ${join(inputDir, 'LICENSE.md')}`);
|
2020-08-15 19:42:22 -04:00
|
|
|
await copyFile(join(cwd, 'LICENSE.md'), join(inputDir, 'LICENSE.md'));
|
2023-09-09 17:51:42 -06:00
|
|
|
console.log(`Copying file ${join(outputDir, 'marked.min.js')}`);
|
|
|
|
await copyFile(join(cwd, 'marked.min.js'), join(outputDir, 'marked.min.js'));
|
2020-08-15 19:20:00 -04:00
|
|
|
const tmpl = await readFile(templateFile, 'utf8');
|
2020-08-15 19:05:08 -04:00
|
|
|
console.log('Building markdown...');
|
2024-11-24 15:31:41 -05:00
|
|
|
const [original, commonmark, gfm] = await getTests([
|
|
|
|
join(__dirname, '../test/specs/original'),
|
|
|
|
join(__dirname, '../test/specs/commonmark'),
|
|
|
|
join(__dirname, '../test/specs/gfm'),
|
|
|
|
]);
|
|
|
|
const testResultsTable =
|
|
|
|
convertTestsToTable('Markdown 1.0', original)
|
|
|
|
+ convertTestsToTable('CommonMark 0.31', commonmark)
|
|
|
|
+ convertTestsToTable('GitHub Flavored Markdown 0.29', gfm);
|
|
|
|
await build(inputDir, tmpl, testResultsTable);
|
2020-08-15 19:05:08 -04:00
|
|
|
console.log('Build complete!');
|
|
|
|
}
|
|
|
|
|
2023-09-09 17:51:42 -06:00
|
|
|
const ignoredFiles = [
|
|
|
|
join(cwd, 'docs', 'build.js'),
|
|
|
|
join(cwd, 'docs', '.eslintrc.json'),
|
2024-07-14 18:54:46 -06:00
|
|
|
join(cwd, 'docs', '_document.html'),
|
2023-09-09 17:51:42 -06:00
|
|
|
];
|
|
|
|
|
2024-11-24 15:31:41 -05:00
|
|
|
async function build(currentDir, tmpl, testResultsTable) {
|
2020-08-15 19:05:08 -04:00
|
|
|
const files = await readdir(currentDir);
|
|
|
|
for (const file of files) {
|
|
|
|
const filename = join(currentDir, file);
|
2023-09-09 17:51:42 -06:00
|
|
|
if (ignoredFiles.includes(filename)) {
|
|
|
|
continue;
|
|
|
|
}
|
2020-08-15 19:05:08 -04:00
|
|
|
const stats = await stat(filename);
|
|
|
|
const { mode } = stats;
|
|
|
|
if (stats.isDirectory()) {
|
2020-08-15 19:20:00 -04:00
|
|
|
await build(filename, tmpl);
|
2020-08-15 19:05:08 -04:00
|
|
|
} else {
|
2023-08-11 21:46:54 -06:00
|
|
|
let html = await readFile(filename, 'utf8');
|
2020-08-16 22:11:24 -04:00
|
|
|
const parsed = parse(filename);
|
|
|
|
if (parsed.ext === '.md' && isUppercase(parsed.name)) {
|
2024-11-24 15:31:41 -05:00
|
|
|
const mdHtml = markedInstance.parse(
|
|
|
|
html.replace('<!--{{test-results-table}}-->', testResultsTable),
|
|
|
|
);
|
2023-08-11 21:46:54 -06:00
|
|
|
html = tmpl
|
2020-08-16 23:34:13 -04:00
|
|
|
.replace('<!--{{title}}-->', getTitle(parsed.name))
|
2023-08-11 21:46:54 -06:00
|
|
|
.replace('<!--{{content}}-->', mdHtml);
|
2020-08-16 23:07:03 -04:00
|
|
|
parsed.ext = '.html';
|
2020-08-16 22:11:24 -04:00
|
|
|
parsed.name = parsed.name.toLowerCase();
|
|
|
|
delete parsed.base;
|
2020-08-15 19:05:08 -04:00
|
|
|
}
|
2020-08-16 22:11:24 -04:00
|
|
|
parsed.dir = parsed.dir.replace(inputDir, outputDir);
|
|
|
|
const outfile = format(parsed);
|
2020-08-15 19:05:08 -04:00
|
|
|
await mkdir(dirname(outfile), { recursive: true });
|
2020-08-16 22:28:55 -04:00
|
|
|
console.log('Writing file ' + outfile);
|
2023-08-11 21:46:54 -06:00
|
|
|
await writeFile(outfile, html, { mode });
|
2020-08-15 19:05:08 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
init().catch(console.error);
|