@cogenta/theme-magazine 1.1.3 → 1.3.4

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 (126) hide show
  1. package/dist/src/index.d.ts +3 -0
  2. package/dist/src/index.d.ts.map +1 -1
  3. package/dist/src/index.js +3 -0
  4. package/dist/src/index.js.map +1 -1
  5. package/dist/src/render/article.d.ts +32 -0
  6. package/dist/src/render/article.d.ts.map +1 -0
  7. package/dist/src/render/article.js +137 -0
  8. package/dist/src/render/article.js.map +1 -0
  9. package/dist/src/render/blocks/accordion.d.ts.map +1 -1
  10. package/dist/src/render/blocks/accordion.js +9 -13
  11. package/dist/src/render/blocks/accordion.js.map +1 -1
  12. package/dist/src/render/blocks/collection-list.d.ts.map +1 -1
  13. package/dist/src/render/blocks/collection-list.js +91 -118
  14. package/dist/src/render/blocks/collection-list.js.map +1 -1
  15. package/dist/src/render/blocks/cta.d.ts +4 -4
  16. package/dist/src/render/blocks/cta.d.ts.map +1 -1
  17. package/dist/src/render/blocks/cta.js +7 -9
  18. package/dist/src/render/blocks/cta.js.map +1 -1
  19. package/dist/src/render/blocks/embed.d.ts.map +1 -1
  20. package/dist/src/render/blocks/embed.js +17 -20
  21. package/dist/src/render/blocks/embed.js.map +1 -1
  22. package/dist/src/render/blocks/faq.d.ts.map +1 -1
  23. package/dist/src/render/blocks/faq.js +12 -11
  24. package/dist/src/render/blocks/faq.js.map +1 -1
  25. package/dist/src/render/blocks/feature-grid.d.ts.map +1 -1
  26. package/dist/src/render/blocks/feature-grid.js +13 -20
  27. package/dist/src/render/blocks/feature-grid.js.map +1 -1
  28. package/dist/src/render/blocks/gallery.d.ts +6 -6
  29. package/dist/src/render/blocks/gallery.d.ts.map +1 -1
  30. package/dist/src/render/blocks/gallery.js +15 -13
  31. package/dist/src/render/blocks/gallery.js.map +1 -1
  32. package/dist/src/render/blocks/hero.d.ts +6 -5
  33. package/dist/src/render/blocks/hero.d.ts.map +1 -1
  34. package/dist/src/render/blocks/hero.js +15 -14
  35. package/dist/src/render/blocks/hero.js.map +1 -1
  36. package/dist/src/render/blocks/logo-strip.d.ts.map +1 -1
  37. package/dist/src/render/blocks/logo-strip.js +8 -11
  38. package/dist/src/render/blocks/logo-strip.js.map +1 -1
  39. package/dist/src/render/blocks/logos.d.ts.map +1 -1
  40. package/dist/src/render/blocks/logos.js +16 -16
  41. package/dist/src/render/blocks/logos.js.map +1 -1
  42. package/dist/src/render/blocks/media-figure.d.ts +8 -8
  43. package/dist/src/render/blocks/media-figure.d.ts.map +1 -1
  44. package/dist/src/render/blocks/media-figure.js +23 -19
  45. package/dist/src/render/blocks/media-figure.js.map +1 -1
  46. package/dist/src/render/blocks/pricing-table.d.ts.map +1 -1
  47. package/dist/src/render/blocks/pricing-table.js +19 -22
  48. package/dist/src/render/blocks/pricing-table.js.map +1 -1
  49. package/dist/src/render/blocks/prose.d.ts +6 -10
  50. package/dist/src/render/blocks/prose.d.ts.map +1 -1
  51. package/dist/src/render/blocks/prose.js +8 -11
  52. package/dist/src/render/blocks/prose.js.map +1 -1
  53. package/dist/src/render/blocks/quote.d.ts +6 -9
  54. package/dist/src/render/blocks/quote.d.ts.map +1 -1
  55. package/dist/src/render/blocks/quote.js +11 -13
  56. package/dist/src/render/blocks/quote.js.map +1 -1
  57. package/dist/src/render/blocks/stat-counter.d.ts.map +1 -1
  58. package/dist/src/render/blocks/stat-counter.js +9 -10
  59. package/dist/src/render/blocks/stat-counter.js.map +1 -1
  60. package/dist/src/render/blocks/stats.d.ts.map +1 -1
  61. package/dist/src/render/blocks/stats.js +9 -12
  62. package/dist/src/render/blocks/stats.js.map +1 -1
  63. package/dist/src/render/blocks/testimonial.d.ts +4 -13
  64. package/dist/src/render/blocks/testimonial.d.ts.map +1 -1
  65. package/dist/src/render/blocks/testimonial.js +7 -15
  66. package/dist/src/render/blocks/testimonial.js.map +1 -1
  67. package/dist/src/render/chrome.d.ts.map +1 -1
  68. package/dist/src/render/chrome.js +109 -97
  69. package/dist/src/render/chrome.js.map +1 -1
  70. package/dist/src/render/layout.d.ts +28 -0
  71. package/dist/src/render/layout.d.ts.map +1 -0
  72. package/dist/src/render/layout.js +72 -0
  73. package/dist/src/render/layout.js.map +1 -0
  74. package/dist/src/render/render-block.d.ts +15 -13
  75. package/dist/src/render/render-block.d.ts.map +1 -1
  76. package/dist/src/render/render-block.js +53 -29
  77. package/dist/src/render/render-block.js.map +1 -1
  78. package/dist/src/render/story.d.ts +41 -0
  79. package/dist/src/render/story.d.ts.map +1 -0
  80. package/dist/src/render/story.js +65 -0
  81. package/dist/src/render/story.js.map +1 -0
  82. package/dist/src/render/term-archive.d.ts +0 -10
  83. package/dist/src/render/term-archive.d.ts.map +1 -1
  84. package/dist/src/render/term-archive.js +42 -19
  85. package/dist/src/render/term-archive.js.map +1 -1
  86. package/dist/src/render/widget-areas.d.ts +12 -0
  87. package/dist/src/render/widget-areas.d.ts.map +1 -0
  88. package/dist/src/render/widget-areas.js +19 -0
  89. package/dist/src/render/widget-areas.js.map +1 -0
  90. package/dist/theme.config.js +2 -2
  91. package/dist/theme.config.js.map +1 -1
  92. package/package.json +5 -5
  93. package/src/index.ts +3 -0
  94. package/src/render/article.ts +239 -0
  95. package/src/render/blocks/accordion.ts +23 -30
  96. package/src/render/blocks/collection-list.ts +161 -225
  97. package/src/render/blocks/cta.ts +19 -13
  98. package/src/render/blocks/embed.ts +40 -36
  99. package/src/render/blocks/faq.ts +31 -36
  100. package/src/render/blocks/feature-grid.ts +26 -36
  101. package/src/render/blocks/gallery.ts +24 -18
  102. package/src/render/blocks/hero.ts +32 -32
  103. package/src/render/blocks/logo-strip.ts +17 -17
  104. package/src/render/blocks/logos.ts +23 -31
  105. package/src/render/blocks/media-figure.ts +36 -20
  106. package/src/render/blocks/pricing-table.ts +29 -34
  107. package/src/render/blocks/prose.ts +13 -13
  108. package/src/render/blocks/quote.ts +24 -24
  109. package/src/render/blocks/stat-counter.ts +16 -24
  110. package/src/render/blocks/stats.ts +14 -24
  111. package/src/render/blocks/testimonial.ts +12 -17
  112. package/src/render/chrome.ts +123 -104
  113. package/src/render/layout.ts +105 -0
  114. package/src/render/render-block.ts +61 -33
  115. package/src/render/story.ts +139 -0
  116. package/src/render/term-archive.ts +111 -58
  117. package/src/render/widget-areas.ts +22 -0
  118. package/src/styles/archive.css +114 -17
  119. package/src/styles/article.css +237 -0
  120. package/src/styles/base.css +848 -591
  121. package/src/styles/blocks.css +903 -921
  122. package/src/styles/stories.css +593 -0
  123. package/src/styles/theme.css +28 -9
  124. package/src/styles/tokens.css +200 -185
  125. package/src/styles/widgets.css +614 -0
  126. package/tokens.json +18 -18
