van-hmr/gale.js
2025-10-30 09:58:18 -04:00

89 lines
2.6 KiB
JavaScript

/** @type {Gale.CreateSheet} */
export default (sheet, hash="")=>
{
const KeyQuery = "@";
const KeyState = ":";
const KeyChild = ".";
const KeyGroup = "^";
/** @type {Gale.Tier} */
const Tier=(selector, obj, suffix)=>
{
const styles = Object.keys(obj).map((key)=>
{
const value = obj[key];
switch(key[0])
{
case KeyQuery :
return Tier(`@media(max-width:${key.substring(KeyQuery.length)})`, value, suffix);
case KeyState :
return Tier(`&${key}`, value, suffix);
case KeyChild :
return Tier(`${key}${suffix}`, value, suffix);
case KeyGroup :
return Tier(`&:hover .${key.substring(KeyGroup.length)}${suffix}`, value, suffix);
}
return `${ key.replace(/([a-z])([A-Z])/g, '$1-$2') }: ${value};`
});
return `${selector}{${styles.join("\n")}}`;
}
/** @type {(needle:string, str:string)=>string} */
const extractLast =(needle, str)=>{
const ind = str.lastIndexOf(needle)+needle.length;
return ind ? str.substring(ind) : str;
}
const collect =(tagName)=>
{
const pending = van.tags[tagName];
let mentioned = [];
const collector = new Proxy(
(...args)=>
{
const element = pending(...args);
element.className = mentioned.join(id+" ")+id + " " + element.className;
mentioned = [];
return element;
},
{
get(_, prop)
{
mentioned.push(prop.substring(prop.lastIndexOf(".")+1));
return collector;
}
}
);
return collector;
}
const id = hash ? "_"+hash : "";
const css = Object.keys(sheet).map(key=>Tier("."+key+id, sheet[key], id)).join(`\n`);
globalThis.document?.head.insertAdjacentHTML("beforeend", `<style data-sheet="${id}">${css}</style>`);
return {
Tag(...args){
return args.map((arg)=>extractLast(KeyGroup, extractLast(KeyChild, arg))).join(id+" ")+id;
},
CSS: css,
DOM: new Proxy(
{},
{
get(_, prop)
{
return collect(prop)
}
}
),
Div: new Proxy(
{},
{
get(_, prop)
{
return collect("div")[prop]
}
}
)
}
}