@zvndev/darkmown 0.4.0 → 0.6.0
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/AGENTS.md +297 -0
- package/CHANGELOG.md +15 -0
- package/README.md +34 -3
- package/docs/spec-alignment.md +11 -2
- package/package.json +3 -2
- package/site/_/nav.skin +2 -1
- package/site/_/nav.wd +1 -0
- package/site/_/roadmap.json +7 -0
- package/site/pages/app.skin +76 -0
- package/site/pages/app.wd +92 -0
- package/site/pages/docs/index.wd +30 -3
- package/site/pages/index.wd +30 -14
- package/site/pages/reactive.wd +40 -0
- package/src/compiler.js +191 -20
- package/src/runtime.js +37 -2
- package/src/scaffold.js +42 -1
- package/src/skin.js +28 -5
package/src/skin.js
CHANGED
|
@@ -5,11 +5,27 @@ const aliases = new Map([
|
|
|
5
5
|
["bg", "background"]
|
|
6
6
|
]);
|
|
7
7
|
|
|
8
|
+
// `font` is aliased to font-family for the common `font <stack>` case, but the
|
|
9
|
+
// real CSS `font` shorthand (`font 16px/1.4 system-ui`) must pass through. If
|
|
10
|
+
// the value looks like a shorthand (leads with a size or contains `/`), keep it.
|
|
11
|
+
function resolveProp(prop, rest) {
|
|
12
|
+
if (prop === "font" && (/^[\d.]/.test(rest[0] || "") || rest.join(" ").includes("/"))) return "font";
|
|
13
|
+
return aliases.get(prop) || prop;
|
|
14
|
+
}
|
|
15
|
+
|
|
8
16
|
export function compileSkin(source) {
|
|
9
17
|
const lines = source
|
|
10
18
|
.replace(/\r\n?/g, "\n")
|
|
19
|
+
.replace(/\/\*[\s\S]*?\*\//g, "") // strip /* … */ block comments (any span)
|
|
11
20
|
.split("\n")
|
|
12
|
-
.filter((raw) =>
|
|
21
|
+
.filter((raw) => {
|
|
22
|
+
const t = raw.trim();
|
|
23
|
+
if (!t || t.startsWith("//")) return false;
|
|
24
|
+
// Decorative divider lines (----, ====, * * *, ~~~) carry no rule and would
|
|
25
|
+
// otherwise parse as a bogus selector/declaration. Anything with a letter or
|
|
26
|
+
// digit is real content; punctuation-only lines are skipped.
|
|
27
|
+
return /[A-Za-z0-9]/.test(t);
|
|
28
|
+
})
|
|
13
29
|
.map((raw) => ({ indent: raw.match(/^\s*/)[0].length, text: raw.trim() }));
|
|
14
30
|
|
|
15
31
|
const stack = [];
|
|
@@ -39,16 +55,23 @@ export function compileSkin(source) {
|
|
|
39
55
|
|
|
40
56
|
if (opensBlock) {
|
|
41
57
|
const parent = stack.at(-1)?.selector;
|
|
42
|
-
|
|
43
|
-
|
|
58
|
+
// At-rules (@media, @supports) wrap rules instead of extending selectors:
|
|
59
|
+
// carry the outer selector through so nested selectors combine normally.
|
|
60
|
+
if (text.startsWith("@")) {
|
|
61
|
+
stack.push({ indent, selector: parent ?? null, media: text });
|
|
62
|
+
} else {
|
|
63
|
+
stack.push({ indent, selector: normalizeSelector(text, parent) });
|
|
64
|
+
}
|
|
44
65
|
continue;
|
|
45
66
|
}
|
|
46
67
|
|
|
47
68
|
const current = stack.at(-1)?.selector || ":root";
|
|
69
|
+
const media = stack.find((frame) => frame.media)?.media;
|
|
48
70
|
const [prop, ...rest] = text.split(/\s+/);
|
|
49
|
-
const cssProp =
|
|
71
|
+
const cssProp = resolveProp(prop, rest);
|
|
50
72
|
const value = rest.join(" ").replace(/\$([a-zA-Z0-9_-]+)/g, "var(--$1)");
|
|
51
|
-
|
|
73
|
+
const rule = `${current} { ${cssProp}: ${value}; }`;
|
|
74
|
+
css.push(media ? `${media} { ${rule} }` : rule);
|
|
52
75
|
}
|
|
53
76
|
|
|
54
77
|
if (rootVars.length) css.unshift(`:root {\n${rootVars.join("\n")}\n}`);
|