parseDir.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. import fs from "node:fs/promises";
  2. import {constants} from "node:fs";
  3. import path from "path";
  4. import htmlMinifier from "html-minifier-terser";
  5. import esbuild from "esbuild";
  6. export default async (dir)=>{
  7. const existingFiles = await checkFiles(dir);
  8. if(!existingFiles.html) return;
  9. const content = await bundleFiles(existingFiles);
  10. const html = mergeFiles(content);
  11. writeHtml(dir, html);
  12. }
  13. const checkFiles = async (dir)=>{
  14. let htmlPath = path.join(dir, "index.html");
  15. let cssPath = path.join(dir, "index.css");
  16. let jsPath = path.join(dir, "index.js");
  17. let [html, css, js] = await Promise.allSettled([
  18. fs.access(htmlPath, constants.F_OK),
  19. fs.access(cssPath, constants.F_OK),
  20. fs.access(jsPath, constants.f_OK)
  21. ]);
  22. if(html.status !== "fulfilled") return {html: null};
  23. let files = {html: htmlPath};
  24. if(css.status === "fulfilled") files.css = cssPath;
  25. if(js.status === "fulfilled") files.js = jsPath;
  26. return files;
  27. }
  28. const bundleFiles = async (files)=>{
  29. const entryPoints = [];
  30. if(files.css) entryPoints.push(files.css);
  31. if(files.js) entryPoints.push(files.js);
  32. const esbuildProm = esbuild.build({
  33. entryPoints: entryPoints,
  34. bundle: true,
  35. minify: true,
  36. write: false,
  37. outdir: "/"
  38. });
  39. const htmlProm = fs.readFile(files.html, "utf-8");
  40. const data = await Promise.all([esbuildProm, htmlProm]);
  41. const contents = {
  42. html: await htmlMinifier.minify(data[1], {
  43. collapseBooleanAttributes: true,
  44. collapseInlineTagWhitespace: true,
  45. collapseWhitespace: true,
  46. conservativeCollapse: false,
  47. decodeEntities: true,
  48. noNewlinesBeforeTagClose: true,
  49. removeComments: true
  50. }),
  51. js: "",
  52. css: ""
  53. };
  54. if(files.css && files.js){
  55. contents.css = `<style>${data[0].outputFiles[0].text}</style>`;
  56. contents.js = `<script>${data[0].outputFiles[1].text}</script>`;
  57. }else if(files.css){
  58. contents.css = `<style>${data[0].outputFiles[0].text}</style>`;
  59. }else if(files.js){
  60. contents.js = `<script>${data[0].outputFiles[0].text}</script>`;
  61. }
  62. return contents;
  63. }
  64. const mergeFiles = (contents)=>{
  65. const cssIndex = contents.html.indexOf("</head>");
  66. let html = `${contents.html.slice(0, cssIndex)}${contents.css}${contents.html.slice(cssIndex)}`;
  67. const jsIndex = html.indexOf("</body>");
  68. return `${html.slice(0, jsIndex)}${contents.js}${html.slice(jsIndex)}`;
  69. }
  70. const writeHtml = async (dir, html)=>{
  71. const writeDir = `${dir.replace("/src", "/.build")}`;
  72. await fs.mkdir(writeDir, {recursive: true});
  73. fs.writeFile(`${writeDir}/index.html`, html);
  74. }