UNPKG

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.92 kB
#!/usr/bin/env node import g from"fs";import y from"fs/promises";import a from"path";import{pathToFileURL as R,fileURLToPath as k}from"url";import{execSync as v}from"child_process";import{createRequire as $}from"module";var C=$(import.meta.url),j=k(import.meta.url),ae=a.dirname(j),I={COMPONENTS_PATH:"src/components",HTML_FOLDER_PATH:"src/html",OUT_DIR:"dist"},E=a.resolve(process.cwd(),"ssr.config.js"),M={};try{await g.promises.access(E);let e=await import(R(E).href);M=e.default||e}catch{console.warn("\u26A0\uFE0F No ssr.config.js found, using defaults")}var f={...I,...M};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 "${j}"`,{stdio:"inherit"}),process.exit()}}P("vite",U());P("jsdom");var B=C.resolve("vite"),T=await import(R(B).href),{build:G}=T.build?T:T.default,V=f.COMPONENTS_PATH.split("/")[0]||f.COMPONENTS_PATH,Y=f.OUT_DIR.split("/")[0]||f.OUT_DIR,x=a.resolve("./"+V),b=a.resolve("./"+Y);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 G({build:{minify:!1,rollupOptions:{input:a.join(x,"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={},n={},o=0;for(let i of Object.values(t))if(i.type==="chunk"){let s=J(o++);r[i.name]=s,n[s]=i.name}let c={...r,...n},p=` // --- 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+=p),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 y.readdir(e,{withFileTypes:!0})){let n=a.join(e,r.name);r.isDirectory()?r.name!=="layouts"&&t.push(...await F(n)):r.isFile()&&r.name.endsWith(".html")&&t.push(n)}return t}function H(e,t={}){let r=g.readdirSync(e,{withFileTypes:!0});for(let n of r){let o=a.join(e,n.name);if(n.isDirectory())H(o,t);else if(n.isFile()&&n.name.endsWith(".js")){let p=a.basename(n.name,".js").toLowerCase();t[p]="/"+o.replace(/\\/g,"/")}}return t}var K=H(D);async function Q(e,t,r,n={}){globalThis.__CURRENT_COMPONENT__=t,globalThis.__SSR_SIGNAL_REGISTRY__||={},globalThis.__HANDLER_REGISTRY__||={};let o=K[t.toLowerCase()];if(!o)throw new Error(`Component "${t}" not found in ${D}`);let c=await e.ssrLoadModule(o),p=typeof c.default=="function"?await c.default.call(r.defaultView,n):`Missing render fn in ${t}`,l=r.createElement("div");l.innerHTML=p.trim();let i=null;for(let u of l.childNodes)if(u.nodeType===1){i=u;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 n=new O(await y.readFile(t,"utf-8")).window.document,o,c=n.querySelector("layout");if(c){let s=c.getAttribute("data-layout");if(!s)throw new Error(`No data-layout in ${t}`);let u=a.resolve(A,s),m=await y.readFile(u,"utf-8");o=new O(m).window.document,c.remove();let h=n.querySelector("description")?.getAttribute("data-description");h&&o.querySelector('meta[name="description"]')?.setAttribute("content",h);let N=n.querySelector("keywords")?.getAttribute("data-keywords");if(N&&o.querySelector('meta[name="keywords"]')?.setAttribute("content",N),n.querySelectorAll("[data-part]").forEach(d=>{let w=d.getAttribute("data-part"),S=o.querySelector(`[data-part="${w}"]`);if(S){S.innerHTML="";for(let q of d.childNodes)S.appendChild(o.importNode(q,!0))}}),n.querySelectorAll("script[type='module']").forEach(d=>{let w=d.getAttribute("src");w&&!o.querySelector(`script[src="${w}"]`)&&o.body.appendChild(d.cloneNode(!0))}),!o.querySelector(`script[type='module'][src="/bundle.js"]`)){let d=o.createElement("script");d.type="module",d.src="/bundle.js",o.body.appendChild(d)}}else o=n;let p=o.querySelectorAll("[data-component][runAtServer], [data-component][ssr]");for(let s of p){let u=s.getAttribute("data-component"),m={};for(let h of s.attributes)h.name.startsWith("data-prop-")&&(m[h.name.slice(10)]=h.value);let _=await Q(e,u,o,m);s.replaceWith(_)}let l=a.join(L,"component-map.json"),i=JSON.parse(await y.readFile(l,"utf-8"));return o.querySelectorAll("[data-component]").forEach(s=>{let u=s.getAttribute("data-component"),m=Object.keys(i).find(_=>_.toLowerCase()===u.toLowerCase());m&&(console.log("componentMap",i[m]),s.setAttribute("data-component",i[m]))}),o.querySelectorAll("layout, description, keywords").forEach(s=>s.remove()),`<!DOCTYPE html> `+o.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 n=a.join(L,a.relative(A,r));await y.mkdir(a.dirname(n),{recursive:!0}),await y.writeFile(n,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)}})();