import fs from "node:fs/promises";
import {constants} from "node:fs";
import path from "path";
import htmlMinifier from "html-minifier-terser";
import esbuild from "esbuild";
const parseComponent = async (file)=>{
const dir = path.dirname(file);
let data = {};
if(path.extname(file) === ".neovan"){
data = await getNeovanData(file);
}else{
data = await parseHtml(file);
}
return await createBundle(data);
}
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(""));
let css = "";
let js = "";
const cssIndex = neovan.indexOf(""));
}
const jsIndex = 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([
fs.writeFile(cssFile, css),
fs.writeFile(jsFile, js)
]);
return {
html: html,
css: cssFile,
js: jsFile,
dir: parentPath
};
}
const parseHtml = async (index)=>{
const parentPath = path.dirname(index);
const basename = path.basename(index, ".html");
const cssPath = path.join(parentPath, `${basename}.css`);
const jsPath = path.join(parentPath, `${basename}.js`);
const proms = [
fs.readFile(index, "utf-8"),
fs.access(cssPath, constants.F_OK),
fs.access(jsPath, constants.F_OK)
];
let [html, css, js] = await Promise.allSettled(proms);
return {
html: html.value,
css: css.status === "fulfilled" ? cssPath : null,
js: js.status === "fulfilled" ? jsPath : null,
dir: parentPath
};
}
const createBundle = async (data)=>{
const entryPoints = [];
if(data.css) entryPoints.push(data.css);
if(data.js) entryPoints.push(data.js);
data.html = await addComponents(data.html, data.dir);
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)=>{
let cssIndex = comps.html.indexOf("");
cssIndex = cssIndex < 0 ? 0 : cssIndex;
comps.css = comps.css ? `` : "";
const html = `${comps.html.slice(0, cssIndex)}${comps.css}${comps.html.slice(cssIndex)}`;
let jsIndex = html.indexOf("