sigment
Version:
A lightweight reactive JavaScript framework built with signals and vanilla JS — no virtual DOM, no JSX, no transpilation.
9 lines (7 loc) • 5.74 kB
JavaScript
import g from"fs";import h from"fs/promises";import a from"path";import{pathToFileURL as R,fileURLToPath as q}from"url";import{execSync as v}from"child_process";import{createRequire as $}from"module";var C=$(import.meta.url),M=q(import.meta.url),ie=a.dirname(M),I={COMPONENTS_PATH:"src/components",HTML_FOLDER_PATH:"src/html",OUT_DIR:"dist"},E=a.resolve(process.cwd(),"ssr.config.js"),j={};try{await g.promises.access(E);let e=await import(R(E).href);j=e.default||e}catch{console.warn("\u26A0\uFE0F No ssr.config.js found, using defaults")}var f={...I,...j};function U(){return parseInt(process.versions.node.split(".")[0],10)<20?"4":"latest"}function P(e,t="latest"){try{C.resolve(e),console.log(`\u2705 ${e} is already installed.`)}catch{console.log(`\u{1F4E6} ${e} not found, installing ${t}...`),v(`npm install ${e}@${t}`,{stdio:"inherit"}),console.log(`\u2705 ${e} installed successfully.`),console.log("\u{1F501} Restarting script to load newly installed modules..."),v(`node "${M}"`,{stdio:"inherit"}),process.exit()}}P("vite",U());P("jsdom");var G=C.resolve("vite"),T=await import(R(G).href),{build:V}=T.build?T:T.default,Y=f.COMPONENTS_PATH.split("/")[0]||f.COMPONENTS_PATH,x=f.OUT_DIR.split("/")[0]||f.OUT_DIR,B=a.resolve("./"+Y),b=a.resolve("./"+x);g.mkdirSync(b,{recursive:!0});function J(e){let t="";for(;e>=0;)t=String.fromCharCode(e%26+65)+t,e=Math.floor(e/26)-1;return t}async function W(){await V({build:{minify:!0,rollupOptions:{input:a.join(B,"Main.js"),output:{dir:b,entryFileNames:"bundle.js",chunkFileNames:"chunks/chunk-[name]-[hash].js",assetFileNames:"assets/[name]-[hash][extname]"}}},plugins:[{name:"component-map-generator",generateBundle(e,t){let r={},o={},n=0;for(let i of Object.values(t))if(i.type==="chunk"){let s=J(n++);r[i.name]=s,o[s]=i.name}let c={...r,...o},m=`
// --- bidirectional component map ---
const rvs_map_sigment = ${JSON.stringify(c,null,2)};
export { rvs_map_sigment };
`;g.writeFileSync(a.join(b,"component-map.json"),JSON.stringify(c,null,2));let l=Object.values(t).find(i=>i.type==="chunk"&&i.isEntry);l&&(l.code+=m),console.log("\u2705 forward map saved to component-map.json"),console.log("\u2705 bidirectional rvs_map_sigment embedded into bundle.js")}}]}),console.log("\u2705 Build completed! bundle.js + chunks are ready in dist/")}var{createServer:z}=await import("vite"),{JSDOM:O}=await import("jsdom"),A=f.HTML_FOLDER_PATH,D=f.COMPONENTS_PATH,L=f.OUT_DIR;async function F(e){let t=[];for(let r of await h.readdir(e,{withFileTypes:!0})){let o=a.join(e,r.name);r.isDirectory()?r.name!=="layouts"&&t.push(...await F(o)):r.isFile()&&r.name.endsWith(".html")&&t.push(o)}return t}function H(e,t={}){let r=g.readdirSync(e,{withFileTypes:!0});for(let o of r){let n=a.join(e,o.name);if(o.isDirectory())H(n,t);else if(o.isFile()&&o.name.endsWith(".js")){let m=a.basename(o.name,".js").toLowerCase();t[m]="/"+n.replace(/\\/g,"/")}}return t}var K=H(D);async function Q(e,t,r,o={}){globalThis.__CURRENT_COMPONENT__=t,globalThis.__SSR_SIGNAL_REGISTRY__||={},globalThis.__HANDLER_REGISTRY__||={};let n=K[t.toLowerCase()];if(!n)throw new Error(`Component "${t}" not found in ${D}`);let c=await e.ssrLoadModule(n),m=typeof c.default=="function"?await c.default.call(r.defaultView,o):`Missing render fn in ${t}`,l=r.createElement("div");l.innerHTML=m.trim();let i=null;for(let d of l.childNodes)if(d.nodeType===1){i=d;break}i&&i.setAttribute("data-component",t);let s=r.createDocumentFragment();for(;l.firstChild;)s.appendChild(l.firstChild);return s}async function X(e,t){globalThis.__SSR_SIGNAL_REGISTRY__={},globalThis.__HANDLER_REGISTRY__={},globalThis.__SSR_EVENT_MAP__={};let o=new O(await h.readFile(t,"utf-8")).window.document,n,c=o.querySelector("layout");if(c){let s=c.getAttribute("data-layout");if(!s)throw new Error(`No data-layout in ${t}`);let d=a.resolve(A,s),u=await h.readFile(d,"utf-8");n=new O(u).window.document,c.remove();let p=o.querySelector("description")?.getAttribute("data-description");p&&n.querySelector('meta[name="description"]')?.setAttribute("content",p);let N=o.querySelector("keywords")?.getAttribute("data-keywords");N&&n.querySelector('meta[name="keywords"]')?.setAttribute("content",N),o.querySelectorAll("[data-part]").forEach(y=>{let w=y.getAttribute("data-part"),S=n.querySelector(`[data-part="${w}"]`);if(S){S.innerHTML="";for(let k of y.childNodes)S.appendChild(n.importNode(k,!0))}}),o.querySelectorAll("script[type='module']").forEach(y=>{let w=y.getAttribute("src");w&&!n.querySelector(`script[src="${w}"]`)&&n.body.appendChild(y.cloneNode(!0))})}else n=o;let m=n.querySelectorAll("[data-component][runAtServer]");for(let s of m){let d=s.getAttribute("data-component"),u={};for(let p of s.attributes)p.name.startsWith("data-prop-")&&(u[p.name.slice(10)]=p.value);let _=await Q(e,d,n,u);s.replaceWith(_)}let l=a.join(L,"component-map.json"),i=JSON.parse(await h.readFile(l,"utf-8"));return n.querySelectorAll("[data-component]").forEach(s=>{let d=s.getAttribute("data-component"),u=Object.keys(i).find(_=>_.toLowerCase()===d.toLowerCase());u&&(console.log("componentMap",i[u]),s.setAttribute("data-component",i[u]))}),n.querySelectorAll("layout, description, keywords").forEach(s=>s.remove()),`<!DOCTYPE html>
`+n.documentElement.outerHTML}async function Z(){let e=await z({server:{middlewareMode:!0},root:process.cwd(),ssr:{noExternal:!0}}),t=await F(A);for(let r of t){let o=a.join(L,a.relative(A,r));await h.mkdir(a.dirname(o),{recursive:!0}),await h.writeFile(o,await X(e,r),"utf-8")}await e.close()}(async()=>{try{await W(),await Z().catch(e=>{console.error(e),process.exit(1)}),console.log("\u{1F389} All components built and HTML rendered successfully!")}catch(e){console.error("\u274C Build failed:",e),process.exit(1)}})();