astro-ghostcms/.pnpm-store/v3/files/b6/14230ec3cc98108057460c5958c...

122 lines
3.5 KiB
Plaintext
Raw Permalink Normal View History

2024-02-14 14:10:47 +00:00
import { parse, html as __html, walkSync, ELEMENT_NODE, DOCUMENT_NODE, TEXT_NODE, } from "ultrahtml";
import inlineCSS from "ultrahtml/transformers/inline";
const TW_NAMES = new Set([
/[mp](t|b|r|l|x|y)?-/,
`color-`,
`flex`,
`h-`,
`w-`,
`min-w-`,
`min-h-`,
`max-w-`,
`max-h-`,
`leading-`,
`text-`,
`opacity-`,
`font-`,
`aspect-`,
`tint-`,
`bg-`,
`opacity-`,
`shadow-`,
`rounded`,
`top-`,
`right-`,
`bottom-`,
`left-`,
`inset-`,
`border`,
`elevation-`,
`tracking-`,
`z-`,
]);
const inliner = inlineCSS({ useObjectSyntax: true });
const tw = (doc) => {
walkSync(doc, (node) => {
if (node.type !== ELEMENT_NODE)
return;
if (node.attributes.class && !node.attributes.tw) {
const classNames = node.attributes.class.split(/\s+/);
let match = false;
for (const name of TW_NAMES) {
if (match)
break;
for (const item of classNames) {
if (match)
break;
if (item.indexOf(":") > -1) {
match = true;
}
else if (typeof name === "string") {
match = item.startsWith(name);
}
else {
match = name.test(item);
}
}
}
if (match) {
node.attributes.tw = node.attributes.class;
}
}
});
};
const camelize = (ident) => ident.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
export function html(templates, ...expressions) {
const result = __html.call(null, templates, ...expressions);
let doc = parse(result.value.trim());
inliner(doc);
tw(doc);
const nodeMap = new WeakMap();
let root = {
type: "div",
props: {
style: {
display: "flex",
flexDirection: "column",
width: "100%",
height: "100%",
},
children: [],
},
};
walkSync(doc, (node, parent, index) => {
let newNode = {};
if (node.type === DOCUMENT_NODE) {
nodeMap.set(node, root);
}
else if (node.type === ELEMENT_NODE) {
newNode.type = node.name;
const { style, "": _, ...props } = node.attributes;
if (typeof style === "object") {
props["style"] = {};
for (const [decl, value] of Object.entries(style)) {
props["style"][camelize(decl)] = value;
}
}
props.children = [];
Object.assign(newNode, { props });
nodeMap.set(node, newNode);
if (parent) {
const newParent = nodeMap.get(parent);
newParent.props.children[index] = newNode;
}
}
else if (node.type === TEXT_NODE) {
newNode = node.value.trim();
if (newNode.trim()) {
if (parent) {
const newParent = nodeMap.get(parent);
if (parent.children.length === 1) {
newParent.props.children = newNode;
}
else {
newParent.props.children[index] = newNode;
}
}
}
}
});
return root;
}