@geekity/cms 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +870 -0
- package/admin/layouts/_flash.njk +5 -0
- package/admin/layouts/base.njk +27 -0
- package/admin/layouts/dashboard.njk +78 -0
- package/admin/layouts/document-conflict.njk +49 -0
- package/admin/layouts/document-editor.njk +167 -0
- package/admin/layouts/document-list.njk +92 -0
- package/admin/layouts/federation.njk +145 -0
- package/admin/layouts/login.njk +23 -0
- package/admin/layouts/placeholder.njk +10 -0
- package/admin/layouts/settings.njk +116 -0
- package/admin/layouts/setup.njk +27 -0
- package/admin/layouts/shell.njk +37 -0
- package/admin/layouts/users.njk +91 -0
- package/admin/static/admin.css +726 -0
- package/admin/static/editor.js +30 -0
- package/dist/admin/assets.d.ts +26 -0
- package/dist/admin/assets.d.ts.map +1 -0
- package/dist/admin/assets.js +38 -0
- package/dist/admin/assets.js.map +1 -0
- package/dist/admin/credentials.d.ts +28 -0
- package/dist/admin/credentials.d.ts.map +1 -0
- package/dist/admin/credentials.js +39 -0
- package/dist/admin/credentials.js.map +1 -0
- package/dist/admin/documents.d.ts +134 -0
- package/dist/admin/documents.d.ts.map +1 -0
- package/dist/admin/documents.js +613 -0
- package/dist/admin/documents.js.map +1 -0
- package/dist/admin/federation.d.ts +194 -0
- package/dist/admin/federation.d.ts.map +1 -0
- package/dist/admin/federation.js +299 -0
- package/dist/admin/federation.js.map +1 -0
- package/dist/admin/flash.d.ts +24 -0
- package/dist/admin/flash.d.ts.map +1 -0
- package/dist/admin/flash.js +31 -0
- package/dist/admin/flash.js.map +1 -0
- package/dist/admin/index.d.ts +23 -0
- package/dist/admin/index.d.ts.map +1 -0
- package/dist/admin/index.js +15 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/admin/passwords.d.ts +49 -0
- package/dist/admin/passwords.d.ts.map +1 -0
- package/dist/admin/passwords.js +122 -0
- package/dist/admin/passwords.js.map +1 -0
- package/dist/admin/preview.d.ts +18 -0
- package/dist/admin/preview.d.ts.map +1 -0
- package/dist/admin/preview.js +83 -0
- package/dist/admin/preview.js.map +1 -0
- package/dist/admin/routes.d.ts +54 -0
- package/dist/admin/routes.d.ts.map +1 -0
- package/dist/admin/routes.js +383 -0
- package/dist/admin/routes.js.map +1 -0
- package/dist/admin/session.d.ts +44 -0
- package/dist/admin/session.d.ts.map +1 -0
- package/dist/admin/session.js +69 -0
- package/dist/admin/session.js.map +1 -0
- package/dist/admin/settings.d.ts +194 -0
- package/dist/admin/settings.d.ts.map +1 -0
- package/dist/admin/settings.js +470 -0
- package/dist/admin/settings.js.map +1 -0
- package/dist/admin/store.d.ts +407 -0
- package/dist/admin/store.d.ts.map +1 -0
- package/dist/admin/store.js +704 -0
- package/dist/admin/store.js.map +1 -0
- package/dist/admin/templates.d.ts +36 -0
- package/dist/admin/templates.d.ts.map +1 -0
- package/dist/admin/templates.js +43 -0
- package/dist/admin/templates.js.map +1 -0
- package/dist/admin/uploads.d.ts +96 -0
- package/dist/admin/uploads.d.ts.map +1 -0
- package/dist/admin/uploads.js +179 -0
- package/dist/admin/uploads.js.map +1 -0
- package/dist/admin/users.d.ts +95 -0
- package/dist/admin/users.d.ts.map +1 -0
- package/dist/admin/users.js +233 -0
- package/dist/admin/users.js.map +1 -0
- package/dist/cli.d.ts +85 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +424 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +172 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +184 -0
- package/dist/config.js.map +1 -0
- package/dist/content/document.d.ts +66 -0
- package/dist/content/document.d.ts.map +1 -0
- package/dist/content/document.js +13 -0
- package/dist/content/document.js.map +1 -0
- package/dist/content/index.d.ts +17 -0
- package/dist/content/index.d.ts.map +1 -0
- package/dist/content/index.js +10 -0
- package/dist/content/index.js.map +1 -0
- package/dist/content/markdown.d.ts +3 -0
- package/dist/content/markdown.d.ts.map +1 -0
- package/dist/content/markdown.js +39 -0
- package/dist/content/markdown.js.map +1 -0
- package/dist/content/media.d.ts +65 -0
- package/dist/content/media.d.ts.map +1 -0
- package/dist/content/media.js +143 -0
- package/dist/content/media.js.map +1 -0
- package/dist/content/parser.d.ts +24 -0
- package/dist/content/parser.d.ts.map +1 -0
- package/dist/content/parser.js +165 -0
- package/dist/content/parser.js.map +1 -0
- package/dist/content/save.d.ts +60 -0
- package/dist/content/save.d.ts.map +1 -0
- package/dist/content/save.js +103 -0
- package/dist/content/save.js.map +1 -0
- package/dist/content/slug.d.ts +25 -0
- package/dist/content/slug.d.ts.map +1 -0
- package/dist/content/slug.js +75 -0
- package/dist/content/slug.js.map +1 -0
- package/dist/content/store.d.ts +133 -0
- package/dist/content/store.d.ts.map +1 -0
- package/dist/content/store.js +411 -0
- package/dist/content/store.js.map +1 -0
- package/dist/content/sync.d.ts +146 -0
- package/dist/content/sync.d.ts.map +1 -0
- package/dist/content/sync.js +421 -0
- package/dist/content/sync.js.map +1 -0
- package/dist/content/writer.d.ts +37 -0
- package/dist/content/writer.d.ts.map +1 -0
- package/dist/content/writer.js +97 -0
- package/dist/content/writer.js.map +1 -0
- package/dist/env.d.ts +48 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +2 -0
- package/dist/env.js.map +1 -0
- package/dist/federation/actor.d.ts +55 -0
- package/dist/federation/actor.d.ts.map +1 -0
- package/dist/federation/actor.js +101 -0
- package/dist/federation/actor.js.map +1 -0
- package/dist/federation/article.d.ts +83 -0
- package/dist/federation/article.d.ts.map +1 -0
- package/dist/federation/article.js +169 -0
- package/dist/federation/article.js.map +1 -0
- package/dist/federation/delivery.d.ts +90 -0
- package/dist/federation/delivery.d.ts.map +1 -0
- package/dist/federation/delivery.js +289 -0
- package/dist/federation/delivery.js.map +1 -0
- package/dist/federation/federation.d.ts +75 -0
- package/dist/federation/federation.d.ts.map +1 -0
- package/dist/federation/federation.js +190 -0
- package/dist/federation/federation.js.map +1 -0
- package/dist/federation/followers.d.ts +43 -0
- package/dist/federation/followers.d.ts.map +1 -0
- package/dist/federation/followers.js +69 -0
- package/dist/federation/followers.js.map +1 -0
- package/dist/federation/inbox.d.ts +68 -0
- package/dist/federation/inbox.d.ts.map +1 -0
- package/dist/federation/inbox.js +171 -0
- package/dist/federation/inbox.js.map +1 -0
- package/dist/federation/index.d.ts +14 -0
- package/dist/federation/index.d.ts.map +1 -0
- package/dist/federation/index.js +10 -0
- package/dist/federation/index.js.map +1 -0
- package/dist/federation/keys.d.ts +27 -0
- package/dist/federation/keys.d.ts.map +1 -0
- package/dist/federation/keys.js +60 -0
- package/dist/federation/keys.js.map +1 -0
- package/dist/federation/mount.d.ts +23 -0
- package/dist/federation/mount.d.ts.map +1 -0
- package/dist/federation/mount.js +71 -0
- package/dist/federation/mount.js.map +1 -0
- package/dist/federation/paths.d.ts +85 -0
- package/dist/federation/paths.d.ts.map +1 -0
- package/dist/federation/paths.js +97 -0
- package/dist/federation/paths.js.map +1 -0
- package/dist/index.d.ts +106 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +148 -0
- package/dist/index.js.map +1 -0
- package/dist/init.d.ts +71 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.js +125 -0
- package/dist/init.js.map +1 -0
- package/dist/web/assets.d.ts +65 -0
- package/dist/web/assets.d.ts.map +1 -0
- package/dist/web/assets.js +152 -0
- package/dist/web/assets.js.map +1 -0
- package/dist/web/context.d.ts +121 -0
- package/dist/web/context.d.ts.map +1 -0
- package/dist/web/context.js +112 -0
- package/dist/web/context.js.map +1 -0
- package/dist/web/documents.d.ts +28 -0
- package/dist/web/documents.d.ts.map +1 -0
- package/dist/web/documents.js +39 -0
- package/dist/web/documents.js.map +1 -0
- package/dist/web/feeds.d.ts +122 -0
- package/dist/web/feeds.d.ts.map +1 -0
- package/dist/web/feeds.js +229 -0
- package/dist/web/feeds.js.map +1 -0
- package/dist/web/index.d.ts +17 -0
- package/dist/web/index.d.ts.map +1 -0
- package/dist/web/index.js +10 -0
- package/dist/web/index.js.map +1 -0
- package/dist/web/negotiate.d.ts +219 -0
- package/dist/web/negotiate.d.ts.map +1 -0
- package/dist/web/negotiate.js +409 -0
- package/dist/web/negotiate.js.map +1 -0
- package/dist/web/pagination.d.ts +48 -0
- package/dist/web/pagination.d.ts.map +1 -0
- package/dist/web/pagination.js +30 -0
- package/dist/web/pagination.js.map +1 -0
- package/dist/web/render.d.ts +72 -0
- package/dist/web/render.d.ts.map +1 -0
- package/dist/web/render.js +73 -0
- package/dist/web/render.js.map +1 -0
- package/dist/web/routes.d.ts +31 -0
- package/dist/web/routes.d.ts.map +1 -0
- package/dist/web/routes.js +366 -0
- package/dist/web/routes.js.map +1 -0
- package/dist/web/templates.d.ts +34 -0
- package/dist/web/templates.d.ts.map +1 -0
- package/dist/web/templates.js +106 -0
- package/dist/web/templates.js.map +1 -0
- package/package.json +68 -0
- package/templates/site/content/_data/site.json +8 -0
- package/templates/site/content/pages/about.md +11 -0
- package/templates/site/content/pages/pages.json +3 -0
- package/templates/site/content/posts/2026-01-01-hello-world.md +34 -0
- package/templates/site/content/posts/posts.json +4 -0
- package/templates/site/geekity.config.ts +11 -0
- package/templates/site/gitignore +3 -0
- package/templates/site/server.ts +20 -0
- package/templates/site/tsconfig.json +18 -0
- package/themes/default/README.md +148 -0
- package/themes/default/layouts/404.njk +9 -0
- package/themes/default/layouts/base.njk +59 -0
- package/themes/default/layouts/home.njk +9 -0
- package/themes/default/layouts/page.njk +13 -0
- package/themes/default/layouts/post.njk +30 -0
- package/themes/default/layouts/tag.njk +19 -0
- package/themes/default/partials/pagination.njk +14 -0
- package/themes/default/partials/post-list.njk +24 -0
- package/themes/default/partials/tags.njk +12 -0
- package/themes/default/static/style.css +327 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { isTrashedPath } from '../content/store.js';
|
|
2
|
+
import { postObjectId } from '../federation/paths.js';
|
|
3
|
+
/**
|
|
4
|
+
* Whether the public site may show a document.
|
|
5
|
+
*
|
|
6
|
+
* Two things hide one: `draft: true` in the front matter, and living under
|
|
7
|
+
* `_trash/`. Both stay indexed so the admin can find them; neither is ever
|
|
8
|
+
* served, listed, or fed.
|
|
9
|
+
*/
|
|
10
|
+
export function isPublicDocument(document) {
|
|
11
|
+
return !document.draft && !isTrashedPath(document.path);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* The document a public URL resolves to, or `undefined`.
|
|
15
|
+
*
|
|
16
|
+
* This is the single lookup the public site does: every representation of a
|
|
17
|
+
* document — the theme's HTML, the Markdown file, the JSON object — is the
|
|
18
|
+
* same document found the same way, so they cannot disagree about what exists.
|
|
19
|
+
*/
|
|
20
|
+
export function publicDocumentAt(store, permalink) {
|
|
21
|
+
const document = store.getByPermalink(permalink);
|
|
22
|
+
if (document === undefined || !isPublicDocument(document))
|
|
23
|
+
return undefined;
|
|
24
|
+
return document;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The ActivityStreams id of a document, or `undefined` when it has none.
|
|
28
|
+
*
|
|
29
|
+
* Only a published post federates (doc-4), so only a published post has an id
|
|
30
|
+
* to advertise. This is what the theme's `<link rel="alternate">` points at,
|
|
31
|
+
* and it is deliberately the same string the object dispatcher answers under:
|
|
32
|
+
* the page and the object agree about the post's name in the fediverse.
|
|
33
|
+
*/
|
|
34
|
+
export function activityStreamsId(document, baseUrl) {
|
|
35
|
+
if (document.type !== 'post' || !isPublicDocument(document))
|
|
36
|
+
return undefined;
|
|
37
|
+
return postObjectId(document.slug, baseUrl);
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=documents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documents.js","sourceRoot":"","sources":["../../src/web/documents.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEtD;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAkB;IACjD,OAAO,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAC1D,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAmB,EAAE,SAAiB;IACrE,MAAM,QAAQ,GAAG,KAAK,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;IACjD,IAAI,QAAQ,KAAK,SAAS,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC;QAAE,OAAO,SAAS,CAAC;IAC5E,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAkB,EAAE,OAAe;IACnE,IAAI,QAAQ,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC;QAAE,OAAO,SAAS,CAAC;IAC9E,OAAO,YAAY,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AAC9C,CAAC"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import type { Document } from '../content/document.ts';
|
|
2
|
+
import type { SiteData } from './context.ts';
|
|
3
|
+
import type { ConditionalHeaders } from './negotiate.ts';
|
|
4
|
+
/**
|
|
5
|
+
* The two syndication formats the public site serves.
|
|
6
|
+
*
|
|
7
|
+
* Feeds are fixed routes rather than representations (doc-3): a feed reader
|
|
8
|
+
* sends whatever `Accept` header its HTTP library happened to default to, so
|
|
9
|
+
* the URL has to say which format it wants.
|
|
10
|
+
*/
|
|
11
|
+
export type FeedFormat = 'atom' | 'json';
|
|
12
|
+
/** The file name each format is served under, at the site root and per tag. */
|
|
13
|
+
export declare const FEED_FILES: Readonly<Record<FeedFormat, string>>;
|
|
14
|
+
/** What each format is labelled with on the wire. */
|
|
15
|
+
export declare const FEED_CONTENT_TYPES: Readonly<Record<FeedFormat, string>>;
|
|
16
|
+
/** The `version` every JSON Feed this CMS writes declares. */
|
|
17
|
+
export declare const JSON_FEED_VERSION = "https://jsonfeed.org/version/1.1";
|
|
18
|
+
/** How many entries a feed carries when the site does not say. */
|
|
19
|
+
export declare const DEFAULT_FEED_SIZE = 20;
|
|
20
|
+
/** What the feeds name themselves as. */
|
|
21
|
+
export declare const FEED_GENERATOR = "Geekity";
|
|
22
|
+
/** Where a reader can go to find out what wrote the feed. */
|
|
23
|
+
export declare const FEED_GENERATOR_URI = "https://www.npmjs.com/package/@geekity/cms";
|
|
24
|
+
/**
|
|
25
|
+
* How many entries a feed carries.
|
|
26
|
+
*
|
|
27
|
+
* `feedSize` in `content/_data/site.json` wins; without it a feed is longer
|
|
28
|
+
* than an archive page, because a reader that polls once a day should not miss
|
|
29
|
+
* a post on a site that publishes several.
|
|
30
|
+
*/
|
|
31
|
+
export declare function feedSize(site: SiteData): number;
|
|
32
|
+
/** Everything one feed is built from, whichever format it ends up in. */
|
|
33
|
+
export interface FeedSource {
|
|
34
|
+
/** Site-wide data, for the title, subtitle and author. */
|
|
35
|
+
site: SiteData;
|
|
36
|
+
/** The entries, newest first. Already filtered to what the public may see. */
|
|
37
|
+
documents: readonly Document[];
|
|
38
|
+
/** Title of this feed. The site title, or the site title and the tag. */
|
|
39
|
+
title: string;
|
|
40
|
+
/** Path of the HTML page this feed syndicates: `/` or `/tags/{tag}/`. */
|
|
41
|
+
href: string;
|
|
42
|
+
/** Path of the feed itself, for the self link. */
|
|
43
|
+
feedHref: string;
|
|
44
|
+
/** The site's public origin, for absolute ids and links. */
|
|
45
|
+
baseUrl: string;
|
|
46
|
+
}
|
|
47
|
+
/** One feed as an Atom 1.0 document. */
|
|
48
|
+
export declare function atomFeed(source: FeedSource): string;
|
|
49
|
+
/** A JSON Feed 1.1 document. */
|
|
50
|
+
export interface JsonFeed {
|
|
51
|
+
/** {@link JSON_FEED_VERSION}. */
|
|
52
|
+
version: string;
|
|
53
|
+
/** The feed's name. */
|
|
54
|
+
title: string;
|
|
55
|
+
/** The HTML page this feed syndicates. */
|
|
56
|
+
home_page_url: string;
|
|
57
|
+
/** Where this feed itself lives. */
|
|
58
|
+
feed_url: string;
|
|
59
|
+
/** The site's tagline, when it has one. */
|
|
60
|
+
description?: string;
|
|
61
|
+
/** Site-level authors, when the site names one. */
|
|
62
|
+
authors?: JsonFeedAuthor[];
|
|
63
|
+
/** The entries, newest first. */
|
|
64
|
+
items: JsonFeedItem[];
|
|
65
|
+
}
|
|
66
|
+
/** An author, as JSON Feed 1.1 models one. */
|
|
67
|
+
export interface JsonFeedAuthor {
|
|
68
|
+
name: string;
|
|
69
|
+
}
|
|
70
|
+
/** One entry of a {@link JsonFeed}. */
|
|
71
|
+
export interface JsonFeedItem {
|
|
72
|
+
/** Permanent identifier: the document's absolute URL. */
|
|
73
|
+
id: string;
|
|
74
|
+
/** Where the entry can be read. */
|
|
75
|
+
url: string;
|
|
76
|
+
/** Display title. */
|
|
77
|
+
title: string;
|
|
78
|
+
/** The rendered body. */
|
|
79
|
+
content_html: string;
|
|
80
|
+
/** The document's description, when it has one. */
|
|
81
|
+
summary?: string;
|
|
82
|
+
/** Publish date, RFC 3339. */
|
|
83
|
+
date_published?: string;
|
|
84
|
+
/** Last modification date, RFC 3339. */
|
|
85
|
+
date_modified?: string;
|
|
86
|
+
/** The document's tags, in file order. */
|
|
87
|
+
tags?: string[];
|
|
88
|
+
/** The document's own author, when it names one. */
|
|
89
|
+
authors?: JsonFeedAuthor[];
|
|
90
|
+
}
|
|
91
|
+
/** One feed as a JSON Feed 1.1 document. */
|
|
92
|
+
export declare function jsonFeed(source: FeedSource): JsonFeed;
|
|
93
|
+
/** Everything one feed response needs. */
|
|
94
|
+
export interface FeedResponseOptions {
|
|
95
|
+
/** Which format the body is. */
|
|
96
|
+
format: FeedFormat;
|
|
97
|
+
/** What the feed is built from, for the body and the validator alike. */
|
|
98
|
+
source: FeedSource;
|
|
99
|
+
/** The request's conditional headers, for the 304. */
|
|
100
|
+
conditional?: ConditionalHeaders | undefined;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* One feed as an HTTP response, validator and conditional handling included.
|
|
104
|
+
*
|
|
105
|
+
* Feeds are polled far more often than they change, so the cheap 304 matters
|
|
106
|
+
* more here than anywhere else on the site. The validator covers the documents
|
|
107
|
+
* *and* the feed's own metadata, because a renamed site is a changed feed even
|
|
108
|
+
* when no post moved.
|
|
109
|
+
*/
|
|
110
|
+
export declare function feedResponse(options: FeedResponseOptions): Response;
|
|
111
|
+
/**
|
|
112
|
+
* XML character data, escaped.
|
|
113
|
+
*
|
|
114
|
+
* `<` and `&` have to go; `>` follows them because `]]>` in text is not
|
|
115
|
+
* allowed and spotting it is not worth the trouble. Quotes are escaped too so
|
|
116
|
+
* one function serves attribute values as well as text. Characters XML 1.0
|
|
117
|
+
* cannot represent at all — the C0 controls other than tab, newline and
|
|
118
|
+
* carriage return — are dropped rather than escaped, because there is no
|
|
119
|
+
* spelling of them that would parse.
|
|
120
|
+
*/
|
|
121
|
+
export declare function escapeXml(value: string): string;
|
|
122
|
+
//# sourceMappingURL=feeds.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feeds.d.ts","sourceRoot":"","sources":["../../src/web/feeds.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { absoluteUrl, contentEtag, isNotModified, lastModifiedOf, latestModified, } from './negotiate.js';
|
|
2
|
+
/** The file name each format is served under, at the site root and per tag. */
|
|
3
|
+
export const FEED_FILES = {
|
|
4
|
+
atom: 'feed.xml',
|
|
5
|
+
json: 'feed.json',
|
|
6
|
+
};
|
|
7
|
+
/** What each format is labelled with on the wire. */
|
|
8
|
+
export const FEED_CONTENT_TYPES = {
|
|
9
|
+
atom: 'application/atom+xml; charset=utf-8',
|
|
10
|
+
json: 'application/feed+json; charset=utf-8',
|
|
11
|
+
};
|
|
12
|
+
/** The `version` every JSON Feed this CMS writes declares. */
|
|
13
|
+
export const JSON_FEED_VERSION = 'https://jsonfeed.org/version/1.1';
|
|
14
|
+
/** How many entries a feed carries when the site does not say. */
|
|
15
|
+
export const DEFAULT_FEED_SIZE = 20;
|
|
16
|
+
/** What the feeds name themselves as. */
|
|
17
|
+
export const FEED_GENERATOR = 'Geekity';
|
|
18
|
+
/** Where a reader can go to find out what wrote the feed. */
|
|
19
|
+
export const FEED_GENERATOR_URI = 'https://www.npmjs.com/package/@geekity/cms';
|
|
20
|
+
/**
|
|
21
|
+
* How many entries a feed carries.
|
|
22
|
+
*
|
|
23
|
+
* `feedSize` in `content/_data/site.json` wins; without it a feed is longer
|
|
24
|
+
* than an archive page, because a reader that polls once a day should not miss
|
|
25
|
+
* a post on a site that publishes several.
|
|
26
|
+
*/
|
|
27
|
+
export function feedSize(site) {
|
|
28
|
+
const configured = site['feedSize'];
|
|
29
|
+
if (typeof configured === 'number' && Number.isInteger(configured) && configured > 0) {
|
|
30
|
+
return configured;
|
|
31
|
+
}
|
|
32
|
+
return DEFAULT_FEED_SIZE;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The instant a feed reports as its own `updated`.
|
|
36
|
+
*
|
|
37
|
+
* An empty feed still has to carry one, and it has to be the same on every
|
|
38
|
+
* request or the ETag would change while nothing did, so it is the epoch
|
|
39
|
+
* rather than the clock.
|
|
40
|
+
*/
|
|
41
|
+
const EMPTY_FEED_UPDATED = new Date(0);
|
|
42
|
+
/** One feed as an Atom 1.0 document. */
|
|
43
|
+
export function atomFeed(source) {
|
|
44
|
+
const { site, documents, baseUrl } = source;
|
|
45
|
+
const updated = latestModified(documents) ?? EMPTY_FEED_UPDATED;
|
|
46
|
+
const lines = [
|
|
47
|
+
'<?xml version="1.0" encoding="utf-8"?>',
|
|
48
|
+
'<feed xmlns="http://www.w3.org/2005/Atom">',
|
|
49
|
+
element('id', absoluteUrl(source.href, baseUrl)),
|
|
50
|
+
element('title', source.title),
|
|
51
|
+
...optionalElement('subtitle', site.tagline),
|
|
52
|
+
element('updated', updated.toISOString()),
|
|
53
|
+
link({
|
|
54
|
+
rel: 'self',
|
|
55
|
+
type: FEED_CONTENT_TYPES.atom.split(';')[0] ?? '',
|
|
56
|
+
href: absoluteUrl(source.feedHref, baseUrl),
|
|
57
|
+
}),
|
|
58
|
+
link({ rel: 'alternate', type: 'text/html', href: absoluteUrl(source.href, baseUrl) }),
|
|
59
|
+
` <generator uri="${escapeXml(FEED_GENERATOR_URI)}">${escapeXml(FEED_GENERATOR)}</generator>`,
|
|
60
|
+
...author(site.author, 1),
|
|
61
|
+
];
|
|
62
|
+
for (const document of documents) {
|
|
63
|
+
lines.push(...atomEntry(document, baseUrl));
|
|
64
|
+
}
|
|
65
|
+
lines.push('</feed>', '');
|
|
66
|
+
return lines.join('\n');
|
|
67
|
+
}
|
|
68
|
+
/** One document as an Atom entry. */
|
|
69
|
+
function atomEntry(document, baseUrl) {
|
|
70
|
+
const url = absoluteUrl(document.permalink, baseUrl);
|
|
71
|
+
const updated = lastModifiedOf(document) ?? EMPTY_FEED_UPDATED;
|
|
72
|
+
const published = document.date === undefined ? undefined : new Date(document.date);
|
|
73
|
+
return [
|
|
74
|
+
' <entry>',
|
|
75
|
+
element('id', url, 2),
|
|
76
|
+
element('title', document.title, 2),
|
|
77
|
+
element('updated', updated.toISOString(), 2),
|
|
78
|
+
...(published === undefined || Number.isNaN(published.getTime())
|
|
79
|
+
? []
|
|
80
|
+
: [element('published', published.toISOString(), 2)]),
|
|
81
|
+
link({ rel: 'alternate', type: 'text/html', href: url }, 2),
|
|
82
|
+
...author(document.author, 2),
|
|
83
|
+
...document.tags.map((tag) => ` <category term="${escapeXml(tag)}"/>`),
|
|
84
|
+
...(document.description === undefined
|
|
85
|
+
? []
|
|
86
|
+
: [` <summary type="text">${escapeXml(document.description)}</summary>`]),
|
|
87
|
+
// `type="html"` means the markup is escaped rather than inlined, so a
|
|
88
|
+
// reader that does not parse XHTML still gets the whole post.
|
|
89
|
+
` <content type="html">${escapeXml(document.html)}</content>`,
|
|
90
|
+
' </entry>',
|
|
91
|
+
];
|
|
92
|
+
}
|
|
93
|
+
/** One feed as a JSON Feed 1.1 document. */
|
|
94
|
+
export function jsonFeed(source) {
|
|
95
|
+
const { site, baseUrl } = source;
|
|
96
|
+
return {
|
|
97
|
+
version: JSON_FEED_VERSION,
|
|
98
|
+
title: source.title,
|
|
99
|
+
home_page_url: absoluteUrl(source.href, baseUrl),
|
|
100
|
+
feed_url: absoluteUrl(source.feedHref, baseUrl),
|
|
101
|
+
...(site.tagline === undefined ? {} : { description: site.tagline }),
|
|
102
|
+
...(site.author === undefined ? {} : { authors: [{ name: site.author }] }),
|
|
103
|
+
items: source.documents.map((document) => jsonFeedItem(document, baseUrl)),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/** One document as a JSON Feed item. */
|
|
107
|
+
function jsonFeedItem(document, baseUrl) {
|
|
108
|
+
const url = absoluteUrl(document.permalink, baseUrl);
|
|
109
|
+
const item = {
|
|
110
|
+
id: url,
|
|
111
|
+
url,
|
|
112
|
+
title: document.title,
|
|
113
|
+
content_html: document.html,
|
|
114
|
+
};
|
|
115
|
+
if (document.description !== undefined)
|
|
116
|
+
item.summary = document.description;
|
|
117
|
+
const published = document.date === undefined ? undefined : new Date(document.date);
|
|
118
|
+
if (published !== undefined && !Number.isNaN(published.getTime())) {
|
|
119
|
+
item.date_published = published.toISOString();
|
|
120
|
+
}
|
|
121
|
+
const modified = lastModifiedOf(document);
|
|
122
|
+
if (modified !== undefined)
|
|
123
|
+
item.date_modified = modified.toISOString();
|
|
124
|
+
if (document.tags.length > 0)
|
|
125
|
+
item.tags = [...document.tags];
|
|
126
|
+
if (document.author !== undefined)
|
|
127
|
+
item.authors = [{ name: document.author }];
|
|
128
|
+
return item;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* One feed as an HTTP response, validator and conditional handling included.
|
|
132
|
+
*
|
|
133
|
+
* Feeds are polled far more often than they change, so the cheap 304 matters
|
|
134
|
+
* more here than anywhere else on the site. The validator covers the documents
|
|
135
|
+
* *and* the feed's own metadata, because a renamed site is a changed feed even
|
|
136
|
+
* when no post moved.
|
|
137
|
+
*/
|
|
138
|
+
export function feedResponse(options) {
|
|
139
|
+
const { format, source } = options;
|
|
140
|
+
const etag = contentEtag(`feed:${format}`, feedFingerprint(source));
|
|
141
|
+
const lastModified = latestModified(source.documents);
|
|
142
|
+
const headers = new Headers({ etag, 'cache-control': 'no-cache' });
|
|
143
|
+
if (lastModified !== undefined)
|
|
144
|
+
headers.set('last-modified', lastModified.toUTCString());
|
|
145
|
+
if (isNotModified(options.conditional, etag, lastModified)) {
|
|
146
|
+
return new Response(null, { status: 304, headers });
|
|
147
|
+
}
|
|
148
|
+
headers.set('content-type', FEED_CONTENT_TYPES[format]);
|
|
149
|
+
const body = format === 'atom' ? atomFeed(source) : `${JSON.stringify(jsonFeed(source), undefined, 2)}\n`;
|
|
150
|
+
return new Response(body, { headers });
|
|
151
|
+
}
|
|
152
|
+
/** What a feed is made of, as one string to hash. */
|
|
153
|
+
function feedFingerprint(source) {
|
|
154
|
+
return [
|
|
155
|
+
source.feedHref,
|
|
156
|
+
source.title,
|
|
157
|
+
source.site.tagline ?? '',
|
|
158
|
+
source.site.author ?? '',
|
|
159
|
+
source.baseUrl,
|
|
160
|
+
...source.documents.map((document) => document.hash),
|
|
161
|
+
].join('\n');
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* XML character data, escaped.
|
|
165
|
+
*
|
|
166
|
+
* `<` and `&` have to go; `>` follows them because `]]>` in text is not
|
|
167
|
+
* allowed and spotting it is not worth the trouble. Quotes are escaped too so
|
|
168
|
+
* one function serves attribute values as well as text. Characters XML 1.0
|
|
169
|
+
* cannot represent at all — the C0 controls other than tab, newline and
|
|
170
|
+
* carriage return — are dropped rather than escaped, because there is no
|
|
171
|
+
* spelling of them that would parse.
|
|
172
|
+
*/
|
|
173
|
+
export function escapeXml(value) {
|
|
174
|
+
let out = '';
|
|
175
|
+
for (const character of value) {
|
|
176
|
+
switch (character) {
|
|
177
|
+
case '&':
|
|
178
|
+
out += '&';
|
|
179
|
+
break;
|
|
180
|
+
case '<':
|
|
181
|
+
out += '<';
|
|
182
|
+
break;
|
|
183
|
+
case '>':
|
|
184
|
+
out += '>';
|
|
185
|
+
break;
|
|
186
|
+
case '"':
|
|
187
|
+
out += '"';
|
|
188
|
+
break;
|
|
189
|
+
case "'":
|
|
190
|
+
out += ''';
|
|
191
|
+
break;
|
|
192
|
+
default:
|
|
193
|
+
if (isValidXmlChar(character))
|
|
194
|
+
out += character;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return out;
|
|
198
|
+
}
|
|
199
|
+
/** Whether a character is one XML 1.0 allows in a document at all. */
|
|
200
|
+
function isValidXmlChar(character) {
|
|
201
|
+
const code = character.codePointAt(0) ?? 0;
|
|
202
|
+
if (code === 0x9 || code === 0xa || code === 0xd)
|
|
203
|
+
return true;
|
|
204
|
+
if (code >= 0x20 && code <= 0xd7ff)
|
|
205
|
+
return true;
|
|
206
|
+
if (code >= 0xe000 && code <= 0xfffd)
|
|
207
|
+
return true;
|
|
208
|
+
return code >= 0x10000 && code <= 0x10ffff;
|
|
209
|
+
}
|
|
210
|
+
/** An element holding text, indented. */
|
|
211
|
+
function element(name, text, depth = 1) {
|
|
212
|
+
return `${' '.repeat(depth)}<${name}>${escapeXml(text)}</${name}>`;
|
|
213
|
+
}
|
|
214
|
+
/** The same, or nothing at all when there is no value. */
|
|
215
|
+
function optionalElement(name, text, depth = 1) {
|
|
216
|
+
return text === undefined ? [] : [element(name, text, depth)];
|
|
217
|
+
}
|
|
218
|
+
/** An Atom `<link>`. */
|
|
219
|
+
function link(attributes, depth = 1) {
|
|
220
|
+
return `${' '.repeat(depth)}<link rel="${escapeXml(attributes.rel)}" type="${escapeXml(attributes.type)}" href="${escapeXml(attributes.href)}"/>`;
|
|
221
|
+
}
|
|
222
|
+
/** An Atom `<author>`, or nothing when nobody is named. */
|
|
223
|
+
function author(name, depth) {
|
|
224
|
+
if (name === undefined)
|
|
225
|
+
return [];
|
|
226
|
+
const indent = ' '.repeat(depth);
|
|
227
|
+
return [`${indent}<author>`, element('name', name, depth + 1), `${indent}</author>`];
|
|
228
|
+
}
|
|
229
|
+
//# sourceMappingURL=feeds.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feeds.js","sourceRoot":"","sources":["../../src/web/feeds.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export { assetNotModified, assetResponse, findAsset, findThemeAsset, findUpload, matchesEtag, themeAssetNotModified, themeAssetResponse, themeSearchPath, THEME_ASSET_MAX_AGE, THEME_ASSET_PREFIX, THEME_STATIC_DIR, UPLOAD_ASSET_MAX_AGE, UPLOAD_ASSET_PREFIX, UPLOAD_DIRECTORY, } from './assets.ts';
|
|
2
|
+
export type { AssetResponseOptions, StaticAsset, ThemeAsset } from './assets.ts';
|
|
3
|
+
export { createSiteDataSource, DEFAULT_POSTS_PER_PAGE, documentContext, postsPerPage, SITE_DATA_FILE, } from './context.ts';
|
|
4
|
+
export type { CreateSiteDataSourceOptions, DocumentContext, PageContext, SiteData, SiteDataSource, SiteSettingsSource, } from './context.ts';
|
|
5
|
+
export { activityStreamsId, isPublicDocument, publicDocumentAt } from './documents.ts';
|
|
6
|
+
export { atomFeed, DEFAULT_FEED_SIZE, escapeXml, FEED_CONTENT_TYPES, FEED_FILES, FEED_GENERATOR, FEED_GENERATOR_URI, feedResponse, feedSize, jsonFeed, JSON_FEED_VERSION, } from './feeds.ts';
|
|
7
|
+
export type { FeedFormat, FeedResponseOptions, FeedSource, JsonFeed, JsonFeedAuthor, JsonFeedItem, } from './feeds.ts';
|
|
8
|
+
export { absoluteUrl, ACTIVITY_STREAMS_MEDIA_TYPES, alternateLinks, contentEtag, DOCUMENT_REPRESENTATIONS, documentJson, isNotModified, latestModified, JSON_SCHEMA_VERSION, lastModifiedOf, LISTING_REPRESENTATIONS, MEDIA_TYPES, notAcceptableResponse, parseAccept, prefersActivityStreams, representationEtag, representationHref, REPRESENTATION_EXTENSIONS, representationResponse, selectRepresentation, splitRepresentationExtension, } from './negotiate.ts';
|
|
9
|
+
export type { AcceptRange, ConditionalHeaders, DocumentJson, DocumentJsonOptions, Representation, RepresentationExtension, RepresentationResponseOptions, } from './negotiate.ts';
|
|
10
|
+
export { offsetForPage, paginate } from './pagination.ts';
|
|
11
|
+
export type { Pagination, PaginateOptions } from './pagination.ts';
|
|
12
|
+
export { createRenderer, TEMPLATES } from './render.ts';
|
|
13
|
+
export type { CreateRendererOptions, Listing, Renderer } from './render.ts';
|
|
14
|
+
export { feedHref, homeHref, mountPublicSite, PAGE_SEGMENT, tagHref, TAG_SEGMENT, } from './routes.ts';
|
|
15
|
+
export { createTemplateEnvironment, formatDate, PACKAGED_THEME_DIR } from './templates.ts';
|
|
16
|
+
export type { CreateTemplateEnvironmentOptions, DateFormat } from './templates.ts';
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/web/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,SAAS,EACT,cAAc,EACd,UAAU,EACV,WAAW,EACX,qBAAqB,EACrB,kBAAkB,EAClB,eAAe,EACf,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,oBAAoB,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACjF,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,eAAe,EACf,YAAY,EACZ,cAAc,GACf,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,2BAA2B,EAC3B,eAAe,EACf,WAAW,EACX,QAAQ,EACR,cAAc,EACd,kBAAkB,GACnB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvF,OAAO,EACL,QAAQ,EACR,iBAAiB,EACjB,SAAS,EACT,kBAAkB,EAClB,UAAU,EACV,cAAc,EACd,kBAAkB,EAClB,YAAY,EACZ,QAAQ,EACR,QAAQ,EACR,iBAAiB,GAClB,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,UAAU,EACV,mBAAmB,EACnB,UAAU,EACV,QAAQ,EACR,cAAc,EACd,YAAY,GACb,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,WAAW,EACX,4BAA4B,EAC5B,cAAc,EACd,WAAW,EACX,wBAAwB,EACxB,YAAY,EACZ,aAAa,EACb,cAAc,EACd,mBAAmB,EACnB,cAAc,EACd,uBAAuB,EACvB,WAAW,EACX,qBAAqB,EACrB,WAAW,EACX,sBAAsB,EACtB,kBAAkB,EAClB,kBAAkB,EAClB,yBAAyB,EACzB,sBAAsB,EACtB,oBAAoB,EACpB,4BAA4B,GAC7B,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,WAAW,EACX,kBAAkB,EAClB,YAAY,EACZ,mBAAmB,EACnB,cAAc,EACd,uBAAuB,EACvB,6BAA6B,GAC9B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC1D,YAAY,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,qBAAqB,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5E,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,eAAe,EACf,YAAY,EACZ,OAAO,EACP,WAAW,GACZ,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,yBAAyB,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAC3F,YAAY,EAAE,gCAAgC,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { assetNotModified, assetResponse, findAsset, findThemeAsset, findUpload, matchesEtag, themeAssetNotModified, themeAssetResponse, themeSearchPath, THEME_ASSET_MAX_AGE, THEME_ASSET_PREFIX, THEME_STATIC_DIR, UPLOAD_ASSET_MAX_AGE, UPLOAD_ASSET_PREFIX, UPLOAD_DIRECTORY, } from './assets.js';
|
|
2
|
+
export { createSiteDataSource, DEFAULT_POSTS_PER_PAGE, documentContext, postsPerPage, SITE_DATA_FILE, } from './context.js';
|
|
3
|
+
export { activityStreamsId, isPublicDocument, publicDocumentAt } from './documents.js';
|
|
4
|
+
export { atomFeed, DEFAULT_FEED_SIZE, escapeXml, FEED_CONTENT_TYPES, FEED_FILES, FEED_GENERATOR, FEED_GENERATOR_URI, feedResponse, feedSize, jsonFeed, JSON_FEED_VERSION, } from './feeds.js';
|
|
5
|
+
export { absoluteUrl, ACTIVITY_STREAMS_MEDIA_TYPES, alternateLinks, contentEtag, DOCUMENT_REPRESENTATIONS, documentJson, isNotModified, latestModified, JSON_SCHEMA_VERSION, lastModifiedOf, LISTING_REPRESENTATIONS, MEDIA_TYPES, notAcceptableResponse, parseAccept, prefersActivityStreams, representationEtag, representationHref, REPRESENTATION_EXTENSIONS, representationResponse, selectRepresentation, splitRepresentationExtension, } from './negotiate.js';
|
|
6
|
+
export { offsetForPage, paginate } from './pagination.js';
|
|
7
|
+
export { createRenderer, TEMPLATES } from './render.js';
|
|
8
|
+
export { feedHref, homeHref, mountPublicSite, PAGE_SEGMENT, tagHref, TAG_SEGMENT, } from './routes.js';
|
|
9
|
+
export { createTemplateEnvironment, formatDate, PACKAGED_THEME_DIR } from './templates.js';
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/web/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,SAAS,EACT,cAAc,EACd,UAAU,EACV,WAAW,EACX,qBAAqB,EACrB,kBAAkB,EAClB,eAAe,EACf,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,eAAe,EACf,YAAY,EACZ,cAAc,GACf,MAAM,cAAc,CAAC;AAStB,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvF,OAAO,EACL,QAAQ,EACR,iBAAiB,EACjB,SAAS,EACT,kBAAkB,EAClB,UAAU,EACV,cAAc,EACd,kBAAkB,EAClB,YAAY,EACZ,QAAQ,EACR,QAAQ,EACR,iBAAiB,GAClB,MAAM,YAAY,CAAC;AASpB,OAAO,EACL,WAAW,EACX,4BAA4B,EAC5B,cAAc,EACd,WAAW,EACX,wBAAwB,EACxB,YAAY,EACZ,aAAa,EACb,cAAc,EACd,mBAAmB,EACnB,cAAc,EACd,uBAAuB,EACvB,WAAW,EACX,qBAAqB,EACrB,WAAW,EACX,sBAAsB,EACtB,kBAAkB,EAClB,kBAAkB,EAClB,yBAAyB,EACzB,sBAAsB,EACtB,oBAAoB,EACpB,4BAA4B,GAC7B,MAAM,gBAAgB,CAAC;AAUxB,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE1D,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExD,OAAO,EACL,QAAQ,EACR,QAAQ,EACR,eAAe,EACf,YAAY,EACZ,OAAO,EACP,WAAW,GACZ,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,yBAAyB,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC"}
|