@gjsify/site 0.63.1-next.237 → 0.64.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.
@@ -362,16 +362,20 @@ h1 {
362
362
  border-block-start: 1px solid var(--band-line);
363
363
  }
364
364
 
365
+ /* Three fixed rows — pill, value, label — so a badge whose pill is taller (the platform glyphs) or
366
+ * that carries no value at all still lands its label on the neighbours' line. */
365
367
  .badge {
366
- display: flex;
367
- flex-direction: column;
368
+ display: grid;
369
+ grid-template-rows: 2.75rem minmax(1.5rem, auto) auto;
368
370
  align-items: center;
371
+ justify-items: center;
369
372
  gap: 0.3rem;
370
373
  min-width: 0;
371
374
  text-align: center;
372
375
  }
373
376
 
374
377
  .badge-pill {
378
+ grid-row: 1;
375
379
  display: flex;
376
380
  align-items: center;
377
381
  justify-content: center;
@@ -451,10 +455,10 @@ h1 {
451
455
  --platform-color: #4285f4;
452
456
  }
453
457
 
454
- /* Kept in the flow even when a badge has no value, so every label sits on the same line. */
458
+ /* The row is reserved even when a badge has no value, so every label sits on the same line. */
455
459
  .badge-value {
460
+ grid-row: 2;
456
461
  line-height: 1.5;
457
- min-height: 1.5em;
458
462
  font-weight: 700;
459
463
  font-size: 0.95rem;
460
464
  /* A long licence id must wrap inside the badge instead of widening the row. */
@@ -462,6 +466,7 @@ h1 {
462
466
  }
463
467
 
464
468
  .badge-label {
469
+ grid-row: 3;
465
470
  color: var(--muted);
466
471
  font-size: 0.78rem;
467
472
  }
@@ -34,6 +34,11 @@ export declare function languageName(code: string): string;
34
34
  export declare function ctaLabel(target: DownloadTarget, t: Translate): string;
35
35
  /** A window shot brings its own shadow; ours would draw a second one around it. */
36
36
  export declare function frameAttribute(ctx: Pick<RenderContext, 'images'>, screenshot: Screenshot): 'none' | undefined;
37
+ /**
38
+ * The facts row under the hero. A badge whose fact is missing is left out, not faked, and the row
39
+ * tells CSS how many it ended up with so the columns divide the width evenly.
40
+ */
41
+ export declare function badges(ctx: Pick<RenderContext, 'data' | 't' | 'lang'>): string;
37
42
  export declare function linkCard(href: string, title: string, glyph: IconName): string;
38
43
  /** A bank transfer as a card: the details to read or copy, and an EPC QR code that fills them into a banking app. */
39
44
  export declare function sepaCard(entry: SiteSupportSepa, t: Translate): string;
@@ -254,9 +254,12 @@ ${data.downloads.hasReleases ? `<p class="dialog-foot"><a href="${esc(data.downl
254
254
  </app-download>`;
255
255
  }
256
256
  function badge(spec) {
257
+ // An absent value is not an empty element: the row reserves the line, the DOM stays clean.
258
+ const value = spec.value
259
+ ? `\n<span${attrs({ class: 'badge-value', title: spec.title })}>${esc(spec.value)}</span>`
260
+ : '';
257
261
  return `<li${attrs({ class: spec.class ? `badge ${spec.class}` : 'badge', hidden: spec.hidden })}>
258
- <span class="badge-pill">${spec.pill ?? icon(spec.glyph)}</span>
259
- <span${attrs({ class: 'badge-value', title: spec.title })}>${esc(spec.value)}</span>
262
+ <span class="badge-pill">${spec.pill ?? icon(spec.glyph)}</span>${value}
260
263
  <span class="badge-label">${esc(spec.label)}</span>
261
264
  </li>`;
262
265
  }
@@ -268,7 +271,7 @@ function shortLicense(id) {
268
271
  * The facts row under the hero. A badge whose fact is missing is left out, not faked, and the row
269
272
  * tells CSS how many it ended up with so the columns divide the width evenly.
270
273
  */
271
- function badges(ctx) {
274
+ export function badges(ctx) {
272
275
  const { data, t, lang } = ctx;
273
276
  const number = new Intl.NumberFormat(lang, { notation: 'compact', maximumFractionDigits: 1 });
274
277
  const targets = data.downloads.targets;
@@ -295,7 +298,7 @@ function badges(ctx) {
295
298
  .map((os) => icon(PLATFORM_ICONS[os], { title: osName(os, t), class: `platform platform-${os}` }))
296
299
  .join('');
297
300
  const label = oses.every(isBrowserPlatform) ? t('Browsers') : t('Platforms');
298
- specs.push({ pill: `<span class="badge-platforms">${glyphs}</span>`, value: '', label });
301
+ specs.push({ pill: `<span class="badge-platforms">${glyphs}</span>`, label });
299
302
  }
300
303
  if (data.app.ageRating) {
301
304
  const { minAge } = data.app.ageRating;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gjsify/site",
3
- "version": "0.63.1-next.237",
3
+ "version": "0.64.0",
4
4
  "description": "Static landing page generator for a GNOME-style app, rendered from its AppStream metainfo — downloads, screenshots, release notes, support links, no JavaScript required.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -54,26 +54,25 @@
54
54
  "license": "MIT",
55
55
  "dependencies": {
56
56
  "@girs/gdkpixbuf-2.0": "5.4.0",
57
- "@gjsify/console": "0.63.1-next.237",
58
- "@gjsify/crypto": "0.63.1-next.237",
59
- "@gjsify/fs": "0.63.1-next.237",
60
- "@gjsify/module": "0.63.1-next.237",
61
- "@gjsify/os": "0.63.1-next.237",
62
- "@gjsify/path": "0.63.1-next.237",
63
- "@gjsify/process": "0.63.1-next.237",
64
- "@gjsify/url": "0.63.1-next.237",
57
+ "@gjsify/console": "^0.64.0",
58
+ "@gjsify/crypto": "^0.64.0",
59
+ "@gjsify/fs": "^0.64.0",
60
+ "@gjsify/module": "^0.64.0",
61
+ "@gjsify/os": "^0.64.0",
62
+ "@gjsify/path": "^0.64.0",
63
+ "@gjsify/process": "^0.64.0",
64
+ "@gjsify/url": "^0.64.0",
65
65
  "fast-xml-parser": "^5.11.2",
66
66
  "qrcode-generator": "^2.0.4"
67
67
  },
68
68
  "devDependencies": {
69
- "@gjsify/cli": "0.63.1-next.237",
69
+ "@gjsify/cli": "^0.64.0",
70
70
  "@gjsify/node-gi": "file:../../node-gi/node-gi",
71
- "@gjsify/unit": "0.63.1-next.237",
71
+ "@gjsify/unit": "^0.64.0",
72
72
  "@types/node": "^25.9.2",
73
73
  "typescript": "^6.0.3"
74
74
  },
75
75
  "gjsify": {
76
76
  "tier": 2
77
- },
78
- "gitHead": "a349db400a7e68befc11ba6381ddb0e4caff09b6"
77
+ }
79
78
  }