@cogenta/theme-association 0.3.2 → 0.5.3

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 (148) hide show
  1. package/dist/src/index.d.ts +6 -0
  2. package/dist/src/index.d.ts.map +1 -1
  3. package/dist/src/index.js +9 -0
  4. package/dist/src/index.js.map +1 -1
  5. package/dist/src/render/blocks/accordion.d.ts.map +1 -1
  6. package/dist/src/render/blocks/accordion.js +13 -10
  7. package/dist/src/render/blocks/accordion.js.map +1 -1
  8. package/dist/src/render/blocks/breakdown.d.ts +14 -0
  9. package/dist/src/render/blocks/breakdown.d.ts.map +1 -0
  10. package/dist/src/render/blocks/breakdown.js +17 -0
  11. package/dist/src/render/blocks/breakdown.js.map +1 -0
  12. package/dist/src/render/blocks/collection-list.d.ts +4 -10
  13. package/dist/src/render/blocks/collection-list.d.ts.map +1 -1
  14. package/dist/src/render/blocks/collection-list.js +89 -58
  15. package/dist/src/render/blocks/collection-list.js.map +1 -1
  16. package/dist/src/render/blocks/cta.d.ts +0 -5
  17. package/dist/src/render/blocks/cta.d.ts.map +1 -1
  18. package/dist/src/render/blocks/cta.js +22 -10
  19. package/dist/src/render/blocks/cta.js.map +1 -1
  20. package/dist/src/render/blocks/embed.d.ts.map +1 -1
  21. package/dist/src/render/blocks/embed.js +30 -22
  22. package/dist/src/render/blocks/embed.js.map +1 -1
  23. package/dist/src/render/blocks/faq.d.ts.map +1 -1
  24. package/dist/src/render/blocks/faq.js +11 -15
  25. package/dist/src/render/blocks/faq.js.map +1 -1
  26. package/dist/src/render/blocks/feature-grid.d.ts +6 -0
  27. package/dist/src/render/blocks/feature-grid.d.ts.map +1 -1
  28. package/dist/src/render/blocks/feature-grid.js +42 -20
  29. package/dist/src/render/blocks/feature-grid.js.map +1 -1
  30. package/dist/src/render/blocks/gallery.d.ts +9 -7
  31. package/dist/src/render/blocks/gallery.d.ts.map +1 -1
  32. package/dist/src/render/blocks/gallery.js +22 -16
  33. package/dist/src/render/blocks/gallery.js.map +1 -1
  34. package/dist/src/render/blocks/hero.d.ts +23 -9
  35. package/dist/src/render/blocks/hero.d.ts.map +1 -1
  36. package/dist/src/render/blocks/hero.js +40 -23
  37. package/dist/src/render/blocks/hero.js.map +1 -1
  38. package/dist/src/render/blocks/logo-strip.d.ts +6 -0
  39. package/dist/src/render/blocks/logo-strip.d.ts.map +1 -1
  40. package/dist/src/render/blocks/logo-strip.js +7 -9
  41. package/dist/src/render/blocks/logo-strip.js.map +1 -1
  42. package/dist/src/render/blocks/logos.d.ts +14 -0
  43. package/dist/src/render/blocks/logos.d.ts.map +1 -1
  44. package/dist/src/render/blocks/logos.js +30 -16
  45. package/dist/src/render/blocks/logos.js.map +1 -1
  46. package/dist/src/render/blocks/media-figure.d.ts +12 -5
  47. package/dist/src/render/blocks/media-figure.d.ts.map +1 -1
  48. package/dist/src/render/blocks/media-figure.js +32 -18
  49. package/dist/src/render/blocks/media-figure.js.map +1 -1
  50. package/dist/src/render/blocks/pricing-table.d.ts.map +1 -1
  51. package/dist/src/render/blocks/pricing-table.js +18 -20
  52. package/dist/src/render/blocks/pricing-table.js.map +1 -1
  53. package/dist/src/render/blocks/prose.d.ts +9 -3
  54. package/dist/src/render/blocks/prose.d.ts.map +1 -1
  55. package/dist/src/render/blocks/prose.js +11 -4
  56. package/dist/src/render/blocks/prose.js.map +1 -1
  57. package/dist/src/render/blocks/quote.d.ts +4 -7
  58. package/dist/src/render/blocks/quote.d.ts.map +1 -1
  59. package/dist/src/render/blocks/quote.js +12 -17
  60. package/dist/src/render/blocks/quote.js.map +1 -1
  61. package/dist/src/render/blocks/stat-counter.d.ts +8 -1
  62. package/dist/src/render/blocks/stat-counter.d.ts.map +1 -1
  63. package/dist/src/render/blocks/stat-counter.js +18 -10
  64. package/dist/src/render/blocks/stat-counter.js.map +1 -1
  65. package/dist/src/render/blocks/stats.d.ts +12 -1
  66. package/dist/src/render/blocks/stats.d.ts.map +1 -1
  67. package/dist/src/render/blocks/stats.js +24 -14
  68. package/dist/src/render/blocks/stats.js.map +1 -1
  69. package/dist/src/render/blocks/testimonial.d.ts +6 -5
  70. package/dist/src/render/blocks/testimonial.d.ts.map +1 -1
  71. package/dist/src/render/blocks/testimonial.js +13 -11
  72. package/dist/src/render/blocks/testimonial.js.map +1 -1
  73. package/dist/src/render/chrome.d.ts +38 -1
  74. package/dist/src/render/chrome.d.ts.map +1 -1
  75. package/dist/src/render/chrome.js +117 -91
  76. package/dist/src/render/chrome.js.map +1 -1
  77. package/dist/src/render/details.d.ts +79 -0
  78. package/dist/src/render/details.d.ts.map +1 -0
  79. package/dist/src/render/details.js +221 -0
  80. package/dist/src/render/details.js.map +1 -0
  81. package/dist/src/render/figures.d.ts +29 -0
  82. package/dist/src/render/figures.d.ts.map +1 -0
  83. package/dist/src/render/figures.js +59 -0
  84. package/dist/src/render/figures.js.map +1 -0
  85. package/dist/src/render/layout.d.ts +31 -0
  86. package/dist/src/render/layout.d.ts.map +1 -0
  87. package/dist/src/render/layout.js +46 -0
  88. package/dist/src/render/layout.js.map +1 -0
  89. package/dist/src/render/page-head.d.ts +7 -0
  90. package/dist/src/render/page-head.d.ts.map +1 -0
  91. package/dist/src/render/page-head.js +95 -0
  92. package/dist/src/render/page-head.js.map +1 -0
  93. package/dist/src/render/render-block.d.ts +8 -12
  94. package/dist/src/render/render-block.d.ts.map +1 -1
  95. package/dist/src/render/render-block.js +40 -29
  96. package/dist/src/render/render-block.js.map +1 -1
  97. package/dist/src/render/strings.d.ts +15 -0
  98. package/dist/src/render/strings.d.ts.map +1 -0
  99. package/dist/src/render/strings.js +39 -0
  100. package/dist/src/render/strings.js.map +1 -0
  101. package/dist/src/render/term-archive.d.ts.map +1 -1
  102. package/dist/src/render/term-archive.js +33 -25
  103. package/dist/src/render/term-archive.js.map +1 -1
  104. package/dist/src/render/widget-areas.d.ts +14 -0
  105. package/dist/src/render/widget-areas.d.ts.map +1 -0
  106. package/dist/src/render/widget-areas.js +21 -0
  107. package/dist/src/render/widget-areas.js.map +1 -0
  108. package/dist/theme.config.d.ts +1 -1
  109. package/dist/theme.config.js +3 -3
  110. package/dist/theme.config.js.map +1 -1
  111. package/package.json +5 -5
  112. package/src/index.ts +9 -0
  113. package/src/render/blocks/accordion.ts +28 -22
  114. package/src/render/blocks/breakdown.ts +42 -0
  115. package/src/render/blocks/collection-list.ts +234 -103
  116. package/src/render/blocks/cta.ts +48 -19
  117. package/src/render/blocks/embed.ts +47 -29
  118. package/src/render/blocks/faq.ts +22 -31
  119. package/src/render/blocks/feature-grid.ts +73 -41
  120. package/src/render/blocks/gallery.ts +32 -26
  121. package/src/render/blocks/hero.ts +56 -43
  122. package/src/render/blocks/logo-strip.ts +23 -21
  123. package/src/render/blocks/logos.ts +45 -40
  124. package/src/render/blocks/media-figure.ts +49 -24
  125. package/src/render/blocks/pricing-table.ts +31 -40
  126. package/src/render/blocks/prose.ts +16 -6
  127. package/src/render/blocks/quote.ts +34 -27
  128. package/src/render/blocks/stat-counter.ts +35 -29
  129. package/src/render/blocks/stats.ts +46 -38
  130. package/src/render/blocks/testimonial.ts +29 -20
  131. package/src/render/chrome.ts +165 -91
  132. package/src/render/details.ts +276 -0
  133. package/src/render/figures.ts +68 -0
  134. package/src/render/layout.ts +78 -0
  135. package/src/render/page-head.ts +193 -0
  136. package/src/render/render-block.ts +45 -32
  137. package/src/render/strings.ts +74 -0
  138. package/src/render/term-archive.ts +94 -58
  139. package/src/render/widget-areas.ts +24 -0
  140. package/src/styles/archive.css +38 -102
  141. package/src/styles/base.css +503 -554
  142. package/src/styles/blocks.css +913 -666
  143. package/src/styles/chrome.css +506 -0
  144. package/src/styles/listings.css +591 -0
  145. package/src/styles/theme.css +25 -19
  146. package/src/styles/tokens.css +284 -234
  147. package/src/styles/widgets.css +1059 -0
  148. package/tokens.json +18 -18
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Two readings of plain text a charity writes all the time, recognised from
3
+ * the words themselves rather than from a setting contract B does not have.
4
+ *
5
+ * - **A breakdown.** Figures that are all percentages and add up to a whole
6
+ * (95 to 105, for rounding) say where the money goes: they are drawn as
7
+ * shares of one total, with a bar each, instead of four unrelated numbers.
8
+ * - **What a gift pays for.** A call to action whose sentences start with an
9
+ * amount of money ("£12 buys a week of fresh vegetables for one family.")
10
+ * lists those amounts large beside what they pay for. Any other text stays
11
+ * the paragraph it was written as.
12
+ */
13
+ export function shareOf(value, unit) {
14
+ const joined = unit === undefined ? value.trim() : `${value.trim()}${unit.trim()}`;
15
+ const match = /^(\d{1,3}(?:[.,]\d+)?)\s*%$/.exec(joined);
16
+ if (match === null)
17
+ return undefined;
18
+ const share = Number.parseFloat(match[1].replace(',', '.'));
19
+ return share >= 0 && share <= 100 ? share : undefined;
20
+ }
21
+ export function isBreakdown(items) {
22
+ if (items.length < 2)
23
+ return false;
24
+ const shares = items.map((item) => shareOf(item.value, item.unit));
25
+ if (shares.some((share) => share === undefined))
26
+ return false;
27
+ const total = shares.reduce((sum, share) => sum + share, 0);
28
+ return total >= 95 && total <= 105;
29
+ }
30
+ const GIFT = /^([£€$]\s?\d[\d,.]*(?:\s(?:a|per|each)\s(?:week|month|year))?)\s+(\S[\s\S]*)$/u;
31
+ /** The sentences of `text` that start with an amount, or `undefined` when fewer than two do. */
32
+ export function giftsOf(text) {
33
+ if (text === undefined)
34
+ return undefined;
35
+ const sentences = text
36
+ .trim()
37
+ .split(/(?<=[.;])\s+/)
38
+ .filter((sentence) => sentence !== '');
39
+ const first = sentences.findIndex((sentence) => GIFT.test(sentence));
40
+ if (first === -1)
41
+ return undefined;
42
+ let last = first;
43
+ while (last + 1 < sentences.length && GIFT.test(sentences[last + 1]))
44
+ last += 1;
45
+ const gifts = sentences.slice(first, last + 1).map((sentence) => {
46
+ const match = GIFT.exec(sentence);
47
+ return { amount: match[1], text: match[2] };
48
+ });
49
+ if (gifts.length < 2)
50
+ return undefined;
51
+ const lead = sentences.slice(0, first).join(' ');
52
+ const tail = sentences.slice(last + 1).join(' ');
53
+ return {
54
+ lead: lead === '' ? undefined : lead,
55
+ gifts,
56
+ tail: tail === '' ? undefined : tail,
57
+ };
58
+ }
59
+ //# sourceMappingURL=figures.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"figures.js","sourceRoot":"","sources":["../../../src/render/figures.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import { type Attributes, type Child, type HtmlElement } from '@cogenta/theme-kit';
2
+ /**
3
+ * The frame every block of this theme renders into.
4
+ *
5
+ * The outer element carries the one section rhythm (`--ca-section`, the same
6
+ * for every block) and paints edge to edge when a block is a band. The inner
7
+ * element is the twelve-column container, so a section title, a figure, a
8
+ * date and a caption all start on the same line.
9
+ *
10
+ * `inner` is `figure` for a block whose semantics are a figure (a quotation
11
+ * and its attribution, an image and its caption): `<figcaption>` must be a
12
+ * direct child of its `<figure>`.
13
+ */
14
+ export declare function section(outer: 'section' | 'div', block: string, className: string, attrs: Attributes, inner: 'div' | 'figure', ...children: readonly Child[]): HtmlElement;
15
+ /**
16
+ * A titled block's heading, in the display face at the section size, on the
17
+ * first column of the grid. `null` for an untitled block: no empty heading.
18
+ */
19
+ export declare function sectionHead(blockName: string, title: string | undefined): HtmlElement | null;
20
+ /**
21
+ * The words of an arrow link, with the last word wrapped in a span that
22
+ * cannot break and that carries the arrow (`::after`, drawn by the
23
+ * stylesheet). A line can then break between words but never between the
24
+ * last word and its arrow, so an arrow is never left alone at the start of a
25
+ * line, and the words keep one continuous underline: the arrow is an atomic
26
+ * inline, which a text decoration does not reach.
27
+ */
28
+ export declare function arrowWords(text: string): Child[];
29
+ /** A paragraph that renders only when the text is there: no empty `<p>` on the page. */
30
+ export declare function optionalText(tag: string, className: string, value: string | undefined, attrs?: Attributes): HtmlElement | null;
31
+ //# sourceMappingURL=layout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../../src/render/layout.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,UAAU,EAEf,KAAK,KAAK,EACV,KAAK,WAAW,EAGjB,MAAM,oBAAoB,CAAA;AAE3B;;;;;;;;;;;GAWG;AACH,wBAAgB,OAAO,CACrB,KAAK,EAAE,SAAS,GAAG,KAAK,EACxB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,KAAK,GAAG,QAAQ,EACvB,GAAG,QAAQ,EAAE,SAAS,KAAK,EAAE,GAC5B,WAAW,CAMb;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,GAAG,IAAI,CAW5F;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,EAAE,CAKhD;AAED,wFAAwF;AACxF,wBAAgB,YAAY,CAC1B,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,KAAK,GAAE,UAAe,GACrB,WAAW,GAAG,IAAI,CAGpB"}
@@ -0,0 +1,46 @@
1
+ import { blockHeadingTag, h, heading, } from '@cogenta/theme-kit';
2
+ /**
3
+ * The frame every block of this theme renders into.
4
+ *
5
+ * The outer element carries the one section rhythm (`--ca-section`, the same
6
+ * for every block) and paints edge to edge when a block is a band. The inner
7
+ * element is the twelve-column container, so a section title, a figure, a
8
+ * date and a caption all start on the same line.
9
+ *
10
+ * `inner` is `figure` for a block whose semantics are a figure (a quotation
11
+ * and its attribution, an image and its caption): `<figcaption>` must be a
12
+ * direct child of its `<figure>`.
13
+ */
14
+ export function section(outer, block, className, attrs, inner, ...children) {
15
+ return h(outer, { class: `ca-section ${className}`, 'data-block': block, ...attrs }, h(inner, { class: `ca-container ${className}__inner` }, ...children));
16
+ }
17
+ /**
18
+ * A titled block's heading, in the display face at the section size, on the
19
+ * first column of the grid. `null` for an untitled block: no empty heading.
20
+ */
21
+ export function sectionHead(blockName, title) {
22
+ if (title === undefined)
23
+ return null;
24
+ return h('div', { class: 'ca-head' }, heading(blockHeadingTag(blockName) ?? 'h2', { class: 'ca-head__title', 'data-field': 'title' }, title));
25
+ }
26
+ /**
27
+ * The words of an arrow link, with the last word wrapped in a span that
28
+ * cannot break and that carries the arrow (`::after`, drawn by the
29
+ * stylesheet). A line can then break between words but never between the
30
+ * last word and its arrow, so an arrow is never left alone at the start of a
31
+ * line, and the words keep one continuous underline: the arrow is an atomic
32
+ * inline, which a text decoration does not reach.
33
+ */
34
+ export function arrowWords(text) {
35
+ const trimmed = text.trim();
36
+ const at = trimmed.lastIndexOf(' ');
37
+ const end = h('span', { class: 'ca-arrow-link__end' }, trimmed.slice(at + 1));
38
+ return at === -1 ? [end] : [trimmed.slice(0, at + 1), end];
39
+ }
40
+ /** A paragraph that renders only when the text is there: no empty `<p>` on the page. */
41
+ export function optionalText(tag, className, value, attrs = {}) {
42
+ if (value === undefined || value.trim() === '')
43
+ return null;
44
+ return h(tag, { class: className, ...attrs }, value);
45
+ }
46
+ //# sourceMappingURL=layout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layout.js","sourceRoot":"","sources":["../../../src/render/layout.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,eAAe,EAGf,CAAC,EACD,OAAO,GACR,MAAM,oBAAoB,CAAA;AAE3B;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,OAAO,CACrB,KAAwB,EACxB,KAAa,EACb,SAAiB,EACjB,KAAiB,EACjB,KAAuB,EACvB,GAAG,QAA0B;IAE7B,OAAO,CAAC,CACN,KAAK,EACL,EAAE,KAAK,EAAE,cAAc,SAAS,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,EACnE,CAAC,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,gBAAgB,SAAS,SAAS,EAAE,EAAE,GAAG,QAAQ,CAAC,CACrE,CAAA;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,SAAiB,EAAE,KAAyB;IACtE,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,IAAI,CAAA;IACpC,OAAO,CAAC,CACN,KAAK,EACL,EAAE,KAAK,EAAE,SAAS,EAAE,EACpB,OAAO,CACL,eAAe,CAAC,SAAS,CAAC,IAAI,IAAI,EAClC,EAAE,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,OAAO,EAAE,EAClD,KAAK,CACN,CACF,CAAA;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAA;IAC3B,MAAM,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,CAAA;IACnC,MAAM,GAAG,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,oBAAoB,EAAE,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAA;IAC7E,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;AAC5D,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,YAAY,CAC1B,GAAW,EACX,SAAiB,EACjB,KAAyB,EACzB,KAAK,GAAe,EAAE;IAEtB,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,IAAI,CAAA;IAC3D,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,CAAA;AACtD,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { type HtmlElement, type PageContent, type RenderContext } from '@cogenta/theme-kit';
2
+ export type PageHeadKind = 'event' | 'entry' | 'page';
3
+ export declare function renderPageHead(page: PageContent, ctx: RenderContext): {
4
+ readonly kind: PageHeadKind;
5
+ readonly node: HtmlElement;
6
+ };
7
+ //# sourceMappingURL=page-head.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-head.d.ts","sourceRoot":"","sources":["../../../src/render/page-head.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,WAAW,EAEhB,KAAK,WAAW,EAEhB,KAAK,aAAa,EAEnB,MAAM,oBAAoB,CAAA;AA2K3B,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,CAAA;AAErD,wBAAgB,cAAc,CAC5B,IAAI,EAAE,WAAW,EACjB,GAAG,EAAE,aAAa,GACjB;IAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAA;CAAE,CAS7D"}
@@ -0,0 +1,95 @@
1
+ import { h, renderImageSource, } from '@cogenta/theme-kit';
2
+ import { eventTimeOf, factsOf, renderDateBlock, renderFacts } from './details.js';
3
+ import { associationString } from './strings.js';
4
+ /**
5
+ * The opening of every page that has no hero. Three kinds, and exactly one
6
+ * `h1` in each:
7
+ *
8
+ * - **An event** (its `theme@1.5` fields carry a date): the date block large
9
+ * on the first three columns, the way a noticeboard poster leads with the
10
+ * day; the title, the summary and the practical details (when, where, what
11
+ * it costs, whether to book) on the rest; the photograph under them across
12
+ * the container.
13
+ * - **An entry with details or a photograph** (a programme, a story): the
14
+ * title, the summary and the details on the first seven columns; a portrait
15
+ * photograph beside them on the last four, a landscape one under them.
16
+ * - **Anything else** (about, donate, a privacy notice): the title large on
17
+ * the grid, and the summary under it when there is one.
18
+ *
19
+ * A host older than `theme@1.5` sends no fields, so its event pages open like
20
+ * any other entry: title, summary and photograph, never a date read from
21
+ * somewhere it was not given. A host older than `theme@1.4` sends no entry at
22
+ * all, and the page opens on its bare title.
23
+ */
24
+ function formatDate(iso, locale) {
25
+ try {
26
+ return new Intl.DateTimeFormat(locale, { dateStyle: 'long', timeZone: 'UTC' }).format(new Date(iso));
27
+ }
28
+ catch {
29
+ return iso;
30
+ }
31
+ }
32
+ /** Date, author and reading time, for an entry that has a publication date. */
33
+ function meta(entry, ctx) {
34
+ if (entry.publishedAt === undefined)
35
+ return null;
36
+ return h('p', { class: 'ca-page-head__meta' }, h('time', { datetime: entry.publishedAt }, formatDate(entry.publishedAt, ctx.locale)), entry.author === undefined ? null : h('span', {}, entry.author.name), entry.readingMinutes === undefined
37
+ ? null
38
+ : h('span', {}, ctx.t('entry.readingTime', { minutes: entry.readingMinutes })));
39
+ }
40
+ function terms(entry) {
41
+ if (entry.terms === undefined || entry.terms.length === 0)
42
+ return null;
43
+ return h('ul', { class: 'ca-page-head__terms' }, entry.terms.map((term) => h('li', {}, term.href === null ? term.label : h('a', { href: term.href }, term.label))));
44
+ }
45
+ function details(entry, ctx, className) {
46
+ const facts = renderFacts(factsOf(entry.fields ?? {}, ctx.locale), 'ca-facts');
47
+ if (facts === null)
48
+ return null;
49
+ return h('div', { class: className }, h('h2', { class: 'cg-visually-hidden' }, associationString(ctx.locale, 'details')), facts);
50
+ }
51
+ function renderEventHead(page, entry, ctx) {
52
+ const time = eventTimeOf(entry.fields);
53
+ if (time === undefined)
54
+ return null;
55
+ return h('header', { class: 'ca-event', 'data-cover': String(entry.image !== undefined) }, h('div', { class: 'ca-container ca-event__inner' }, h('div', { class: 'ca-event__date' }, renderDateBlock(time, ctx.locale, 'ca-when', { year: true })), h('div', { class: 'ca-event__heading' }, terms(entry), h('h1', { class: 'ca-event__title' }, page.title), entry.excerpt === undefined ? null : h('p', { class: 'ca-event__lead' }, entry.excerpt)), details(entry, ctx, 'ca-event__details'), entry.image === undefined
56
+ ? null
57
+ : h('figure', { class: 'ca-event__cover' }, renderImageSource(entry.image, {
58
+ className: 'ca-event__image',
59
+ loading: 'eager',
60
+ sizes: '(min-width: 82rem) 78rem, 100vw',
61
+ }))));
62
+ }
63
+ function renderEntryHead(page, entry, ctx) {
64
+ const facts = details(entry, ctx, 'ca-entry__details');
65
+ const cover = entry.image;
66
+ if (facts === null && cover === undefined)
67
+ return null;
68
+ const orientation = cover === undefined ? 'none' : cover.height > cover.width ? 'portrait' : 'landscape';
69
+ return h('header', { class: 'ca-entry', 'data-cover': orientation }, h('div', { class: 'ca-container ca-entry__inner' }, h('div', { class: 'ca-entry__heading' }, terms(entry), h('h1', { class: 'ca-entry__title' }, page.title), entry.excerpt === undefined ? null : h('p', { class: 'ca-entry__lead' }, entry.excerpt), meta(entry, ctx), facts), cover === undefined
70
+ ? null
71
+ : h('figure', { class: 'ca-entry__cover' }, renderImageSource(cover, {
72
+ className: 'ca-entry__image',
73
+ loading: 'eager',
74
+ sizes: orientation === 'portrait'
75
+ ? '(min-width: 64rem) 30vw, 100vw'
76
+ : '(min-width: 82rem) 78rem, 100vw',
77
+ }))));
78
+ }
79
+ function renderPlainHead(page, ctx) {
80
+ const entry = page.entry;
81
+ return h('header', { class: 'ca-page-head' }, h('div', { class: 'ca-container ca-page-head__inner' }, entry === undefined ? null : terms(entry), h('h1', { class: 'ca-page-head__title' }, page.title), entry?.excerpt === undefined ? null : h('p', { class: 'ca-page-head__lead' }, entry.excerpt), entry === undefined ? null : meta(entry, ctx)));
82
+ }
83
+ export function renderPageHead(page, ctx) {
84
+ const entry = page.entry;
85
+ if (entry !== undefined) {
86
+ const eventHead = renderEventHead(page, entry, ctx);
87
+ if (eventHead !== null)
88
+ return { kind: 'event', node: eventHead };
89
+ const entryHead = renderEntryHead(page, entry, ctx);
90
+ if (entryHead !== null)
91
+ return { kind: 'entry', node: entryHead };
92
+ }
93
+ return { kind: 'page', node: renderPlainHead(page, ctx) };
94
+ }
95
+ //# sourceMappingURL=page-head.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-head.js","sourceRoot":"","sources":["../../../src/render/page-head.ts"],"names":[],"mappings":"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"}
@@ -1,21 +1,17 @@
1
1
  import { type BlockRegistry, type VocabularyBlock } from '@cogenta/blocks';
