@fluixi/compiler 1.0.0-alpha.73 → 1.0.0-alpha.75
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -16
- package/dist/analyze/expr-shape.cjs +1 -0
- package/dist/analyze/expr-shape.d.ts +15 -0
- package/dist/analyze/expr-shape.d.ts.map +1 -0
- package/dist/analyze/expr-shape.js +37 -0
- package/dist/analyze/expr-shape.mjs +1 -0
- package/dist/analyze/reactive-expr.cjs +1 -0
- package/dist/analyze/reactive-expr.d.ts +39 -0
- package/dist/analyze/reactive-expr.d.ts.map +1 -0
- package/dist/analyze/reactive-expr.js +31 -0
- package/dist/analyze/reactive-expr.mjs +1 -0
- package/dist/babel-GXO3KAVI.mjs +1 -0
- package/dist/chunk-3SAEGOMQ.mjs +1 -0
- package/dist/chunk-E2PW2OZU.mjs +1 -0
- package/dist/chunk-IBRM4W7I.mjs +10 -0
- package/dist/chunk-OHHZCYIQ.mjs +1 -0
- package/dist/chunk-TIE4XNAM.mjs +1 -0
- package/dist/frontend/babel/build-ir-lit.cjs +1 -1
- package/dist/frontend/babel/build-ir-lit.d.ts +1 -0
- package/dist/frontend/babel/build-ir-lit.d.ts.map +1 -1
- package/dist/frontend/babel/build-ir-lit.mjs +1 -1
- package/dist/frontend/babel/build-ir.cjs +1 -1
- package/dist/frontend/babel/build-ir.d.ts +13 -11
- package/dist/frontend/babel/build-ir.d.ts.map +1 -1
- package/dist/frontend/babel/build-ir.js +27 -217
- package/dist/frontend/babel/build-ir.mjs +1 -1
- package/dist/frontend/babel/index.cjs +1 -2
- package/dist/frontend/babel/index.mjs +1 -2
- package/dist/frontend/babel/lower-template.cjs +1 -1
- package/dist/frontend/babel/lower-template.d.ts +12 -9
- package/dist/frontend/babel/lower-template.d.ts.map +1 -1
- package/dist/frontend/babel/lower-template.js +33 -445
- package/dist/frontend/babel/lower-template.mjs +1 -1
- package/dist/frontend/babel/plugin.cjs +1 -2
- package/dist/frontend/babel/plugin.d.ts +24 -85
- package/dist/frontend/babel/plugin.d.ts.map +1 -1
- package/dist/frontend/babel/plugin.js +52 -1285
- package/dist/frontend/babel/plugin.mjs +1 -2
- package/dist/frontend/babel/server-functions.cjs +1 -1
- package/dist/frontend/babel/server-functions.d.ts.map +1 -1
- package/dist/frontend/babel/server-functions.js +2 -9
- package/dist/frontend/babel/server-functions.mjs +1 -1
- package/dist/index.cjs +8 -8
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.mjs +9 -9
- package/dist/integrations.cjs +15 -19
- package/dist/integrations.d.ts +39 -151
- package/dist/integrations.d.ts.map +1 -1
- package/dist/integrations.js +79 -491
- package/dist/integrations.mjs +11 -17
- package/dist/lower/compile-template.cjs +1 -0
- package/dist/lower/compile-template.d.ts +57 -0
- package/dist/lower/compile-template.d.ts.map +1 -0
- package/dist/lower/compile-template.js +72 -0
- package/dist/lower/compile-template.mjs +1 -0
- package/dist/lower/jsx.cjs +1 -0
- package/dist/lower/jsx.d.ts +24 -0
- package/dist/lower/jsx.d.ts.map +1 -0
- package/dist/lower/jsx.js +193 -0
- package/dist/lower/jsx.mjs +1 -0
- package/dist/lower/template.cjs +1 -0
- package/dist/lower/template.d.ts +41 -0
- package/dist/lower/template.d.ts.map +1 -0
- package/dist/lower/template.js +445 -0
- package/dist/lower/template.mjs +1 -0
- package/dist/lower/text.cjs +1 -0
- package/dist/lower/text.d.ts +11 -0
- package/dist/lower/text.d.ts.map +1 -0
- package/dist/lower/text.js +31 -0
- package/dist/lower/text.mjs +1 -0
- package/dist/options.cjs +1 -1
- package/dist/options.d.ts +0 -2
- package/dist/options.d.ts.map +1 -1
- package/dist/options.js +0 -1
- package/dist/options.mjs +1 -1
- package/dist/server-fns-6QM243HC.mjs +2 -0
- package/dist/server-functions-E3LKCZ4R.mjs +1 -0
- package/dist/transform/bindings.cjs +1 -0
- package/dist/transform/bindings.d.ts +17 -0
- package/dist/transform/bindings.d.ts.map +1 -0
- package/dist/transform/bindings.js +69 -0
- package/dist/transform/bindings.mjs +1 -0
- package/dist/transform/index.cjs +3 -0
- package/dist/transform/index.d.ts +12 -0
- package/dist/transform/index.d.ts.map +1 -0
- package/dist/transform/index.js +10 -0
- package/dist/transform/index.mjs +12 -0
- package/dist/transform/server-fn-id.cjs +1 -0
- package/dist/transform/server-fn-id.d.ts +10 -0
- package/dist/transform/server-fn-id.d.ts.map +1 -0
- package/dist/transform/server-fn-id.js +18 -0
- package/dist/transform/server-fn-id.mjs +1 -0
- package/dist/transform/server-fns.cjs +2 -0
- package/dist/transform/server-fns.d.ts +13 -0
- package/dist/transform/server-fns.d.ts.map +1 -0
- package/dist/transform/server-fns.js +94 -0
- package/dist/transform/server-fns.mjs +11 -0
- package/dist/transform/templates.cjs +3 -0
- package/dist/transform/templates.d.ts +26 -0
- package/dist/transform/templates.d.ts.map +1 -0
- package/dist/transform/templates.js +347 -0
- package/dist/transform/templates.mjs +12 -0
- package/dist/transform-PJX2GNSV.mjs +3 -0
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +30 -8
- package/dist/babel-E7EQLX36.mjs +0 -2
- package/dist/chunk-EF6V4GTD.mjs +0 -1
package/dist/integrations.mjs
CHANGED
|
@@ -1,32 +1,26 @@
|
|
|
1
|
-
import{a as
|
|
1
|
+
import{a as R,f as j}from"./chunk-E2PW2OZU.mjs";import{a as T}from"./chunk-3SAEGOMQ.mjs";import{mkdirSync as L,readFileSync as v,writeFileSync as B}from"node:fs";import{dirname as $,relative as E,sep as F,resolve as b}from"node:path";var I=new Set(["Text","Image","Option","Audio","Comment","Range","Selection","Notification","Event","Document","Element","Node","Screen","Window","Location","History","Storage","Response","Request","Headers"]);function _(e){if(e.startsWith(".")||e.startsWith("/")||/^[~@]\//.test(e))return;let t=e.split("/");return e.startsWith("@")?t.slice(0,2).join("/"):t[0]}function C(e){return`_${e.replace(/[^A-Za-z0-9]/g,"_")}`}function M(e,t={}){let{available:n,builtins:r=!0,generator:s="@fluixi/compiler",specifier:o=i=>i}=t,l=[...e];r&&l.push({components:j()});let a=R(l),f=n?new Set(n):void 0,c=[],p=[],d=[],h=new Map;for(let i of[...a.names()].sort()){let u=a.resolve(i);if(!u)continue;let m=_(u.module);I.has(i)?p.push(i):f&&m&&!f.has(m)?d.push(i):(c.push(i),h.set(i,u))}let S=[...new Set(c.map(i=>h.get(i).module))].sort().map(i=>`import * as ${C(i)} from '${o(i)}';`),D=c.map(i=>{let u=h.get(i),m=C(u.module);return u.export==="default"?` const ${i}: typeof ${m}.default;`:` export import ${i} = ${m}.${u.export};`}),W=p.length>0?`//
|
|
2
2
|
// Import these explicitly — lib.dom already declares the name, so an ambient
|
|
3
3
|
// declaration cannot win:
|
|
4
|
-
`+
|
|
5
|
-
`}).join(""):"",
|
|
6
|
-
// ${
|
|
4
|
+
`+p.map(i=>{let u=a.resolve(i)?.module;return`// import { ${i} } from '${u?o(u):""}';
|
|
5
|
+
`}).join(""):"",g=e.filter(i=>"match"in i).length,N=g>0?`//
|
|
6
|
+
// ${g} pattern rule${g===1?"":"s"} cannot be declared:
|
|
7
7
|
// a pattern matches unboundedly many names, so there is no list to emit. Those
|
|
8
8
|
// tags still resolve at build time; declare them by hand if the editor needs them.
|
|
9
9
|
`:"";return{source:`// GENERATED by ${s} — do not edit.
|
|
10
10
|
//
|
|
11
11
|
// The components \`resolve\` supplies without an import. This describes what the
|
|
12
12
|
// compiler already does; it does not enable it.
|
|
13
|
-
`+
|
|
14
|
-
${
|
|
13
|
+
`+W+N+(S.length>0?`
|
|
14
|
+
${S.join(`
|
|
15
15
|
`)}
|
|
16
16
|
`:`
|
|
17
17
|
`)+`
|
|
18
18
|
declare global {
|
|
19
|
-
${
|
|
19
|
+
${D.join(`
|
|
20
20
|
`)}
|
|
21
21
|
}
|
|
22
|
-
`,declared:
|
|
23
|
-
`
|
|
24
|
-
|
|
25
|
-
`+r)}return r=ye(r,n,t),{code:r,metadata:n}}function me(e){let t=new Set,n=/on([A-Z][a-z]+)/g,r;for(;(r=n.exec(e))!==null;)t.add(r[1].toLowerCase());return Array.from(t)}function ye(e,t,n){let r=[],s=n.importSource||"@fluixi/jsx";return r.push(`import { jsx, jsxs, Fragment, spread } from '${s}';`),t.hasSignals&&r.push("import { signal } from '@fluixi/dom/reactive';"),(e.includes("<Show")||e.includes("<For")||e.includes("<Switch"))&&r.push("import { Show, For, Index, Switch, Match } from '@fluixi/dom/control-flow';"),n.delegateEvents!==!1&&r.push("import { delegateEvents } from '@fluixi/dom/runtime';"),r.join(`
|
|
26
|
-
`)+`
|
|
27
|
-
|
|
28
|
-
`+e}async function y(e={}){let t=null;try{t=await import("./babel-E7EQLX36.mjs")}catch(n){console.warn("Could not load the babel front-end:",n)}return{name:"babel-fluixi-jsx",plugin:t?t.default||t:null,getOptions(){return{runtime:"automatic",importSource:e.importSource||"@fluixi/jsx",pragma:e.pragma||"jsx",pragmaFrag:e.pragmaFrag||"Fragment",development:e.development||!1,detectReactivity:!0,useLitHTML:e.useLitHTML!==!1,hoistStatics:e.optimize!==!1,delegateEvents:e.delegateEvents!==!1,delegatedEvents:e.delegatedEvents||["click","input","change","submit"],optimizeControlFlow:e.optimize!==!1,sourceMaps:e.sourceMaps!==!1,backend:e.backend||"imperative",...e.codegen?{codegen:e.codegen}:{},...e.format?{format:e.format}:{},...e.resolve?{resolve:e.resolve}:{},...e.templateClone!==void 0?{templateClone:e.templateClone}:{},...e.partialTemplates!==void 0?{partialTemplates:e.partialTemplates}:{},...e.litTag?{litTag:e.litTag}:{},...e.signalModule?{signalModule:e.signalModule}:{},...e.controlFlowModule?{controlFlowModule:e.controlFlowModule}:{},...e.routerModule?{routerModule:e.routerModule}:{},...e.reactiveModule?{reactiveModule:e.reactiveModule}:{}}}}}function be(e={}){let t=h("typescript");return t?n=>{let r=s=>t.isJsxElement(s)||t.isJsxSelfClosingElement(s)?ve(s,e,t):t.visitEachChild(s,r,n);return s=>t.visitNode(s,r)}:(console.warn("TypeScript not found, transformer unavailable"),n=>r=>r)}function ve(e,t,n){return e}function h(e){try{return S(e)}catch{return null}}function he(e={}){return{name:"vite-fluixi-jsx",enforce:"pre",config(){return{esbuild:{jsx:"automatic",jsxImportSource:e.importSource||"@fluixi/jsx"}}},configResolved(t){let n=N(e,t?.root??process.cwd());n.warning&&console.warn(n.warning)},async transform(t,n){let r=await y(e);if(!/\.(jsx|tsx|ts)$/i.test(n))return null;try{let s=await import("@babel/core").catch(()=>null);if(!s)return{code:d(t,e).code,map:null};let i=/\.tsx$/.test(n),o=/\.ts$/.test(n),a=[],c=[];if(i||o){let f=await import("@babel/preset-typescript").then(g=>g.default||g).catch(()=>null);f&&a.push([f,{isTSX:i,allExtensions:!0,jsxPragma:e.pragma||"jsx",jsxPragmaFrag:e.pragmaFrag||"Fragment",onlyRemoveTypeImports:!0}])}r&&r.plugin?c.push([r.plugin,r.getOptions()]):console.warn("[createVitePlugin] custom babel plugin not found");let u=await s.transformAsync(t,{filename:n,configFile:!1,babelrc:!1,presets:a,plugins:c,sourceMaps:e.sourceMaps!==!1});return{code:u?.code||t,map:u?.map}}catch(s){console.error("Transform error:",s);try{return{code:d(t,e).code,map:null}}catch(i){return console.error("Fallback transform also failed:",i),null}}}}}function xe(e={}){return async function(t){let n=this.async(),r=h("@babel/core"),s=await y(e);if(!r||!s.plugin){let i=d(t,e);n(null,i.code);return}r.transformAsync(t,{filename:this.resourcePath,plugins:[[s.plugin,s.getOptions()]],sourceMaps:e.sourceMaps!==!1}).then(i=>{n(null,i?.code,i?.map)}).catch(i=>{n(i)})}}function Se(e={}){return{name:"rollup-fluixi-jsx",async transform(t,n){let r=await y(e);if(!/\.[jt]sx$/.test(n))return null;try{let s=h("@babel/core");if(!s||!r.plugin)return{code:d(t,e).code,map:null};let i=await s.transformAsync(t,{filename:n,plugins:[[r.plugin,r.getOptions()]],sourceMaps:e.sourceMaps!==!1});return{code:i?.code||t,map:i?.map}}catch(s){return console.error("Transform error:",s),null}}}}function $e(e={}){return{name:"esbuild-fluixi-jsx",setup(t){t.onLoad({filter:/\.[jt]sx$/},async n=>{let r=h("@babel/core"),s=await y(e),o=S("fs").readFileSync(n.path,"utf8");try{return!r||!s.plugin?{contents:d(o,e).code,loader:"js"}:{contents:(await r.transformAsync(o,{filename:n.path,plugins:[[s.plugin,s.getOptions()]],sourceMaps:!1}))?.code||o,loader:"js"}}catch(a){return{errors:[{text:`Transform error: ${a}`}]}}})}}}var R="virtual:fluixi-server-fns";function V(e,t=[]){let n;try{n=we(e,{withFileTypes:!0})}catch{return t}for(let r of n){if(r.name==="node_modules"||r.name==="dist"||r.name.startsWith("."))continue;let s=U(e,r.name);if(r.isDirectory())V(s,t);else if(/\.[jt]sx?$/.test(r.name))try{Re(s,"utf8").includes("use server")&&t.push(s)}catch{}}return t}function Ie(){let e=process.cwd();return{name:"fluixi-server-functions",enforce:"pre",configResolved(t){e=t.root||e},resolveId(t){return t===R?"\0"+R:null},load(t){if(t!=="\0"+R)return null;let n=V(U(e,"src")),r=`import '@fluixi/start/server-fn-setup';
|
|
29
|
-
`,s=n.map(o=>`import ${JSON.stringify(o)};`).join(`
|
|
30
|
-
`);return r+s+`
|
|
22
|
+
`,declared:c,shadowedByDom:p,unavailable:d,patternRules:g}}var J="GENERATED by @fluixi/compiler",q="fluixi.d.ts";function V(e,t){let n;try{let s=v(b(e,"tsconfig.json"),"utf8");n=JSON.parse(s.replace(/^\s*\/\/.*$/gm,""))}catch{return}if(n.extends!==void 0)return;if(!Array.isArray(n.include))return!0;let r=G(e,t);return n.include.some(s=>{if(typeof s!="string")return!1;let o=s.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*\*\//g,"(?:.*/)?").replace(/\*/g,"[^/]*");return new RegExp(`^${o}(?:/.*)?$`).test(r)})}function G(e,t){return E(e,t).split(F).join("/")}function H(e,t,n){if(!e.startsWith("/"))return e;let r=b(n,e.slice(1)),s=E(t,r).split(F).join("/");return s.startsWith(".")||(s=`./${s}`),s.replace(/\.(tsx|ts|jsx|mts|cts)$/,".js")}function X(e){try{let t=JSON.parse(v(b(e,"package.json"),"utf8"));return[...Object.keys(t.dependencies??{}),...Object.keys(t.devDependencies??{}),...Object.keys(t.peerDependencies??{})]}catch{return}}function A(e,t){if(e.globals===!1)return{status:"skipped",reason:"disabled"};let n=e.resolve??[],r=b(t,e.globals??q),s;try{s=v(r,"utf8")}catch{s=void 0}if(s!==void 0&&!s.includes(J))return{status:"skipped",reason:"foreign-file",path:r};let{source:o,declared:l}=M(n,{available:X(t),specifier:a=>H(a,$(r),t)});return s===o?{status:"unchanged",path:r,declared:l.length,warning:O(t,r)}:(L($(r),{recursive:!0}),B(r,o),{status:"written",path:r,declared:l.length,warning:O(t,r)})}function O(e,t){if(V(e,t)!==!1)return;let n=G(e,t);return`[fluixi] ${n} is not covered by "include" in tsconfig.json, so TypeScript will ignore it and every resolved component stays "Cannot find name". Add "${n}" to "include".`}import{readdirSync as ne,readFileSync as re}from"node:fs";import{join as k}from"node:path";async function w(e={}){let t=null;try{t=await import("./babel-GXO3KAVI.mjs")}catch(n){console.warn("Could not load the babel front-end:",n)}return{name:"babel-fluixi-jsx",plugin:t?t.default||t:null,getOptions(){return{importSource:e.importSource||"@fluixi/jsx",development:e.development||!1,delegateEvents:e.delegateEvents!==!1,...e.format?{format:e.format}:{},...e.resolve?{resolve:e.resolve}:{},...e.templateClone!==void 0?{templateClone:e.templateClone}:{},...e.partialTemplates!==void 0?{partialTemplates:e.partialTemplates}:{},...e.litTag?{litTag:e.litTag}:{},...e.signalModule?{signalModule:e.signalModule}:{},...e.controlFlowModule?{controlFlowModule:e.controlFlowModule}:{},...e.routerModule?{routerModule:e.routerModule}:{},...e.reactiveModule?{reactiveModule:e.reactiveModule}:{}}}}}function U(e={}){let t=K("typescript");return t?n=>{let r=s=>t.isJsxElement(s)||t.isJsxSelfClosingElement(s)?z(s,e,t):t.visitEachChild(s,r,n);return s=>t.visitNode(s,r)}:(console.warn("TypeScript not found, transformer unavailable"),n=>r=>r)}function z(e,t,n){return e}function K(e){try{return T(e)}catch{return null}}function Z(e={}){return{name:"vite-fluixi-jsx",enforce:"pre",config(){return{esbuild:{jsx:"automatic",jsxImportSource:e.importSource||"@fluixi/jsx"}}},configResolved(t){let n=A(e,t?.root??process.cwd());n.warning&&console.warn(n.warning)},async transform(t,n){if(!/\.(jsx|tsx|ts)$/i.test(n))return null;if(!e.babel)return y(t,n,e);let r=await w(e);try{let s=await import("@babel/core").catch(()=>null);if(!s)throw new Error(`[fluixi] @babel/core is required to compile ${n} but could not be loaded. Install it alongside @fluixi/compiler.`);let o=/\.tsx$/.test(n),l=/\.ts$/.test(n),a=[],f=[];if(o||l){let p=await import("@babel/preset-typescript").then(d=>d.default||d).catch(()=>null);p&&a.push([p,{isTSX:o,allExtensions:!0,jsxPragma:"jsx",jsxPragmaFrag:"Fragment",onlyRemoveTypeImports:!0}])}r&&r.plugin?f.push([r.plugin,r.getOptions()]):console.warn("[createVitePlugin] custom babel plugin not found");let c=await s.transformAsync(t,{filename:n,configFile:!1,babelrc:!1,presets:a,plugins:f,sourceMaps:e.sourceMaps!==!1});return{code:c?.code||t,map:c?.map}}catch(s){throw s}}}}function Q(e){return{resolve:e.resolve,litTag:e.litTag,templateClone:e.templateClone,partialTemplates:e.partialTemplates,runtimeModule:e.signalModule,controlFlowModule:e.controlFlowModule,routerModule:e.routerModule,reactiveModule:e.reactiveModule}}async function y(e,t,n){if(!n.babel){let{transformTemplates:l}=await import("./transform-PJX2GNSV.mjs");return l(e,t,Q(n))}let r=await import("@babel/core").catch(()=>null),s=await w(n);if(!r||!s.plugin)throw new Error(`[fluixi] babel: true needs @babel/core, which could not be loaded for ${t}. Install it, or drop the option to use the built-in compiler.`);let o=await r.transformAsync(e,{filename:t,configFile:!1,babelrc:!1,plugins:[[s.plugin,s.getOptions()]],sourceMaps:n.sourceMaps!==!1});return o?.code?{code:o.code,map:o.map}:null}function Y(e={}){return async function(t){let n=this.async();y(t,this.resourcePath,e).then(r=>{n(null,r?.code,r?.map)}).catch(r=>{n(r)})}}function ee(e={}){return{name:"rollup-fluixi-jsx",async transform(t,n){return/\.[jt]sx?$/.test(n)?y(t,n,e):null}}}function te(e={}){return{name:"esbuild-fluixi-jsx",setup(t){t.onLoad({filter:/\.[jt]sx?$/},async n=>{let{readFileSync:r}=await import("node:fs"),s=r(n.path,"utf8");try{return{contents:(await y(s,n.path,e))?.code??s,loader:n.path.endsWith("x")?"tsx":"ts"}}catch(o){return{errors:[{text:`Transform error: ${o}`}]}}})}}}var x="virtual:fluixi-server-fns";function P(e,t=[]){let n;try{n=ne(e,{withFileTypes:!0})}catch{return t}for(let r of n){if(r.name==="node_modules"||r.name==="dist"||r.name.startsWith("."))continue;let s=k(e,r.name);if(r.isDirectory())P(s,t);else if(/\.[jt]sx?$/.test(r.name))try{re(s,"utf8").includes("use server")&&t.push(s)}catch{}}return t}function be(e={}){let t=process.cwd();return{name:"fluixi-server-functions",enforce:"pre",configResolved(n){t=n.root||t},resolveId(n){return n===x||n==="@fluixi/start/server-fns"?"\0"+x:null},load(n){if(n!=="\0"+x)return null;let r=P(k(t,"src")),s=`import '@fluixi/start/server-fn-setup';
|
|
23
|
+
`,o=r.map(a=>`import ${JSON.stringify(a)};`).join(`
|
|
24
|
+
`);return s+o+`
|
|
31
25
|
export { isServerFnRequest, handleServerFn } from '@fluixi/start/server-fn';
|
|
32
|
-
`},transform(
|
|
26
|
+
`},async transform(n,r,s){if(!/\.[jt]sx?$/.test(r)||!n.includes("use server"))return null;let o={ssr:!!s?.ssr,filename:r,root:t};if(e.babel){let{transformServerFunctions:a}=await import("./server-functions-E3LKCZ4R.mjs");return a(n,o)}let{transformServerFns:l}=await import("./server-fns-6QM243HC.mjs");return l(n,o)}}}var ye={createBabelPlugin:w,createTypeScriptTransformer:U,createVitePlugin:Z,createWebpackLoader:Y,createRollupPlugin:ee,createESBuildPlugin:te};export{w as createBabelPlugin,te as createESBuildPlugin,ee as createRollupPlugin,U as createTypeScriptTransformer,Z as createVitePlugin,Y as createWebpackLoader,ye as default,be as serverFunctionsVitePlugin};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var E=Object.defineProperty;var le=Object.getOwnPropertyDescriptor;var ae=Object.getOwnPropertyNames;var ce=Object.prototype.hasOwnProperty;var pe=(t,e)=>{for(var n in e)E(t,n,{get:e[n],enumerable:!0})},de=(t,e,n,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of ae(e))!ce.call(t,r)&&r!==n&&E(t,r,{get:()=>e[r],enumerable:!(o=le(e,r))||o.enumerable});return t};var ue=t=>de(E({},"__esModule",{value:!0}),t);var Be={};pe(Be,{compilePieces:()=>se,compileTemplate:()=>_e});module.exports=ue(Be);function me(t){switch(t.kind){case"event":return"event";case"ref":return"ref";case"spread":return"spread";case"class":case"style":return"class-or-style-directive";case"attr":case"prop":return t.reactive?"reactive-prop":t.expr!==void 0?"expression-prop":void 0;default:return"expression-prop"}}function L(t){let e=[],n=new Map,o=r=>{switch(r.kind){case"text":return!0;case"expr":return!1;case"component":case"control":for(let i of r.children)o(i);return!1;case"fragment":for(let i of r.children)o(i);return!1;case"element":{let i=!0;for(let s of r.children)o(s)||(i=!1);let a;for(let s of r.props)if(a=me(s),a)break;return!a&&!i&&(a=fe(r)),r.static=!a,a?n.set(r,a):e.push(r),r.static}default:return!1}};for(let r of Array.isArray(t)?t:[t])o(r);return{staticElements:e,reasons:n}}function fe(t){for(let e of t.children){if(e.kind==="expr")return"expression-child";if(e.kind==="component")return"component-child";if(e.kind==="control")return"control-child";if(e.kind==="element"&&!e.static||e.kind==="fragment")return"expression-child"}return"expression-child"}var k={kind:"eager"},he=["pointerdown","focusin","keydown"],j=new Set(["eager","idle","visible","interaction","media","never"]),f=class extends Error{};function _(t,e){let n=t.slice(5);if(!j.has(n))throw new f(`Unknown load strategy 'load:${n}'. Expected one of ${[...j].join(", ")}.`);switch(n){case"eager":return k;case"idle":return{kind:"idle"};case"never":return{kind:"never"};case"visible":return e?{kind:"visible",rootMargin:e}:{kind:"visible"};case"interaction":return{kind:"interaction",events:e?ge(e):[...he]};case"media":if(!e)throw new f(`'load:media' needs a query, e.g. load:media="(min-width: 1024px)".`);return{kind:"media",query:e};default:throw new f(`Unhandled load strategy '${n}'.`)}}function ge(t){let e=t.split(/[\s,]+/).map(n=>n.trim()).filter(Boolean);if(e.length===0)throw new f("'load:interaction' was given no event names.");return e}function B(t){return t.kind!=="eager"&&t.kind!=="never"}var w=["Show","For","Index","Switch","Match","Portal","Dynamic","ErrorBoundary"],$=["Suspense","SuspenseList","Await"],x=["Router","Outlet","Redirect","Link"],Je=[...w,...$,...x],T=new Set([...w,...$]);function H(t={}){let{controlFlowModule:e="@fluixi/dom",coreModule:n="@fluixi/core",routerModule:o="@fluixi/core/router-next"}=t,r={};for(let i of w)r[i]=e;for(let i of $)r[i]=n;for(let i of x)r[i]=o;return r}function F(t,e={}){let{resolver:n,isBound:o,modules:r,strategyFor:i}=e,a=H(r),s=new Map,l=new Set,c=p=>{let{name:u}=p;if(!u||u.includes(".")||o?.(u))return;let m=d(u);if(!m){l.add(u);return}let v=m.origin==="builtin"&&T.has(u)?k:i?.(p)??k;p.source={...m,loading:v},s.set(u,p.source)},d=p=>{if(T.has(p))return{module:a[p],export:p,origin:"builtin"};let u=n?.resolve(p);if(u)return{module:u.module,export:u.export,origin:"rule"};if(x.includes(p))return{module:a[p],export:p,origin:"builtin"}};return N(t,p=>{p.kind==="component"&&c(p)}),{resolved:s,unresolved:[...l]}}function N(t,e){let n=Array.isArray(t)?t:[t];for(let o of n){e(o);let r=o.children;r&&N(r,e)}}function z(t){let e=[];N(t,i=>{i.kind==="component"&&i.source&&e.push(i)});let n=new Set,o=new Set;for(let i of e){let{module:a,loading:s}=i.source;s.kind==="eager"&&n.add(a),s.kind==="never"&&o.add(a)}let r=new Map;for(let i of e){let a=i.source;B(a.loading)&&n.has(a.module)&&(a.loading={kind:"eager"},r.set(a.module,(r.get(a.module)??0)+1))}return{collapsed:r,conflicted:[...o].filter(i=>n.has(i))}}var Re=new Set(["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"]),J={className:"class",htmlFor:"for"},ve=new Set(["innerHTML","outerHTML","innerText","textContent","value","checked","selected","muted","defaultValue","defaultChecked","children","ref"]),ke=new Set(["script","style","textarea","title"]);function S(t){return ke.has(t)}function U(t){return J[t]??t}function h(t){return t.kind!=="attr"||t.expr!==void 0||t.name.includes(":")?!1:!ve.has(t.name)}function P(t){if(!t.static||S(t.tag))return!1;for(let e of t.props)if(!h(e))return!1;for(let e of t.children)if(e.kind!=="text"&&!(e.kind==="element"&&P(e)))return!1;return!0}function g(t){let e=t.props.map(Ne).filter(Boolean).join(""),n=`<${t.tag}${e}>`;return Re.has(t.tag)?n:`${n}${t.children.map(xe).join("")}</${t.tag}>`}function xe(t){if(t.kind==="text")return ye(t.value);if(t.kind!=="element")throw new Error(`serializeStatic: unexpected ${t.kind}`);return g(t)}function Ne(t){let e=J[t.name]??t.name,n=t.literal;return n===!0||n===void 0?` ${e}`:n===!1||n===null?"":` ${e}="${Ie(String(n))}"`}function Ie(t){return t.replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">")}function ye(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}var be="<!--fx-->",Ce="<!--fx/-->";function y(t){return t.kind==="expr"||t.kind==="component"||t.kind==="control"}function Ee(t){return t.kind==="text"||t.kind==="element"&&V(t)}function V(t){return t.svg||S(t.tag)||!t.props.every(e=>h(e))?!1:t.children.every(e=>Ee(e)||y(e))}function I(t){if(y(t))return!0;let e=t.children;return e?e.some(I):!1}function W(t){for(let e=0;e<t.children.length;e++){let n=t.children[e];if(n.kind==="text"&&(n.value===""||t.children[e+1]?.kind==="text"))return!1}return t.children.every(e=>e.kind!=="element"||W(e))}function q(t){if(!V(t)||!W(t)||!t.children.some(I))return null;let e=[],n=[],o=0,r=a=>{let s=`_n$${o++}`;return e.push({ref:s,expr:a}),s};return i(t,"_el$"),{html:we(t),tag:t.tag,steps:e,holes:n};function i(a,s){let l=-1;a.children.forEach((d,p)=>{I(d)&&(l=p)});let c=null;for(let d=0;d<=l;d++){let p=a.children[d],u=c?`${c}.nextSibling`:`${s}.firstChild`;if(y(p)){let v=r(u),D=r(`holeEnd(${v})`);n.push({parentRef:s,startRef:v,endRef:D,node:p}),c=D;continue}let m=r(u);p.kind==="element"&&I(p)&&i(p,m),c=m}}}function we(t){return g(G(t)).split(K).join(be+Ce)}function G(t){return{...t,children:t.children.map(e=>y(e)?{kind:"text",value:K}:e.kind==="element"?G(e):e)}}var K="\0fx-hole\0";var M={version:1,module:"@fluixi/dom",symbols:["createNativeElement","insert","spread","setAttribute","delegateEvents","createComponent","createMemo","untrack","Show","For","Index","Switch","Match","Dynamic","ErrorBoundary"]},et={version:2,module:"@fluixi/dom",symbols:[...M.symbols,"template","cloneTemplate","walk"]};var $e={show:"Show",for:"For",index:"Index",switch:"Switch",match:"Match",dynamic:"Dynamic",errorBoundary:"ErrorBoundary",suspense:"Suspense"};function Te(t){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(t)}function Z(t){return Te(t)?t:JSON.stringify(t)}function Se(t){return t.expr!==void 0?t.reactive?`() => (${t.expr})`:`(${t.expr})`:JSON.stringify(t.literal??!0)}function Pe(t){return t.expr!==void 0?`(${t.expr})`:JSON.stringify(t.literal??!0)}function Me(t,e,n){let o=t.filter(s=>s.kind==="spread"),i=t.filter(s=>s.kind!=="spread").map(s=>`${Z(s.name)}: ${Se(s)}`);e!=null&&i.push(`children: ${e}`);let a=`{ ${i.join(", ")} }`;return o.length>0?(n.add("mergeProps"),`mergeProps(${o.map(s=>s.expr).join(", ")}, ${a})`):a}function X(t,e,n){return t.length===1?R(t[0],e,n):`[${t.map(o=>R(o,e,n)).join(", ")}]`}function Y(t,e,n,o,r){o.add("createMemo"),o.add("createComponent");let i=e.filter(c=>c.kind==="spread"),s=e.filter(c=>c.kind!=="spread").map(c=>`get ${Z(c.name)}() { return ${Pe(c)}; }`);n.length>0&&s.push(`get children() { return ${X(n,o,r)}; }`);let l=`{ ${s.join(", ")} }`;return i.length>0&&(o.add("mergeProps"),l=`mergeProps(${i.map(c=>c.expr).join(", ")}, ${l})`),`createMemo(() => createComponent(${t}, ${l}))`}function Oe(t,e){let n=U(e.name),o=e.literal;return o===!0||o===void 0?`${t}.setAttribute(${JSON.stringify(n)}, "");`:o===!1||o===null?"":`${t}.setAttribute(${JSON.stringify(n)}, ${JSON.stringify(String(o))});`}var Q=!1;function R(t,e,n){switch(t.kind){case"text":return JSON.stringify(t.value);case"expr":return t.reactive?`() => (${t.code})`:`(${t.code})`;case"fragment":return t.children.length===0?"null":X(t.children,e,n);case"component":return Y(t.name,t.props,t.children,e,n);case"control":{let o=$e[t.control]??t.control;return e.add(o),Y(o,t.props,t.children,e,n)}case"element":{if(n&&t.static&&!t.svg&&P(t)){e.add("templateNode");let s=`_tmpl$${n.length}`;return n.push({id:s,html:g(t),tag:t.tag,svg:!1}),`templateNode(${s}, ${JSON.stringify(t.tag)})`}if(n&&Q){let s=q(t);if(s){e.add("templateNode"),e.add("insert"),e.add("holeEnd"),e.add("holeContent"),e.add("holeScope");let l=`_tmpl$${n.length}`;n.push({id:l,html:s.html,tag:s.tag,svg:!1});let c=[`const _el$ = templateNode(${l}, ${JSON.stringify(s.tag)}, true);`];for(let d of s.steps)c.push(`const ${d.ref} = ${d.expr};`);for(let d of s.holes)c.push(`insert(${d.parentRef}, holeScope(${d.startRef}, () => (${R(d.node,e,n)})), ${d.endRef}, holeContent(${d.startRef}, ${d.endRef}));`);return c.push("return _el$;"),`(() => { ${c.join(" ")} })()`}}e.add("createNativeElement");let o=JSON.stringify(t.tag),r="_el$",i=[],a=t.svg?`${o}, true`:o;if(i.push(`const ${r} = createNativeElement(${a});`),t.props.length>0)if(!t.svg&&t.props.every(h))for(let s of t.props)i.push(Oe(r,s));else{e.add("spread");let s=t.svg?", isSVG: true":"";i.push(`spread({ element: ${r}, props: ${Me(t.props,null,e)}${s} });`)}for(let s of t.children){e.add("insert");let l=R(s,e,n),c=s.kind==="expr"&&s.reactive||s.kind==="component"||s.kind==="control";i.push(c?`insert(${r}, ${l}, null);`:`insert(${r}, ${l});`)}return i.push(`return ${r};`),`(() => { ${i.join(" ")} })()`}}}function b(t,e){if(!e||e.length===0)return t;let n=new Map(e.map(o=>[o.id,JSON.stringify(o.html)]));return t.replace(/_tmpl\$\d+/g,o=>n.get(o)??o)}var C={name:"imperative",contract:M,emit(t,e){let n=new Set,o=e?.templateClone!==!1?[]:void 0;return Q=e?.partialTemplates===!0,{code:R(t,n,o),imports:Array.from(n),templates:o}}};var Ae=t=>"components"in t;function ee(t,e){return t.replace(/\$(\d+)/g,(n,o)=>e[Number(o)]??n)}function De(t,e){return typeof e=="string"?{module:e,export:t}:e}function te(t=[]){let e=new Map,n=[],o=[];for(let a of t){if(!Ae(a)){o.push(a);continue}for(let[s,l]of Object.entries(a.components)){let c=De(s,l),d=e.get(s);if(d&&d.module!==c.module){let p=n.find(u=>u.name===s);p?p.modules.push(c.module):n.push({name:s,modules:[d.module,c.module]});continue}e.set(s,c)}}let r=new Map;return{resolve:a=>{if(r.has(a))return r.get(a);let s=e.get(a);if(!s)for(let l of o){let c=a.match(new RegExp(l.match.source,l.match.flags.replace("g","")));if(c){s={module:ee(l.module,c),export:l.export?ee(l.export,c):a};break}}return r.set(a,s),s},names:()=>[...e.keys()],conflicts:()=>n}}var oe=require("@fluixi/template-parser");function O(t){let e=t.split(/\r\n|\n|\r/),n=0;for(let r=0;r<e.length;r++)/[^ \t]/.test(e[r])&&(n=r);let o="";for(let r=0;r<e.length;r++){let i=e[r].replace(/\t/g," ");r!==0&&(i=i.replace(/^ +/,"")),r!==e.length-1&&(i=i.replace(/ +$/,"")),i&&(r!==n&&(i+=" "),o+=i)}return o}var ne=new Set(["click","dblclick","input","change","submit","focus","blur","keydown","keyup","keypress","mousedown","mouseup"]);function Le(t){return t.replace(/\\/g,"\\\\").replace(/`/g,"\\`").replace(/\$\{/g,"\\${")}function re(t){return t.charAt(0).toUpperCase()+t.slice(1)}var A=class{constructor(e,n){this.holes=e;this.used=n}hole(e){return this.holes[e]??{code:"undefined",reactive:!1}}emit(e){let{code:n,imports:o,templates:r}=C.emit(e,{});for(let i of o)this.used.add(i);return b(n,r)}lowerRoot(e){let n=this.lowerChildren(e);return n.length===1?n[0]:{kind:"fragment",children:n}}lowerChildren(e){let n=[];for(let o=0;o<e.length;o++){let r=e[o];if(r.kind==="Element"||r.kind==="Component"){let a=r.attributes.find(s=>s.kind==="IfDirective");if(a&&a.kind==="IfDirective"){let s=o+1;s<e.length&&this.isBlankText(e[s])&&s++;let l=e[s],c=l&&(l.kind==="Element"||l.kind==="Component")&&l.attributes.some(d=>d.kind==="ElseDirective");n.push(this.lowerIf(r,a.hole,c?l:null)),c&&(o=s);continue}if(r.attributes.some(s=>s.kind==="EachDirective")){n.push(this.lowerEach(r));continue}}let i=this.lowerNode(r);i&&n.push(i)}return n}isBlankText(e){return e.kind==="Text"&&!e.raw&&O(e.value)===""}lowerNode(e){switch(e.kind){case"Text":{if(e.raw)return{kind:"text",value:e.value};let n=O(e.value);return n?{kind:"text",value:n}:null}case"Comment":return null;case"Expression":{let n=this.hole(e.hole);return{kind:"expr",code:n.code,reactive:n.reactive}}case"Fragment":return{kind:"fragment",children:this.lowerChildren(e.children)};case"Element":return this.lowerElement(e);case"Component":return this.lowerComponent(e);default:return null}}lowerElement(e){let n=e.attributes.find(o=>o.kind==="Attribute"&&o.name==="is");if(e.tag==="component"&&n&&n.value&&n.value.kind==="hole"){let o=e.attributes.filter(i=>i!==n),r=this.lowerComponent({...e,kind:"Component",tag:"Dynamic",tagHole:null,attributes:o});return r.props.unshift({name:"component",kind:"attr",expr:`() => (${this.hole(n.value.hole).code})`}),r}return{kind:"element",tag:e.tag,svg:e.namespace==="svg",props:this.lowerAttributes(e.attributes),children:this.lowerChildren(e.children),static:!1}}lowerComponent(e){let n=e.tagHole!=null?this.hole(e.tagHole).code:e.tag,o=this.lowerAttributes(e.attributes),{slots:r,rest:i}=this.partitionSlots(e.children);for(let[l,c]of r){let d=c.length===1?c[0]:{kind:"fragment",children:c},p={name:l,kind:"attr",expr:this.emit(d),jsxElement:!0},u=o.findIndex(m=>m.name===l);u>=0?o[u]=p:o.push(p)}let a=e.attributes.find(l=>l.kind==="LoadDirective"),s=a?_(`load:${a.strategy}`,a.modifier):void 0;return{kind:"component",name:n,props:o,children:this.lowerChildren(i),...s?{load:s}:{}}}partitionSlots(e){let n=new Map,o=[];for(let r of e){if(r.kind==="Element"||r.kind==="Component"){let i=r.attributes.find(a=>a.kind==="Attribute"&&a.name==="slot");if(i&&i.value&&i.value.kind==="static"){let a={...r,attributes:r.attributes.filter(c=>c!==i)},s=a.kind==="Element"?this.lowerElement(a):this.lowerComponent(a),l=n.get(i.value.value)??[];l.push(s),n.set(i.value.value,l);continue}}o.push(r)}return{slots:n,rest:o}}lowerIf(e,n,o){let r=this.hole(n),i=[{name:"when",kind:"attr",expr:r.code,reactive:r.reactive}];if(o){let s=this.stripAndLower(o,l=>l.kind==="ElseDirective");i.push({name:"fallback",kind:"attr",expr:this.emit(s),jsxElement:!0})}let a=this.stripAndLower(e,s=>s.kind==="IfDirective");return{kind:"component",name:"Show",props:i,children:[a]}}lowerEach(e){let n=e.attributes.find(l=>l.kind==="EachDirective");if(!n||n.kind!=="EachDirective")return this.lowerNode(e);let o=this.hole(n.hole),r=[{name:"each",kind:"attr",expr:o.code,reactive:o.reactive}];if(n.key){let l="static"in n.key?`(item) => item[${JSON.stringify(n.key.static)}]`:this.hole(n.key.hole).code;r.push({name:"by",kind:"attr",expr:l})}let i=this.itemArrow(e),a;if(i){let l={kind:"expr",code:i.body,reactive:i.bodyReactive},c=this.rebuildWithChildren(e,[l]);a=`(${i.params.join(", ")}) => (${this.emit(c)})`}else{let l=this.stripAndLower(e,c=>c.kind==="EachDirective");a=`() => (${this.emit(l)})`}return{kind:"component",name:"For",props:r,children:[{kind:"expr",code:a,reactive:!1}]}}itemArrow(e){let n=e.children.filter(o=>!this.isBlankText(o));return n.length!==1||n[0].kind!=="Expression"?null:this.hole(n[0].hole).arrow??null}stripAndLower(e,n){let o={...e,attributes:e.attributes.filter(r=>!n(r))};return o.kind==="Element"?this.lowerElement(o):this.lowerComponent(o)}rebuildWithChildren(e,n){let o=this.lowerAttributes(e.attributes.filter(r=>r.kind!=="EachDirective"));return e.kind==="Element"?{kind:"element",tag:e.tag,svg:e.namespace==="svg",props:o,children:n,static:!1}:{kind:"component",name:e.tag,props:o,children:n}}lowerAttributes(e){let n=[],o=[],r=!1,i=[],a=!1,s=[];for(let l of e)switch(l.kind){case"IfDirective":case"EachDirective":case"ElseDirective":break;case"Attribute":n.push(this.plainAttr(l));break;case"PropertyBinding":n.push({name:l.name,kind:"prop",expr:this.hole(l.hole).code,reactive:this.hole(l.hole).reactive});break;case"EventBinding":n.push(this.eventProp(l));break;case"RefBinding":n.push({name:"ref",kind:"ref",expr:this.hole(l.hole).code,reactive:this.hole(l.hole).reactive});break;case"Spread":n.push({name:"",kind:"spread",expr:this.hole(l.hole).code});break;case"ClassDirective":{let c=this.hole(l.hole);o.push(`${JSON.stringify(l.name)}: ${c.code}`),r=r||c.reactive;break}case"StyleDirective":{let c=this.hole(l.hole);i.push(`${JSON.stringify(l.name)}: ${c.code}`),a=a||c.reactive;break}case"BindDirective":n.push(...this.bindProps(l.name,this.hole(l.hole).code));break;case"UseDirective":{let c=l.name??(l.hole!=null?this.hole(l.hole).code:null);if(!c)break;s.push(l.name!=null&&l.hole!=null?`[${c}, () => (${this.hole(l.hole).code})]`:`[${c}]`);break}}return o.length>0&&n.push({name:"classList",kind:"attr",expr:`{ ${o.join(", ")} }`,reactive:r}),i.length>0&&n.push({name:"style",kind:"attr",expr:`{ ${i.join(", ")} }`,reactive:a}),s.length>0&&n.push({name:"use",kind:"attr",expr:`[${s.join(", ")}]`}),n}eventProp(e){let n=e.name.toLowerCase(),o=this.hole(e.hole).code;if(!(e.syntax==="colon"||e.modifiers.length>0))return{name:"on"+re(e.name),kind:"event",event:{name:n,delegated:ne.has(n)},expr:o};let i=this.wrapHandler(o,e.modifiers),a=this.eventOptions(e.modifiers),s=a?`[${i}, ${a}]`:i;return{name:"on:"+n,kind:"attr",expr:s}}wrapHandler(e,n){let o=n.includes("self")?"if (e.target !== e.currentTarget) return; ":"",r=[];return n.includes("prevent")&&r.push("e.preventDefault();"),n.includes("stop")&&r.push("e.stopPropagation();"),!o&&r.length===0?e:`(e) => { ${o}${r.join(" ")} return (${e})(e); }`}eventOptions(e){let n=[];return e.includes("capture")&&n.push("capture: true"),e.includes("once")&&n.push("once: true"),e.includes("passive")&&n.push("passive: true"),n.length?`{ ${n.join(", ")} }`:null}bindProps(e,n){let o=e==="checked",r=o?"change":"input",i=o?"checked":"value",a=`(${n})`;return[{name:e,kind:"attr",expr:`${a}[0]()`,reactive:!0},{name:"on"+re(r),kind:"event",event:{name:r,delegated:ne.has(r)},expr:`(e) => ${a}[1](e.target.${i})`}]}plainAttr(e){let n=e.value,o=e.name;e.name==="class"?o=n&&n.kind==="hole"&&this.hole(n.hole).object?"classList":"className":e.name==="html"&&(o="innerHTML");let i={name:o,kind:"attr"};if(n==null)return i.literal=!0,i;if(n.kind==="static")return i.literal=n.value,i;if(n.kind==="hole"){let l=this.hole(n.hole);return i.expr=l.code,i.reactive=l.reactive,i}let a=!1,s=n.parts.map(l=>{if("text"in l)return Le(l.text);let c=this.hole(l.hole);return a=a||c.reactive,"${"+c.code+"}"}).join("");return i.expr="`"+s+"`",i.reactive=a,i}};function ie(t,e,n,o={}){let{root:r}=(0,oe.parseTemplate)(t,{svg:o.svg});return new A(e,n).lowerRoot(r.children)}function je(t){let e=[],n=0;return t.statics.forEach((o,r)=>{if(e.push({kind:"static",text:o,start:n}),n+=o.length,r<t.holes.length){let i=n+t.holes[r].code.length;e.push({kind:"hole",index:r,start:n,end:i}),n=i}}),e}function _e(t,e={}){if(t.statics.length!==t.holes.length+1)throw new Error(`[fluixi] compileTemplate: ${t.statics.length} static runs for ${t.holes.length} holes — a template always has exactly one more.`);return se(je(t),t.holes,e)}function se(t,e,n={}){let o=new Set,r=ie(t,[...e],o,{svg:n.svg});L(r),F(r,{resolver:te(n.resolve??[]),modules:{controlFlowModule:n.controlFlowModule??"@fluixi/dom",coreModule:n.coreModule??"@fluixi/core",routerModule:n.routerModule??"@fluixi/core/router-next"},strategyFor:l=>l.load}),z(r);let{code:i,imports:a,templates:s}=C.emit(r,{templateClone:n.templateClone,partialTemplates:n.partialTemplates});for(let l of a)o.add(l);return n.hoistTemplates?{code:i,imports:[...o],ir:r,templates:s}:{code:b(i,s),imports:[...o],ir:r}}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { type ComponentResolverRule } from '../resolve/component-resolver.js';
|
|
2
|
+
import type { IRNode } from '../ir/nodes.js';
|
|
3
|
+
import { type TemplateHole } from './template.js';
|
|
4
|
+
import type { Piece } from '@fluixi/template-parser';
|
|
5
|
+
import type { StaticTemplate } from '../codegen/backend.js';
|
|
6
|
+
export interface TemplateSource {
|
|
7
|
+
/**
|
|
8
|
+
* The static text runs, in order. Always one more than `holes` — the text
|
|
9
|
+
* before the first `${`, between each pair, and after the last `}`.
|
|
10
|
+
*/
|
|
11
|
+
statics: readonly string[];
|
|
12
|
+
/** One descriptor per `${…}`, in source order. */
|
|
13
|
+
holes: readonly TemplateHole[];
|
|
14
|
+
}
|
|
15
|
+
export interface CompileTemplateOptions {
|
|
16
|
+
/** An `` svg`...` `` root, which changes how the parser namespaces tags. */
|
|
17
|
+
svg?: boolean;
|
|
18
|
+
/** Clone static subtrees from a template instead of building them element by element. */
|
|
19
|
+
templateClone?: boolean;
|
|
20
|
+
/** Also clone subtrees whose structure is static but which contain holes. */
|
|
21
|
+
partialTemplates?: boolean;
|
|
22
|
+
/** Rules that resolve an unbound capitalised tag to a module. */
|
|
23
|
+
resolve?: readonly ComponentResolverRule[];
|
|
24
|
+
/** Where control-flow components are imported from. @default '@fluixi/dom' */
|
|
25
|
+
controlFlowModule?: string;
|
|
26
|
+
/** Where core-only components (Suspense, Portal) come from. @default '@fluixi/core' */
|
|
27
|
+
coreModule?: string;
|
|
28
|
+
/** Where router components come from. @default '@fluixi/core/router-next' */
|
|
29
|
+
routerModule?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Leave static templates as `_tmpl$N` references and hand them back, for a
|
|
32
|
+
* caller that has a module scope to declare them in. Off inlines them.
|
|
33
|
+
*/
|
|
34
|
+
hoistTemplates?: boolean;
|
|
35
|
+
}
|
|
36
|
+
export interface CompileTemplateResult {
|
|
37
|
+
/** A JavaScript expression that builds the DOM when evaluated. */
|
|
38
|
+
code: string;
|
|
39
|
+
/** Runtime symbols the code refers to, for the caller to import. */
|
|
40
|
+
imports: string[];
|
|
41
|
+
/** The IR it was emitted from, for a caller that wants to inspect or transform it. */
|
|
42
|
+
ir: IRNode;
|
|
43
|
+
/**
|
|
44
|
+
* Static templates the code refers to by local `_tmpl$N` id, when the caller
|
|
45
|
+
* asked to hoist them. `compileTemplate` inlines them instead — it has no module
|
|
46
|
+
* scope to hoist into.
|
|
47
|
+
*/
|
|
48
|
+
templates?: StaticTemplate[];
|
|
49
|
+
}
|
|
50
|
+
export declare function compileTemplate(source: TemplateSource, options?: CompileTemplateOptions): CompileTemplateResult;
|
|
51
|
+
/**
|
|
52
|
+
* Same pipeline entered with pieces that already carry real source offsets, so a
|
|
53
|
+
* caller reading a file keeps its positions instead of the synthetic ones derived
|
|
54
|
+
* from the static runs.
|
|
55
|
+
*/
|
|
56
|
+
export declare function compilePieces(pieces: Piece[], holes: readonly TemplateHole[], options?: CompileTemplateOptions): CompileTemplateResult;
|
|
57
|
+
//# sourceMappingURL=compile-template.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compile-template.d.ts","sourceRoot":"","sources":["../../src/lower/compile-template.ts"],"names":[],"mappings":"AAcA,OAAO,EAA2B,KAAK,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACvG,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,kDAAkD;IAClD,KAAK,EAAE,SAAS,YAAY,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,sBAAsB;IACrC,4EAA4E;IAC5E,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,yFAAyF;IACzF,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,6EAA6E;IAC7E,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,iEAAiE;IACjE,OAAO,CAAC,EAAE,SAAS,qBAAqB,EAAE,CAAC;IAC3C,8EAA8E;IAC9E,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,uFAAuF;IACvF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,qBAAqB;IACpC,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,sFAAsF;IACtF,EAAE,EAAE,MAAM,CAAC;IACX;;;;OAIG;IACH,SAAS,CAAC,EAAE,cAAc,EAAE,CAAC;CAC9B;AAqBD,wBAAgB,eAAe,CAC7B,MAAM,EAAE,cAAc,EACtB,OAAO,GAAE,sBAA2B,GACnC,qBAAqB,CASvB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,KAAK,EAAE,EACf,KAAK,EAAE,SAAS,YAAY,EAAE,EAC9B,OAAO,GAAE,sBAA2B,GACnC,qBAAqB,CA0BvB"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compile a `` html`...` `` template to runtime calls, with no JS toolchain in
|
|
3
|
+
* the path.
|
|
4
|
+
*
|
|
5
|
+
* statics + holes → parseTemplate → IR → resolve → optimize → codegen → code
|
|
6
|
+
*
|
|
7
|
+
* Finding templates in a module and describing each hole still needs a front-end;
|
|
8
|
+
* everything after that point is here. Passes run in the same order as
|
|
9
|
+
* `emitLitViaIR` — compile-template.spec.ts compares the two.
|
|
10
|
+
*/
|
|
11
|
+
import { analyzeStatic } from '../optimize/analyze-static.js';
|
|
12
|
+
import { collapseStrategies } from '../optimize/collapse-strategies.js';
|
|
13
|
+
import { imperativeBackend, inlineTemplates } from '../codegen/backends/imperative.js';
|
|
14
|
+
import { resolveComponentSources } from '../resolve/resolve-ir.js';
|
|
15
|
+
import { createComponentResolver } from '../resolve/component-resolver.js';
|
|
16
|
+
import { lowerTemplate } from './template.js';
|
|
17
|
+
/**
|
|
18
|
+
* `statics`/`holes` as the parser wants them. Offsets are cumulative so a
|
|
19
|
+
* diagnostic can point back into the original template text.
|
|
20
|
+
*/
|
|
21
|
+
function toPieces(source) {
|
|
22
|
+
const pieces = [];
|
|
23
|
+
let offset = 0;
|
|
24
|
+
source.statics.forEach((text, i) => {
|
|
25
|
+
pieces.push({ kind: 'static', text, start: offset });
|
|
26
|
+
offset += text.length;
|
|
27
|
+
if (i < source.holes.length) {
|
|
28
|
+
const end = offset + source.holes[i].code.length;
|
|
29
|
+
pieces.push({ kind: 'hole', index: i, start: offset, end });
|
|
30
|
+
offset = end;
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
return pieces;
|
|
34
|
+
}
|
|
35
|
+
export function compileTemplate(source, options = {}) {
|
|
36
|
+
if (source.statics.length !== source.holes.length + 1) {
|
|
37
|
+
throw new Error(`[fluixi] compileTemplate: ${source.statics.length} static runs for ` +
|
|
38
|
+
`${source.holes.length} holes — a template always has exactly one more.`);
|
|
39
|
+
}
|
|
40
|
+
return compilePieces(toPieces(source), source.holes, options);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Same pipeline entered with pieces that already carry real source offsets, so a
|
|
44
|
+
* caller reading a file keeps its positions instead of the synthetic ones derived
|
|
45
|
+
* from the static runs.
|
|
46
|
+
*/
|
|
47
|
+
export function compilePieces(pieces, holes, options = {}) {
|
|
48
|
+
const used = new Set();
|
|
49
|
+
const ir = lowerTemplate(pieces, [...holes], used, { svg: options.svg });
|
|
50
|
+
analyzeStatic(ir);
|
|
51
|
+
// Same order as the Babel front-end: decide where each component reference
|
|
52
|
+
// comes from, then drop deferred boundaries around modules already in the chunk.
|
|
53
|
+
resolveComponentSources(ir, {
|
|
54
|
+
resolver: createComponentResolver(options.resolve ?? []),
|
|
55
|
+
modules: {
|
|
56
|
+
controlFlowModule: options.controlFlowModule ?? '@fluixi/dom',
|
|
57
|
+
coreModule: options.coreModule ?? '@fluixi/core',
|
|
58
|
+
routerModule: options.routerModule ?? '@fluixi/core/router-next',
|
|
59
|
+
},
|
|
60
|
+
strategyFor: (node) => node.load,
|
|
61
|
+
});
|
|
62
|
+
collapseStrategies(ir);
|
|
63
|
+
const { code, imports, templates } = imperativeBackend.emit(ir, {
|
|
64
|
+
templateClone: options.templateClone,
|
|
65
|
+
partialTemplates: options.partialTemplates,
|
|
66
|
+
});
|
|
67
|
+
for (const symbol of imports)
|
|
68
|
+
used.add(symbol);
|
|
69
|
+
if (options.hoistTemplates)
|
|
70
|
+
return { code, imports: [...used], ir, templates };
|
|
71
|
+
return { code: inlineTemplates(code, templates), imports: [...used], ir };
|
|
72
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function oe(t){switch(t.kind){case"event":return"event";case"ref":return"ref";case"spread":return"spread";case"class":case"style":return"class-or-style-directive";case"attr":case"prop":return t.reactive?"reactive-prop":t.expr!==void 0?"expression-prop":void 0;default:return"expression-prop"}}function D(t){let e=[],n=new Map,r=o=>{switch(o.kind){case"text":return!0;case"expr":return!1;case"component":case"control":for(let i of o.children)r(i);return!1;case"fragment":for(let i of o.children)r(i);return!1;case"element":{let i=!0;for(let s of o.children)r(s)||(i=!1);let a;for(let s of o.props)if(a=oe(s),a)break;return!a&&!i&&(a=ie(o)),o.static=!a,a?n.set(o,a):e.push(o),o.static}default:return!1}};for(let o of Array.isArray(t)?t:[t])r(o);return{staticElements:e,reasons:n}}function ie(t){for(let e of t.children){if(e.kind==="expr")return"expression-child";if(e.kind==="component")return"component-child";if(e.kind==="control")return"control-child";if(e.kind==="element"&&!e.static||e.kind==="fragment")return"expression-child"}return"expression-child"}var k={kind:"eager"},se=["pointerdown","focusin","keydown"],L=new Set(["eager","idle","visible","interaction","media","never"]),f=class extends Error{};function j(t,e){let n=t.slice(5);if(!L.has(n))throw new f(`Unknown load strategy 'load:${n}'. Expected one of ${[...L].join(", ")}.`);switch(n){case"eager":return k;case"idle":return{kind:"idle"};case"never":return{kind:"never"};case"visible":return e?{kind:"visible",rootMargin:e}:{kind:"visible"};case"interaction":return{kind:"interaction",events:e?le(e):[...se]};case"media":if(!e)throw new f(`'load:media' needs a query, e.g. load:media="(min-width: 1024px)".`);return{kind:"media",query:e};default:throw new f(`Unhandled load strategy '${n}'.`)}}function le(t){let e=t.split(/[\s,]+/).map(n=>n.trim()).filter(Boolean);if(e.length===0)throw new f("'load:interaction' was given no event names.");return e}function _(t){return t.kind!=="eager"&&t.kind!=="never"}var E=["Show","For","Index","Switch","Match","Portal","Dynamic","ErrorBoundary"],w=["Suspense","SuspenseList","Await"],x=["Router","Outlet","Redirect","Link"],Oe=[...E,...w,...x],$=new Set([...E,...w]);function B(t={}){let{controlFlowModule:e="@fluixi/dom",coreModule:n="@fluixi/core",routerModule:r="@fluixi/core/router-next"}=t,o={};for(let i of E)o[i]=e;for(let i of w)o[i]=n;for(let i of x)o[i]=r;return o}function H(t,e={}){let{resolver:n,isBound:r,modules:o,strategyFor:i}=e,a=B(o),s=new Map,l=new Set,c=p=>{let{name:u}=p;if(!u||u.includes(".")||r?.(u))return;let m=d(u);if(!m){l.add(u);return}let v=m.origin==="builtin"&&$.has(u)?k:i?.(p)??k;p.source={...m,loading:v},s.set(u,p.source)},d=p=>{if($.has(p))return{module:a[p],export:p,origin:"builtin"};let u=n?.resolve(p);if(u)return{module:u.module,export:u.export,origin:"rule"};if(x.includes(p))return{module:a[p],export:p,origin:"builtin"}};return N(t,p=>{p.kind==="component"&&c(p)}),{resolved:s,unresolved:[...l]}}function N(t,e){let n=Array.isArray(t)?t:[t];for(let r of n){e(r);let o=r.children;o&&N(o,e)}}function F(t){let e=[];N(t,i=>{i.kind==="component"&&i.source&&e.push(i)});let n=new Set,r=new Set;for(let i of e){let{module:a,loading:s}=i.source;s.kind==="eager"&&n.add(a),s.kind==="never"&&r.add(a)}let o=new Map;for(let i of e){let a=i.source;_(a.loading)&&n.has(a.module)&&(a.loading={kind:"eager"},o.set(a.module,(o.get(a.module)??0)+1))}return{collapsed:o,conflicted:[...r].filter(i=>n.has(i))}}var ae=new Set(["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"]),z={className:"class",htmlFor:"for"},ce=new Set(["innerHTML","outerHTML","innerText","textContent","value","checked","selected","muted","defaultValue","defaultChecked","children","ref"]),pe=new Set(["script","style","textarea","title"]);function T(t){return pe.has(t)}function J(t){return z[t]??t}function h(t){return t.kind!=="attr"||t.expr!==void 0||t.name.includes(":")?!1:!ce.has(t.name)}function S(t){if(!t.static||T(t.tag))return!1;for(let e of t.props)if(!h(e))return!1;for(let e of t.children)if(e.kind!=="text"&&!(e.kind==="element"&&S(e)))return!1;return!0}function g(t){let e=t.props.map(ue).filter(Boolean).join(""),n=`<${t.tag}${e}>`;return ae.has(t.tag)?n:`${n}${t.children.map(de).join("")}</${t.tag}>`}function de(t){if(t.kind==="text")return fe(t.value);if(t.kind!=="element")throw new Error(`serializeStatic: unexpected ${t.kind}`);return g(t)}function ue(t){let e=z[t.name]??t.name,n=t.literal;return n===!0||n===void 0?` ${e}`:n===!1||n===null?"":` ${e}="${me(String(n))}"`}function me(t){return t.replace(/&/g,"&").replace(/"/g,""").replace(/</g,"<").replace(/>/g,">")}function fe(t){return t.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}var he="<!--fx-->",ge="<!--fx/-->";function y(t){return t.kind==="expr"||t.kind==="component"||t.kind==="control"}function Re(t){return t.kind==="text"||t.kind==="element"&&U(t)}function U(t){return t.svg||T(t.tag)||!t.props.every(e=>h(e))?!1:t.children.every(e=>Re(e)||y(e))}function I(t){if(y(t))return!0;let e=t.children;return e?e.some(I):!1}function V(t){for(let e=0;e<t.children.length;e++){let n=t.children[e];if(n.kind==="text"&&(n.value===""||t.children[e+1]?.kind==="text"))return!1}return t.children.every(e=>e.kind!=="element"||V(e))}function W(t){if(!U(t)||!V(t)||!t.children.some(I))return null;let e=[],n=[],r=0,o=a=>{let s=`_n$${r++}`;return e.push({ref:s,expr:a}),s};return i(t,"_el$"),{html:ve(t),tag:t.tag,steps:e,holes:n};function i(a,s){let l=-1;a.children.forEach((d,p)=>{I(d)&&(l=p)});let c=null;for(let d=0;d<=l;d++){let p=a.children[d],u=c?`${c}.nextSibling`:`${s}.firstChild`;if(y(p)){let v=o(u),A=o(`holeEnd(${v})`);n.push({parentRef:s,startRef:v,endRef:A,node:p}),c=A;continue}let m=o(u);p.kind==="element"&&I(p)&&i(p,m),c=m}}}function ve(t){return g(q(t)).split(G).join(he+ge)}function q(t){return{...t,children:t.children.map(e=>y(e)?{kind:"text",value:G}:e.kind==="element"?q(e):e)}}var G="\0fx-hole\0";var P={version:1,module:"@fluixi/dom",symbols:["createNativeElement","insert","spread","setAttribute","delegateEvents","createComponent","createMemo","untrack","Show","For","Index","Switch","Match","Dynamic","ErrorBoundary"]},Ue={version:2,module:"@fluixi/dom",symbols:[...P.symbols,"template","cloneTemplate","walk"]};var ke={show:"Show",for:"For",index:"Index",switch:"Switch",match:"Match",dynamic:"Dynamic",errorBoundary:"ErrorBoundary",suspense:"Suspense"};function xe(t){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(t)}function Y(t){return xe(t)?t:JSON.stringify(t)}function Ne(t){return t.expr!==void 0?t.reactive?`() => (${t.expr})`:`(${t.expr})`:JSON.stringify(t.literal??!0)}function Ie(t){return t.expr!==void 0?`(${t.expr})`:JSON.stringify(t.literal??!0)}function ye(t,e,n){let r=t.filter(s=>s.kind==="spread"),i=t.filter(s=>s.kind!=="spread").map(s=>`${Y(s.name)}: ${Ne(s)}`);e!=null&&i.push(`children: ${e}`);let a=`{ ${i.join(", ")} }`;return r.length>0?(n.add("mergeProps"),`mergeProps(${r.map(s=>s.expr).join(", ")}, ${a})`):a}function Z(t,e,n){return t.length===1?R(t[0],e,n):`[${t.map(r=>R(r,e,n)).join(", ")}]`}function K(t,e,n,r,o){r.add("createMemo"),r.add("createComponent");let i=e.filter(c=>c.kind==="spread"),s=e.filter(c=>c.kind!=="spread").map(c=>`get ${Y(c.name)}() { return ${Ie(c)}; }`);n.length>0&&s.push(`get children() { return ${Z(n,r,o)}; }`);let l=`{ ${s.join(", ")} }`;return i.length>0&&(r.add("mergeProps"),l=`mergeProps(${i.map(c=>c.expr).join(", ")}, ${l})`),`createMemo(() => createComponent(${t}, ${l}))`}function be(t,e){let n=J(e.name),r=e.literal;return r===!0||r===void 0?`${t}.setAttribute(${JSON.stringify(n)}, "");`:r===!1||r===null?"":`${t}.setAttribute(${JSON.stringify(n)}, ${JSON.stringify(String(r))});`}var X=!1;function R(t,e,n){switch(t.kind){case"text":return JSON.stringify(t.value);case"expr":return t.reactive?`() => (${t.code})`:`(${t.code})`;case"fragment":return t.children.length===0?"null":Z(t.children,e,n);case"component":return K(t.name,t.props,t.children,e,n);case"control":{let r=ke[t.control]??t.control;return e.add(r),K(r,t.props,t.children,e,n)}case"element":{if(n&&t.static&&!t.svg&&S(t)){e.add("templateNode");let s=`_tmpl$${n.length}`;return n.push({id:s,html:g(t),tag:t.tag,svg:!1}),`templateNode(${s}, ${JSON.stringify(t.tag)})`}if(n&&X){let s=W(t);if(s){e.add("templateNode"),e.add("insert"),e.add("holeEnd"),e.add("holeContent"),e.add("holeScope");let l=`_tmpl$${n.length}`;n.push({id:l,html:s.html,tag:s.tag,svg:!1});let c=[`const _el$ = templateNode(${l}, ${JSON.stringify(s.tag)}, true);`];for(let d of s.steps)c.push(`const ${d.ref} = ${d.expr};`);for(let d of s.holes)c.push(`insert(${d.parentRef}, holeScope(${d.startRef}, () => (${R(d.node,e,n)})), ${d.endRef}, holeContent(${d.startRef}, ${d.endRef}));`);return c.push("return _el$;"),`(() => { ${c.join(" ")} })()`}}e.add("createNativeElement");let r=JSON.stringify(t.tag),o="_el$",i=[],a=t.svg?`${r}, true`:r;if(i.push(`const ${o} = createNativeElement(${a});`),t.props.length>0)if(!t.svg&&t.props.every(h))for(let s of t.props)i.push(be(o,s));else{e.add("spread");let s=t.svg?", isSVG: true":"";i.push(`spread({ element: ${o}, props: ${ye(t.props,null,e)}${s} });`)}for(let s of t.children){e.add("insert");let l=R(s,e,n),c=s.kind==="expr"&&s.reactive||s.kind==="component"||s.kind==="control";i.push(c?`insert(${o}, ${l}, null);`:`insert(${o}, ${l});`)}return i.push(`return ${o};`),`(() => { ${i.join(" ")} })()`}}}function b(t,e){if(!e||e.length===0)return t;let n=new Map(e.map(r=>[r.id,JSON.stringify(r.html)]));return t.replace(/_tmpl\$\d+/g,r=>n.get(r)??r)}var C={name:"imperative",contract:P,emit(t,e){let n=new Set,r=e?.templateClone!==!1?[]:void 0;return X=e?.partialTemplates===!0,{code:R(t,n,r),imports:Array.from(n),templates:r}}};var Ce=t=>"components"in t;function Q(t,e){return t.replace(/\$(\d+)/g,(n,r)=>e[Number(r)]??n)}function Ee(t,e){return typeof e=="string"?{module:e,export:t}:e}function ee(t=[]){let e=new Map,n=[],r=[];for(let a of t){if(!Ce(a)){r.push(a);continue}for(let[s,l]of Object.entries(a.components)){let c=Ee(s,l),d=e.get(s);if(d&&d.module!==c.module){let p=n.find(u=>u.name===s);p?p.modules.push(c.module):n.push({name:s,modules:[d.module,c.module]});continue}e.set(s,c)}}let o=new Map;return{resolve:a=>{if(o.has(a))return o.get(a);let s=e.get(a);if(!s)for(let l of r){let c=a.match(new RegExp(l.match.source,l.match.flags.replace("g","")));if(c){s={module:Q(l.module,c),export:l.export?Q(l.export,c):a};break}}return o.set(a,s),s},names:()=>[...e.keys()],conflicts:()=>n}}import{parseTemplate as we}from"@fluixi/template-parser";function M(t){let e=t.split(/\r\n|\n|\r/),n=0;for(let o=0;o<e.length;o++)/[^ \t]/.test(e[o])&&(n=o);let r="";for(let o=0;o<e.length;o++){let i=e[o].replace(/\t/g," ");o!==0&&(i=i.replace(/^ +/,"")),o!==e.length-1&&(i=i.replace(/ +$/,"")),i&&(o!==n&&(i+=" "),r+=i)}return r}var te=new Set(["click","dblclick","input","change","submit","focus","blur","keydown","keyup","keypress","mousedown","mouseup"]);function $e(t){return t.replace(/\\/g,"\\\\").replace(/`/g,"\\`").replace(/\$\{/g,"\\${")}function ne(t){return t.charAt(0).toUpperCase()+t.slice(1)}var O=class{constructor(e,n){this.holes=e;this.used=n}hole(e){return this.holes[e]??{code:"undefined",reactive:!1}}emit(e){let{code:n,imports:r,templates:o}=C.emit(e,{});for(let i of r)this.used.add(i);return b(n,o)}lowerRoot(e){let n=this.lowerChildren(e);return n.length===1?n[0]:{kind:"fragment",children:n}}lowerChildren(e){let n=[];for(let r=0;r<e.length;r++){let o=e[r];if(o.kind==="Element"||o.kind==="Component"){let a=o.attributes.find(s=>s.kind==="IfDirective");if(a&&a.kind==="IfDirective"){let s=r+1;s<e.length&&this.isBlankText(e[s])&&s++;let l=e[s],c=l&&(l.kind==="Element"||l.kind==="Component")&&l.attributes.some(d=>d.kind==="ElseDirective");n.push(this.lowerIf(o,a.hole,c?l:null)),c&&(r=s);continue}if(o.attributes.some(s=>s.kind==="EachDirective")){n.push(this.lowerEach(o));continue}}let i=this.lowerNode(o);i&&n.push(i)}return n}isBlankText(e){return e.kind==="Text"&&!e.raw&&M(e.value)===""}lowerNode(e){switch(e.kind){case"Text":{if(e.raw)return{kind:"text",value:e.value};let n=M(e.value);return n?{kind:"text",value:n}:null}case"Comment":return null;case"Expression":{let n=this.hole(e.hole);return{kind:"expr",code:n.code,reactive:n.reactive}}case"Fragment":return{kind:"fragment",children:this.lowerChildren(e.children)};case"Element":return this.lowerElement(e);case"Component":return this.lowerComponent(e);default:return null}}lowerElement(e){let n=e.attributes.find(r=>r.kind==="Attribute"&&r.name==="is");if(e.tag==="component"&&n&&n.value&&n.value.kind==="hole"){let r=e.attributes.filter(i=>i!==n),o=this.lowerComponent({...e,kind:"Component",tag:"Dynamic",tagHole:null,attributes:r});return o.props.unshift({name:"component",kind:"attr",expr:`() => (${this.hole(n.value.hole).code})`}),o}return{kind:"element",tag:e.tag,svg:e.namespace==="svg",props:this.lowerAttributes(e.attributes),children:this.lowerChildren(e.children),static:!1}}lowerComponent(e){let n=e.tagHole!=null?this.hole(e.tagHole).code:e.tag,r=this.lowerAttributes(e.attributes),{slots:o,rest:i}=this.partitionSlots(e.children);for(let[l,c]of o){let d=c.length===1?c[0]:{kind:"fragment",children:c},p={name:l,kind:"attr",expr:this.emit(d),jsxElement:!0},u=r.findIndex(m=>m.name===l);u>=0?r[u]=p:r.push(p)}let a=e.attributes.find(l=>l.kind==="LoadDirective"),s=a?j(`load:${a.strategy}`,a.modifier):void 0;return{kind:"component",name:n,props:r,children:this.lowerChildren(i),...s?{load:s}:{}}}partitionSlots(e){let n=new Map,r=[];for(let o of e){if(o.kind==="Element"||o.kind==="Component"){let i=o.attributes.find(a=>a.kind==="Attribute"&&a.name==="slot");if(i&&i.value&&i.value.kind==="static"){let a={...o,attributes:o.attributes.filter(c=>c!==i)},s=a.kind==="Element"?this.lowerElement(a):this.lowerComponent(a),l=n.get(i.value.value)??[];l.push(s),n.set(i.value.value,l);continue}}r.push(o)}return{slots:n,rest:r}}lowerIf(e,n,r){let o=this.hole(n),i=[{name:"when",kind:"attr",expr:o.code,reactive:o.reactive}];if(r){let s=this.stripAndLower(r,l=>l.kind==="ElseDirective");i.push({name:"fallback",kind:"attr",expr:this.emit(s),jsxElement:!0})}let a=this.stripAndLower(e,s=>s.kind==="IfDirective");return{kind:"component",name:"Show",props:i,children:[a]}}lowerEach(e){let n=e.attributes.find(l=>l.kind==="EachDirective");if(!n||n.kind!=="EachDirective")return this.lowerNode(e);let r=this.hole(n.hole),o=[{name:"each",kind:"attr",expr:r.code,reactive:r.reactive}];if(n.key){let l="static"in n.key?`(item) => item[${JSON.stringify(n.key.static)}]`:this.hole(n.key.hole).code;o.push({name:"by",kind:"attr",expr:l})}let i=this.itemArrow(e),a;if(i){let l={kind:"expr",code:i.body,reactive:i.bodyReactive},c=this.rebuildWithChildren(e,[l]);a=`(${i.params.join(", ")}) => (${this.emit(c)})`}else{let l=this.stripAndLower(e,c=>c.kind==="EachDirective");a=`() => (${this.emit(l)})`}return{kind:"component",name:"For",props:o,children:[{kind:"expr",code:a,reactive:!1}]}}itemArrow(e){let n=e.children.filter(r=>!this.isBlankText(r));return n.length!==1||n[0].kind!=="Expression"?null:this.hole(n[0].hole).arrow??null}stripAndLower(e,n){let r={...e,attributes:e.attributes.filter(o=>!n(o))};return r.kind==="Element"?this.lowerElement(r):this.lowerComponent(r)}rebuildWithChildren(e,n){let r=this.lowerAttributes(e.attributes.filter(o=>o.kind!=="EachDirective"));return e.kind==="Element"?{kind:"element",tag:e.tag,svg:e.namespace==="svg",props:r,children:n,static:!1}:{kind:"component",name:e.tag,props:r,children:n}}lowerAttributes(e){let n=[],r=[],o=!1,i=[],a=!1,s=[];for(let l of e)switch(l.kind){case"IfDirective":case"EachDirective":case"ElseDirective":break;case"Attribute":n.push(this.plainAttr(l));break;case"PropertyBinding":n.push({name:l.name,kind:"prop",expr:this.hole(l.hole).code,reactive:this.hole(l.hole).reactive});break;case"EventBinding":n.push(this.eventProp(l));break;case"RefBinding":n.push({name:"ref",kind:"ref",expr:this.hole(l.hole).code,reactive:this.hole(l.hole).reactive});break;case"Spread":n.push({name:"",kind:"spread",expr:this.hole(l.hole).code});break;case"ClassDirective":{let c=this.hole(l.hole);r.push(`${JSON.stringify(l.name)}: ${c.code}`),o=o||c.reactive;break}case"StyleDirective":{let c=this.hole(l.hole);i.push(`${JSON.stringify(l.name)}: ${c.code}`),a=a||c.reactive;break}case"BindDirective":n.push(...this.bindProps(l.name,this.hole(l.hole).code));break;case"UseDirective":{let c=l.name??(l.hole!=null?this.hole(l.hole).code:null);if(!c)break;s.push(l.name!=null&&l.hole!=null?`[${c}, () => (${this.hole(l.hole).code})]`:`[${c}]`);break}}return r.length>0&&n.push({name:"classList",kind:"attr",expr:`{ ${r.join(", ")} }`,reactive:o}),i.length>0&&n.push({name:"style",kind:"attr",expr:`{ ${i.join(", ")} }`,reactive:a}),s.length>0&&n.push({name:"use",kind:"attr",expr:`[${s.join(", ")}]`}),n}eventProp(e){let n=e.name.toLowerCase(),r=this.hole(e.hole).code;if(!(e.syntax==="colon"||e.modifiers.length>0))return{name:"on"+ne(e.name),kind:"event",event:{name:n,delegated:te.has(n)},expr:r};let i=this.wrapHandler(r,e.modifiers),a=this.eventOptions(e.modifiers),s=a?`[${i}, ${a}]`:i;return{name:"on:"+n,kind:"attr",expr:s}}wrapHandler(e,n){let r=n.includes("self")?"if (e.target !== e.currentTarget) return; ":"",o=[];return n.includes("prevent")&&o.push("e.preventDefault();"),n.includes("stop")&&o.push("e.stopPropagation();"),!r&&o.length===0?e:`(e) => { ${r}${o.join(" ")} return (${e})(e); }`}eventOptions(e){let n=[];return e.includes("capture")&&n.push("capture: true"),e.includes("once")&&n.push("once: true"),e.includes("passive")&&n.push("passive: true"),n.length?`{ ${n.join(", ")} }`:null}bindProps(e,n){let r=e==="checked",o=r?"change":"input",i=r?"checked":"value",a=`(${n})`;return[{name:e,kind:"attr",expr:`${a}[0]()`,reactive:!0},{name:"on"+ne(o),kind:"event",event:{name:o,delegated:te.has(o)},expr:`(e) => ${a}[1](e.target.${i})`}]}plainAttr(e){let n=e.value,r=e.name;e.name==="class"?r=n&&n.kind==="hole"&&this.hole(n.hole).object?"classList":"className":e.name==="html"&&(r="innerHTML");let i={name:r,kind:"attr"};if(n==null)return i.literal=!0,i;if(n.kind==="static")return i.literal=n.value,i;if(n.kind==="hole"){let l=this.hole(n.hole);return i.expr=l.code,i.reactive=l.reactive,i}let a=!1,s=n.parts.map(l=>{if("text"in l)return $e(l.text);let c=this.hole(l.hole);return a=a||c.reactive,"${"+c.code+"}"}).join("");return i.expr="`"+s+"`",i.reactive=a,i}};function re(t,e,n,r={}){let{root:o}=we(t,{svg:r.svg});return new O(e,n).lowerRoot(o.children)}function Te(t){let e=[],n=0;return t.statics.forEach((r,o)=>{if(e.push({kind:"static",text:r,start:n}),n+=r.length,o<t.holes.length){let i=n+t.holes[o].code.length;e.push({kind:"hole",index:o,start:n,end:i}),n=i}}),e}function ct(t,e={}){if(t.statics.length!==t.holes.length+1)throw new Error(`[fluixi] compileTemplate: ${t.statics.length} static runs for ${t.holes.length} holes — a template always has exactly one more.`);return Se(Te(t),t.holes,e)}function Se(t,e,n={}){let r=new Set,o=re(t,[...e],r,{svg:n.svg});D(o),H(o,{resolver:ee(n.resolve??[]),modules:{controlFlowModule:n.controlFlowModule??"@fluixi/dom",coreModule:n.coreModule??"@fluixi/core",routerModule:n.routerModule??"@fluixi/core/router-next"},strategyFor:l=>l.load}),F(o);let{code:i,imports:a,templates:s}=C.emit(o,{templateClone:n.templateClone,partialTemplates:n.partialTemplates});for(let l of a)r.add(l);return n.hoistTemplates?{code:i,imports:[...r],ir:o,templates:s}:{code:b(i,s),imports:[...r],ir:o}}export{Se as compilePieces,ct as compileTemplate};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var d=Object.defineProperty;var J=Object.getOwnPropertyDescriptor;var L=Object.getOwnPropertyNames;var C=Object.prototype.hasOwnProperty;var X=(e,t)=>{for(var n in t)d(e,n,{get:t[n],enumerable:!0})},A=(e,t,n,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of L(t))!C.call(e,r)&&r!==n&&d(e,r,{get:()=>t[r],enumerable:!(i=J(t,r))||i.enumerable});return e};var $=e=>A(d({},"__esModule",{value:!0}),e);var W={};X(W,{SVG_TAGS:()=>I,buildJsxIR:()=>z});module.exports=$(W);var T={kind:"eager"},D=["pointerdown","focusin","keydown"],E=new Set(["eager","idle","visible","interaction","media","never"]),c=class extends Error{};function f(e){return e.startsWith("load:")}function k(e,t){let n=e.slice(5);if(!E.has(n))throw new c(`Unknown load strategy 'load:${n}'. Expected one of ${[...E].join(", ")}.`);switch(n){case"eager":return T;case"idle":return{kind:"idle"};case"never":return{kind:"never"};case"visible":return t?{kind:"visible",rootMargin:t}:{kind:"visible"};case"interaction":return{kind:"interaction",events:t?P(t):[...D]};case"media":if(!t)throw new c(`'load:media' needs a query, e.g. load:media="(min-width: 1024px)".`);return{kind:"media",query:t};default:throw new c(`Unhandled load strategy '${n}'.`)}}function P(e){let t=e.split(/[\s,]+/).map(n=>n.trim()).filter(Boolean);if(t.length===0)throw new c("'load:interaction' was given no event names.");return t}var M="children";function m(e){switch(e.kind){case"call":return!0;case"member":return e.property!==M;case"compound":return e.parts.some(m);case"opaque":return!1}}var j=new Set(["CallExpression","OptionalCallExpression"]),q=new Set(["MemberExpression","OptionalMemberExpression"]);function y(e){if(!e)return{kind:"opaque"};if(j.has(e.type))return{kind:"call"};if(q.has(e.type)){let t=e.property;return{kind:"member",property:!(e.computed===!0)&&t?.type==="Identifier"?t.name:null}}return e.type==="ConditionalExpression"?{kind:"compound",parts:[e.test,e.consequent,e.alternate].map(l)}:e.type==="LogicalExpression"||e.type==="BinaryExpression"?{kind:"compound",parts:[e.left,e.right].map(l)}:e.type==="TemplateLiteral"?{kind:"compound",parts:e.expressions.map(l)}:e.type==="ObjectExpression"?{kind:"compound",parts:e.properties.filter(n=>(n.type==="ObjectProperty"||n.type==="Property")&&n.computed!==!0).map(n=>l(n.value))}:e.type==="ArrayExpression"?{kind:"compound",parts:e.elements.filter(n=>n!=null&&n.type!=="SpreadElement").map(l)}:{kind:"opaque"}}var l=e=>y(e);function O(e){switch(e.kind){case"event":return"event";case"ref":return"ref";case"spread":return"spread";case"class":case"style":return"class-or-style-directive";case"attr":case"prop":return e.reactive?"reactive-prop":e.expr!==void 0?"expression-prop":void 0;default:return"expression-prop"}}function v(e){let t=[],n=new Map,i=r=>{switch(r.kind){case"text":return!0;case"expr":return!1;case"component":case"control":for(let s of r.children)i(s);return!1;case"fragment":for(let s of r.children)i(s);return!1;case"element":{let s=!0;for(let a of r.children)i(a)||(s=!1);let o;for(let a of r.props)if(o=O(a),o)break;return!o&&!s&&(o=B(r)),r.static=!o,o?n.set(r,o):t.push(r),r.static}default:return!1}};for(let r of Array.isArray(e)?e:[e])i(r);return{staticElements:t,reasons:n}}function B(e){for(let t of e.children){if(t.kind==="expr")return"expression-child";if(t.kind==="component")return"component-child";if(t.kind==="control")return"control-child";if(t.kind==="element"&&!t.static||t.kind==="fragment")return"expression-child"}return"expression-child"}function S(e){let t=e.split(/\r\n|\n|\r/),n=0;for(let r=0;r<t.length;r++)/[^ \t]/.test(t[r])&&(n=r);let i="";for(let r=0;r<t.length;r++){let s=t[r].replace(/\t/g," ");r!==0&&(s=s.replace(/^ +/,"")),r!==t.length-1&&(s=s.replace(/ +$/,"")),s&&(r!==n&&(s+=" "),i+=s)}return i}var I=new Set(["svg","path","circle","rect","line","polygon","polyline","ellipse","g","defs","clipPath","text"]),G=/^on[A-Z]/,_=new Set(["click","dblclick","input","change","submit","focus","blur","keydown","keyup","keypress","mousedown","mouseup"]),b=e=>m(y(e));function u(e){if(e.type==="StringLiteral"||e.type==="NumericLiteral"||e.type==="BooleanLiteral"||e.type==="Literal"&&(typeof e.value=="string"||typeof e.value=="number"||typeof e.value=="boolean"))return e.value}var x=e=>!!e&&typeof u(e)=="string";function F(e,t){return e.type==="JSXIdentifier"?{tag:e.name,component:e.name[0]!==e.name[0].toLowerCase()}:e.type==="JSXMemberExpression"?{tag:t.code(e),component:!0}:e.type==="JSXNamespacedName"?{tag:`${e.namespace.name}:${e.name.name}`,component:!1}:{tag:"div",component:!1}}function g(e){return e.type==="JSXIdentifier"?e.name==="class"?"className":e.name:e.type==="JSXNamespacedName"?`${e.namespace.name}:${e.name.name}`:"unknown"}function K(e,t){let n=g(e.name),i=G.test(n),r=i||n.startsWith("on:")||n==="ref",o={name:n,kind:i?"event":"attr"};if(i){let p=n.slice(2).toLowerCase();o.event={name:p,delegated:_.has(p)}}let a=e.value;if(a==null)return o.literal=!0,o;if(x(a))return o.literal=u(a),o;if(a.type==="JSXExpressionContainer"&&a.expression?.type!=="JSXEmptyExpression"){let p=a.expression,h=u(p);return h!==void 0?(o.literal=h,o):(o.expr=t.code(p),o.reactive=r?!1:b(p),(p.type==="JSXElement"||p.type==="JSXFragment")&&(o.jsxElement=!0),o)}return o.literal=!0,o}function R(e,t){let n=e.value;return n==null?null:x(n)?JSON.stringify(u(n)):n.type==="JSXExpressionContainer"&&n.expression?.type!=="JSXEmptyExpression"?t.code(n.expression):null}function U(e,t){let n=[],i=[];for(let r of e){if(r.type==="JSXSpreadAttribute"){n.push({name:"",kind:"spread",expr:t.code(r.argument)});continue}if(r.type!=="JSXAttribute"||f(g(r.name)))continue;let s=r.name.type==="JSXNamespacedName"?r.name.namespace.name:null;if(s==="use"){let o=r.name.name.name;t.used.add(o);let a=R(r,t);i.push(a!=null?`[${o}, () => (${a})]`:`[${o}]`);continue}if(s==="oncapture"){let o=r.name.name.name.toLowerCase(),a=R(r,t)??"undefined";n.push({name:"on:"+o,kind:"attr",expr:`[${a}, { capture: true }]`});continue}n.push(K(r,t))}return i.length>0&&n.push({name:"use",kind:"attr",expr:`[${i.join(", ")}]`}),n}function N(e,t){let n=[];for(let i of e)if(i.type==="JSXText"){let r=S(i.value);r&&n.push({kind:"text",value:r})}else if(i.type==="JSXExpressionContainer"){if(i.expression?.type!=="JSXEmptyExpression"){let r=i.expression;n.push({kind:"expr",code:t.code(r),reactive:b(r)})}}else i.type==="JSXElement"||i.type==="JSXFragment"?n.push(w(i,t)):i.type==="JSXSpreadChild"&&n.push({kind:"expr",code:t.code(i.expression),reactive:!1});return n}function V(e){for(let t of e){if(t.type!=="JSXAttribute")continue;let n=g(t.name);if(f(n)){if(t.value&&!x(t.value))throw new c(`'${n}' needs a literal value, not an expression — the strategy is compile-time.`);return k(n,t.value?u(t.value):null)}}}function w(e,t){if(e.type==="JSXFragment")return{kind:"fragment",children:N(e.children,t)};let{tag:n,component:i}=F(e.openingElement.name,t),r=U(e.openingElement.attributes,t),s=N(e.children,t);if(i){let o=V(e.openingElement.attributes);return{kind:"component",name:n,props:r,children:s,...o?{load:o}:{}}}return{kind:"element",tag:n,svg:I.has(n),props:r,children:s,static:!1}}function z(e,t){let n=w(e,t);return v(n),n}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build IR from a JSX tree.
|
|
3
|
+
*
|
|
4
|
+
* Reads `node.type` rather than a parser's helpers, and asks the caller for the
|
|
5
|
+
* source of an expression through `code()` — a front-end that can slice the
|
|
6
|
+
* original text returns that, one that reprints returns the printed form. Either
|
|
7
|
+
* way the IR is the same, which is what keeps one builder for both.
|
|
8
|
+
*/
|
|
9
|
+
import type { IRNode } from '../ir/nodes.js';
|
|
10
|
+
interface Node {
|
|
11
|
+
type: string;
|
|
12
|
+
[key: string]: any;
|
|
13
|
+
}
|
|
14
|
+
export interface JsxContext {
|
|
15
|
+
/** The source of an expression node, with anything nested already compiled. */
|
|
16
|
+
code(node: Node): string;
|
|
17
|
+
/** Runtime symbols the emitted code needs; `use:` directives register here too. */
|
|
18
|
+
used: Set<string>;
|
|
19
|
+
}
|
|
20
|
+
export declare const SVG_TAGS: Set<string>;
|
|
21
|
+
/** Build IR from a JSXElement or JSXFragment. */
|
|
22
|
+
export declare function buildJsxIR(node: Node, ctx: JsxContext): IRNode;
|
|
23
|
+
export {};
|
|
24
|
+
//# sourceMappingURL=jsx.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsx.d.ts","sourceRoot":"","sources":["../../src/lower/jsx.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAkB,MAAM,EAAsB,MAAM,gBAAgB,CAAC;AAOjF,UAAU,IAAI;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,+EAA+E;IAC/E,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAAC;IACzB,mFAAmF;IACnF,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACnB;AAED,eAAO,MAAM,QAAQ,aAGnB,CAAC;AAsLH,iDAAiD;AACjD,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,GAAG,MAAM,CAM9D"}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { isLoadDirective, parseLoadDirective, LoadDirectiveError } from '../resolve/load-directive.js';
|
|
2
|
+
import { isReactiveShape } from '../analyze/reactive-expr.js';
|
|
3
|
+
import { shapeOf } from '../analyze/expr-shape.js';
|
|
4
|
+
import { analyzeStatic } from '../optimize/analyze-static.js';
|
|
5
|
+
import { cleanTemplateText } from './text.js';
|
|
6
|
+
export const SVG_TAGS = new Set([
|
|
7
|
+
'svg', 'path', 'circle', 'rect', 'line', 'polygon', 'polyline',
|
|
8
|
+
'ellipse', 'g', 'defs', 'clipPath', 'text',
|
|
9
|
+
]);
|
|
10
|
+
const EVENT_RE = /^on[A-Z]/;
|
|
11
|
+
const DELEGATED = new Set([
|
|
12
|
+
'click', 'dblclick', 'input', 'change', 'submit', 'focus', 'blur',
|
|
13
|
+
'keydown', 'keyup', 'keypress', 'mousedown', 'mouseup',
|
|
14
|
+
]);
|
|
15
|
+
const isReactive = (node) => isReactiveShape(shapeOf(node));
|
|
16
|
+
/** A literal value, or undefined when the node is not one. */
|
|
17
|
+
function literalOf(node) {
|
|
18
|
+
if (node.type === 'StringLiteral' || node.type === 'NumericLiteral' || node.type === 'BooleanLiteral') {
|
|
19
|
+
return node.value;
|
|
20
|
+
}
|
|
21
|
+
// ESTree spells all three `Literal`; regexes and null are not values we inline.
|
|
22
|
+
if (node.type === 'Literal' && (typeof node.value === 'string' || typeof node.value === 'number' || typeof node.value === 'boolean')) {
|
|
23
|
+
return node.value;
|
|
24
|
+
}
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
const isString = (node) => !!node && typeof literalOf(node) === 'string';
|
|
28
|
+
/** A capitalized / member / namespaced tag is a component. */
|
|
29
|
+
function tagInfo(name, ctx) {
|
|
30
|
+
if (name.type === 'JSXIdentifier') {
|
|
31
|
+
return { tag: name.name, component: name.name[0] !== name.name[0].toLowerCase() };
|
|
32
|
+
}
|
|
33
|
+
if (name.type === 'JSXMemberExpression')
|
|
34
|
+
return { tag: ctx.code(name), component: true };
|
|
35
|
+
if (name.type === 'JSXNamespacedName') {
|
|
36
|
+
return { tag: `${name.namespace.name}:${name.name.name}`, component: false };
|
|
37
|
+
}
|
|
38
|
+
return { tag: 'div', component: false };
|
|
39
|
+
}
|
|
40
|
+
function attrName(name) {
|
|
41
|
+
if (name.type === 'JSXIdentifier')
|
|
42
|
+
return name.name === 'class' ? 'className' : name.name;
|
|
43
|
+
if (name.type === 'JSXNamespacedName')
|
|
44
|
+
return `${name.namespace.name}:${name.name.name}`;
|
|
45
|
+
return 'unknown';
|
|
46
|
+
}
|
|
47
|
+
function buildAttr(attr, ctx) {
|
|
48
|
+
const name = attrName(attr.name);
|
|
49
|
+
const isEvent = EVENT_RE.test(name);
|
|
50
|
+
// on: reaches the runtime as a native listener; a handler, never reactive. `ref`
|
|
51
|
+
// joins them: the runtime CALLS it with the element, so a thunk gets called
|
|
52
|
+
// instead and the real ref never sees anything.
|
|
53
|
+
const isHandler = isEvent || name.startsWith('on:') || name === 'ref';
|
|
54
|
+
const kind = isEvent ? 'event' : 'attr';
|
|
55
|
+
const base = { name, kind };
|
|
56
|
+
if (isEvent) {
|
|
57
|
+
const evt = name.slice(2).toLowerCase();
|
|
58
|
+
base.event = { name: evt, delegated: DELEGATED.has(evt) };
|
|
59
|
+
}
|
|
60
|
+
const v = attr.value;
|
|
61
|
+
if (v == null) {
|
|
62
|
+
base.literal = true; // valueless attribute
|
|
63
|
+
return base;
|
|
64
|
+
}
|
|
65
|
+
if (isString(v)) {
|
|
66
|
+
base.literal = literalOf(v);
|
|
67
|
+
return base;
|
|
68
|
+
}
|
|
69
|
+
if (v.type === 'JSXExpressionContainer' && v.expression?.type !== 'JSXEmptyExpression') {
|
|
70
|
+
const expr = v.expression;
|
|
71
|
+
const literal = literalOf(expr);
|
|
72
|
+
if (literal !== undefined) {
|
|
73
|
+
base.literal = literal;
|
|
74
|
+
return base;
|
|
75
|
+
}
|
|
76
|
+
base.expr = ctx.code(expr);
|
|
77
|
+
base.reactive = isHandler ? false : isReactive(expr);
|
|
78
|
+
if (expr.type === 'JSXElement' || expr.type === 'JSXFragment')
|
|
79
|
+
base.jsxElement = true;
|
|
80
|
+
return base;
|
|
81
|
+
}
|
|
82
|
+
base.literal = true;
|
|
83
|
+
return base;
|
|
84
|
+
}
|
|
85
|
+
/** Attribute value as JS code, or null when valueless. */
|
|
86
|
+
function attrExprCode(attr, ctx) {
|
|
87
|
+
const v = attr.value;
|
|
88
|
+
if (v == null)
|
|
89
|
+
return null;
|
|
90
|
+
if (isString(v))
|
|
91
|
+
return JSON.stringify(literalOf(v));
|
|
92
|
+
if (v.type === 'JSXExpressionContainer' && v.expression?.type !== 'JSXEmptyExpression') {
|
|
93
|
+
return ctx.code(v.expression);
|
|
94
|
+
}
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
function buildProps(attrs, ctx) {
|
|
98
|
+
const props = [];
|
|
99
|
+
const usePairs = []; // use:name directives collapse into one `use` prop
|
|
100
|
+
for (const a of attrs) {
|
|
101
|
+
if (a.type === 'JSXSpreadAttribute') {
|
|
102
|
+
props.push({ name: '', kind: 'spread', expr: ctx.code(a.argument) });
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (a.type !== 'JSXAttribute')
|
|
106
|
+
continue;
|
|
107
|
+
// load: is a directive, not a prop — the resolve pass reads it off the node.
|
|
108
|
+
if (isLoadDirective(attrName(a.name)))
|
|
109
|
+
continue;
|
|
110
|
+
const ns = a.name.type === 'JSXNamespacedName' ? a.name.namespace.name : null;
|
|
111
|
+
// use:name / use:name={opts} -> [dir, () => opts]; dir is an in-scope fn
|
|
112
|
+
if (ns === 'use') {
|
|
113
|
+
const dir = a.name.name.name;
|
|
114
|
+
ctx.used.add(dir); // keep the import
|
|
115
|
+
const opts = attrExprCode(a, ctx);
|
|
116
|
+
// parens round the body so an object literal is not read as a block
|
|
117
|
+
usePairs.push(opts != null ? `[${dir}, () => (${opts})]` : `[${dir}]`);
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
// oncapture:name -> native on:name with { capture: true }
|
|
121
|
+
if (ns === 'oncapture') {
|
|
122
|
+
const evt = a.name.name.name.toLowerCase();
|
|
123
|
+
const h = attrExprCode(a, ctx) ?? 'undefined';
|
|
124
|
+
props.push({ name: 'on:' + evt, kind: 'attr', expr: `[${h}, { capture: true }]` });
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
props.push(buildAttr(a, ctx));
|
|
128
|
+
}
|
|
129
|
+
if (usePairs.length > 0)
|
|
130
|
+
props.push({ name: 'use', kind: 'attr', expr: `[${usePairs.join(', ')}]` });
|
|
131
|
+
return props;
|
|
132
|
+
}
|
|
133
|
+
function buildChildren(children, ctx) {
|
|
134
|
+
const out = [];
|
|
135
|
+
for (const child of children) {
|
|
136
|
+
if (child.type === 'JSXText') {
|
|
137
|
+
// Drop whitespace-only text spanning a newline so a lone child stays lone —
|
|
138
|
+
// an array insert will not reactively bind a memo/component inside it.
|
|
139
|
+
const text = cleanTemplateText(child.value);
|
|
140
|
+
if (text)
|
|
141
|
+
out.push({ kind: 'text', value: text });
|
|
142
|
+
}
|
|
143
|
+
else if (child.type === 'JSXExpressionContainer') {
|
|
144
|
+
if (child.expression?.type !== 'JSXEmptyExpression') {
|
|
145
|
+
const expr = child.expression;
|
|
146
|
+
out.push({ kind: 'expr', code: ctx.code(expr), reactive: isReactive(expr) });
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
else if (child.type === 'JSXElement' || child.type === 'JSXFragment') {
|
|
150
|
+
out.push(buildNode(child, ctx));
|
|
151
|
+
}
|
|
152
|
+
else if (child.type === 'JSXSpreadChild') {
|
|
153
|
+
out.push({ kind: 'expr', code: ctx.code(child.expression), reactive: false });
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return out;
|
|
157
|
+
}
|
|
158
|
+
/** The load: strategy written on a component tag, if any. */
|
|
159
|
+
function readLoad(attrs) {
|
|
160
|
+
for (const a of attrs) {
|
|
161
|
+
if (a.type !== 'JSXAttribute')
|
|
162
|
+
continue;
|
|
163
|
+
const name = attrName(a.name);
|
|
164
|
+
if (!isLoadDirective(name))
|
|
165
|
+
continue;
|
|
166
|
+
if (a.value && !isString(a.value)) {
|
|
167
|
+
throw new LoadDirectiveError(`'${name}' needs a literal value, not an expression — the strategy is compile-time.`);
|
|
168
|
+
}
|
|
169
|
+
return parseLoadDirective(name, a.value ? literalOf(a.value) : null);
|
|
170
|
+
}
|
|
171
|
+
return undefined;
|
|
172
|
+
}
|
|
173
|
+
function buildNode(node, ctx) {
|
|
174
|
+
if (node.type === 'JSXFragment') {
|
|
175
|
+
return { kind: 'fragment', children: buildChildren(node.children, ctx) };
|
|
176
|
+
}
|
|
177
|
+
const { tag, component } = tagInfo(node.openingElement.name, ctx);
|
|
178
|
+
const props = buildProps(node.openingElement.attributes, ctx);
|
|
179
|
+
const children = buildChildren(node.children, ctx);
|
|
180
|
+
if (component) {
|
|
181
|
+
const load = readLoad(node.openingElement.attributes);
|
|
182
|
+
return { kind: 'component', name: tag, props, children, ...(load ? { load } : {}) };
|
|
183
|
+
}
|
|
184
|
+
return { kind: 'element', tag, svg: SVG_TAGS.has(tag), props, children, static: false };
|
|
185
|
+
}
|
|
186
|
+
/** Build IR from a JSXElement or JSXFragment. */
|
|
187
|
+
export function buildJsxIR(node, ctx) {
|
|
188
|
+
const ir = buildNode(node, ctx);
|
|
189
|
+
// `static` is a property of a whole subtree, so one pass decides it rather than
|
|
190
|
+
// each node at construction.
|
|
191
|
+
analyzeStatic(ir);
|
|
192
|
+
return ir;
|
|
193
|
+
}
|