@cogenta/theme-magazine 1.1.2 → 1.3.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.
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/render/article.d.ts +32 -0
- package/dist/src/render/article.d.ts.map +1 -0
- package/dist/src/render/article.js +137 -0
- package/dist/src/render/article.js.map +1 -0
- package/dist/src/render/blocks/accordion.d.ts.map +1 -1
- package/dist/src/render/blocks/accordion.js +9 -13
- package/dist/src/render/blocks/accordion.js.map +1 -1
- package/dist/src/render/blocks/collection-list.d.ts.map +1 -1
- package/dist/src/render/blocks/collection-list.js +91 -118
- package/dist/src/render/blocks/collection-list.js.map +1 -1
- package/dist/src/render/blocks/cta.d.ts +4 -4
- package/dist/src/render/blocks/cta.d.ts.map +1 -1
- package/dist/src/render/blocks/cta.js +7 -9
- package/dist/src/render/blocks/cta.js.map +1 -1
- package/dist/src/render/blocks/embed.d.ts.map +1 -1
- package/dist/src/render/blocks/embed.js +17 -20
- package/dist/src/render/blocks/embed.js.map +1 -1
- package/dist/src/render/blocks/faq.d.ts.map +1 -1
- package/dist/src/render/blocks/faq.js +12 -11
- package/dist/src/render/blocks/faq.js.map +1 -1
- package/dist/src/render/blocks/feature-grid.d.ts.map +1 -1
- package/dist/src/render/blocks/feature-grid.js +13 -20
- package/dist/src/render/blocks/feature-grid.js.map +1 -1
- package/dist/src/render/blocks/gallery.d.ts +6 -6
- package/dist/src/render/blocks/gallery.d.ts.map +1 -1
- package/dist/src/render/blocks/gallery.js +15 -13
- package/dist/src/render/blocks/gallery.js.map +1 -1
- package/dist/src/render/blocks/hero.d.ts +6 -5
- package/dist/src/render/blocks/hero.d.ts.map +1 -1
- package/dist/src/render/blocks/hero.js +15 -14
- package/dist/src/render/blocks/hero.js.map +1 -1
- package/dist/src/render/blocks/logo-strip.d.ts.map +1 -1
- package/dist/src/render/blocks/logo-strip.js +8 -11
- package/dist/src/render/blocks/logo-strip.js.map +1 -1
- package/dist/src/render/blocks/logos.d.ts.map +1 -1
- package/dist/src/render/blocks/logos.js +16 -16
- package/dist/src/render/blocks/logos.js.map +1 -1
- package/dist/src/render/blocks/media-figure.d.ts +8 -8
- package/dist/src/render/blocks/media-figure.d.ts.map +1 -1
- package/dist/src/render/blocks/media-figure.js +23 -19
- package/dist/src/render/blocks/media-figure.js.map +1 -1
- package/dist/src/render/blocks/pricing-table.d.ts.map +1 -1
- package/dist/src/render/blocks/pricing-table.js +19 -22
- package/dist/src/render/blocks/pricing-table.js.map +1 -1
- package/dist/src/render/blocks/prose.d.ts +6 -10
- package/dist/src/render/blocks/prose.d.ts.map +1 -1
- package/dist/src/render/blocks/prose.js +8 -11
- package/dist/src/render/blocks/prose.js.map +1 -1
- package/dist/src/render/blocks/quote.d.ts +6 -9
- package/dist/src/render/blocks/quote.d.ts.map +1 -1
- package/dist/src/render/blocks/quote.js +11 -13
- package/dist/src/render/blocks/quote.js.map +1 -1
- package/dist/src/render/blocks/stat-counter.d.ts.map +1 -1
- package/dist/src/render/blocks/stat-counter.js +9 -10
- package/dist/src/render/blocks/stat-counter.js.map +1 -1
- package/dist/src/render/blocks/stats.d.ts.map +1 -1
- package/dist/src/render/blocks/stats.js +9 -12
- package/dist/src/render/blocks/stats.js.map +1 -1
- package/dist/src/render/blocks/testimonial.d.ts +4 -13
- package/dist/src/render/blocks/testimonial.d.ts.map +1 -1
- package/dist/src/render/blocks/testimonial.js +7 -15
- package/dist/src/render/blocks/testimonial.js.map +1 -1
- package/dist/src/render/chrome.d.ts.map +1 -1
- package/dist/src/render/chrome.js +109 -97
- package/dist/src/render/chrome.js.map +1 -1
- package/dist/src/render/layout.d.ts +28 -0
- package/dist/src/render/layout.d.ts.map +1 -0
- package/dist/src/render/layout.js +72 -0
- package/dist/src/render/layout.js.map +1 -0
- package/dist/src/render/render-block.d.ts +15 -13
- package/dist/src/render/render-block.d.ts.map +1 -1
- package/dist/src/render/render-block.js +53 -29
- package/dist/src/render/render-block.js.map +1 -1
- package/dist/src/render/story.d.ts +41 -0
- package/dist/src/render/story.d.ts.map +1 -0
- package/dist/src/render/story.js +65 -0
- package/dist/src/render/story.js.map +1 -0
- package/dist/src/render/term-archive.d.ts +0 -10
- package/dist/src/render/term-archive.d.ts.map +1 -1
- package/dist/src/render/term-archive.js +42 -19
- package/dist/src/render/term-archive.js.map +1 -1
- package/dist/src/render/widget-areas.d.ts +12 -0
- package/dist/src/render/widget-areas.d.ts.map +1 -0
- package/dist/src/render/widget-areas.js +19 -0
- package/dist/src/render/widget-areas.js.map +1 -0
- package/dist/theme.config.js +2 -2
- package/dist/theme.config.js.map +1 -1
- package/package.json +5 -5
- package/src/index.ts +3 -0
- package/src/render/article.ts +239 -0
- package/src/render/blocks/accordion.ts +23 -30
- package/src/render/blocks/collection-list.ts +161 -225
- package/src/render/blocks/cta.ts +19 -13
- package/src/render/blocks/embed.ts +40 -36
- package/src/render/blocks/faq.ts +31 -36
- package/src/render/blocks/feature-grid.ts +26 -36
- package/src/render/blocks/gallery.ts +24 -18
- package/src/render/blocks/hero.ts +32 -32
- package/src/render/blocks/logo-strip.ts +17 -17
- package/src/render/blocks/logos.ts +23 -31
- package/src/render/blocks/media-figure.ts +36 -20
- package/src/render/blocks/pricing-table.ts +29 -34
- package/src/render/blocks/prose.ts +13 -13
- package/src/render/blocks/quote.ts +24 -24
- package/src/render/blocks/stat-counter.ts +16 -24
- package/src/render/blocks/stats.ts +14 -24
- package/src/render/blocks/testimonial.ts +12 -17
- package/src/render/chrome.ts +123 -104
- package/src/render/layout.ts +105 -0
- package/src/render/render-block.ts +61 -33
- package/src/render/story.ts +139 -0
- package/src/render/term-archive.ts +111 -58
- package/src/render/widget-areas.ts +22 -0
- package/src/styles/archive.css +114 -17
- package/src/styles/article.css +237 -0
- package/src/styles/base.css +848 -591
- package/src/styles/blocks.css +903 -921
- package/src/styles/stories.css +593 -0
- package/src/styles/theme.css +28 -9
- package/src/styles/tokens.css +200 -185
- package/src/styles/widgets.css +614 -0
- 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;
|
|
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
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
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
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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', {},
|
|
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 },
|
|
23
|
-
? h('p', { class: 'cg-
|
|
24
|
-
: h('
|
|
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":"AAAA,OAAO,EAAoB,CAAC,EAAyB,MAAM,oBAAoB,CAAA;
|
|
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"}
|
package/dist/theme.config.js
CHANGED
|
@@ -10,8 +10,8 @@ import { defineTheme } from '@cogenta/theme-kit';
|
|
|
10
10
|
*/
|
|
11
11
|
export default defineTheme({
|
|
12
12
|
name: 'magazine',
|
|
13
|
-
version: '1.
|
|
14
|
-
description: '
|
|
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',
|
package/dist/theme.config.js.map
CHANGED
|
@@ -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,
|
|
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.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.3.3",
|
|
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.
|
|
40
|
-
"@cogenta/
|
|
41
|
-
"@cogenta/
|
|
39
|
+
"@cogenta/blocks": "1.1.3",
|
|
40
|
+
"@cogenta/theme-kit": "0.5.3",
|
|
41
|
+
"@cogenta/render": "0.3.5"
|
|
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
|
+
}
|