@@ -0,0 +1,41 @@
1
+ import { type ContentEntry, type HeadingTag, type HtmlElement, type ImageSource, type RenderContext, type TermArchiveEntry } from '@cogenta/theme-kit';
2
+ /**
3
+ * One story as a listing sets it: a kicker, a headline, a standfirst, a date
4
+ * and, where the slot allows, a photograph. The front page, the rails, the
5
+ * opinion strip, the ranked list and the section front all build their rows
6
+ * from this one unit, so a kicker or a headline reads the same wherever the
7
+ * reader meets it. Which parts show, and at what size, is the slot's choice
8
+ * (`StoryOptions`) and the stylesheet's.
9
+ *
10
+ * The headline is the one link. The photograph links to the same place but
11
+ * is taken out of the tab order and hidden from assistive technology, so a
12
+ * keyboard or screen-reader user meets each story once.
13
+ */
14
+ export interface Story {
15
+ readonly href: string | null;
16
+ readonly title: string;
17
+ readonly kicker?: string;
18
+ readonly standfirst?: string;
19
+ readonly date?: {
20
+ readonly iso: string;
21
+ readonly label: string;
22
+ };
23
+ readonly image?: ImageSource;
24
+ }
25
+ export interface StoryOptions {
26
+ readonly tag: HeadingTag;
27
+ /** A modifier, `cg-story--<variant>`: `lead`, `brief`, `secondary`, `rail`, `column`, `ranked`. */
28
+ readonly variant: string;
29
+ readonly image?: boolean;
30
+ readonly standfirst?: boolean;
31
+ readonly date?: boolean;
32
+ readonly sizes?: string;
33
+ readonly loading?: 'eager' | 'lazy';
34
+ readonly numeral?: string;
35
+ }
36
+ /** A `ContentEntry` as a story: every field read through the shared entry helpers, never assumed. */
37
+ export declare function storyFromEntry(entry: ContentEntry, ctx: RenderContext, imageWidth: number): Story;
38
+ /** A term archive row as a story. `TermArchiveEntry` carries no picture and no kicker, so neither is invented. */
39
+ export declare function storyFromArchive(entry: TermArchiveEntry, locale: string): Story;
40
+ export declare function renderStory(story: Story, options: StoryOptions): HtmlElement;
41
+ //# sourceMappingURL=story.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"story.d.ts","sourceRoot":"","sources":["../../../src/render/story.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,YAAY,EAMjB,KAAK,UAAU,EACf,KAAK,WAAW,EAGhB,KAAK,WAAW,EAChB,KAAK,aAAa,EAElB,KAAK,gBAAgB,EACtB,MAAM,oBAAoB,CAAA;AAG3B;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IAChE,QAAQ,CAAC,KAAK,CAAC,EAAE,WAAW,CAAA;CAC7B;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAA;IACxB,mGAAmG;IACnG,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;IACxB,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAA;IAC7B,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAA;IACvB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,CAAA;IACnC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAC1B;AAED,qGAAqG;AACrG,wBAAgB,cAAc,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,GAAG,KAAK,CAkBjG;AAED,kHAAkH;AAClH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,GAAG,KAAK,CAU/E;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,YAAY,GAAG,WAAW,CAoD5E"}
@@ -0,0 +1,65 @@
1
+ import { entryDate, entryExcerpt, entryHref, entryImage, entryTitle, h, heading, renderImageSource, } from '@cogenta/theme-kit';
2
+ import { entryKicker, shortDate } from './layout.js';
3
+ /** A `ContentEntry` as a story: every field read through the shared entry helpers, never assumed. */
4
+ export function storyFromEntry(entry, ctx, imageWidth) {
5
+ const iso = entryDate(entry);
6
+ const label = iso === undefined ? null : shortDate(iso, ctx.locale);
7
+ const kicker = entryKicker(entry);
8
+ const standfirst = entryExcerpt(entry);
9
+ const image = entryImage(entry, ctx, {
10
+ width: imageWidth,
11
+ height: Math.round((imageWidth * 2) / 3),
12
+ fit: 'cover',
13
+ });
14
+ return {
15
+ href: entryHref(entry, ctx),
16
+ title: entryTitle(entry, ctx),
17
+ ...(kicker === undefined ? {} : { kicker }),
18
+ ...(standfirst === undefined ? {} : { standfirst }),
19
+ ...(iso === undefined || label === null ? {} : { date: { iso, label } }),
20
+ ...(image === undefined || image.kind !== 'image' ? {} : { image }),
21
+ };
22
+ }
23
+ /** A term archive row as a story. `TermArchiveEntry` carries no picture and no kicker, so neither is invented. */
24
+ export function storyFromArchive(entry, locale) {
25
+ const label = entry.publishedAt === null ? null : shortDate(entry.publishedAt, locale);
26
+ return {
27
+ href: entry.href,
28
+ title: entry.title,
29
+ ...(entry.summary === null ? {} : { standfirst: entry.summary }),
30
+ ...(entry.publishedAt === null || label === null
31
+ ? {}
32
+ : { date: { iso: entry.publishedAt, label } }),
33
+ };
34
+ }
35
+ export function renderStory(story, options) {
36
+ const imageOptions = {
37
+ className: 'cg-story__image',
38
+ ...(options.sizes === undefined ? {} : { sizes: options.sizes }),
39
+ ...(options.loading === undefined ? {} : { loading: options.loading }),
40
+ };
41
+ const showImage = options.image === true && story.image !== undefined;
42
+ const titleNode = story.href === null
43
+ ? story.title
44
+ : h('a', { class: 'cg-story__link', href: story.href }, story.title);
45
+ return h('article', {
46
+ class: `cg-story cg-story--${options.variant}`,
47
+ 'data-media': showImage ? 'image' : 'none',
48
+ }, showImage && story.image !== undefined
49
+ ? story.href === null
50
+ ? h('div', { class: 'cg-story__media' }, renderImageSource(story.image, imageOptions))
51
+ : h('a', {
52
+ class: 'cg-story__media',
53
+ href: story.href,
54
+ tabindex: '-1',
55
+ 'aria-hidden': 'true',
56
+ }, renderImageSource(story.image, imageOptions))
57
+ : null, h('div', { class: 'cg-story__body' }, options.numeral === undefined
58
+ ? null
59
+ : h('span', { class: 'cg-story__numeral', 'aria-hidden': 'true' }, options.numeral), story.kicker === undefined ? null : h('p', { class: 'cg-story__kicker' }, story.kicker), heading(options.tag, { class: 'cg-story__title' }, titleNode), options.standfirst === true && story.standfirst !== undefined
60
+ ? h('p', { class: 'cg-story__standfirst' }, story.standfirst)
61
+ : null, options.date === true && story.date !== undefined
62
+ ? h('p', { class: 'cg-story__meta' }, h('time', { datetime: story.date.iso }, story.date.label))
63
+ : null));
64
+ }
65
+ //# sourceMappingURL=story.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"story.js","sourceRoot":"","sources":["../../../src/render/story.ts"],"names":[],"mappings":"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"}
@@ -1,13 +1,3 @@
1
1
  import { type HtmlElement, type TermArchiveInput } from '@cogenta/theme-kit';