2
- import { type FetchedEntries, type HtmlElement, type PageContent, pageHasOwnHeading, type RenderContext, renderEntryHeader, withBlockKey } from '@cogenta/theme-kit';
2
+ import { type FetchedEntries, type HtmlElement, type PageContent, type RenderContext } from '@cogenta/theme-kit';
3
3
  export type { FetchedEntries, PageContent };
4
- export { pageHasOwnHeading, renderEntryHeader, withBlockKey };
5
4
  export declare function renderBlock(block: VocabularyBlock, ctx: RenderContext, entries?: FetchedEntries, registry?: BlockRegistry): HtmlElement | null;
6
5
  /**
7
- * `<main id="cg-main">` is mandatory: it is the skip-link's target, written
8
- * once by `@cogenta/cli`'s `theme-render.ts` outside any theme's control.
6
+ * `<main id="cg-main">` is mandatory: it is the skip link's target, written
7
+ * by the host outside any theme's control.
9
8
  *
10
- * `theme@1.4` (L25 D2): `renderEntryHeader` returns `null` both for a page
11
- * with no `entry` meta and for one whose blocks already draw their own
12
- * heading (a `hero`) — the bare `<h1 class="cg-page__title">` fallback below
13
- * is the right markup in both of those cases and only those, so the page
14
- * always carries exactly one `<h1>`.
9
+ * A page whose blocks include a `hero` lets the hero carry the title; any
10
+ * other page opens on `renderPageHead` (an event, an entry with details, or
11
+ * a plain title), so every page has exactly one `h1`.
15
12
  *
16
- * `withBlockKey` stamps every rendered block with its contract-B `_key` —
17
- * required so the visual page builder (L16) can map a clicked element in the
18
- * rendered iframe back to the block that produced it.
13
+ * `withBlockKey` stamps every rendered block with its contract-B `_key`, so
14
+ * the visual page builder (L16) can map a clicked element back to its block.
19
15
  */
