@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/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) => raw.trim() && !raw.trim().startsWith("//"))
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
- const selector = normalizeSelector(text, parent);
43
- stack.push({ indent, selector });
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 = aliases.get(prop) || prop;
71
+ const cssProp = resolveProp(prop, rest);
50
72
  const value = rest.join(" ").replace(/\$([a-zA-Z0-9_-]+)/g, "var(--$1)");
51
- css.push(`${current} { ${cssProp}: ${value}; }`);
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}`);