2
- /**
3
- * The taxonomy-term archive (contract D `theme@1.3`), as a section front.
4
- *
5
- * A magazine's archive is a section page, so it is built from the same
6
- * `cg-issue__row` rows `collectionList` already sets here — a contents strip,
7
- * not a card grid — under a section head that names the taxonomy as a kicker
8
- * and the term as the section title. Reusing the block's classes is what
9
- * keeps the two looking like the same publication without a second
10
- * stylesheet.
11
- */
12
2
  export declare function renderTermArchive(input: TermArchiveInput): HtmlElement;
13
3
  //# sourceMappingURL=term-archive.d.ts.map
@@ -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;AAE/E;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,gBAAgB,GAAG,WAAW,CA4DtE"}
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;AAmB/E,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,gBAAgB,GAAG,WAAW,CAkGtE"}
@@ -1,35 +1,58 @@
1
1
  import { h } from '@cogenta/theme-kit';
2
+ import { renderStory, storyFromArchive } from './story.js';
2
3
  /**
3
- * The taxonomy-term archive (contract D `theme@1.3`), as a section front.
4
+ * The taxonomy-term archive (contract D `theme@1.3`), set as a section front.
4
5
  *
5
- * A magazine's archive is a section page, so it is built from the same
6
- * `cg-issue__row` rows `collectionList` already sets here — a contents strip,
7
- * not a card grid — under a section head that names the taxonomy as a kicker
8
- * and the term as the section title. Reusing the block's classes is what
9
- * keeps the two looking like the same publication without a second
10
- * stylesheet.
6
+ * The term is the page's title, very large on a double rule, under the
7
+ * taxonomy's name as a kicker. Its stories follow the front page's own
8
+ * composition: the newest as the lead across eight columns, the next three
9
+ * as briefs behind a vertical rule, and the rest in a row of three divided by
10
+ * hairlines. `TermArchiveEntry` carries no picture and no kicker, so a
11
+ * section front is set entirely in type, which is how a newspaper's inside
12
+ * section pages read anyway.
13
+ *
14
+ * Every visible word that is not content comes from `input.labels`, already
15
+ * in the page's language.
11
16
  */