20
16
  export declare function renderPage(page: PageContent, ctx: RenderContext, entries?: FetchedEntries, registry?: BlockRegistry): HtmlElement;
21
17
  //# sourceMappingURL=render-block.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"render-block.d.ts","sourceRoot":"","sources":["../../../src/render/render-block.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAoB,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAC5F,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,WAAW,EAEhB,KAAK,WAAW,EAChB,iBAAiB,EACjB,KAAK,aAAa,EAClB,iBAAiB,EAEjB,YAAY,EAEb,MAAM,oBAAoB,CAAA;AAmB3B,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,CAAA;AAC3C,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,YAAY,EAAE,CAAA;AAE7D,wBAAgB,WAAW,CACzB,KAAK,EAAE,eAAe,EACtB,GAAG,EAAE,aAAa,EAClB,OAAO,GAAE,cAAmB,EAC5B,QAAQ,CAAC,EAAE,aAAa,GACvB,WAAW,GAAG,IAAI,CAYpB;AAwDD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,UAAU,CACxB,IAAI,EAAE,WAAW,EACjB,GAAG,EAAE,aAAa,EAClB,OAAO,GAAE,cAAmB,EAC5B,QAAQ,CAAC,EAAE,aAAa,GACvB,WAAW,CAab"}
1
+ {"version":3,"file":"render-block.d.ts","sourceRoot":"","sources":["../../../src/render/render-block.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAoB,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAC5F,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,WAAW,EAEhB,KAAK,WAAW,EAGhB,KAAK,aAAa,EAInB,MAAM,oBAAoB,CAAA;AAoB3B,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,CAAA;AAE3C,wBAAgB,WAAW,CACzB,KAAK,EAAE,eAAe,EACtB,GAAG,EAAE,aAAa,EAClB,OAAO,GAAE,cAAmB,EAC5B,QAAQ,CAAC,EAAE,aAAa,GACvB,WAAW,GAAG,IAAI,CAepB;AAgED;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CACxB,IAAI,EAAE,WAAW,EACjB,GAAG,EAAE,aAAa,EAClB,OAAO,GAAE,cAAmB,EAC5B,QAAQ,CAAC,EAAE,aAAa,GACvB,WAAW,CAkBb"}
@@ -1,5 +1,5 @@
1
1
  import { VOCABULARY_NAMES } from '@cogenta/blocks';
2
- import { h, pageHasOwnHeading, renderEntryHeader, resolveBlockForRender, withBlockKey, withBlockVariant, } from '@cogenta/theme-kit';
2
+ import { h, pageHasOwnHeading, providedBlockNode, resolveBlockForRender, withBlockKey, withBlockVariant, } from '@cogenta/theme-kit';
3
3
  import { renderAccordion } from './blocks/accordion.js';
4
4
  import { renderCollectionList } from './blocks/collection-list.js';
5
5
  import { renderCta } from './blocks/cta.js';
@@ -17,19 +17,23 @@ import { renderQuote } from './blocks/quote.js';
17
17
  import { renderStatCounter } from './blocks/stat-counter.js';
18
18
  import { renderStats } from './blocks/stats.js';
19
19
  import { renderTestimonial } from './blocks/testimonial.js';
20
- export { pageHasOwnHeading, renderEntryHeader, withBlockKey };
20
+ import { renderPageHead } from './page-head.js';
21
21
  export function renderBlock(block, ctx, entries = {}, registry) {
22
- // `block`'s type says `VocabularyBlock`, but the value crossing this
23
- // boundary from stored content is not always literally one of the shared
24
- // vocabulary — resolving here is what turns an unimplemented theme-private
25
- // block into its declared fallback instead of a silently blank slot.
22
+ // A block a plugin provides arrives already rendered by the host, in a
23
+ // process of its own (contract D theme@1.7). Nothing else in this theme
24
+ // needs to know such blocks exist.
25
+ const provided = providedBlockNode(block, ctx);
26
+ if (provided !== null)
27
+ return withBlockVariant(provided, block.variant);
28
+ // A stored block is not always literally one of the shared vocabulary:
29
+ // resolving here turns an unimplemented theme-private block into its
30
+ // declared fallback instead of a silently blank slot.
26
31
  const resolved = resolveBlockForRender(block, VOCABULARY_NAMES, registry);
27
32
  if (resolved === null)
28
33
  return null;
29
34
  const known = resolved;
30
- // `withBlockVariant` (blocks@2.0, RFC 0002) is applied once here, after
31
- // dispatch, rather than inside each of the seventeen block renderers —
32
- // `variant` is envelope data every block carries identically.
35
+ // `variant` is envelope data every block carries identically, applied once
36
+ // here rather than by each of the seventeen renderers.
33
37
  return withBlockVariant(renderKnownBlock(known, ctx, entries), known.variant);
34
38
  }
35
39
  function renderKnownBlock(known, ctx, entries) {
@@ -69,12 +73,9 @@ function renderKnownBlock(known, ctx, entries) {
69
73
  case 'logoStrip':
70
74
  return renderLogoStrip(known, ctx);
71
75
  default: {
72
- // Exhaustive over contract B's vocabulary: `known` is `never` here, so
73
- // a block this package does not implement stops it compiling until it
74
- // is. Returning null rather than throwing is deliberate — a theme has
75
- // no access to `@cogenta/core`'s error types (contract D refuses the
76
- // import), and choosing a fallback block is the render layer's job,
77
- // not the theme's.
76
+ // Exhaustive over contract B: `known` is `never` here, so a block this
77
+ // package does not implement stops it compiling until it is. `null`
78
+ // rather than a throw: choosing a fallback is the render layer's job.
78
79
  const unreachable = known;
79
80
  void unreachable;
80
81
  return null;
@@ -82,23 +83,33 @@ function renderKnownBlock(known, ctx, entries) {
82
83
  }
83
84
  }
84
85
  /**
85
- * `<main id="cg-main">` is mandatory: it is the skip-link's target, written
86
- * once by `@cogenta/cli`'s `theme-render.ts` outside any theme's control.
86
+ * A real `id` beside `withBlockKey`'s `data-block-key`, so a link to
87
+ * `/donate#<key>` has somewhere to land. Contract B's `_key` is unique within
88
+ * one page's block list, so it can never collide on a page this theme
89
+ * rendered.
90
+ */
91
+ function withAnchorId(element, key) {
92
+ if (element === null)
93
+ return null;
94
+ return { ...element, attrs: { ...element.attrs, id: key } };
95
+ }
96
+ /**
97
+ * `<main id="cg-main">` is mandatory: it is the skip link's target, written
98
+ * by the host outside any theme's control.
87
99
  *
88
- * `theme@1.4` (L25 D2): `renderEntryHeader` returns `null` both for a page
89
- * with no `entry` meta and for one whose blocks already draw their own
90
- * heading (a `hero`) — the bare `<h1 class="cg-page__title">` fallback below
91
- * is the right markup in both of those cases and only those, so the page
92
- * always carries exactly one `<h1>`.
100
+ * A page whose blocks include a `hero` lets the hero carry the title; any
101
+ * other page opens on `renderPageHead` (an event, an entry with details, or
102
+ * a plain title), so every page has exactly one `h1`.
93
103
  *
94
- * `withBlockKey` stamps every rendered block with its contract-B `_key` —
95
- * required so the visual page builder (L16) can map a clicked element in the
96
- * rendered iframe back to the block that produced it.
104
+ * `withBlockKey` stamps every rendered block with its contract-B `_key`, so
105
+ * the visual page builder (L16) can map a clicked element back to its block.
97
106
  */
98
107
  export function renderPage(page, ctx, entries = {}, registry) {
99
- const entryHeader = renderEntryHeader(page, ctx);
100
- return h('main', { class: 'cg-main', id: 'cg-main' }, entryHeader, entryHeader === null && !pageHasOwnHeading(page.blocks)
101
- ? h('h1', { class: 'cg-page__title' }, page.title)
102
- : null, page.blocks.map((block) => withBlockKey(renderBlock(block, ctx, entries, registry), block._key)));
108
+ const head = pageHasOwnHeading(page.blocks) ? null : renderPageHead(page, ctx);
109
+ return h('main', {
110
+ class: 'cg-main ca-main',
111
+ id: 'cg-main',
112
+ 'data-opening': head === null ? 'hero' : head.kind,
113
+ }, head?.node ?? null, page.blocks.map((block) => withAnchorId(withBlockKey(renderBlock(block, ctx, entries, registry), block._key), block._key)));
103
114
  }
104
115
  //# sourceMappingURL=render-block.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"render-block.js","sourceRoot":"","sources":["../../../src/render/render-block.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"render-block.js","sourceRoot":"","sources":["../../../src/render/render-block.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * The few words a charity's own pages need that the shared vocabulary does
3
+ * not: the labels of an event's or a programme's details, the menu button,
4
+ * and the joining words of a time range.
5
+ *
6
+ * `@cogenta/theme-kit`'s `THEME_STRINGS` carries the strings every theme's
7
+ * blocks share; these belong to one register, so they live with the theme
8
+ * that draws them, in the two languages the shared table knows. A locale the
9
+ * table does not know reads English, the same rule `createThemeTranslator`
10
+ * follows.
11
+ */
12
+ type AssociationStringKey = 'when' | 'where' | 'address' | 'cost' | 'booking' | 'audience' | 'contact' | 'details' | 'timeRange' | 'menu' | 'close' | 'primaryNav' | 'footerNav' | 'share';
13
+ export declare function associationString(locale: string, key: AssociationStringKey, values?: Readonly<Record<string, string | number>>): string;
14
+ export type { AssociationStringKey };
15
+ //# sourceMappingURL=strings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strings.d.ts","sourceRoot":"","sources":["../../../src/render/strings.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AAEH,KAAK,oBAAoB,GACrB,MAAM,GACN,OAAO,GACP,SAAS,GACT,MAAM,GACN,SAAS,GACT,UAAU,GACV,SAAS,GACT,SAAS,GACT,WAAW,GACX,MAAM,GACN,OAAO,GACP,YAAY,GACZ,WAAW,GACX,OAAO,CAAA;AAqCX,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,oBAAoB,EACzB,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC,GACjD,MAAM,CAER;AAED,YAAY,EAAE,oBAAoB,EAAE,CAAA"}
@@ -0,0 +1,39 @@
1
+ import { interpolate, themeLocaleFor } from '@cogenta/theme-kit';
2
+ const STRINGS = {
3
+ en: {
4
+ when: 'When',
5
+ where: 'Where',
6
+ address: 'Address',
7
+ cost: 'Cost',
8
+ booking: 'Booking',
9
+ audience: 'Who it is for',
10
+ contact: 'Contact',
11
+ details: 'Details',
12
+ timeRange: '{{start}} to {{end}}',
13
+ menu: 'Menu',
14
+ close: 'Close',
15
+ primaryNav: 'Primary',
16
+ footerNav: 'Footer',
17
+ share: 'Share of the total',
18
+ },
19
+ fr: {
20
+ when: 'Quand',
21
+ where: 'Où',
22
+ address: 'Adresse',
23
+ cost: 'Tarif',
24
+ booking: 'Inscription',
25
+ audience: 'Pour qui',
26
+ contact: 'Contact',
27
+ details: 'Informations pratiques',
28
+ timeRange: 'de {{start}} à {{end}}',
29
+ menu: 'Menu',
30
+ close: 'Fermer',
31
+ primaryNav: 'Navigation principale',
32
+ footerNav: 'Pied de page',
33
+ share: 'Part du total',
34
+ },
35
+ };
36
+ export function associationString(locale, key, values) {
37
+ return interpolate(STRINGS[themeLocaleFor(locale)][key], values);
38
+ }
39
+ //# sourceMappingURL=strings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strings.js","sourceRoot":"","sources":["../../../src/render/strings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AA8BhE,MAAM,OAAO,GAAkF;IAC7F,EAAE,EAAE;QACF,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,OAAO;QACd,OAAO,EAAE,SAAS;QAClB,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,SAAS;QAClB,QAAQ,EAAE,eAAe;QACzB,OAAO,EAAE,SAAS;QAClB,OAAO,EAAE,SAAS;QAClB,SAAS,EAAE,sBAAsB;QACjC,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,OAAO;QACd,UAAU,EAAE,SAAS;QACrB,SAAS,EAAE,QAAQ;QACnB,KAAK,EAAE,oBAAoB;KAC5B;IACD,EAAE,EAAE;QACF,IAAI,EAAE,OAAO;QACb,KAAK,EAAE,IAAI;QACX,OAAO,EAAE,SAAS;QAClB,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,aAAa;QACtB,QAAQ,EAAE,UAAU;QACpB,OAAO,EAAE,SAAS;QAClB,OAAO,EAAE,wBAAwB;QACjC,SAAS,EAAE,wBAAwB;QACnC,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,QAAQ;QACf,UAAU,EAAE,uBAAuB;QACnC,SAAS,EAAE,cAAc;QACzB,KAAK,EAAE,eAAe;KACvB;CACF,CAAA;AAED,MAAM,UAAU,iBAAiB,CAC/B,MAAc,EACd,GAAyB,EACzB,MAAkD;IAElD,OAAO,WAAW,CAAC,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAA;AAClE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"term-archive.d.ts","sourceRoot":"","sources":["../../../src/render/term-archive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAK,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AA2B/E,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,gBAAgB,GAAG,WAAW,CAkDtE"}
1
+ {"version":3,"file":"term-archive.d.ts","sourceRoot":"","sources":["../../../src/render/term-archive.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAK,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAwB/E,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,gBAAgB,GAAG,WAAW,CA4EtE"}
@@ -1,42 +1,50 @@
1
1
  import { h } from '@cogenta/theme-kit';
2
+ import { arrowWords } from './layout.js';
2
3
  /**
3
- * The taxonomy-term archive (contract D `theme@1.3`) — a card grid, the same
4
- * register the home page's "Upcoming events" `collectionList` uses: a
5
- * rounded, shadowed card per entry, with a big day/month badge when the
6
- * entry carries a publication date, title and summary underneath. There is
7
- * no `entryImage` here (`TermArchiveEntry` carries no image field), so the
8
- * card leans on the date badge and warm surface colour for shape instead of
9
- * a missing photo.
4
+ * The taxonomy-term archive (contract D `theme@1.3`), in the organisation's
5
+ * own register: a breadcrumb in small words, the term as the page title, its
6
+ * sub-terms as a row of links, then the classified entries as ruled rows of
7
+ * titles, dates and summaries, and a pager of two arrow links.
8
+ *
9
+ * `TermArchiveEntry` carries no picture and no event date, so an archive is
10
+ * an index, drawn like one, rather than a calendar with its days missing. A
11
+ * site that wants a calendar of one kind of event builds it from a
12
+ * `collectionList`, which carries both.
10
13
  */
11
- function dateBadge(publishedAt) {
12
- if (publishedAt === null)
13
- return null;
14
- const date = new Date(publishedAt);
15
- if (Number.isNaN(date.getTime()))
16
- return null;
17
- return h('time', { class: 'cg-archive-card__date', datetime: publishedAt }, h('span', { class: 'cg-archive-card__day' }, String(date.getUTCDate())), h('span', { class: 'cg-archive-card__month' }, new Intl.DateTimeFormat('en', { month: 'short' }).format(date)));
14
+ function formatDate(iso, locale) {
15
+ try {
16
+ return new Intl.DateTimeFormat(locale, { dateStyle: 'long', timeZone: 'UTC' }).format(new Date(iso));
17
+ }
18
+ catch {
19
+ return iso;
20
+ }
18
21
  }
19
22
  export function renderTermArchive(input) {
20
- const cards = input.entries.map((entry) => h('li', { class: 'cg-archive-card' }, dateBadge(entry.publishedAt), h('div', { class: 'cg-archive-card__body' }, h('h2', { class: 'cg-archive-card__title' }, entry.href === null
23
+ const rows = input.entries.map((entry) => h('li', { class: 'ca-index__item' }, h('h2', { class: 'ca-index__title' }, entry.href === null
21
24
  ? entry.title
22
- : h('a', { class: 'cg-archive-card__link', href: entry.href }, entry.title)), entry.summary === null
25
+ : h('a', { class: 'ca-index__link', href: entry.href }, entry.title)), entry.publishedAt === null
23
26
  ? null
24
- : h('p', { class: 'cg-archive-card__excerpt' }, entry.summary))));
25
- return h('main', { class: 'cg-main cg-archive', id: 'cg-main' }, input.ancestors.length === 0
27
+ : h('p', { class: 'ca-index__date' }, h('time', { datetime: entry.publishedAt }, formatDate(entry.publishedAt, input.locale))), entry.summary === null ? null : h('p', { class: 'ca-index__text' }, entry.summary)));
28
+ return h('main', { class: 'cg-main ca-main ca-archive', id: 'cg-main' }, h('header', { class: 'ca-page-head' }, h('div', { class: 'ca-container ca-page-head__inner' }, input.ancestors.length === 0
26
29
  ? null
27
- : h('nav', { class: 'cg-archive__breadcrumb', 'aria-label': input.labels.breadcrumb }, h('ol', {}, ...input.ancestors.map((link) => h('li', {}, h('a', { href: link.href }, link.label))))), h('h1', { class: 'cg-archive__title' }, input.term.label), input.children.length === 0
30
+ : h('nav', { class: 'ca-archive__breadcrumb', 'aria-label': input.labels.breadcrumb }, h('ol', { class: 'ca-archive__trail' }, input.ancestors.map((link) => h('li', {}, h('a', { href: link.href }, link.label))))), h('h1', { class: 'ca-page-head__title' }, input.term.label))), input.children.length === 0
28
31
  ? null
29
- : h('ul', { class: 'cg-archive__children', 'aria-label': input.labels.subterms }, ...input.children.map((child) => h('li', {}, h('a', { href: child.href }, child.label)))), cards.length === 0
30
- ? h('p', { class: 'cg-archive__empty' }, input.labels.empty)
31
- : h('ul', { class: 'cg-archive__grid' }, ...cards), pager(input));
32
+ : h('div', { class: 'ca-section ca-archive__children' }, h('div', { class: 'ca-container' }, h('ul', { class: 'ca-archive__terms', 'aria-label': input.labels.subterms }, input.children.map((child) => h('li', { class: 'ca-archive__term' }, h('a', { href: child.href }, child.label)))))), h('section', { class: 'ca-section ca-list', 'data-shape': rows.length === 0 ? 'empty' : 'index' }, h('div', { class: 'ca-container ca-list__inner' }, rows.length === 0
33
+ ? h('p', { class: 'ca-empty' }, input.labels.empty)
34
+ : h('ul', { class: 'ca-list__items ca-index' }, rows), pager(input))));
32
35
  }
33
36
  function pager(input) {
34
37
  if (input.page.previousHref === null && input.page.nextHref === null)
35
38
  return null;
36
- return h('nav', { class: 'cg-archive__pager', 'aria-label': input.labels.pagination }, input.page.previousHref === null
39
+ return h('nav', { class: 'ca-archive__pager', 'aria-label': input.labels.pagination }, input.page.previousHref === null
37
40
  ? null
38
- : h('a', { rel: 'prev', href: input.page.previousHref }, input.labels.previous), input.page.nextHref === null
41
+ : h('a', {
42
+ class: 'ca-arrow-link',
43
+ 'data-direction': 'back',
44
+ rel: 'prev',
45
+ href: input.page.previousHref,
46
+ }, h('span', { class: 'ca-arrow-link__start' }, input.labels.previous)), input.page.nextHref === null
39
47
  ? null
40
- : h('a', { rel: 'next', href: input.page.nextHref }, input.labels.next));
48
+ : h('a', { class: 'ca-arrow-link', rel: 'next', href: input.page.nextHref }, arrowWords(input.labels.next)));
41
49
  }
42
50
  //# sourceMappingURL=term-archive.js.map