Comparing version
@@ -5,7 +5,8 @@ #!/usr/bin/env node | ||
import c from "path"; | ||
import { compile as y, inferModes as S, transformJSX as v } from "./compiler.js"; | ||
import { optimize as w, optimizeStrings as x, optimizeFunctions as C } from "./optimizer.js"; | ||
import { createServer as h, build as j } from "vite"; | ||
import { compile as y } from "./compiler.js"; | ||
import { optimize as S, optimizeStrings as v, optimizeFunctions as w } from "./optimizer.js"; | ||
import { createServer as x, build as C } from "vite"; | ||
import p from "./vite.js"; | ||
import { execSync as m } from "child_process"; | ||
import { i as h, t as j } from "./modes-kS_CsyZ5.js"; | ||
const o = { | ||
@@ -56,15 +57,15 @@ pattern: (t) => `${t} <file>`, | ||
e.command("dev").action(async () => { | ||
const t = await h({ plugins: [p()] }); | ||
const t = await x({ plugins: [p()] }); | ||
await t.listen(), t.printUrls(), t.bindCLIShortcuts({ print: !0 }); | ||
}); | ||
e.command("bundle").option("-m, --minify <boolean>", "Minify the chunks", !0).action(async (t) => { | ||
await j({ plugins: [p()], build: { minify: t.minify } }); | ||
await C({ plugins: [p()], build: { minify: t.minify } }); | ||
}); | ||
e.command(o.pattern("compile")).action(o.wrap((t, n) => y(t, n))); | ||
e.command(o.pattern("compile:modes")).action(o.wrap((t, n) => S(t, n))); | ||
e.command(o.pattern("compile:jsx")).action(o.wrap((t) => v(t).code)); | ||
e.command(o.pattern("optimize")).action(o.wrap((t) => w(t).code)); | ||
e.command(o.pattern("optimize:strings")).action(o.wrap((t) => x(t).code)); | ||
e.command(o.pattern("optimize:functions")).action(o.wrap((t) => C(t).code)); | ||
e.command(o.pattern("compile:modes")).action(o.wrap((t, n) => h(t, n))); | ||
e.command(o.pattern("compile:jsx")).action(o.wrap((t) => j(t).code)); | ||
e.command(o.pattern("optimize")).action(o.wrap((t) => S(t).code)); | ||
e.command(o.pattern("optimize:strings")).action(o.wrap((t) => v(t).code)); | ||
e.command(o.pattern("optimize:functions")).action(o.wrap((t) => w(t).code)); | ||
e.name("battuta").description("CLI tool for battuta").version("0.0.0"); | ||
e.parse(process.argv); |
@@ -1,432 +0,9 @@ | ||
import O from "@babel/parser"; | ||
import j from "@babel/generator"; | ||
import G from "@babel/traverse"; | ||
import * as t from "@babel/types"; | ||
import { Project as K, SyntaxKind as F } from "ts-morph"; | ||
import T from "crypto"; | ||
const I = { | ||
filter: !0, | ||
defs: !0, | ||
altGlyph: !0, | ||
altGlyphDef: !0, | ||
altGlyphItem: !0, | ||
animate: !0, | ||
animateColor: !0, | ||
animateMotion: !0, | ||
animateTransform: !0, | ||
animation: !0, | ||
circle: !0, | ||
clipPath: !0, | ||
"color-profile": !0, | ||
cursor: !0, | ||
desc: !0, | ||
discard: !0, | ||
ellipse: !0, | ||
feBlend: !0, | ||
feColorMatrix: !0, | ||
feComponentTransfer: !0, | ||
feComposite: !0, | ||
feConvolveMatrix: !0, | ||
feDiffuseLighting: !0, | ||
feDisplacementMap: !0, | ||
feDistantLight: !0, | ||
feDropShadow: !0, | ||
feFlood: !0, | ||
feFuncA: !0, | ||
feFuncB: !0, | ||
feFuncG: !0, | ||
feFuncR: !0, | ||
feGaussianBlur: !0, | ||
feImage: !0, | ||
feMerge: !0, | ||
feMergeNode: !0, | ||
feMorphology: !0, | ||
feOffset: !0, | ||
fePointLight: !0, | ||
feSpecularLighting: !0, | ||
feSpotLight: !0, | ||
feTile: !0, | ||
feTurbulence: !0, | ||
font: !0, | ||
"font-face": !0, | ||
"font-face-format": !0, | ||
"font-face-name": !0, | ||
"font-face-src": !0, | ||
"font-face-uri": !0, | ||
foreignObject: !0, | ||
g: !0, | ||
glyph: !0, | ||
glyphRef: !0, | ||
handler: !0, | ||
hkern: !0, | ||
image: !0, | ||
line: !0, | ||
linearGradient: !0, | ||
listener: !0, | ||
marker: !0, | ||
mask: !0, | ||
metadata: !0, | ||
"missing-glyph": !0, | ||
mpath: !0, | ||
path: !0, | ||
pattern: !0, | ||
polygon: !0, | ||
polyline: !0, | ||
prefetch: !0, | ||
radialGradient: !0, | ||
rect: !0, | ||
set: !0, | ||
solidColor: !0, | ||
stop: !0, | ||
switch: !0, | ||
symbol: !0, | ||
tbreak: !0, | ||
text: !0, | ||
textArea: !0, | ||
textPath: !0, | ||
tref: !0, | ||
tspan: !0, | ||
unknown: !0, | ||
use: !0, | ||
view: !0, | ||
vkern: !0 | ||
}, M = { | ||
...I, | ||
a: !0, | ||
abbr: !0, | ||
address: !0, | ||
area: !0, | ||
article: !0, | ||
aside: !0, | ||
audio: !0, | ||
b: !0, | ||
base: !0, | ||
bdi: !0, | ||
bdo: !0, | ||
blockquote: !0, | ||
body: !0, | ||
br: !0, | ||
button: !0, | ||
canvas: !0, | ||
caption: !0, | ||
cite: !0, | ||
code: !0, | ||
col: !0, | ||
colgroup: !0, | ||
data: !0, | ||
datalist: !0, | ||
dd: !0, | ||
del: !0, | ||
details: !0, | ||
dfn: !0, | ||
dialog: !0, | ||
div: !0, | ||
dl: !0, | ||
dt: !0, | ||
em: !0, | ||
embed: !0, | ||
fieldset: !0, | ||
figcaption: !0, | ||
figure: !0, | ||
footer: !0, | ||
form: !0, | ||
h1: !0, | ||
h2: !0, | ||
h3: !0, | ||
h4: !0, | ||
h5: !0, | ||
h6: !0, | ||
head: !0, | ||
header: !0, | ||
hgroup: !0, | ||
hr: !0, | ||
html: !0, | ||
i: !0, | ||
iframe: !0, | ||
img: !0, | ||
input: !0, | ||
ins: !0, | ||
kbd: !0, | ||
label: !0, | ||
legend: !0, | ||
li: !0, | ||
link: !0, | ||
main: !0, | ||
map: !0, | ||
mark: !0, | ||
math: !0, | ||
menu: !0, | ||
menuitem: !0, | ||
meta: !0, | ||
meter: !0, | ||
nav: !0, | ||
noscript: !0, | ||
object: !0, | ||
ol: !0, | ||
optgroup: !0, | ||
option: !0, | ||
output: !0, | ||
p: !0, | ||
param: !0, | ||
picture: !0, | ||
pre: !0, | ||
progress: !0, | ||
q: !0, | ||
rb: !0, | ||
rp: !0, | ||
rt: !0, | ||
rtc: !0, | ||
ruby: !0, | ||
s: !0, | ||
samp: !0, | ||
script: !0, | ||
search: !0, | ||
section: !0, | ||
select: !0, | ||
slot: !0, | ||
small: !0, | ||
source: !0, | ||
span: !0, | ||
strong: !0, | ||
style: !0, | ||
sub: !0, | ||
summary: !0, | ||
sup: !0, | ||
svg: !0, | ||
table: !0, | ||
tbody: !0, | ||
td: !0, | ||
template: !0, | ||
textarea: !0, | ||
tfoot: !0, | ||
th: !0, | ||
thead: !0, | ||
time: !0, | ||
title: !0, | ||
tr: !0, | ||
track: !0, | ||
u: !0, | ||
ul: !0, | ||
var: !0, | ||
video: !0, | ||
wbr: !0 | ||
}, v = G.default, _ = j.default; | ||
function H(e) { | ||
const r = O.parse(e, { | ||
sourceType: "module", | ||
plugins: ["jsx", "typescript", "decorators"] | ||
}); | ||
return v(r, { | ||
JSXElement: (a) => { | ||
a.replaceWith(S(a.node) || t.nullLiteral()); | ||
}, | ||
JSXFragment: (a) => { | ||
a.replaceWith(S(a.node) || t.nullLiteral()); | ||
} | ||
}), g(r, "createElement", "battuta/dom"), g(r, "createSVGElement", "battuta/dom"), g(r, "create", "battuta/runtime"), g(r, "assign", "battuta/runtime"), g(r, "set", "battuta/runtime"), g(r, "call", "battuta/runtime"), g(r, "append", "battuta/runtime"), _(r, {}, e); | ||
import { i, t as n } from "./modes-kS_CsyZ5.js"; | ||
function m(r, t) { | ||
return r = i(r, t), r = n(r).code, r; | ||
} | ||
function S(e) { | ||
var h, b, $, C; | ||
let r = "$d"; | ||
const a = () => e.children.map((f) => R(f, r)).filter(Boolean); | ||
if (e.type == "JSXFragment") return t.arrayExpression(a()); | ||
const i = e.openingElement; | ||
let u = ""; | ||
switch (i.name.type) { | ||
case "JSXIdentifier": | ||
u = i.name.name; | ||
break; | ||
case "JSXNamespacedName": | ||
u = i.name.name.name; | ||
break; | ||
case "JSXMemberExpression": | ||
u = i.name.object.name + "." + i.name.property.name; | ||
break; | ||
} | ||
const s = (b = (h = i.attributes.find((f) => f.type === "JSXAttribute" && f.name.type == "JSXIdentifier" && W[f.name.name])) == null ? void 0 : h.name) == null ? void 0 : b.name; | ||
s && (r = s); | ||
const o = a(), c = M[u], x = I[u], m = i.attributes.map((f) => V(f)).filter(Boolean); | ||
if (c) | ||
return P(o, A(m, t.callExpression(t.identifier(p(x ? "createSVGElement" : "createElement")), [t.stringLiteral(u)]))); | ||
if (r === "$c") { | ||
const w = (($ = m.find(({ | ||
key: n | ||
}) => n[0].type == "StringLiteral" && n[0].value == "$c")) == null ? void 0 : $.value).elements.map((n) => n.elements.map((l) => l.value)), L = m.reduce((n, l) => (l.key.length > 1 || (n[l.key[0].value] = l.value), n), {}), J = w.map((n) => n.map((l) => L[l])), d = J.sort((n, l) => l.filter(Boolean).length - n.filter(Boolean).length)[0], X = d.findLastIndex(Boolean), k = d.slice(0, X + 1), N = w[J.indexOf(d)]; | ||
return P(o, A(m.filter((n) => n.key.length > 1 || !N.includes(n.key[0].value)), t.callExpression(t.memberExpression(t.identifier(u), t.identifier(p("create")), !0), k.map((n) => n || t.identifier("undefined"))))); | ||
} | ||
if (r === "$f") { | ||
const w = ((C = m.find(({ | ||
key: n | ||
}) => n[0].type == "StringLiteral" && n[0].value == "$f")) == null ? void 0 : C.value).elements.map((n) => n.elements.map((l) => l.value)), L = m.reduce((n, l) => (l.key.length > 1 || (n[l.key[0].value] = l.value), n), {}), J = w.map((n) => n.map((l) => L[l])), d = J.sort((n, l) => l.filter(Boolean).length - n.filter(Boolean).length)[0], X = d.findLastIndex(Boolean), k = d.slice(0, X + 1), N = w[J.indexOf(d)]; | ||
return A(m.filter((n) => n.key.length > 1 || !N.includes(n.key[0].value)), t.callExpression(t.identifier(u), k.map((n) => n || t.identifier("undefined")))); | ||
} | ||
return t.callExpression(t.identifier(u), [t.objectExpression([...m.map(({ | ||
key: f, | ||
value: E | ||
}) => ["StringLiteral", "BooleanLiteral"].includes(E.type) ? t.objectProperty(t.stringLiteral(B(...f)), E) : t.objectMethod("get", t.identifier(B(...f)), [], t.blockStatement([t.returnStatement(E)]))), t.objectProperty(t.stringLiteral("children"), t.arrowFunctionExpression([t.identifier("_")], t.arrayExpression(o)))])]); | ||
} | ||
function A(e, r) { | ||
return e.reduce((a, { | ||
key: i, | ||
value: u | ||
}) => { | ||
switch (!0) { | ||
case (i[0].type == "StringLiteral" && ["$", "$c", "$d", "$f", "$n"].includes(i[0].value)): | ||
return a; | ||
case ["StringLiteral", "BooleanLiteral"].includes(u.type): | ||
return t.callExpression(t.memberExpression(a, t.identifier(p("set")), !0), [u, ...i]); | ||
case (u.type == "CallExpression" && u.callee.type == "Identifier" && u.callee.name == "$call"): | ||
return t.callExpression(t.memberExpression(a, t.identifier(p("call")), !0), [t.arrowFunctionExpression([t.identifier("_")], t.arrayExpression(u.arguments)), ...i]); | ||
default: | ||
return t.callExpression(t.memberExpression(a, t.identifier(p("assign")), !0), [t.arrowFunctionExpression([t.identifier("_")], u), ...i]); | ||
} | ||
}, r); | ||
} | ||
function P(e, r) { | ||
return !e || e.length == 0 ? r : t.callExpression(t.memberExpression(r, t.identifier(p("append")), !0), e); | ||
} | ||
function R(e, r) { | ||
var a, i; | ||
switch (e.type) { | ||
case "JSXElement": | ||
return S(e); | ||
case "JSXText": { | ||
const u = (i = (a = e.value) == null ? void 0 : a.trim) == null ? void 0 : i.call(a); | ||
return u ? t.stringLiteral(u) : void 0; | ||
} | ||
case "JSXExpressionContainer": | ||
switch (e.expression.type) { | ||
case "JSXEmptyExpression": | ||
return; | ||
default: | ||
return ["$f", "$n"].includes(r) ? e.expression : t.arrowFunctionExpression([t.identifier("_")], e.expression); | ||
} | ||
case "JSXFragment": | ||
return S(e); | ||
case "JSXSpreadChild": | ||
return; | ||
default: | ||
return; | ||
} | ||
} | ||
function V(e, r) { | ||
switch (e.type) { | ||
case "JSXAttribute": { | ||
const a = z(e.value); | ||
return a ? { | ||
key: q(e.name), | ||
value: a | ||
} : void 0; | ||
} | ||
case "JSXSpreadAttribute": | ||
return; | ||
default: | ||
return; | ||
} | ||
} | ||
function q(e) { | ||
switch (e == null ? void 0 : e.type) { | ||
case "JSXIdentifier": | ||
return [t.stringLiteral(e.name)]; | ||
case "JSXNamespacedName": | ||
return [t.stringLiteral(e.namespace.name), t.stringLiteral(e.name.name)]; | ||
} | ||
} | ||
function z(e, r) { | ||
switch (e == null ? void 0 : e.type) { | ||
case "JSXElement": | ||
return S(e); | ||
case "JSXExpressionContainer": | ||
switch (e.expression.type) { | ||
case "JSXEmptyExpression": | ||
return; | ||
default: | ||
return e.expression; | ||
} | ||
case "StringLiteral": | ||
return e; | ||
case "JSXFragment": | ||
return S(e); | ||
case void 0: | ||
return t.booleanLiteral(!0); | ||
} | ||
} | ||
function B(...e) { | ||
return e.map((r) => r.value).join(":"); | ||
} | ||
function g(e, r, a) { | ||
let i = !1; | ||
const u = p(r); | ||
v(e, { | ||
ImportDeclaration(s) { | ||
const { | ||
node: o | ||
} = s; | ||
o.specifiers.some((c) => t.isImportSpecifier(c) && c.local.name === u && c.imported.name === r) && (i = !0); | ||
} | ||
}), i || e.program.body.unshift(t.importDeclaration([t.importSpecifier(t.identifier(u), t.identifier(r))], t.stringLiteral(a))); | ||
} | ||
function p(e) { | ||
return `$btt_${e}`; | ||
} | ||
const W = { | ||
$d: !0, | ||
$c: !0, | ||
$f: !0 | ||
}, D = new K({}), y = {}; | ||
function Q(e, r) { | ||
if (y[r]) { | ||
const s = y[r].hash; | ||
if (T.createHash("md5").update(e).digest("hex") != s) | ||
D.removeSourceFile(y[r].file), delete y[r]; | ||
else | ||
return y[r].result; | ||
} | ||
const a = D.addSourceFileAtPath(r), i = []; | ||
a.getDescendantsOfKind(F.JsxElement).forEach((s) => i.push(s.getOpeningElement())), a.getDescendantsOfKind(F.JsxSelfClosingElement).forEach((s) => i.push(s)), i.forEach((s) => { | ||
const o = U(s); | ||
o && s.insertAttribute(0, o); | ||
}); | ||
const u = a.print(); | ||
return y[r] = { | ||
hash: T.createHash("md5").update(e).digest("hex"), | ||
file: a, | ||
result: u | ||
}, u; | ||
} | ||
function U(e) { | ||
const r = e.getTagNameNode(); | ||
if (M[r.getText()] || e.getAttribute("$f") || e.getAttribute("$d") || e.getAttribute("$c")) return; | ||
const a = r.getType(), i = a.getConstructSignatures(); | ||
if (i.length > 0) { | ||
const s = i.map( | ||
(o) => o.getParameters().map( | ||
(c) => c.getName() | ||
) | ||
); | ||
return { name: "$c", initializer: `{${JSON.stringify(s)}}` }; | ||
} | ||
const u = a.getCallSignatures(); | ||
if (u.length > 0) { | ||
const s = `{${JSON.stringify(u.map( | ||
(o) => o.getParameters().map( | ||
(c) => c.getName() | ||
) | ||
))}}`; | ||
if (u.some((o) => o.getParameters().length > 1)) return { name: "$f", initializer: s }; | ||
if (u.some((o) => o.getParameters().some((c) => !c.getDeclaredType().isObject() && !c.getDeclaredType().isAny()))) return { name: "$f", initializer: s }; | ||
if (u.some((o) => o.getParameters().some((c) => { | ||
const x = c.getDeclaredType(), m = x.getSymbol(), h = m == null ? void 0 : m.getDeclarations(), b = h == null ? void 0 : h.filter(($) => $.getKindName() === "ClassDeclaration"); | ||
return x.isArray() || x.isClass() || !!(b != null && b.length); | ||
}))) return { name: "$f", initializer: s }; | ||
} | ||
return { name: "$d" }; | ||
} | ||
function ne(e, r) { | ||
return e = Q(e, r), e = H(e).code, e; | ||
} | ||
export { | ||
ne as compile, | ||
Q as inferModes, | ||
H as transformJSX | ||
m as compile, | ||
i as inferModes, | ||
n as transformJSX | ||
}; |
import { MacroContext } from 'unplugin-macros'; | ||
export declare function css(this: any, css: TemplateStringsArray, ..._args: any[]): Record<string, string>; | ||
export { MacroContext } | ||
@@ -6,0 +4,0 @@ |
@@ -1,36 +0,1 @@ | ||
import c from "fs"; | ||
import u from "path"; | ||
import p from "postcss"; | ||
const l = { BASE_URL: "/", DEV: !1, MODE: "production", PROD: !0, SSR: !1 }; | ||
function h(a, ...g) { | ||
const m = this, t = {}, o = p.parse(a); | ||
o.walkRules((e) => { | ||
e.selectors = e.selectors.map((r) => r.replace(/\.[\w-]+/g, (n) => { | ||
const s = n.slice(1); | ||
return t[s] ?? (t[s] = d()), "." + t[s]; | ||
})); | ||
}); | ||
const i = o.toString(); | ||
if (l) { | ||
const e = ".temp", r = `${f()}.css`, n = u.join(process.cwd(), e, r); | ||
return c.mkdirSync(u.dirname(n), { recursive: !0 }), c.writeFileSync(n, i, "utf8"), m.magicString.prepend(`import '/${e}/${r}'; | ||
`), new String(`(${JSON.stringify(t)})`); | ||
} else | ||
return new String(` | ||
(() => { | ||
const style = document.createElement("style"); | ||
style.innerHTML = ${JSON.stringify(i)}; | ||
document.head.appendChild(style); | ||
return ${JSON.stringify(t)}; | ||
})(); | ||
`); | ||
} | ||
function d() { | ||
return "cls-" + Math.random().toString(36).substr(2, 8); | ||
} | ||
function f() { | ||
return "style-" + Math.random().toString(36).substr(2, 8); | ||
} | ||
export { | ||
h as css | ||
}; | ||
@@ -12,6 +12,6 @@ import { parse as S } from "@babel/parser"; | ||
function u(e) { | ||
var g, P, b, k; | ||
const i = (g = e.parentPath) == null ? void 0 : g.node; | ||
if (!n.isFunction(i)) return; | ||
const r = e.scope, t = []; | ||
var h, P, b, k; | ||
const r = (h = e.parentPath) == null ? void 0 : h.node; | ||
if (!n.isFunction(r)) return; | ||
const i = e.scope, t = []; | ||
e.parentPath.traverse({ | ||
@@ -30,3 +30,3 @@ ReferencedIdentifier(s) { | ||
} | ||
}), t.every((s) => y.hasOwnBinding(s) || r.hasOwnBinding(s)); | ||
}), t.every((s) => y.hasOwnBinding(s) || i.hasOwnBinding(s)); | ||
let d = e.parentPath; | ||
@@ -36,6 +36,6 @@ function v() { | ||
if (w != s) | ||
return !(!s || t.some((l) => { | ||
return !(!s || t.some((m) => { | ||
var B; | ||
return ((B = w == null ? void 0 : w.scope) == null ? void 0 : B.hasOwnBinding(l)) && !r.hasOwnBinding(l); | ||
}) || !t.every((l) => s.scope.hasBinding(l) || r.hasOwnBinding(l) || I[l])); | ||
return ((B = w == null ? void 0 : w.scope) == null ? void 0 : B.hasOwnBinding(m)) && !i.hasOwnBinding(m); | ||
}) || !t.every((m) => s.scope.hasBinding(m) || i.hasOwnBinding(m) || I[m])); | ||
} | ||
@@ -51,13 +51,13 @@ for (; v(); ) | ||
} | ||
function m({ | ||
function l({ | ||
blockPath: e, | ||
path: i | ||
path: r | ||
}) { | ||
var d, v, f, p, g, P, b, k, s; | ||
const r = F(), t = (d = i.parentPath) == null ? void 0 : d.node; | ||
var d, v, f, p, h, P, b, k, s; | ||
const i = F(), t = (d = r.parentPath) == null ? void 0 : d.node; | ||
switch (t.type) { | ||
case "ArrowFunctionExpression": { | ||
(v = i.parentPath) == null || v.replaceWith(n.identifier(r)), e.unshiftContainer("body", n.variableDeclaration("const", [ | ||
(v = r.parentPath) == null || v.replaceWith(n.identifier(i)), e.unshiftContainer("body", n.variableDeclaration("const", [ | ||
n.variableDeclarator( | ||
n.identifier(r), | ||
n.identifier(i), | ||
t | ||
@@ -70,5 +70,5 @@ ) | ||
if (t.key.type == "Identifier" && t.key.name == "constructor") return; | ||
(f = i.parentPath) == null || f.replaceWith(n.classProperty( | ||
(f = r.parentPath) == null || f.replaceWith(n.classProperty( | ||
t.key, | ||
n.identifier(r), | ||
n.identifier(i), | ||
void 0, | ||
@@ -79,3 +79,3 @@ t.decorators, | ||
)), e.unshiftContainer("body", n.functionDeclaration( | ||
n.identifier(r), | ||
n.identifier(i), | ||
t.params, | ||
@@ -90,9 +90,9 @@ t.body, | ||
if (t.key.id.name == "constructor") return; | ||
(p = i.parentPath) == null || p.replaceWith(n.classPrivateProperty( | ||
(p = r.parentPath) == null || p.replaceWith(n.classPrivateProperty( | ||
t.key, | ||
n.identifier(r), | ||
n.identifier(i), | ||
t.decorators, | ||
t.static | ||
)), e.unshiftContainer("body", n.functionDeclaration( | ||
n.identifier(r), | ||
n.identifier(i), | ||
t.params, | ||
@@ -106,4 +106,4 @@ t.body, | ||
case "FunctionDeclaration": { | ||
(g = i.parentPath) == null || g.replaceWith(n.identifier(r)), (P = t.id) != null && P.name && i.parentPath.scope.rename((b = t.id) == null ? void 0 : b.name, r), e.unshiftContainer("body", n.functionDeclaration( | ||
n.identifier(r), | ||
(h = r.parentPath) == null || h.replaceWith(n.identifier(i)), (P = t.id) != null && P.name && r.parentPath.scope.rename((b = t.id) == null ? void 0 : b.name, i), e.unshiftContainer("body", n.functionDeclaration( | ||
n.identifier(i), | ||
t.params, | ||
@@ -117,4 +117,4 @@ t.body, | ||
case "FunctionExpression": { | ||
(k = i.parentPath) == null || k.replaceWith(n.identifier(r)), e.unshiftContainer("body", n.functionDeclaration( | ||
n.identifier(r), | ||
(k = r.parentPath) == null || k.replaceWith(n.identifier(i)), e.unshiftContainer("body", n.functionDeclaration( | ||
n.identifier(i), | ||
t.params, | ||
@@ -128,5 +128,5 @@ t.body, | ||
case "ObjectMethod": { | ||
(s = i.parentPath) == null || s.replaceWith(n.objectProperty( | ||
(s = r.parentPath) == null || s.replaceWith(n.objectProperty( | ||
t.key, | ||
n.identifier(r), | ||
n.identifier(i), | ||
t.computed, | ||
@@ -136,3 +136,3 @@ void 0, | ||
)), e.unshiftContainer("body", n.functionDeclaration( | ||
n.identifier(r), | ||
n.identifier(i), | ||
t.params, | ||
@@ -154,10 +154,10 @@ t.body, | ||
Function(e) { | ||
const i = e.node; | ||
i.type == "ObjectMethod" && ["get", "set"].includes(i.kind) || u(e.get("body")); | ||
const r = e.node; | ||
r.type == "ObjectMethod" && ["get", "set"].includes(r.kind) || u(e.get("body")); | ||
} | ||
}), o.forEach(m); | ||
const h = W(a, {}, c); | ||
}), o.forEach(l); | ||
const g = W(a, {}, c); | ||
return { | ||
code: h.code, | ||
map: h.map | ||
code: g.code, | ||
map: g.map | ||
}; | ||
@@ -182,3 +182,4 @@ } | ||
}), o = {}, u = (e) => { | ||
e in o ? o[e].count++ : o[e] = { count: 1, name: A(e) }; | ||
var r; | ||
(r = o[e]) != null && r.count ? o[e].count++ : o[e] = { count: 1, name: A(e) }; | ||
}; | ||
@@ -190,12 +191,13 @@ D(a, { | ||
ObjectProperty(e) { | ||
const i = e.node.key; | ||
i.type === "Identifier" && u(i.name); | ||
if (e.node.computed) return; | ||
const r = e.node.key; | ||
r.type === "Identifier" && u(r.name); | ||
} | ||
}); | ||
const m = []; | ||
for (const [e, { count: i, name: r }] of Object.entries(o)) | ||
i > 1 && m.push( | ||
const l = []; | ||
for (const [e, { count: r, name: i }] of Object.entries(o)) | ||
r > 1 && l.push( | ||
n.variableDeclaration("const", [ | ||
n.variableDeclarator( | ||
n.identifier(r), | ||
n.identifier(i), | ||
n.stringLiteral(e) | ||
@@ -205,18 +207,19 @@ ) | ||
); | ||
const y = (e, i, r) => { | ||
e in o && o[e].count > 1 && i.replaceWith(r(o[e].name, i)); | ||
const y = (e, r, i) => { | ||
e in o && o[e].count > 1 && r.replaceWith(i(o[e].name, r)); | ||
}; | ||
m.length > 0 && (D(a, { | ||
l.length > 0 && (D(a, { | ||
StringLiteral(e) { | ||
y(e.node.value, e, (i, r) => (r.parent.type == "ObjectProperty" && r.parent.key == r.node && (r.parent.computed = !0), n.identifier(i))); | ||
y(e.node.value, e, (r, i) => (i.parent.type == "ObjectProperty" && i.parent.key == i.node && (i.parent.computed = !0), n.identifier(r))); | ||
}, | ||
ObjectProperty(e) { | ||
const i = e.node.key; | ||
i.type === "Identifier" && y(i.name, e, (r) => n.objectProperty(n.identifier(r), e.node.value, !0)); | ||
if (e.node.computed) return; | ||
const r = e.node.key; | ||
r.type === "Identifier" && y(r.name, e, (i) => n.objectProperty(n.identifier(i), e.node.value, !0)); | ||
} | ||
}), a.program.body.unshift(...m)); | ||
const h = L(a, {}, c); | ||
}), a.program.body.unshift(...l)); | ||
const g = L(a, {}, c); | ||
return { | ||
code: h.code, | ||
map: h.map | ||
code: g.code, | ||
map: g.map | ||
}; | ||
@@ -223,0 +226,0 @@ } |
@@ -1,39 +0,41 @@ | ||
import { currentContext as x, contextStack as j } from "./contexts.js"; | ||
import { useEffect as y } from "./signals.js"; | ||
const b = Symbol("insert"), w = Symbol("append"), A = Symbol("assign"), I = Symbol("set"), R = Symbol("create"), S = Symbol("listeners"), d = Symbol("on"), O = Symbol("childrenIndex"), C = Symbol("remove"), r = Symbol("context"), E = Symbol("call"), T = Symbol("empty"), g = Symbol("parent"), f = Symbol("cleanup"), c = Object.prototype; | ||
c[O] = function() { | ||
import { currentContext as x, contextStack as w } from "./contexts.js"; | ||
import { useEffect as v } from "./signals.js"; | ||
const b = Symbol("insert"), O = Symbol("append"), I = Symbol("assign"), R = Symbol("set"), E = Symbol("create"), a = Symbol("listeners"), y = Symbol("on"), S = Symbol("childrenIndex"), A = Symbol("remove"), r = Symbol("context"), g = Symbol("call"), P = Symbol("empty"), q = Symbol("parent"), p = Symbol("cleanup"), e = Object.prototype; | ||
e[S] = function() { | ||
return -1; | ||
}; | ||
c[b] = function() { | ||
e[b] = function() { | ||
return this; | ||
}; | ||
c[R] = function(...t) { | ||
e[P] = function() { | ||
}; | ||
e[E] = function(...t) { | ||
return Reflect.construct(this, t); | ||
}; | ||
c[w] = function(...t) { | ||
return p(this, t, this), this; | ||
e[O] = function(...t) { | ||
return m(this, t, this), this; | ||
}; | ||
c[f] = function(t) { | ||
const o = this[S], n = o.cleanup, s = !!this[C]; | ||
if (n) for (const l of n) l(s); | ||
delete o.cleanup, !t && s && this[C](); | ||
e[p] = function(t) { | ||
const o = this[a], n = o.cleanup, c = !!this[A]; | ||
if (n) for (const i of n) i(c); | ||
delete o.cleanup, !t && c && this[A](); | ||
}; | ||
c[d] = function(t, o) { | ||
const n = this[S]; | ||
e[y] = function(t, o) { | ||
const n = this[a]; | ||
return n[t] ?? (n[t] = []), n[t].push(o), this; | ||
}; | ||
c[I] = function(t, ...o) { | ||
e[R] = function(t, ...o) { | ||
const n = o.pop(); | ||
return a(this, o)[n] = t, this; | ||
return j(this, o)[n] = t, this; | ||
}; | ||
c[A] = function(t, ...o) { | ||
const n = o.pop(), s = a(this, o); | ||
return y(() => s[n] = t()), this; | ||
e[I] = function(t, ...o) { | ||
const n = o.pop(), c = j(this, o); | ||
return v(() => c[n] = t()), this; | ||
}; | ||
c[E] = function(t, ...o) { | ||
const n = o.pop(), s = a(this, o), l = s[n].bind(s); | ||
return y(() => l(...t())), this; | ||
e[g] = function(t, ...o) { | ||
const n = o.pop(), c = j(this, o), i = c[n].bind(c); | ||
return v(() => i(...t())), this; | ||
}; | ||
const h = Symbol("l"); | ||
Object.defineProperty(c, S, { | ||
Object.defineProperty(e, a, { | ||
get() { | ||
@@ -43,51 +45,54 @@ return this[h] ?? (this[h] = {}), this[h]; | ||
}); | ||
function p(t, o, n, s = { v: -1 }) { | ||
let l = null; | ||
for (let m = 0; m < o.length; m++) { | ||
const u = o[m]; | ||
function m(t, o, n, c = { v: -1 }) { | ||
let i; | ||
for (let d = 0; d < o.length; d++) { | ||
const u = o[d]; | ||
if (typeof u == "function") { | ||
let e = s; | ||
y(() => { | ||
const i = new Object(); | ||
n[d]("cleanup", () => i[f]()), n[r] ?? (n[r] = x()), i[r] = { | ||
let l = c; | ||
v(() => { | ||
const s = new Object(); | ||
n[y]("cleanup", () => s[p]()), n[r] ?? (n[r] = x()), s[r] = { | ||
...n[r], | ||
[b]: (...P) => p(t, P, i, e), | ||
[g]: i | ||
}, j.push(i[r]); | ||
const v = p(t, [u()], i, e); | ||
return j.pop(), l ?? (l = v), () => { | ||
e = { v: t[O](v) }, i[f](); | ||
[b]: (...T) => f = m(t, T, s, { v: t[S](f) + 1 }), | ||
[q]: s | ||
}, w.push(s[r]); | ||
let f; | ||
const C = f = m(t, [u()], s, l); | ||
return w.pop(), i ?? (i = C), () => { | ||
l = { v: t[S](C) }, s[p](); | ||
}; | ||
}); | ||
} else if (Array.isArray(u)) { | ||
const e = p(t, u, n, s); | ||
l ?? (l = e); | ||
const l = m(t, u, n, c); | ||
i ?? (i = l); | ||
} else { | ||
const e = t[b](u ?? t[T](), s.v); | ||
s.v > -1 && s.v++, e[r] = n[r], n[d]("cleanup", (i) => e[f](i)), l ?? (l = e); | ||
const l = u ?? t[P](); | ||
if (l == null) continue; | ||
const s = t[b](l, c.v); | ||
c.v > -1 && c.v++, s[r] = n[r], n[y]("cleanup", (f) => s[p](f)), i ?? (i = s); | ||
} | ||
} | ||
return l; | ||
return i; | ||
} | ||
function a(t, o) { | ||
function j(t, o) { | ||
for (; o.length; ) t = t[o.shift()]; | ||
return t; | ||
} | ||
const B = (t, o) => o[w](t); | ||
const D = (t, o) => o[O](t); | ||
export { | ||
w as append, | ||
A as assign, | ||
E as call, | ||
O as childrenIndex, | ||
f as cleanup, | ||
O as append, | ||
I as assign, | ||
g as call, | ||
S as childrenIndex, | ||
p as cleanup, | ||
r as context, | ||
R as create, | ||
T as empty, | ||
E as create, | ||
P as empty, | ||
b as insert, | ||
S as listeners, | ||
d as on, | ||
g as parent, | ||
C as remove, | ||
B as render, | ||
I as set | ||
a as listeners, | ||
y as on, | ||
q as parent, | ||
A as remove, | ||
D as render, | ||
R as set | ||
}; |
@@ -1,7 +0,15 @@ | ||
export declare function createSignal<T>(defaultValue: T): readonly [() => T, (_value: T) => void]; | ||
export declare function coalesce(f: Function, depth?: number): any; | ||
export declare function createSignal<T>(defaultValue: T): GetSet<T>; | ||
export declare type GetSet<T> = Parameters<(get: () => T, set: (v: T) => void) => void>; | ||
export declare function notify(f: Function & { | ||
[prev]: Function; | ||
}): void; | ||
declare const prev: unique symbol; | ||
export declare function untrack<T>(f: (...args: any) => T): T; | ||
export declare function useDebounced(callback: Function, debounceTime?: number): void; | ||
export declare function useEffect(callback: Function): void; | ||
@@ -8,0 +16,0 @@ |
@@ -1,33 +0,38 @@ | ||
const o = []; | ||
let c = !1; | ||
const u = Symbol("prev"); | ||
function a(e) { | ||
const t = /* @__PURE__ */ new Set(); | ||
let s = e; | ||
const n = [], o = [], i = Symbol("untracked"), r = Symbol("prev"); | ||
function d(t) { | ||
const e = /* @__PURE__ */ new Set(); | ||
let c = t; | ||
return [() => { | ||
const n = o[o.length - 1]; | ||
return n && !c && t.add(n), s; | ||
}, (n) => { | ||
s = n, t.forEach((r) => (typeof r[u] == "function" && r[u](), r[u] = r())); | ||
const s = n[n.length - 1]; | ||
return s && !s[i] && e.add(s), c; | ||
}, (s) => { | ||
c = s; | ||
const u = o[o.length - 1]; | ||
if (u) return e.forEach((a) => u.add(a)); | ||
f(() => e.forEach(p)); | ||
}]; | ||
} | ||
function i(e) { | ||
o.push(e), e[u] = e(), o.pop(); | ||
function h(t) { | ||
n.push(t), t[r] = t(), n.pop(); | ||
} | ||
function p(e, t = 250) { | ||
let s = !0, f; | ||
i(() => { | ||
s ? (s = !1, e()) : (clearTimeout(f), setTimeout(e, t)); | ||
}); | ||
function f(t, e = 1 / 0) { | ||
if (e == 0) return t(); | ||
o.push(/* @__PURE__ */ new Set()), t(); | ||
const c = o.pop(); | ||
c.size != 0 && f(() => c.forEach(p), e - 1); | ||
} | ||
function b(e) { | ||
c = !0; | ||
const t = e(); | ||
return c = !1, t; | ||
function p(t) { | ||
typeof t[r] == "function" && t[r](), h(t); | ||
} | ||
function g(t) { | ||
t[i] = !0, n.push(t); | ||
const e = t(); | ||
return n.pop(), e; | ||
} | ||
export { | ||
a as createSignal, | ||
b as untrack, | ||
p as useDebounced, | ||
i as useEffect | ||
f as coalesce, | ||
d as createSignal, | ||
p as notify, | ||
g as untrack, | ||
h as useEffect | ||
}; |
@@ -5,11 +5,13 @@ import { default as battutaMacros } from 'unplugin-macros/vite'; | ||
export declare function battutaCompiler(config?: Config["compiler"]): Plugin_2; | ||
export declare function battutaConfig(): Plugin_2; | ||
export declare function battutaFolders(config?: any): Plugin_2; | ||
export declare function battutaFolders(config?: FoldersConfig): Plugin_2; | ||
export declare function battutaInferModes(config?: ModesConfig): Plugin_2; | ||
export declare function battutaJSX(config?: JSXConfig): Plugin_2; | ||
export { battutaMacros } | ||
export declare function battutaOptimizer(config?: Config["optimizer"]): Plugin_2; | ||
export declare function battutaOptimizer(config?: OptimizerConfig): Plugin_2; | ||
@@ -19,18 +21,31 @@ declare function battutaPlugin(config?: Config): Plugin_2[]; | ||
export declare function battutaVirtualRoot(root?: string): Plugin_2; | ||
export declare function battutaVirtualRoot(opts?: RootConfig): Plugin_2; | ||
declare type Config = { | ||
macros?: Options; | ||
compiler?: {}; | ||
folders?: { | ||
temp: string; | ||
move: string; | ||
}; | ||
optimizer?: { | ||
strings?: boolean; | ||
functions?: boolean; | ||
}; | ||
root?: string; | ||
modes?: ModesConfig; | ||
jsx?: JSXConfig; | ||
optimizer?: OptimizerConfig; | ||
root?: RootConfig; | ||
folders?: FoldersConfig; | ||
}; | ||
declare type FoldersConfig = { | ||
temp: string; | ||
move: string; | ||
}; | ||
declare type JSXConfig = {}; | ||
declare type ModesConfig = {}; | ||
declare type OptimizerConfig = { | ||
strings?: boolean; | ||
functions?: boolean; | ||
}; | ||
declare type RootConfig = { | ||
pages: Record<string, string>; | ||
}; | ||
export { } | ||
@@ -37,0 +52,0 @@ |
123
dist/vite.js
@@ -1,40 +0,42 @@ | ||
import { compile as h } from "./compiler.js"; | ||
import b from "unplugin-macros/vite"; | ||
import { default as I } from "unplugin-macros/vite"; | ||
import { existsSync as u, mkdirSync as s, rmdirSync as d, readdirSync as v, lstatSync as x, renameSync as y, readFileSync as m } from "fs"; | ||
import o, { resolve as p, join as c } from "path"; | ||
import { optimize as f } from "./optimizer.js"; | ||
function F(t) { | ||
import { i as S, t as $ } from "./modes-kS_CsyZ5.js"; | ||
import F from "unplugin-macros/vite"; | ||
import { default as A } from "unplugin-macros/vite"; | ||
import { existsSync as i, mkdirSync as h, rmdirSync as v, readdirSync as M, lstatSync as D, renameSync as P, readFileSync as p } from "fs"; | ||
import m, { resolve as f, join as y } from "path"; | ||
import { optimize as z } from "./optimizer.js"; | ||
function C(t) { | ||
return { | ||
name: "battuta-build-folders", | ||
generateBundle(r, e) { | ||
S(r.dir, (t == null ? void 0 : t.temp) ?? ".temp"), C(r.dir, (t == null ? void 0 : t.move) ?? ".move"); | ||
E(r.dir, (t == null ? void 0 : t.temp) ?? ".temp"), O(r.dir, (t == null ? void 0 : t.move) ?? ".move"); | ||
} | ||
}; | ||
} | ||
function S(t, r) { | ||
const e = p(r), a = c(t); | ||
u(a) || s(a, { recursive: !0 }), u(e) && d(e, { recursive: !0, force: !0 }); | ||
function E(t, r) { | ||
const e = f(r), n = y(t); | ||
i(n) || h(n, { recursive: !0 }), i(e) && v(e, { recursive: !0, force: !0 }); | ||
} | ||
function C(t, r) { | ||
const e = p(r), a = c(t); | ||
u(a) || s(a, { recursive: !0 }), u(e) && (v(e).forEach((i) => { | ||
const n = o.join(e, i), l = o.join(a, i); | ||
x(n).isFile() && y(n, l); | ||
}), d(e, { recursive: !0, force: !0 })); | ||
function O(t, r) { | ||
const e = f(r), n = y(t); | ||
i(n) || h(n, { recursive: !0 }), i(e) && (M(e).forEach((a) => { | ||
const u = m.join(e, a), s = m.join(n, a); | ||
D(u).isFile() && P(u, s); | ||
}), v(e, { recursive: !0, force: !0 })); | ||
} | ||
function D(t) { | ||
const r = P(t ?? "/src/main.tsx"); | ||
function T(t) { | ||
const r = (t == null ? void 0 : t.pages) || { index: "/src/main.tsx" }, e = b(r, (a, u) => [`${a}.html`, u]), n = b(e, (a, u) => [a, w(u)]); | ||
return { | ||
name: "battuta-virtual-root", | ||
enforce: "pre", | ||
load: (e) => e !== "index.html" ? void 0 : u("./index.html") ? m("./index.html", "utf-8") : r, | ||
resolveId: (e, a, i) => { | ||
if (i.isEntry) return "index.html"; | ||
load: (a) => n[a] ? i(`./${a}`) ? p(`./${a}`, "utf-8") : n[a] : void 0, | ||
resolveId: (a, u, s) => { | ||
if (s.isEntry) return m.relative(m.resolve("./"), a); | ||
}, | ||
configureServer: (e) => { | ||
e.middlewares.use((a, i, n) => { | ||
if (a.url !== "/") return n(); | ||
const l = u("./index.html") ? m("./index.html", "utf-8") : r; | ||
i.setHeader("Content-Type", "text/html"), i.statusCode = 200, i.end(l); | ||
configureServer: (a) => { | ||
a.middlewares.use((u, s, x) => { | ||
var d, c; | ||
const o = (c = (d = u.url) == null ? void 0 : d.slice(1)) == null ? void 0 : c.replace(".html", ""), l = o ? `${o}.html` : "index.html"; | ||
if (!n[l]) return x(); | ||
const j = i(`./${l}`) ? p(`./${l}`, "utf-8") : k(n[l]); | ||
s.setHeader("Content-Type", "text/html"), s.statusCode = 200, s.end(j); | ||
}); | ||
@@ -44,3 +46,3 @@ }, | ||
optimizeDeps: { | ||
entries: ["index.html"] | ||
entries: Object.keys(e) | ||
} | ||
@@ -50,3 +52,9 @@ }) | ||
} | ||
const P = (t) => ` | ||
function b(t, r) { | ||
return Object.fromEntries(Object.entries(t).map(([e, n]) => r(e, n))); | ||
} | ||
function k(t) { | ||
return t.replace("<head>", '<head><script type="module" src="/@vite/client"><\/script>'); | ||
} | ||
const w = (t) => ` | ||
<!DOCTYPE html> | ||
@@ -69,7 +77,7 @@ <html lang="en"> | ||
`; | ||
function z() { | ||
function B() { | ||
return { | ||
name: "battuta-config", | ||
config: (t) => { | ||
var r, e, a, i; | ||
var r, e, n, a; | ||
return { | ||
@@ -85,4 +93,4 @@ build: { | ||
server: { | ||
host: ((a = t.server) == null ? void 0 : a.host) ?? "0.0.0.0", | ||
port: ((i = t.server) == null ? void 0 : i.port) ?? 5173 | ||
host: ((n = t.server) == null ? void 0 : n.host) ?? "0.0.0.0", | ||
port: ((a = t.server) == null ? void 0 : a.port) ?? 5173 | ||
} | ||
@@ -93,35 +101,46 @@ }; | ||
} | ||
function T(t) { | ||
function H(t) { | ||
return { | ||
name: "battuta-compiler", | ||
name: "battuta-infer-modes", | ||
enforce: "pre", | ||
transform(r, e) { | ||
return /\.[jt]sx$/.test(e) ? h(r, e) : null; | ||
return /\.[jt]sx$/.test(e) ? S(r, e) : null; | ||
} | ||
}; | ||
} | ||
function j(t) { | ||
function I(t) { | ||
return { | ||
name: "battuta-jsx", | ||
enforce: "pre", | ||
transform(r, e) { | ||
return /\.[jt]sx$/.test(e) ? $(r) : null; | ||
} | ||
}; | ||
} | ||
function J(t) { | ||
return { | ||
name: "battuta-optimizer", | ||
renderChunk: (r) => f(r, t) | ||
renderChunk: (r) => z(r, t) | ||
}; | ||
} | ||
function H(t) { | ||
function Y(t) { | ||
return [ | ||
z(), | ||
D(t == null ? void 0 : t.root), | ||
b(t == null ? void 0 : t.macros), | ||
T(t == null ? void 0 : t.compiler), | ||
F(t == null ? void 0 : t.folders), | ||
j(t == null ? void 0 : t.optimizer) | ||
B(), | ||
T(t == null ? void 0 : t.root), | ||
H(t == null ? void 0 : t.modes), | ||
F(t == null ? void 0 : t.macros), | ||
I(t == null ? void 0 : t.jsx), | ||
C(t == null ? void 0 : t.folders), | ||
J(t == null ? void 0 : t.optimizer) | ||
]; | ||
} | ||
export { | ||
T as battutaCompiler, | ||
z as battutaConfig, | ||
F as battutaFolders, | ||
I as battutaMacros, | ||
j as battutaOptimizer, | ||
D as battutaVirtualRoot, | ||
H as default | ||
B as battutaConfig, | ||
C as battutaFolders, | ||
H as battutaInferModes, | ||
I as battutaJSX, | ||
A as battutaMacros, | ||
J as battutaOptimizer, | ||
T as battutaVirtualRoot, | ||
Y as default | ||
}; |
{ | ||
"name": "battuta", | ||
"private": false, | ||
"version": "0.0.15-modeless", | ||
"version": "0.0.15-modeless10", | ||
"type": "module", | ||
@@ -20,11 +20,18 @@ "license": "MIT", | ||
"./runtime": "./dist/runtime.js", | ||
"./three": "./dist/three.js", | ||
"./dom": "./dist/dom.js", | ||
"./signals": "./dist/signals.js", | ||
"./contexts": "./dist/contexts.js", | ||
"./hooks": "./dist/hooks.js", | ||
"./tweak": "./dist/tweak.js", | ||
"./signals/screen": "./dist/signals/screen.js", | ||
"./jsx-runtime": "./dist/jsx-runtime.js", | ||
"./jsx-dev-runtime": "./dist/jsx-dev-runtime.js" | ||
"./jsx-dev-runtime": "./dist/jsx-dev-runtime.js", | ||
"./utils/animate": "./dist/utils.animate.js", | ||
"./utils/dev": "./dist/utils.dev.js", | ||
"./utils/lazy": "./dist/utils.lazy.js", | ||
"./utils/screen": "./dist/utils.screen.js", | ||
"./utils/signals": "./dist/utils.signals.js", | ||
"./utils/structure": "./dist/utils.structure.js", | ||
"./utils/three": "./dist/utils.three.js", | ||
"./utils/tree": "./dist/utils.tree.js", | ||
"./utils/tweak": "./dist/utils.tweak.js", | ||
"./macros/css.macro": "./dist/macros.css.macro.js", | ||
"./macros/glsl.macro": "./dist/macros.glsl.macro.js" | ||
}, | ||
@@ -48,5 +55,2 @@ "typesVersions": { | ||
], | ||
"three": [ | ||
"dist/three.d.ts" | ||
], | ||
"dom": [ | ||
@@ -61,11 +65,2 @@ "dist/dom.d.ts" | ||
], | ||
"hooks": [ | ||
"dist/hooks.d.ts" | ||
], | ||
"tweak": [ | ||
"dist/tweak.d.ts" | ||
], | ||
"signals/screen": [ | ||
"dist/signals/screen.d.ts" | ||
], | ||
"jsx-runtime": [ | ||
@@ -76,2 +71,35 @@ "dist/jsx-runtime.d.ts" | ||
"dist/jsx-dev-runtime.d.ts" | ||
], | ||
"utils/animate": [ | ||
"dist/utils.animate.d.ts" | ||
], | ||
"utils/dev": [ | ||
"dist/utils.dev.d.ts" | ||
], | ||
"utils/lazy": [ | ||
"dist/utils.lazy.d.ts" | ||
], | ||
"utils/screen": [ | ||
"dist/utils.screen.d.ts" | ||
], | ||
"utils/signals": [ | ||
"dist/utils.signals.d.ts" | ||
], | ||
"utils/structure": [ | ||
"dist/utils.structure.d.ts" | ||
], | ||
"utils/three": [ | ||
"dist/utils.three.d.ts" | ||
], | ||
"utils/tree": [ | ||
"dist/utils.tree.d.ts" | ||
], | ||
"utils/tweak": [ | ||
"dist/utils.tweak.d.ts" | ||
], | ||
"macros/css.macro": [ | ||
"dist/macros.css.macro.d.ts" | ||
], | ||
"macros/glsl.macro": [ | ||
"dist/macros.glsl.macro.d.ts" | ||
] | ||
@@ -83,6 +111,6 @@ } | ||
"build:quick": "vite build --mode quick", | ||
"build:quick-types": "vite build --mode quick-types", | ||
"build:nocheck": "vite build" | ||
}, | ||
"devDependencies": { | ||
"@tweakpane/core": "^2.0.4", | ||
"@types/babel__generator": "^7.6.8", | ||
@@ -108,5 +136,6 @@ "@types/babel__traverse": "^7.20.6", | ||
"tweakpane": "^4.0.4", | ||
"unplugin-macros": "github:BobochD-Brew/unplugin-macros.git#6b6e4a810e781baf2b5778ad7276b8948713c6a3", | ||
"@tweakpane/core": "^2.0.4", | ||
"unplugin-macros": "github:BobochD-Brew/unplugin-macros.git#0d7dc8bfc26bcc86a0bf8e40929994eaa6ca339e", | ||
"vite": "^5.4.1" | ||
} | ||
} |
328
README.md
@@ -16,8 +16,7 @@ # Battuta | ||
- [JSX](#jsx) | ||
- [Default Mode](#default-mode---d) | ||
- [Class Mode](#class-mode---c) | ||
- [Function Mode](#function-mode---f) | ||
- [Mixed Mode](#mixed-mode---n) | ||
- [DOM](#dom) | ||
- [Components](#components) | ||
- [Constructors](#constructors) | ||
- [Functions](#functions) | ||
- [Contexts](#contexts) | ||
- [Hooks](#some-hooks) | ||
- [CLI](#cli) | ||
@@ -36,73 +35,80 @@ - [Vite](#use-with-vite) | ||
the JSX compiler use a mode system that change how jsx expressions are compiled. | ||
to switch between modes you can use `$` utils like this: | ||
JSX expressions are compiled differently based on the type of tag used | ||
### DOM | ||
This expression: | ||
```tsx | ||
// as a separate tag | ||
<$f> {/* Function Mode */} | ||
<Component> | ||
<Child/> {/* affected */} | ||
{() => <Child/>} {/* not affected */} | ||
</Component> | ||
</$f> | ||
// inside a tag | ||
<Component $f> | ||
<Child/> {/* affected */} | ||
{() => <Child/>} {/* not affected */} | ||
</Component> | ||
<div style:color={color()}> | ||
{value()} | ||
</div> | ||
``` | ||
Transforms to: | ||
```tsx | ||
createElement("div") | ||
[assign](() => color(), "style", "color") | ||
[append](() => value()) | ||
``` | ||
> I hate to have to do it this way but it's the best I found yet | ||
### Components | ||
### Default Mode - $d | ||
Given | ||
```tsx | ||
function Component(props) { | ||
return <div>{props.value}</div> | ||
} | ||
``` | ||
This expression: | ||
```tsx | ||
<Component value={value()}> | ||
``` | ||
Transforms to: | ||
```tsx | ||
Component({ get value() { return value() } }) | ||
``` | ||
the default mode compile JSX expressions to match the react component apis, as solid it use accesors for props | ||
### Constructors | ||
Given | ||
```tsx | ||
<Component key1={value()} key2="value"> | ||
<div/> | ||
<div/> | ||
</Component> | ||
// turns into | ||
const createElement = document.bind(document); | ||
Component({ | ||
get key1() { return value() }, | ||
key2: "value", | ||
children: () => [ createElement("div"), createElement("div") ] | ||
}) | ||
class A { | ||
prop = 0; | ||
constructor(arg_2); | ||
constructor(arg_1, arg_2, arg_3) {} | ||
} | ||
``` | ||
Those expressions: | ||
```tsx | ||
<A arg_2={value_2()} prop={value_3()}> | ||
<A arg_2={value_2()} arg_3={value_4()} prop={value_3()}> | ||
``` | ||
Transform to: | ||
```tsx | ||
A[create](value_2()) | ||
[assign](() => value_3(), "prop") | ||
A[create](undefined, value_2(), value_4()) | ||
[assign](() => value_3(), "prop") | ||
``` | ||
### Class Mode - $c | ||
> The props names are matched with the args names | ||
the class mode allow to use already existing classes in JSX and compose them | ||
### Functions | ||
Given | ||
```tsx | ||
import { create, appendMultiple, set, assign, call } from "battuta/runtime" | ||
const group = <THREE.Group $c> | ||
<THREE.PointLight | ||
$c={[0xffff00, 2, 100]} | ||
color:set={$call(color())} | ||
position:y={positionY()} | ||
position:x={1} | ||
castShadow | ||
/> | ||
</THREE.Group> | ||
// turns into | ||
const group = THREE.Group[create]() // by default -> new THREE.Group() | ||
[appendMultiple]( | ||
THREE.PointLight[create](0xffff00, 2, 100) | ||
[call](() => color(), "color", "set") // calls light.color.set(color()) when color get updated | ||
[assign](() => position(), "position", "y") | ||
[set](1, "position", "x") | ||
[set](true, "castShadow") | ||
) | ||
function F(first: string, second: number) {} | ||
``` | ||
Those expressions: | ||
```tsx | ||
<F first={value_1()} second={value_2()}> | ||
<F second={value_2()} prop={value_3()}> | ||
``` | ||
Transform to: | ||
```tsx | ||
F(value_1(), value_2()) | ||
F(undefined, value_2()) | ||
[assign](() => value_3(), "prop") | ||
``` | ||
for this to work some methods need to be implmented on the parent prototypes, by default Object instances define default implementations that can be overwriten, at least `empty`, `childrenIndex`, `insert` and `remove` need to be implemented, those last two should never be called directly, instead use the `useAppend` & `useRemove` hooks or the `append` and `cleanup` methods | ||
for this to work some methods need to be implemented on the parent prototypes, by default Object instances define default implementations that can be overwriten, at least `insert` and `remove` need to be implemented | ||
@@ -115,2 +121,3 @@ this is an example in the case of threejs | ||
// required | ||
Object3D.prototype[insert] = function(child: any, index?: number){ | ||
@@ -121,60 +128,48 @@ this.add(child); | ||
// required | ||
Object3D.prototype[remove] = function(){ | ||
return this.removeFromParent(); | ||
this.removeFromParent(); | ||
return this; | ||
} | ||
// not needed if the childrens order doesn't matter | ||
Object3D.prototype[childrenIndex] = function(child){ | ||
return -1; | ||
return this.children.indexOf(child); | ||
} | ||
// not needed if the childrens order doesn't matter | ||
Object3D.prototype[empty] = function(){ | ||
return new Group(); | ||
} | ||
``` | ||
### Function Mode - $f | ||
// implemented by default, can be overwriten | ||
Object3D.prototype[create] = function (...props) { | ||
return Reflect.construct(this as any, props); | ||
} | ||
the function mode allow to compose functions with each other | ||
// implemented by default, can be overwriten | ||
Object3D.prototype[set] = function (value, ...keys) { | ||
const key = keys.pop()!; | ||
resolveObj(this, keys)[key] = value; | ||
return this; | ||
} | ||
```tsx | ||
const switchCase = <t.switchCase $f> | ||
{value} | ||
<array> | ||
<t.returnStatement> | ||
{result} | ||
</t.returnStatement> | ||
</array> | ||
</t.switchCase> | ||
// implemented by default, can be overwriten | ||
Object3D.prototype[assign] = function (value, ...keys) { | ||
const key = keys.pop()!; | ||
const target = resolveObj(this, keys); | ||
useEffect(() => target[key] = value()); | ||
return this; | ||
} | ||
// turns into | ||
const switchStatment = t.switchCase(value, [ t.returnStatment(result) ]) | ||
// implemented by default, can be overwriten | ||
Object3D.prototype[call] = function (value, ...keys) { | ||
const key = keys.pop()!; | ||
const target = resolveObj(this, keys); | ||
const f = target[key].bind(target); | ||
useEffect(() => f(...value())); | ||
return this; | ||
} | ||
``` | ||
### Mixed Mode - $n | ||
the mixed mode is a mix between the class mode and the function mode | ||
```tsx | ||
const boxMesh = <Mesh $n | ||
castShadow | ||
receiveShadow | ||
> | ||
<BoxGeometry/> | ||
<MeshPhongMaterial | ||
color:set={$call(color())} | ||
/> | ||
</Mesh> | ||
// turns into | ||
const boxMesh = Mesh[create]( | ||
BoxGeometry[create](), // this return new BoxGeometry() | ||
MeshPhongMaterial[create]() | ||
[call](() => color(), "color", "set") | ||
) | ||
[set](true, "castShadow") | ||
[set](true, "receiveShadow") | ||
``` | ||
## Contexts | ||
@@ -206,11 +201,9 @@ | ||
const child1 = <Child/> // run outside the EventsProvider so can't access the context | ||
const child2 = () => <Child/> // run inside the EventsProvider | ||
const child1 = <Child/> | ||
const child2 = () => <Child/> | ||
doSomething(<Child/>) // run outside the doSomething function | ||
return <EventsProvider> | ||
<Child/> | ||
{child1} | ||
{child2} | ||
<Child/> {/* run inside the EventsProvider */} | ||
{child1} {/* run outside the EventsProvider */} | ||
{child2} {/* run inside the EventsProvider */} | ||
<EventsProvider> | ||
@@ -221,111 +214,2 @@ } | ||
## Some Hooks | ||
quick examples of some builtin hooks | ||
```tsx | ||
function Component() { | ||
const add = useAppend(); | ||
// append the child to the closest real element | ||
// derivate from the current context | ||
add(<Child />) | ||
const remove = useRemove(); | ||
remove(); // remove this component & the elements bellow the current context | ||
onCleanup(() => { | ||
// component has been removed | ||
// atm there's no way to unmount -> remount | ||
}) | ||
// useEffect can be used outside of components and JSX | ||
useEffect(() => { | ||
reactive() + 1; | ||
}) | ||
useDebounced(() => { | ||
reactive() + 1; | ||
}, 1000) | ||
// for now only inside the Canvas helper in battuta/three | ||
const { camera, scene } = useScene(); | ||
useFrame((delta) => {}) | ||
// TweakPanel wrappers | ||
const [getValue, setValue] = createTweakSignal("#ffffff"); | ||
useMonitor(() => Date.now()) | ||
} | ||
``` | ||
Even tho there's no virtual dom we still has virtual relations & contexts. For example in this situation | ||
```tsx | ||
const Component = () => () => () => () => () => { | ||
return <h1>Hello</h1> | ||
} | ||
const div = <div/> | ||
``` | ||
the real tree looks like | ||
``` | ||
- div | ||
|---- h1 | ||
``` | ||
tho in relatity the relations look like this | ||
``` | ||
- div | ||
|---- f1 | ||
| |---- f2 | ||
| |---- f3 | ||
| |---- f4 | ||
| |---- f5 | ||
|-------------------|---- h1 | ||
``` | ||
the real tree is still composed just of the div and the h1 elements but the intermediary contexts exist (if consumed) so here each element are bound to their parent. | ||
one thing to keep in mind is the virtual element exist only if the real elements received an uncalled function, this happens by default to components in the normal mode as their children prop is a function but for other modes it is not the case, so for example here | ||
```tsx | ||
function Child() { | ||
return <h1/> | ||
} | ||
function Parent() { | ||
return <div> | ||
<Child/> | ||
</div> | ||
} | ||
``` | ||
here two uncommon things happen, first here's the relation map of this code | ||
``` | ||
- Parent (virtual, assuming it was used in a default mode component) | ||
|---- div | ||
| |---- h1 | ||
|---- Child | ||
``` | ||
You can see the the child function don't appear where it should, this happens because the compilation result here is | ||
```ts | ||
function Parent() { | ||
return createElement(div)[append](Child()) | ||
} | ||
``` | ||
the div only receive the result of the child which is the second div so it never knows about the Child context, this generally don't cause issues as the div don't hold any special context. | ||
the second uncommon behavior is that if you have a `onCleanup` hook in your Child the Child is gonna consume from the parenting context, which in this case is the Parent element, this doesn't cause issues unless you're directly removing the div separatly using the `cleanup` method, in this case the div will be removed as well as the h1 but the `onCleanup` hook won't run for the child as it's bound to the Parent component | ||
## CLI | ||
@@ -362,2 +246,3 @@ | ||
macros: Options, | ||
root: "src/main.tsx", | ||
optimizer: { | ||
@@ -380,6 +265,7 @@ strings: true, | ||
import { battutaJSX } from "battuta/vite"; | ||
import { battutaJSX, battutaInferModes } from "battuta/vite"; | ||
export default defineConfig({ | ||
plugins: [ | ||
battutaInferModes(), | ||
battutaJSX() | ||
@@ -386,0 +272,0 @@ ] |
GitHub dependency
Supply chain riskContains a dependency which resolves to a GitHub URL. Dependencies fetched from GitHub specifiers are not immutable can be used to inject untrusted code or reduce the likelihood of a reproducible install.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
GitHub dependency
Supply chain riskContains a dependency which resolves to a GitHub URL. Dependencies fetched from GitHub specifiers are not immutable can be used to inject untrusted code or reduce the likelihood of a reproducible install.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
70889
11.37%8
-11.11%47
42.42%1799
18.9%13
8.33%412
-21.67%5
25%3
50%