17
+ const BRIEFS = 3;
12
18
  export function renderTermArchive(input) {
13
- const rows = input.entries.map((entry, index) => h('li', { class: 'cg-issue__row' }, h('span', { class: 'cg-issue__row-number', 'aria-hidden': 'true' }, String(index + 1).padStart(2, '0')), h('div', { class: 'cg-issue__row-body' }, h('h2', { class: 'cg-issue__row-title' }, entry.href === null
14
- ? entry.title
15
- : h('a', { class: 'cg-issue__link', href: entry.href }, entry.title)), entry.publishedAt === null
16
- ? null
17
- : h('time', { class: 'cg-issue__row-date', datetime: entry.publishedAt }, entry.publishedAt.slice(0, 10)), entry.summary === null ? null : h('p', { class: 'cg-issue__lead-excerpt' }, entry.summary))));
18
- return h('main', { class: 'cg-main cg-archive', id: 'cg-main' }, input.ancestors.length === 0
19
+ const stories = input.entries.map((entry) => storyFromArchive(entry, input.locale));
20
+ const [lead, ...others] = stories;
21
+ const briefs = others.slice(0, BRIEFS);
22
+ const more = others.slice(BRIEFS);
23
+ return h('main', { class: 'cg-main cg-archive', id: 'cg-main' }, h('header', { class: 'cg-archive__head' }, h('div', { class: 'cg-container cg-archive__head-inner' }, input.ancestors.length === 0
19
24
  ? null
20
- : h('nav', { class: 'cg-archive__breadcrumb', 'aria-label': input.labels.breadcrumb }, h('ol', {}, ...input.ancestors.map((l) => h('li', {}, h('a', { href: l.href }, l.label))))), h('p', { class: 'cg-issue__kicker' }, input.taxonomyName), h('h1', { class: 'cg-page__title' }, input.term.label), input.children.length === 0
25
+ : 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('p', { class: 'cg-archive__kicker' }, input.taxonomyName), h('h1', { class: 'cg-archive__title' }, input.term.label), input.children.length === 0
21
26
  ? null
22
- : h('ul', { class: 'cg-archive__children', 'aria-label': input.labels.subterms }, ...input.children.map((c) => h('li', {}, h('a', { href: c.href }, c.label)))), rows.length === 0
23
- ? h('p', { class: 'cg-issue__empty' }, input.labels.empty)
24
- : h('ul', { class: 'cg-issue__rest' }, ...rows), pager(input));
27
+ : h('ul', { class: 'cg-archive__children', 'aria-label': input.labels.subterms }, input.children.map((child) => h('li', {}, h('a', { href: child.href }, child.label)))))), h('section', { class: 'cg-section cg-listing', 'data-form': 'archive' }, h('div', { class: 'cg-container cg-listing__inner' }, lead === undefined
28
+ ? h('p', { class: 'cg-empty' }, input.labels.empty)
29
+ : h('div', {
30
+ class: 'cg-front',
31
+ 'data-briefs': String(briefs.length),
32
+ 'data-more': String(more.length),
33
+ }, h('div', { class: 'cg-front__lead' }, renderStory(lead, { tag: 'h2', variant: 'lead', standfirst: true, date: true })), briefs.length === 0
34
+ ? null
35
+ : h('ul', { class: 'cg-front__briefs' }, briefs.map((story) => h('li', { class: 'cg-front__brief' }, renderStory(story, {
36
+ tag: 'h2',
37
+ variant: 'brief',
38
+ standfirst: true,
39
+ date: true,
40
+ })))), more.length === 0
41
+ ? null
42
+ : h('ul', { class: 'cg-front__more' }, more.map((story) => h('li', { class: 'cg-front__item' }, renderStory(story, {
43
+ tag: 'h2',
44
+ variant: 'secondary',
45
+ standfirst: true,
46
+ date: true,
47
+ }))))), pager(input))));
25
48
  }
