@uniweb/theming 0.1.11 → 0.1.13

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/processor.js +52 -36
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uniweb/theming",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "description": "Theming utilities for the Uniweb platform — shade generation, CSS generation, theme processing",
5
5
  "type": "module",
6
6
  "exports": {
package/src/processor.js CHANGED
@@ -115,36 +115,6 @@ function normalizeApplyTo(applyTo) {
115
115
  return cleaned.length ? cleaned : null
116
116
  }
117
117
 
118
- /**
119
- * Default code block theme configuration
120
- * Uses Shiki CSS variable names for compatibility
121
- * These values are NOT converted to CSS here - the kit's Code component
122
- * injects them at runtime only when code blocks are used (tree-shaking)
123
- */
124
- const DEFAULT_CODE_THEME = {
125
- // Background and foreground
126
- background: '#1e1e2e', // Dark editor background
127
- foreground: '#cdd6f4', // Default text color
128
-
129
- // Syntax highlighting colors (Shiki token variables)
130
- keyword: '#cba6f7', // Purple - keywords (if, else, function)
131
- string: '#a6e3a1', // Green - strings
132
- number: '#fab387', // Orange - numbers
133
- comment: '#6c7086', // Gray - comments
134
- function: '#89b4fa', // Blue - function names
135
- variable: '#f5e0dc', // Light pink - variables
136
- operator: '#89dceb', // Cyan - operators
137
- punctuation: '#9399b2', // Gray - punctuation
138
- type: '#f9e2af', // Yellow - types
139
- constant: '#f38ba8', // Red - constants
140
- property: '#94e2d5', // Teal - properties
141
- tag: '#89b4fa', // Blue - HTML/JSX tags
142
- attribute: '#f9e2af', // Yellow - attributes
143
-
144
- // UI elements
145
- lineNumber: '#6c7086', // Line number color
146
- selection: '#45475a', // Selection background
147
- }
148
118
 
149
119
  /**
150
120
  * Validate color configuration
@@ -378,6 +348,49 @@ export function validateThemeConfig(config) {
378
348
  }
379
349
  }
380
350
 
351
+ /**
352
+ * Merge inline text styles over the framework defaults, property by property.
353
+ *
354
+ * Everything else in theme.yml merges at the granularity of the leaf value —
355
+ * `contexts[name]` merges your tokens into the default context object, `colors`
356
+ * and `appearance` merge per key. This does the same one level down, so a site
357
+ * declares only the deltas:
358
+ *
359
+ * inline:
360
+ * accent:
361
+ * font-weight: inherit # keeps the default colour
362
+ *
363
+ * A shallow merge replaced the whole style object instead, so the example above
364
+ * silently produced `span[accent] { font-weight: inherit }` with no colour at
365
+ * all, and accented text rendered in the surrounding heading colour. The failure
366
+ * was subtractive and invisible in the config — you had to know what the default
367
+ * contained to notice it was gone. Three of the shipped templates carried a
368
+ * verbatim restatement of the default `accent` style purely to work around this.
369
+ *
370
+ * To *drop* a default property rather than change it, give it a neutral CSS
371
+ * value — `font-weight: inherit` to follow the surrounding text, or `initial` /
372
+ * `unset` / `revert`. Setting a whole style to null still removes it entirely
373
+ * (the CSS generator skips non-object entries).
374
+ *
375
+ * @param {Object} defaults - DEFAULT_INLINE
376
+ * @param {Object} [overrides] - rawConfig.inline
377
+ * @returns {Object} merged style map
378
+ */
379
+ function mergeInlineStyles(defaults, overrides) {
380
+ const merged = { ...defaults }
381
+
382
+ for (const [name, style] of Object.entries(overrides || {})) {
383
+ // Non-objects (null/false) pass through so a site can delete a default
384
+ // style outright; anything else layers over the default of the same name.
385
+ merged[name] =
386
+ style && typeof style === 'object' && !Array.isArray(style)
387
+ ? { ...(defaults[name] || {}), ...style }
388
+ : style
389
+ }
390
+
391
+ return merged
392
+ }
393
+
381
394
  /**
382
395
  * Normalize appearance configuration
383
396
  *
@@ -650,17 +663,20 @@ export function processTheme(rawConfig = {}, options = {}) {
650
663
  // Process code block theme
651
664
  // These values are stored for runtime injection by kit's Code component
652
665
  // (not converted to CSS here - enables tree-shaking when code blocks aren't used)
653
- const code = {
654
- ...DEFAULT_CODE_THEME,
655
- ...(rawConfig.code || {}),
656
- }
666
+ // Passed through exactly as declared — no defaults filled in.
667
+ //
668
+ // A default palette here would defeat the point of the setting downstream: a
669
+ // site naming a bundled theme and overriding one colour would arrive carrying
670
+ // fifteen, and the theme it named would be overridden in full by values it
671
+ // never asked for. Whoever renders code owns the default; this only carries
672
+ // what the site said.
673
+ const code = rawConfig.code ?? null
657
674
 
658
675
  // Site background (pass through as CSS value)
659
676
  const background = rawConfig.background || null
660
677
 
661
678
  // Inline text styles (semantic names → CSS declarations)
662
- // Merge framework defaults with user overrides (user values win)
663
- const inline = { ...DEFAULT_INLINE, ...(rawConfig.inline || {}) }
679
+ const inline = mergeInlineStyles(DEFAULT_INLINE, rawConfig.inline)
664
680
 
665
681
  const config = {
666
682
  colors, // Raw colors for CSS generator