2
0

build.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. /* global marked */
  2. import '../marked.min.js';
  3. import { promises } from 'fs';
  4. import { join, dirname, parse, format } from 'path';
  5. import { fileURLToPath } from 'url';
  6. import { markedHighlight } from 'marked-highlight';
  7. import { HighlightJS } from 'highlight.js';
  8. import titleize from 'titleize';
  9. import { getTests } from '@markedjs/testutils';
  10. const { mkdir, rm, readdir, stat, readFile, writeFile, copyFile } = promises;
  11. const { highlight, highlightAuto } = HighlightJS;
  12. const cwd = process.cwd();
  13. const __filename = fileURLToPath(import.meta.url);
  14. const __dirname = dirname(__filename);
  15. const inputDir = join(cwd, 'docs');
  16. const outputDir = join(cwd, 'public');
  17. const templateFile = join(inputDir, '_document.html');
  18. const isUppercase = str => /[A-Z_]+/.test(str);
  19. const getTitle = str => str === 'INDEX' ? '' : titleize(str.replace(/_/g, ' ')) + ' - ';
  20. function convertTestsToTable(name, tests) {
  21. let total = 0;
  22. let passing = 0;
  23. let table = '\n| Section | Passing | Percent |\n';
  24. table += '|:--------|:--------|--------:|\n';
  25. for (const [key, value] of Object.entries(tests)) {
  26. total += value.total;
  27. passing += value.pass;
  28. table += ` | ${key}`;
  29. table += ` | ${(value.pass)} of ${(value.total)}`;
  30. table += ` | ${((value.pass) / value.total * 100).toFixed()}%`;
  31. table += ' |\n';
  32. }
  33. return `\n<details name="markdown-spec">
  34. <summary>${name} (${(passing / total * 100).toFixed()}%)</summary>
  35. ${table}
  36. </details>\n`;
  37. }
  38. const markedInstance = new marked.Marked(markedHighlight((code, language) => {
  39. if (!language) {
  40. return highlightAuto(code).value;
  41. }
  42. return highlight(code, { language }).value;
  43. }));
  44. async function init() {
  45. console.log('Cleaning up output directory ' + outputDir);
  46. await rm(outputDir, { force: true, recursive: true });
  47. await mkdir(outputDir);
  48. console.log(`Copying file ${join(inputDir, 'LICENSE.md')}`);
  49. await copyFile(join(cwd, 'LICENSE.md'), join(inputDir, 'LICENSE.md'));
  50. console.log(`Copying file ${join(outputDir, 'marked.min.js')}`);
  51. await copyFile(join(cwd, 'marked.min.js'), join(outputDir, 'marked.min.js'));
  52. const tmpl = await readFile(templateFile, 'utf8');
  53. console.log('Building markdown...');
  54. const [original, commonmark, gfm] = await getTests([
  55. join(__dirname, '../test/specs/original'),
  56. join(__dirname, '../test/specs/commonmark'),
  57. join(__dirname, '../test/specs/gfm'),
  58. ]);
  59. const testResultsTable =
  60. convertTestsToTable('Markdown 1.0', original)
  61. + convertTestsToTable('CommonMark 0.31', commonmark)
  62. + convertTestsToTable('GitHub Flavored Markdown 0.29', gfm);
  63. await build(inputDir, tmpl, testResultsTable);
  64. console.log('Build complete!');
  65. }
  66. const ignoredFiles = [
  67. join(cwd, 'docs', 'build.js'),
  68. join(cwd, 'docs', '.eslintrc.json'),
  69. join(cwd, 'docs', '_document.html'),
  70. ];
  71. async function build(currentDir, tmpl, testResultsTable) {
  72. const files = await readdir(currentDir);
  73. for (const file of files) {
  74. const filename = join(currentDir, file);
  75. if (ignoredFiles.includes(filename)) {
  76. continue;
  77. }
  78. const stats = await stat(filename);
  79. const { mode } = stats;
  80. if (stats.isDirectory()) {
  81. await build(filename, tmpl);
  82. } else {
  83. let html = await readFile(filename, 'utf8');
  84. const parsed = parse(filename);
  85. if (parsed.ext === '.md' && isUppercase(parsed.name)) {
  86. const mdHtml = markedInstance.parse(
  87. html.replace('<!--{{test-results-table}}-->', testResultsTable),
  88. );
  89. html = tmpl
  90. .replace('<!--{{title}}-->', getTitle(parsed.name))
  91. .replace('<!--{{content}}-->', mdHtml);
  92. parsed.ext = '.html';
  93. parsed.name = parsed.name.toLowerCase();
  94. delete parsed.base;
  95. }
  96. parsed.dir = parsed.dir.replace(inputDir, outputDir);
  97. const outfile = format(parsed);
  98. await mkdir(dirname(outfile), { recursive: true });
  99. console.log('Writing file ' + outfile);
  100. await writeFile(outfile, html, { mode });
  101. }
  102. }
  103. }
  104. init().catch(console.error);