26
49
  function pager(input) {
27
50
  if (input.page.previousHref === null && input.page.nextHref === null)
28
51
  return null;
29
52
  return h('nav', { class: 'cg-archive__pager', 'aria-label': input.labels.pagination }, input.page.previousHref === null
30
53
  ? null
31
- : h('a', { rel: 'prev', href: input.page.previousHref }, input.labels.previous), input.page.nextHref === null
54
+ : h('a', { class: 'cg-archive__pager-link', rel: 'prev', href: input.page.previousHref }, input.labels.previous), input.page.nextHref === null
32
55
  ? null
33
- : h('a', { rel: 'next', href: input.page.nextHref }, input.labels.next));
56
+ : h('a', { class: 'cg-archive__pager-link', rel: 'next', href: input.page.nextHref }, input.labels.next));
34
57
  }
35
58
  //# sourceMappingURL=term-archive.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"term-archive.js","sourceRoot":"","sources":["../../../src/render/term-archive.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"term-archive.js","sourceRoot":"","sources":["../../../src/render/term-archive.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * The widget areas this theme names (contract D `theme@1.6`). Declaring them
3
+ * is what tells the host this theme draws the footer columns inside its own
4
+ * colophon; the page areas are placed by the host in the shared
5
+ * `cg-sidebar-layout` markup, which `styles/widgets.css` sets as a rail.
6
+ */
7
+ export declare const widgetAreas: readonly {
8
+ readonly id: string;
9
+ readonly label: string;
10
+ readonly description?: string;
11
+ }[];
12
+ //# sourceMappingURL=widget-areas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"widget-areas.d.ts","sourceRoot":"","sources":["../../../src/render/widget-areas.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,WAAW,EAAE,SAAS;IACjC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAC9B,EAWA,CAAA"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * The widget areas this theme names (contract D `theme@1.6`). Declaring them
3
+ * is what tells the host this theme draws the footer columns inside its own
4
+ * colophon; the page areas are placed by the host in the shared
5
+ * `cg-sidebar-layout` markup, which `styles/widgets.css` sets as a rail.
6
+ */
7
+ export const widgetAreas = [
8
+ {
9
+ id: 'sidebar',
10
+ label: 'Rail',
11
+ description: 'Beside stories, section fronts and search results.',
12
+ },
13
+ {
14
+ id: 'content-after',
15
+ label: 'Under the story',
16
+ description: 'After an article or a page, before the comments.',
17
+ },
18
+ ];
19
+ //# sourceMappingURL=widget-areas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"widget-areas.js","sourceRoot":"","sources":["../../../src/render/widget-areas.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GAIlB;IACJ;QACE,EAAE,EAAE,SAAS;QACb,KAAK,EAAE,MAAM;QACb,WAAW,EAAE,oDAAoD;KAClE;IACD;QACE,EAAE,EAAE,eAAe;QACnB,KAAK,EAAE,iBAAiB;QACxB,WAAW,EAAE,kDAAkD;KAChE;CACF,CAAA"}
@@ -10,8 +10,8 @@ import { defineTheme } from '@cogenta/theme-kit';
10
10
  */
