@uniweb/theming 0.1.4 → 0.1.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uniweb/theming",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "Theming utilities for the Uniweb platform — shade generation, CSS generation, theme processing",
5
5
  "type": "module",
6
6
  "exports": {
@@ -358,16 +358,22 @@ function generateFontCSS(fonts = {}) {
358
358
  }
359
359
 
360
360
  if (allFamilies.length > 0) {
361
- const merged = new URL('https://fonts.googleapis.com/css2')
362
- for (const f of allFamilies) {
363
- merged.searchParams.append('family', f)
364
- }
365
- merged.searchParams.set('display', display)
361
+ // Build the css2 URL by hand. Google's css2 axis syntax uses ':' ',' ';'
362
+ // '@' as LITERAL separators and '+' for spaces. URLSearchParams.toString()
363
+ // percent-encodes all of them (%3A/%2C/%3B/%40), producing a URL that
364
+ // parses but is non-canonical — it only loads because Google's server
365
+ // decodes it leniently. A strict Google Fonts mirror/proxy or a future API
366
+ // change could reject it. Emit the canonical literal form instead.
367
+ // (getAll() already decoded '+'/'%20' to spaces, so restore spaces to '+'.)
368
+ const familyQuery = allFamilies
369
+ .map((f) => `family=${f.trim().replace(/\s+/g, '+')}`)
370
+ .join('&')
371
+ const href = `https://fonts.googleapis.com/css2?${familyQuery}&display=${display}`
366
372
 
367
373
  linkTags.unshift(
368
374
  `<link rel="preconnect" href="https://fonts.googleapis.com">`,
369
375
  `<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>`,
370
- `<link rel="stylesheet" href="${merged.toString()}">`,
376
+ `<link rel="stylesheet" href="${href}">`,
371
377
  )
372
378
  }
373
379
  }
@@ -390,6 +396,33 @@ function generateFontCSS(fonts = {}) {
390
396
  cssLines.push('}')
391
397
  }
392
398
 
399
+ // --- Apply font families to elements ---
400
+ // Defining --font-* on :root is not enough — something must actually set
401
+ // `font-family` on rendered elements, the same way colors get an application
402
+ // rule ([id^="section-"] { background-color: var(--section) }). Without this
403
+ // the font vars are orphaned and text never picks them up, even though the
404
+ // vars are set and the @import/@font-face load. Only apply slots the SITE
405
+ // explicitly set (fonts._userSlots) so a foundation's own default typography
406
+ // is left untouched when theme.yml doesn't override that slot.
407
+ const userSlots = new Set(fonts._userSlots || [])
408
+ const applyRules = []
409
+ if (userSlots.has('body')) {
410
+ applyRules.push('body { font-family: var(--font-body); }')
411
+ }
412
+ if (userSlots.has('heading')) {
413
+ // Only the prominent headings — display/heading faces are drawn for large
414
+ // sizes; h4–h6 usually render at or near body size where a display face
415
+ // reads awkwardly, so they stay in the body font.
416
+ applyRules.push('h1, h2, h3 { font-family: var(--font-heading); }')
417
+ }
418
+ if (userSlots.has('mono')) {
419
+ applyRules.push('code, pre, kbd, samp { font-family: var(--font-mono); }')
420
+ }
421
+ if (applyRules.length > 0) {
422
+ cssLines.push('')
423
+ cssLines.push(...applyRules)
424
+ }
425
+
393
426
  return {
394
427
  css: cssLines.join('\n'),
395
428
  links: linkTags.join('\n'),