import fs from "node:fs/promises"; import path from "path"; import htmlMinifier from "html-minifier-terser"; import esbuild from "esbuild"; export default async (file)=>{ const dir = path.dirname(file); let data = {}; if(path.extname(file) === ".neovan"){ data = await getNeovanData(file); }else{ data = await parseHtml(file); } const bundle = await createBundle(data); writeFile(dir, bundle); fs.rm(path.join(dir, "tmp/"), {recursive: true, force: true}); } const getNeovanData = async (index)=>{ const neovan = await fs.readFile(index, "utf-8"); const parentPath = path.dirname(index); const html = neovan.slice(neovan.indexOf("") + 10, neovan.indexOf("")); const css = neovan.slice(neovan.indexOf("")); const js = neovan.slice(neovan.indexOf("")); const cssFile = path.join(parentPath, `tmp/${path.basename(index, ".neovan")}.css`); const jsFile = path.join(parentPath, `tmp/${path.basename(index, ".neovan")}.js`); await fs.mkdir(path.join(parentPath, "tmp/")); await Promise.all([ css === "" ? null : fs.writeFile(cssFile, css), js === "" ? null : fs.writeFile(jsFile, js) ]); return { html: html, css: cssFile, js: jsFile }; } const parseHtml = async (index)=>{ const parentPath = path.dirname(index); const basename = path.basename(index, ".html"); return { html: await fs.readFile(index, "utf-8"), css: path.join(parentPath, `${basename}.css`), js: path.join(parentPath, `${basename}.js`) }; } const createBundle = async (data)=>{ const entryPoints = []; if(data.css) entryPoints.push(data.css); if(data.js) entryPoints.push(data.js); const esbuildProm = esbuild.build({ entryPoints: entryPoints, bundle: true, minify: true, write: false, outdir: "/" }); const htmlProm = htmlMinifier.minify(data.html, { collapseBooleanAttributes: true, collapseInlineTagWhitespace: true, collapseWhitespace: true, decodeEntities: true, html5: true, includeAutoGeneratedTags: false, noNewlinesBeforeTagClose: true, removeComments: true, useShortDoctype: true }); const [buildData, html] = await Promise.all([esbuildProm, htmlProm]); const comps = {html: html}; for(let i = 0; i < buildData.outputFiles.length; i++){ const ext = path.extname(buildData.outputFiles[i].path).replace(".", ""); comps[ext] = buildData.outputFiles[i].text; } return mergeFiles(comps); } const mergeFiles = (comps)=>{ const cssIndex = comps.html.indexOf(""); const html = `${comps.html.slice(0, cssIndex)}${comps.html.slice(cssIndex)}`; const jsIndex = html.indexOf(""); return `${html.slice(0, jsIndex)}${html.slice(jsIndex)}`; } const writeFile = async (dir, bundle)=>{ const writeDir = dir.replace("routes", ".build"); await fs.mkdir(writeDir, {recursive: true}); await fs.writeFile(`${writeDir}/index.html`, bundle); }