11
11
  export default defineTheme({
12
12
  name: 'magazine',
13
- version: '1.2.0',
14
- description: 'An editorial magazine theme: print-inspired typography, a front-page "Top stories" grid with rubric rails, a masthead-styled article header, and zero client JavaScript.',
13
+ version: '1.3.0',
14
+ description: 'A news and culture magazine theme: a dated masthead between double rules, an asymmetric front page with briefs and column rules, section rails, an opinion strip, a ranked list, and articles set in Fraunces, Source Serif 4 and Libre Franklin. Zero client JavaScript.',
15
15
  author: 'Cogenta',
16
16
  engine: '^1.0.0',
17
17
  blocks: '^2.0.0',
@@ -1 +1 @@
1
- {"version":3,"file":"theme.config.js","sourceRoot":"","sources":["../theme.config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAEhD;;;;;;;;GAQG;AACH,eAAe,WAAW,CAAC;IACzB,IAAI,EAAE,UAAU;IAChB,OAAO,EAAE,OAAO;IAChB,WAAW,EACT,0KAA0K;IAC5K,MAAM,EAAE,SAAS;IACjB,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,UAAU,EAAE;QACV,MAAM;QACN,OAAO;QACP,aAAa;QACb,aAAa;QACb,KAAK;QACL,SAAS;QACT,OAAO;QACP,KAAK;QACL,OAAO;QACP,OAAO;QACP,gBAAgB;QAChB,OAAO;QACP,aAAa;QACb,cAAc;QACd,WAAW;QACX,aAAa;QACb,WAAW;KACZ;IACD,WAAW,EAAE,CAAC,SAAS,EAAE,MAAM,CAAC;IAChC,OAAO,EAAE,QAAQ;IACjB,MAAM,EAAE,eAAe;IACvB,IAAI,EAAE,EAAE,QAAQ,EAAE,aAAa,EAAE;CAClC,CAAC,CAAA"}
1
+ {"version":3,"file":"theme.config.js","sourceRoot":"","sources":["../theme.config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAEhD;;;;;;;;GAQG;AACH,eAAe,WAAW,CAAC;IACzB,IAAI,EAAE,UAAU;IAChB,OAAO,EAAE,OAAO;IAChB,WAAW,EACT,2QAA2Q;IAC7Q,MAAM,EAAE,SAAS;IACjB,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,QAAQ;IAChB,UAAU,EAAE;QACV,MAAM;QACN,OAAO;QACP,aAAa;QACb,aAAa;QACb,KAAK;QACL,SAAS;QACT,OAAO;QACP,KAAK;QACL,OAAO;QACP,OAAO;QACP,gBAAgB;QAChB,OAAO;QACP,aAAa;QACb,cAAc;QACd,WAAW;QACX,aAAa;QACb,WAAW;KACZ;IACD,WAAW,EAAE,CAAC,SAAS,EAAE,MAAM,CAAC;IAChC,OAAO,EAAE,QAAQ;IACjB,MAAM,EAAE,eAAe;IACvB,IAAI,EAAE,EAAE,QAAQ,EAAE,aAAa,EAAE;CAClC,CAAC,CAAA"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cogenta/theme-magazine",
3
- "version": "1.1.3",
4
- "description": "An editorial magazine theme for Cogenta: print-inspired typography, a lead-story listing grid, zero client JavaScript.",
3
+ "version": "1.3.4",
4
+ "description": "A news and culture magazine theme for Cogenta: a dated masthead, an asymmetric front page with column rules, section rails and long-form article pages, zero client JavaScript.",
5
5
  "license": "MPL-2.0",
6
6
  "type": "module",
7
7
  "sideEffects": false,
@@ -36,9 +36,9 @@
36
36
  "directory": "packages/theme-magazine"
37
37
  },
38
38
  "dependencies": {
39
- "@cogenta/blocks": "1.0.4",
40
- "@cogenta/render": "0.2.4",
41
- "@cogenta/theme-kit": "0.3.3"
39
+ "@cogenta/blocks": "1.1.4",
40
+ "@cogenta/render": "0.3.6",
41
+ "@cogenta/theme-kit": "0.5.4"
42
42
  },
43
43
  "peerDependencies": {
44
44
  "astro": "^7.2.1"
package/src/index.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export * from './render/article.js'
1
2
  export * from './render/blocks/accordion.js'
2
3
  export * from './render/blocks/collection-list.js'
3
4
  export * from './render/blocks/cta.js'
@@ -17,4 +18,6 @@ export * from './render/blocks/stats.js'
17
18
  export * from './render/blocks/testimonial.js'
18
19
  export * from './render/chrome.js'
19
20
  export * from './render/render-block.js'
21
+ export * from './render/story.js'
20
22
  export * from './render/term-archive.js'
23
+ export * from './render/widget-areas.js'
@@ -0,0 +1,239 @@
1
+ import type { VocabularyBlock } from '@cogenta/blocks'
2
+ import {
3
+ type HtmlElement,
4
+ h,
5
+ type PageContent,
6
+ type PageEntryMeta,
7
+ type PageEntryTerm,
8
+ type RenderContext,
9
+ renderImageSource,
10
+ } from '@cogenta/theme-kit'
11
+ import { longDate } from './layout.js'
12
+
13
+ /**
14
+ * The article page, built from `PageContent.entry` (contract D `theme@1.4`)
15
+ * rather than from `renderEntryHeader`'s shared default, because a newspaper
16
+ * sets its furniture in a fixed order: the section as a red kicker, a very
17
+ * large headline, the standfirst in italic, then the byline and the date
18
+ * between hairlines, then the lead photograph.
19
+ *
20
+ * Classification is read by taxonomy name, the one convention this theme
21
+ * adds on top of contract D:
22
+ *
23
+ * - a term of a taxonomy named like a section (`section`, `category`,
24
+ * `topic`, `department`, `rubric`) is the kicker;
25
+ * - a term of a taxonomy named like a byline (`author`, `authors`, `byline`,
26
+ * `contributor`, `writer`) is a name in the byline, linked to that
27
+ * writer's archive;
28
+ * - `entry.author` (the account that wrote the entry, when it has a public
29
+ * name) is the byline only when no byline term exists;
30
+ * - every other term is listed at the foot of the article.
31
+ *
32
+ * A byline is a list of names and nothing else: "By" and "and" are words in
33
+ * a language, and a theme has no translation for them, so the separators are
34
+ * drawn by the stylesheet.
35
+ */
36
+
37
+ const SECTION_TAXONOMIES: ReadonlySet<string> = new Set([
38
+ 'section',
39
+ 'sections',
40
+ 'category',
41
+ 'categories',
42
+ 'topic',
43
+ 'topics',
44
+ 'department',
45
+ 'rubric',
46
+ ])
47
+
48
+ const BYLINE_TAXONOMIES: ReadonlySet<string> = new Set([
49
+ 'author',
50
+ 'authors',
51
+ 'byline',
52
+ 'contributor',
53
+ 'contributors',
54
+ 'writer',
55
+ 'writers',
56
+ ])
57
+
58
+ /** Below this, a reading time tells a reader nothing they can use. */
59
+ const MIN_READING_MINUTES_SHOWN = 2
60
+
61
+ /**
62
+ * A page is set as an article when its entry carries anything an article has
63
+ * (a date, a standfirst, a picture, a classification). A reading time alone
64
+ * does not count: every page with a few paragraphs has one, and an About page
65
+ * set with a byline rule, "2 min read" and a drop cap reads as a news story.
66
+ */
67
+ export function isArticle(entry: PageEntryMeta | undefined): entry is PageEntryMeta {
68
+ if (entry === undefined) return false
69
+ return (
70
+ entry.publishedAt !== undefined ||
71
+ entry.excerpt !== undefined ||
72
+ entry.image !== undefined ||
73
+ (entry.terms ?? []).length > 0
74
+ )
75
+ }
76
+
77
+ function termNode(term: PageEntryTerm, className: string): HtmlElement {
78
+ return term.href === null
79
+ ? h('span', { class: className }, term.label)
80
+ : h('a', { class: className, href: term.href }, term.label)
81
+ }
82
+
83
+ export interface ArticleTerms {
84
+ readonly kicker: PageEntryTerm | undefined
85
+ readonly byline: readonly PageEntryTerm[]
86
+ readonly other: readonly PageEntryTerm[]
87
+ }
88
+
89
+ export function articleTerms(entry: PageEntryMeta): ArticleTerms {
90
+ const terms = entry.terms ?? []
91
+ const kicker = terms.find((term) => SECTION_TAXONOMIES.has(term.taxonomy))
92
+ const byline = terms.filter((term) => BYLINE_TAXONOMIES.has(term.taxonomy))
93
+ const other = terms.filter((term) => term !== kicker && !BYLINE_TAXONOMIES.has(term.taxonomy))
94
+ return { kicker, byline, other }
95
+ }
96
+
97
+ /** The article opens its body with a photograph of its own: that figure, captioned, is the lead image. */
98
+ export function opensWithFigure(blocks: readonly VocabularyBlock[]): boolean {
99
+ return blocks[0]?._type === 'mediaFigure'
100
+ }
101
+
102
+ function renderByline(entry: PageEntryMeta, terms: ArticleTerms): HtmlElement | null {
103
+ if (terms.byline.length > 0) {
104
+ return h(
105
+ 'ul',
106
+ { class: 'cg-byline' },
107
+ terms.byline.map((term) =>
108
+ h('li', { class: 'cg-byline__name' }, termNode(term, 'cg-byline__link')),
109
+ ),
110
+ )
111
+ }
112
+ if (entry.author === undefined) return null
113
+ return h('ul', { class: 'cg-byline' }, h('li', { class: 'cg-byline__name' }, entry.author.name))
114
+ }
115
+
116
+ function renderMeta(
117
+ entry: PageEntryMeta,
118
+ terms: ArticleTerms,
119
+ ctx: RenderContext,
120
+ ): HtmlElement | null {
121
+ const byline = renderByline(entry, terms)
122
+ const date = entry.publishedAt === undefined ? null : longDate(entry.publishedAt, ctx.locale)
123
+ const minutes =
124
+ entry.readingMinutes !== undefined && entry.readingMinutes >= MIN_READING_MINUTES_SHOWN
125
+ ? entry.readingMinutes
126
+ : undefined
127
+ if (byline === null && date === null && minutes === undefined) return null
128
+ return h(
129
+ 'div',
130
+ { class: 'cg-article-head__meta' },
131
+ byline,
132
+ date === null && minutes === undefined
133
+ ? null
134
+ : h(
135
+ 'p',
136
+ { class: 'cg-article-head__dateline' },
137
+ date === null || entry.publishedAt === undefined
138
+ ? null
139
+ : h('time', { class: 'cg-article-head__date', datetime: entry.publishedAt }, date),
140
+ minutes === undefined
141
+ ? null
142
+ : h(
143
+ 'span',
144
+ { class: 'cg-article-head__reading-time' },
145
+ ctx.t('entry.readingTime', { minutes }),
146
+ ),
147
+ ),
148
+ )
149
+ }
150
+
151
+ export function renderArticleHeader(
152
+ page: PageContent,
153
+ entry: PageEntryMeta,
154
+ ctx: RenderContext,
155
+ ): HtmlElement {
156
+ const terms = articleTerms(entry)
157
+ const cover =
158
+ entry.image === undefined || opensWithFigure(page.blocks)
159
+ ? null
160
+ : h(
161
+ 'figure',
162
+ { class: 'cg-article-head__cover' },
163
+ renderImageSource(entry.image, {
164
+ className: 'cg-article-head__image',
165
+ loading: 'eager',
166
+ sizes: '(min-width: 64rem) 66rem, 100vw',
167
+ }),
168
+ )
169
+
170
+ return h(
171
+ 'header',
172
+ { class: 'cg-article-head', 'data-cover': cover === null ? 'none' : 'image' },
173
+ h(
174
+ 'div',
175
+ { class: 'cg-container cg-article-head__inner' },
176
+ terms.kicker === undefined
177
+ ? null
178
+ : h(
179
+ 'p',
180
+ { class: 'cg-article-head__kicker' },
181
+ termNode(terms.kicker, 'cg-article-head__kicker-link'),
182
+ ),
183
+ h('h1', { class: 'cg-article-head__title' }, page.title),
184
+ entry.excerpt === undefined
185
+ ? null
186
+ : h('p', { class: 'cg-article-head__standfirst' }, entry.excerpt),
187
+ renderMeta(entry, terms, ctx),
188
+ cover,
189
+ ),
190
+ )
191
+ }
192
+
193
+ /**
194
+ * The foot of an article: every term that is neither its section nor a name
195
+ * in its byline, each a link to its archive when it has one. `null` when
196
+ * there is none, so an article ends on its last paragraph.
197
+ */
198
+ export function renderArticleFooter(entry: PageEntryMeta): HtmlElement | null {
199
+ const { other } = articleTerms(entry)
200
+ if (other.length === 0) return null
201
+ return h(
202
+ 'footer',
203
+ { class: 'cg-article-foot' },
204
+ h(
205
+ 'div',
206
+ { class: 'cg-container cg-article-foot__inner' },
207
+ h(
208
+ 'ul',
209
+ { class: 'cg-article-foot__terms' },
210
+ other.map((term) =>
211
+ h(
212
+ 'li',
213
+ { class: 'cg-article-foot__term', 'data-taxonomy': term.taxonomy },
214
+ termNode(term, 'cg-article-foot__link'),
215
+ ),
216
+ ),
217
+ ),
218
+ ),
219
+ )
220
+ }
221
+
222
+ /**
223
+ * The title of a page that is not an article. A page that opens on running
224
+ * text (About, Standards) takes the title over its reading column, the way an
225
+ * article does, without an article's furniture; any other page (a pricing
226
+ * page, a landing page) sets its title as a section title on a heavy rule.
227
+ */
228
+ export function renderPageHeader(page: PageContent): HtmlElement {
229
+ const text = page.blocks[0]?._type === 'prose'
230
+ return h(
231
+ 'header',
232
+ { class: 'cg-page-head', 'data-layout': text ? 'text' : 'section' },
233
+ h(
234
+ 'div',
235
+ { class: 'cg-container cg-page-head__inner' },
236
+ h('h1', { class: 'cg-page-head__title' }, page.title),
237
+ ),
238
+ )
239
+ }