@geekity/cms 0.18.0 → 0.19.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/README.md +26 -25
- package/admin/components/public-admin-bar.njk +3 -1
- package/admin/pages/documents/editor.njk +257 -192
- package/admin/static/admin.css +37 -14
- package/dist/admin/documents.d.ts +5 -3
- package/dist/admin/documents.d.ts.map +1 -1
- package/dist/admin/documents.js +76 -20
- package/dist/admin/documents.js.map +1 -1
- package/dist/admin/editor-layout.d.ts +13 -0
- package/dist/admin/editor-layout.d.ts.map +1 -0
- package/dist/admin/editor-layout.js +61 -0
- package/dist/admin/editor-layout.js.map +1 -0
- package/dist/admin/enclosure-field.d.ts +2 -3
- package/dist/admin/enclosure-field.d.ts.map +1 -1
- package/dist/admin/enclosure-field.js +27 -7
- package/dist/admin/enclosure-field.js.map +1 -1
- package/dist/admin/location-field.d.ts +4 -3
- package/dist/admin/location-field.d.ts.map +1 -1
- package/dist/admin/location-field.js +10 -2
- package/dist/admin/location-field.js.map +1 -1
- package/dist/admin/photo-field.d.ts +2 -3
- package/dist/admin/photo-field.d.ts.map +1 -1
- package/dist/admin/photo-field.js +4 -2
- package/dist/admin/photo-field.js.map +1 -1
- package/dist/admin/read-field.d.ts +2 -3
- package/dist/admin/read-field.d.ts.map +1 -1
- package/dist/admin/read-field.js +12 -4
- package/dist/admin/read-field.js.map +1 -1
- package/dist/content/kept-properties.d.ts +5 -0
- package/dist/content/kept-properties.d.ts.map +1 -0
- package/dist/content/kept-properties.js +12 -0
- package/dist/content/kept-properties.js.map +1 -0
- package/dist/content/location.d.ts +4 -0
- package/dist/content/location.d.ts.map +1 -1
- package/dist/content/location.js +35 -3
- package/dist/content/location.js.map +1 -1
- package/dist/content/locations.d.ts +2 -5
- package/dist/content/locations.d.ts.map +1 -1
- package/dist/content/locations.js +2 -77
- package/dist/content/locations.js.map +1 -1
- package/dist/content/permalink-file.d.ts +7 -0
- package/dist/content/permalink-file.d.ts.map +1 -0
- package/dist/content/permalink-file.js +77 -0
- package/dist/content/permalink-file.js.map +1 -0
- package/dist/federation/article.d.ts +4 -3
- package/dist/federation/article.d.ts.map +1 -1
- package/dist/federation/article.js +32 -13
- package/dist/federation/article.js.map +1 -1
- package/dist/federation/citations.d.ts +7 -6
- package/dist/federation/citations.d.ts.map +1 -1
- package/dist/federation/citations.js +44 -28
- package/dist/federation/citations.js.map +1 -1
- package/dist/federation/delivery.d.ts.map +1 -1
- package/dist/federation/delivery.js +23 -16
- package/dist/federation/delivery.js.map +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/indieauth/bearer.d.ts +10 -6
- package/dist/indieauth/bearer.d.ts.map +1 -1
- package/dist/indieauth/bearer.js +11 -9
- package/dist/indieauth/bearer.js.map +1 -1
- package/dist/indieauth/token.js +1 -1
- package/dist/indieauth/token.js.map +1 -1
- package/dist/micropub/create.d.ts +7 -3
- package/dist/micropub/create.d.ts.map +1 -1
- package/dist/micropub/create.js +62 -16
- package/dist/micropub/create.js.map +1 -1
- package/dist/micropub/endpoint.d.ts +4 -5
- package/dist/micropub/endpoint.d.ts.map +1 -1
- package/dist/micropub/endpoint.js +15 -8
- package/dist/micropub/endpoint.js.map +1 -1
- package/dist/micropub/media.d.ts +6 -4
- package/dist/micropub/media.d.ts.map +1 -1
- package/dist/micropub/media.js +7 -5
- package/dist/micropub/media.js.map +1 -1
- package/dist/micropub/update.d.ts +7 -1
- package/dist/micropub/update.d.ts.map +1 -1
- package/dist/micropub/update.js +32 -7
- package/dist/micropub/update.js.map +1 -1
- package/dist/web/admin-bar.d.ts.map +1 -1
- package/dist/web/admin-bar.js +25 -0
- package/dist/web/admin-bar.js.map +1 -1
- package/dist/web/documents.d.ts +21 -6
- package/dist/web/documents.d.ts.map +1 -1
- package/dist/web/documents.js +23 -12
- package/dist/web/documents.js.map +1 -1
- package/dist/web/render.d.ts +5 -4
- package/dist/web/render.d.ts.map +1 -1
- package/dist/web/render.js +20 -11
- package/dist/web/render.js.map +1 -1
- package/dist/web/routes.d.ts.map +1 -1
- package/dist/web/routes.js +15 -4
- package/dist/web/routes.js.map +1 -1
- package/dist/webmention/fetch-public.d.ts +3 -1
- package/dist/webmention/fetch-public.d.ts.map +1 -1
- package/dist/webmention/fetch-public.js +17 -11
- package/dist/webmention/fetch-public.js.map +1 -1
- package/dist/webmention/reply-context.d.ts +18 -5
- package/dist/webmention/reply-context.d.ts.map +1 -1
- package/dist/webmention/reply-context.js +118 -19
- package/dist/webmention/reply-context.js.map +1 -1
- package/dist/webmention/reply-contexts.d.ts +17 -14
- package/dist/webmention/reply-contexts.d.ts.map +1 -1
- package/dist/webmention/reply-contexts.js +32 -21
- package/dist/webmention/reply-contexts.js.map +1 -1
- package/package.json +9 -9
- package/themes/default/README.md +31 -8
- package/themes/default/layouts/post.njk +5 -6
- package/themes/default/partials/citations.njk +12 -3
- package/themes/default/partials/cited-page.njk +41 -0
- package/themes/default/partials/post-list.njk +8 -5
- package/themes/default/partials/reply-context.njk +2 -9
|
@@ -3,9 +3,9 @@ import type { DocumentChange } from '../content/sync.ts';
|
|
|
3
3
|
import type { HostLookup } from './public-address.ts';
|
|
4
4
|
import type { ReplyContext } from './reply-context.ts';
|
|
5
5
|
/**
|
|
6
|
-
* Where the fetched
|
|
7
|
-
*
|
|
8
|
-
* as the `replyContexts` global.
|
|
6
|
+
* Where the fetched contexts are kept, relative to the content directory: one
|
|
7
|
+
* JSON object keyed by the URL a post replies to, likes, reposts or bookmarks
|
|
8
|
+
* (decision-19). Eleventy reads it as the `replyContexts` global.
|
|
9
9
|
*/
|
|
10
10
|
export declare const REPLY_CONTEXTS_FILE = "_data/replyContexts.json";
|
|
11
11
|
/** Where the service reports a target it could not read. */
|
|
@@ -14,7 +14,7 @@ export interface ReplyContextLogger {
|
|
|
14
14
|
}
|
|
15
15
|
/** What {@link createReplyContextService} needs. */
|
|
16
16
|
export interface CreateReplyContextServiceOptions {
|
|
17
|
-
/** The index, asked which targets are still
|
|
17
|
+
/** The index, asked which targets are still cited. */
|
|
18
18
|
readonly store: ContentStore;
|
|
19
19
|
/** Where the file lives. */
|
|
20
20
|
readonly contentDir: string;
|
|
@@ -23,21 +23,24 @@ export interface CreateReplyContextServiceOptions {
|
|
|
23
23
|
/** Defaults to `console`. */
|
|
24
24
|
readonly logger?: ReplyContextLogger | undefined;
|
|
25
25
|
}
|
|
26
|
-
/**
|
|
26
|
+
/**
|
|
27
|
+
* Keeps the stored contexts in step with the posts that cite: a reply's
|
|
28
|
+
* `in-reply-to`, and a like's, repost's or bookmark's target (TASK-244).
|
|
29
|
+
*/
|
|
27
30
|
export interface ReplyContextService {
|
|
28
31
|
/**
|
|
29
|
-
* Consider one index change. A
|
|
30
|
-
* stored,
|
|
31
|
-
*
|
|
32
|
-
*
|
|
32
|
+
* Consider one index change. A target that is new to the post, or has
|
|
33
|
+
* nothing stored, is fetched; a target no post cites any more is forgotten.
|
|
34
|
+
* Returns at once: the work is queued, so a save never waits on a
|
|
35
|
+
* stranger's server.
|
|
33
36
|
*/
|
|
34
37
|
handle(change: DocumentChange): void;
|
|
35
38
|
/**
|
|
36
|
-
* Fetch every target a live post
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
39
|
+
* Fetch every target a live post cites that the file holds nothing for. Run
|
|
40
|
+
* when the site starts serving, because a scan of an index that is already
|
|
41
|
+
* up to date reports no change: a site upgraded to reply contexts, or one
|
|
42
|
+
* whose file was removed, would otherwise wait for each reply to be edited.
|
|
43
|
+
* Queued like {@link ReplyContextService.handle}.
|
|
41
44
|
*/
|
|
42
45
|
catchUp(): void;
|
|
43
46
|
/** The stored context for a target, from the file. Never touches the network. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reply-contexts.d.ts","sourceRoot":"","sources":["../../src/webmention/reply-contexts.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"reply-contexts.d.ts","sourceRoot":"","sources":["../../src/webmention/reply-contexts.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,6BAA6B,CAAC;AAE9D,4DAA4D;AAC5D,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,oDAAoD;AACpD,MAAM,WAAW,gCAAgC;IAC/C,sDAAsD;IACtD,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,4BAA4B;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,8DAA8D;IAC9D,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,6BAA6B;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;CAClD;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;;;OAKG;IACH,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;IACrC;;;;;;OAMG;IACH,OAAO,IAAI,IAAI,CAAC;IAChB,iFAAiF;IACjF,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAAC;IAC/C,wEAAwE;IACxE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AAED,oDAAoD;AACpD,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,gCAAgC,GACxC,mBAAmB,CAiGrB"}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { readFileSync } from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
+
import { citationsOf } from '../content/citation.js';
|
|
3
4
|
import { replyTarget } from '../content/post-type.js';
|
|
4
5
|
import { updateFileAtomically } from '../files/atomic.js';
|
|
5
6
|
import { fetchReplyContext } from './reply-context.js';
|
|
6
7
|
/**
|
|
7
|
-
* Where the fetched
|
|
8
|
-
*
|
|
9
|
-
* as the `replyContexts` global.
|
|
8
|
+
* Where the fetched contexts are kept, relative to the content directory: one
|
|
9
|
+
* JSON object keyed by the URL a post replies to, likes, reposts or bookmarks
|
|
10
|
+
* (decision-19). Eleventy reads it as the `replyContexts` global.
|
|
10
11
|
*/
|
|
11
12
|
export const REPLY_CONTEXTS_FILE = '_data/replyContexts.json';
|
|
12
13
|
/** Build the reply context service for one site. */
|
|
@@ -47,17 +48,17 @@ export function createReplyContextService(options) {
|
|
|
47
48
|
async function refresh(target) {
|
|
48
49
|
const fetched = await fetchReplyContext(target, { lookup });
|
|
49
50
|
if (!fetched.ok) {
|
|
50
|
-
logger.warn(`Could not read ${target} for a
|
|
51
|
+
logger.warn(`Could not read ${target} for a citation's context: ${fetched.reason}`);
|
|
51
52
|
return;
|
|
52
53
|
}
|
|
53
54
|
await write(target, fetched.context);
|
|
54
55
|
}
|
|
55
|
-
/** Forget a target, unless a post still
|
|
56
|
+
/** Forget a target, unless a post still cites it. */
|
|
56
57
|
async function forget(target) {
|
|
57
58
|
if (!(target in readAll()))
|
|
58
59
|
return;
|
|
59
|
-
const
|
|
60
|
-
if (!
|
|
60
|
+
const stillCited = store.listAll().some((document) => targetsOf(document).includes(target));
|
|
61
|
+
if (!stillCited)
|
|
61
62
|
await write(target, undefined);
|
|
62
63
|
}
|
|
63
64
|
let chain = Promise.resolve();
|
|
@@ -68,27 +69,30 @@ export function createReplyContextService(options) {
|
|
|
68
69
|
}
|
|
69
70
|
return {
|
|
70
71
|
handle(change) {
|
|
71
|
-
const before =
|
|
72
|
-
const after =
|
|
72
|
+
const before = targetsOf(change.previous);
|
|
73
|
+
const after = targetsOf(change.next);
|
|
74
|
+
const held = readAll();
|
|
73
75
|
// A scan rebuilds the index from files the contexts file sits beside, so
|
|
74
76
|
// it only fetches what that file has never held; an edit fetches a
|
|
75
77
|
// target that changed as well.
|
|
76
|
-
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
for (const target of after) {
|
|
79
|
+
const changed = !before.includes(target) && change.origin !== 'scan';
|
|
80
|
+
if (!(target in held) || changed)
|
|
81
|
+
enqueue(() => refresh(target));
|
|
82
|
+
}
|
|
83
|
+
for (const target of before) {
|
|
84
|
+
if (!after.includes(target))
|
|
85
|
+
enqueue(() => forget(target));
|
|
81
86
|
}
|
|
82
|
-
if (before !== undefined && before !== after)
|
|
83
|
-
enqueue(() => forget(before));
|
|
84
87
|
},
|
|
85
88
|
catchUp() {
|
|
86
89
|
const held = readAll();
|
|
87
90
|
const missing = new Set();
|
|
88
91
|
for (const document of store.listAll()) {
|
|
89
|
-
const target
|
|
90
|
-
|
|
91
|
-
|
|
92
|
+
for (const target of targetsOf(document)) {
|
|
93
|
+
if (!(target in held))
|
|
94
|
+
missing.add(target);
|
|
95
|
+
}
|
|
92
96
|
}
|
|
93
97
|
for (const target of missing)
|
|
94
98
|
enqueue(() => refresh(target));
|
|
@@ -101,8 +105,15 @@ export function createReplyContextService(options) {
|
|
|
101
105
|
},
|
|
102
106
|
};
|
|
103
107
|
}
|
|
104
|
-
function
|
|
105
|
-
|
|
108
|
+
function targetsOf(document) {
|
|
109
|
+
if (document === undefined)
|
|
110
|
+
return [];
|
|
111
|
+
const answered = replyTarget(document);
|
|
112
|
+
const targets = [
|
|
113
|
+
...(answered === undefined ? [] : [answered]),
|
|
114
|
+
...citationsOf(document.extra).map((citation) => citation.url),
|
|
115
|
+
];
|
|
116
|
+
return [...new Set(targets)];
|
|
106
117
|
}
|
|
107
118
|
/**
|
|
108
119
|
* The file's entries, each checked, since a person may have edited it by hand.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reply-contexts.js","sourceRoot":"","sources":["../../src/webmention/reply-contexts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAGtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAGvD;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"reply-contexts.js","sourceRoot":"","sources":["../../src/webmention/reply-contexts.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@geekity/cms",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A file-first CMS: Markdown content, a SQLite index, a Hono server that is both the editor and the public site.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -28,25 +28,25 @@
|
|
|
28
28
|
"LICENSE"
|
|
29
29
|
],
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@fedify/fedify": "^2.
|
|
32
|
-
"@fedify/hono": "^2.
|
|
33
|
-
"@fedify/vocab": "^2.
|
|
34
|
-
"@hono/node-server": "^2.1.
|
|
31
|
+
"@fedify/fedify": "^2.4.0",
|
|
32
|
+
"@fedify/hono": "^2.4.0",
|
|
33
|
+
"@fedify/vocab": "^2.4.0",
|
|
34
|
+
"@hono/node-server": "^2.1.3",
|
|
35
35
|
"@js-temporal/polyfill": "^0.5.1",
|
|
36
36
|
"chokidar": "^5.0.0",
|
|
37
37
|
"gray-matter": "^4.0.3",
|
|
38
|
-
"hono": "^4.13.
|
|
38
|
+
"hono": "^4.13.12",
|
|
39
39
|
"js-yaml": "^5.4.2",
|
|
40
40
|
"markdown-it": "^15.0.2",
|
|
41
41
|
"markdown-it-footnote": "^4.0.0",
|
|
42
|
-
"nodemailer": "^10.0.
|
|
42
|
+
"nodemailer": "^10.0.13",
|
|
43
43
|
"nunjucks": "^3.2.4",
|
|
44
|
-
"sharp": "^0.35.
|
|
44
|
+
"sharp": "^0.35.5"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@11ty/eleventy": "^3.1.6",
|
|
48
48
|
"@codemirror/lang-markdown": "^6.5.2",
|
|
49
|
-
"@fedify/cli": "2.
|
|
49
|
+
"@fedify/cli": "2.4.0",
|
|
50
50
|
"@tailwindcss/cli": "^4.3.3",
|
|
51
51
|
"@types/markdown-it-footnote": "^3.0.4",
|
|
52
52
|
"@types/node": "^26.6.3",
|
package/themes/default/README.md
CHANGED
|
@@ -26,6 +26,7 @@ themes/default/
|
|
|
26
26
|
kicker.njk the line above an entry naming its kind and date
|
|
27
27
|
reply-context.njk the citation of what a reply answers
|
|
28
28
|
citations.njk the citation of what a like, repost or bookmark cites
|
|
29
|
+
cited-page.njk the name and author both citations print
|
|
29
30
|
read.njk what a read post read, and how far
|
|
30
31
|
bio.njk who an entry is by, as an h-card
|
|
31
32
|
menu.njk one named menu, as a nav of links
|
|
@@ -405,16 +406,37 @@ is an `h3` inside the form's section.
|
|
|
405
406
|
`div.reply-context.cite.u-in-reply-to.h-cite`: a rule on the start side, a
|
|
406
407
|
`p.cite-line` saying "In reply to" and the target's name, author and date as
|
|
407
408
|
far as they are known, and its excerpt as a `blockquote.cite-quote.p-content`.
|
|
408
|
-
|
|
409
|
-
|
|
409
|
+
Where it goes depends on whether the post shows a title. An untitled reply
|
|
410
|
+
opens on it, under the kicker and before its words. A titled reply prints its
|
|
411
|
+
`header.post-header` first and the citation after it, before the `e-content`,
|
|
412
|
+
so the page opens on its title rather than on a link. A listing follows the
|
|
413
|
+
same rule: an untitled entry cites under its kicker, a titled one after its
|
|
414
|
+
title and summary. The same partial cites a reply in a feed. The layouts own
|
|
415
|
+
the placement; the partial owns only what the citation says, and it stays
|
|
416
|
+
inside the `h-entry` wherever it is printed.
|
|
410
417
|
|
|
411
418
|
**A like, a repost or a bookmark cites what it cites** (TASK-169) with
|
|
412
419
|
`partials/citations.njk`, beside the reply context and drawn the same way: one
|
|
413
420
|
`div.reply-context.cite.h-cite` per entry of `citations`, classed
|
|
414
421
|
`u-repost-of`, `u-like-of` or `u-bookmark-of`, whose `p.cite-line` says
|
|
415
|
-
Reposted, Liked or Bookmarked and links the target as its `u-url`.
|
|
416
|
-
|
|
417
|
-
|
|
422
|
+
Reposted, Liked or Bookmarked and links the target as its `u-url`. The link
|
|
423
|
+
says the target's name, as the reply context does, with its author after it as
|
|
424
|
+
a `p-author h-card`, when the target was read when the post was saved
|
|
425
|
+
(TASK-244): its `h-entry` name, its oEmbed title, or its `<title>`. With only
|
|
426
|
+
an author it says "a post", and with neither the bare URL. Its kicker
|
|
427
|
+
and its hidden `h1` say Repost, Like or Bookmark. It is placed as the reply
|
|
428
|
+
context is: at the top of an untitled post, after the header of a titled one.
|
|
429
|
+
A listing cites each entry's from the same partial, by the same rule.
|
|
430
|
+
|
|
431
|
+
**Both citations name the cited page** through `partials/cited-page.njk`, so
|
|
432
|
+
they print its name and author by one rule. A name that already ends in " by "
|
|
433
|
+
and the author's name, in any case, does not print the author again
|
|
434
|
+
(TASK-247): SoundCloud titles a track "Flickermood by Forss" and names Forss
|
|
435
|
+
as its author. The title link stops before " by ", and the words after it
|
|
436
|
+
become the `p-author h-card`, so the line reads "Liked Flickermood by Forss"
|
|
437
|
+
and a parser still reads the whole title as the `p-name`. A name that mentions
|
|
438
|
+
its author anywhere else, such as "Rick Astley - Never Gonna Give You Up" by
|
|
439
|
+
Rick Astley, keeps the author after it.
|
|
418
440
|
|
|
419
441
|
**A read says what was read** (TASK-229) with `partials/read.njk`, a
|
|
420
442
|
`p.read-line` at the top of the `e-content` that reads like indiebookclub's
|
|
@@ -602,7 +624,8 @@ its kicker:
|
|
|
602
624
|
**Only an article has a headline.** A note, which has no title, is printed
|
|
603
625
|
whole as its `e-content`, and the date in its kicker is its `u-url`. A reply is
|
|
604
626
|
a note that first cites what it answers with `partials/reply-context.njk`, and
|
|
605
|
-
a reply with a title is an article that
|
|
627
|
+
a reply with a title is an article that cites it after its title and summary.
|
|
628
|
+
A like, a repost and a bookmark place `partials/citations.njk` the same way. An article's categories are in
|
|
606
629
|
its kicker; a note's are on its own page.
|
|
607
630
|
|
|
608
631
|
The excerpt is the entry's `summary`, the very line the feeds publish, so a
|
|
@@ -1179,7 +1202,7 @@ A document — one post, one page, or one entry of a listing — adds:
|
|
|
1179
1202
|
| `lang` | The `lang` front matter as a canonical tag, such as `fr-CA`. Absent when it names none or no tag. |
|
|
1180
1203
|
| `enclosure` | The post's recording, parsed, with `player` (`audio` or `video`) and `transcript.captions`. Absent with none. |
|
|
1181
1204
|
| `photos` | The post's photos, each `{ url, alt, html }`; `html` is the `img.u-photo`, responsive. Empty with none. |
|
|
1182
|
-
| `citations` | What it reposts, likes or bookmarks, each `{ property, url }
|
|
1205
|
+
| `citations` | What it reposts, likes or bookmarks, each `{ property, url, context }`; `context` as `replyContext`, when known. |
|
|
1183
1206
|
| `read` | A read post's `{ status, statusLabel, of, line }`; `of` is `{ name, author, uid, uidLabel, url }`. |
|
|
1184
1207
|
| `syndicateTo` | On a post's page, the syndication targets it selects, each `{ id, name, url }`. Empty with none. |
|
|
1185
1208
|
| `syndication` | Its copies elsewhere, each `{ url, label }`: front matter `syndication`, and on its page the copies targets made. |
|
|
@@ -1191,7 +1214,7 @@ A document — one post, one page, or one entry of a listing — adds:
|
|
|
1191
1214
|
| `postsPage` | The page carrying the listing, as `{ title, url }`, on the front page only. Absent when the site names none. |
|
|
1192
1215
|
| `archiveMonths` | Every published post as `{ month, posts }`, newest month first. Only on a page that says `archive: true`. |
|
|
1193
1216
|
| `webmention` | Where a webmention about this page is sent. Only on a rendered document, and only while the site takes them. |
|
|
1194
|
-
| `noindex` | `true` on
|
|
1217
|
+
| `noindex` | `true` on an unlisted or unpublished page, which the base layout prints as a robots `noindex` meta. Else absent. |
|
|
1195
1218
|
| `conversation` | The replies, likes and boosts under the post. Only when there are any. See [The conversation](#the-conversation). |
|
|
1196
1219
|
| everything else | Any front matter key the CMS does not model is on the context under its own name. |
|
|
1197
1220
|
|
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
|
|
6
6
|
An article, and a reply with a title, has the only headline: the title as its
|
|
7
7
|
`p-name` and the author's `description` under it as the deck, a
|
|
8
|
-
`p-summary`. A post with no title opens on its words, set larger.
|
|
9
|
-
|
|
8
|
+
`p-summary`. A post with no title opens on its words, set larger. What a
|
|
9
|
+
reply answers, and what a like, repost or bookmark cites, opens a post with
|
|
10
|
+
no title and follows the header of one with a title, before its words.
|
|
10
11
|
Then the Published line, the tags, a rule and the bio. The neighbouring posts,
|
|
11
12
|
the conversation and the comment form follow the entry.
|
|
12
13
|
|
|
@@ -36,10 +37,6 @@
|
|
|
36
37
|
hidden from sight. It is no `p-name`: a parser would take that as a
|
|
37
38
|
title and read the note as an article. -#}
|
|
38
39
|
{% if named %}
|
|
39
|
-
{#- A reply cites the post it answers, whose URL is also the link its
|
|
40
|
-
webmention points a receiver at. -#}
|
|
41
|
-
{% include "partials/reply-context.njk" %}
|
|
42
|
-
{% include "partials/citations.njk" %}
|
|
43
40
|
<header class="post-header">
|
|
44
41
|
{{ kicker.line(postType | capitalize, false, false, categories) }}
|
|
45
42
|
<h1 class="p-name">{{ title }}</h1>
|
|
@@ -47,6 +44,8 @@
|
|
|
47
44
|
<p class="post-deck p-summary">{{ description }}</p>
|
|
48
45
|
{% endif %}
|
|
49
46
|
</header>
|
|
47
|
+
{% include "partials/reply-context.njk" %}
|
|
48
|
+
{% include "partials/citations.njk" %}
|
|
50
49
|
{% else %}
|
|
51
50
|
<h1 class="screen-reader-text">
|
|
52
51
|
{{- postType | capitalize if postType in ["reply", "like", "repost", "bookmark", "read"] else "Note" }}
|
|
@@ -6,12 +6,21 @@
|
|
|
6
6
|
webmention names links to it.
|
|
7
7
|
|
|
8
8
|
Drawn as the same citation block as `reply-context.njk` (doc-9). An entry
|
|
9
|
-
includes it with `citations` on the context, a list of `{ property, url
|
|
10
|
-
a feed sets it from the entry it is printing.
|
|
9
|
+
includes it with `citations` on the context, a list of `{ property, url,
|
|
10
|
+
context }`; a feed sets it from the entry it is printing.
|
|
11
|
+
|
|
12
|
+
`context` is what the target said about itself when the post was saved or
|
|
13
|
+
synced (TASK-244), only when it said something: its `name` and `author`,
|
|
14
|
+
printed through autoescaping like a reply's context. With a name, the name
|
|
15
|
+
is the link; with only an author, "a post" is; with neither, the bare URL.
|
|
11
16
|
#}
|
|
17
|
+
{% import "partials/cited-page.njk" as cited %}
|
|
12
18
|
{% set citationVerbs = { "repost-of": "Reposted", "like-of": "Liked", "bookmark-of": "Bookmarked" } %}
|
|
13
19
|
{% for citation in citations %}
|
|
20
|
+
{% set citedPage = citation.context %}
|
|
14
21
|
<div class="reply-context cite u-{{ citation.property }} h-cite">
|
|
15
|
-
<p class="cite-line small">{{ citationVerbs[citation.property] }}
|
|
22
|
+
<p class="cite-line small">{{ citationVerbs[citation.property] }}
|
|
23
|
+
{{- cited.page(citation.url, citedPage) -}}
|
|
24
|
+
</p>
|
|
16
25
|
</div>
|
|
17
26
|
{% endfor %}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{#
|
|
2
|
+
What a citation says of the page it cites: its name and its author, the part
|
|
3
|
+
of the line after "In reply to", "Liked" and the rest. Shared by
|
|
4
|
+
`reply-context.njk` and `citations.njk` (TASK-247).
|
|
5
|
+
|
|
6
|
+
{% import "partials/cited-page.njk" as cited %}
|
|
7
|
+
{{ cited.page(inReplyTo, replyContext) }}
|
|
8
|
+
|
|
9
|
+
`url` is the cited page, always its `u-url`. `context` is what the page said
|
|
10
|
+
about itself, from the reply contexts file. With a name, the name is the
|
|
11
|
+
link; with only an author, "a post" is; with neither, the bare URL. The
|
|
12
|
+
author follows as an `h-card`.
|
|
13
|
+
|
|
14
|
+
A name that already ends in " by " and the author's name, matched without
|
|
15
|
+
regard to case (SoundCloud's oEmbed gives "Flickermood by Forss" by Forss),
|
|
16
|
+
is not followed by the author again. Its last words become the `h-card`,
|
|
17
|
+
printed as the title wrote them, and the whole name stays the `p-name`, so a
|
|
18
|
+
parser reads the same name and author either way.
|
|
19
|
+
#}
|
|
20
|
+
{% macro page(url, context) %}
|
|
21
|
+
{%- set title = (context.name or "") | trim -%}
|
|
22
|
+
{%- set author = (context.author.name or "") | trim if context.author else "" -%}
|
|
23
|
+
{%- set cut = title.length - author.length - 4 -%}
|
|
24
|
+
{%- set byline = title.slice(cut) if (author and cut > 0) else "" -%}
|
|
25
|
+
{%- set named = byline and byline.slice(0, 4).toLowerCase() == " by " and byline.slice(4).toLowerCase() == author.toLowerCase() -%}
|
|
26
|
+
{%- if named %} <span class="p-name"><a class="u-url" href="{{ url }}">{{ title.slice(0, cut) }}</a>{{ byline.slice(0, 4) }}{{ card(context.author, byline.slice(4)) }}</span>
|
|
27
|
+
{%- else %}
|
|
28
|
+
{%- if context.name %} <a class="u-url p-name" href="{{ url }}">{{ context.name }}</a>
|
|
29
|
+
{%- elif context.author %} <a class="u-url" href="{{ url }}">a post</a>
|
|
30
|
+
{%- else %} <a class="u-url" href="{{ url }}">{{ url }}</a>
|
|
31
|
+
{%- endif %}
|
|
32
|
+
{%- if context.author %} by {{ card(context.author, context.author.name) }}{% endif %}
|
|
33
|
+
{%- endif %}
|
|
34
|
+
{%- endmacro %}
|
|
35
|
+
|
|
36
|
+
{% macro card(author, name) -%}
|
|
37
|
+
<span class="p-author h-card">
|
|
38
|
+
{%- if author.url %}<a class="u-url p-name" href="{{ author.url }}">{{ name }}</a>
|
|
39
|
+
{%- else %}<span class="p-name">{{ name }}</span>{% endif -%}
|
|
40
|
+
</span>
|
|
41
|
+
{%- endmacro %}
|
|
@@ -8,9 +8,10 @@
|
|
|
8
8
|
categories it is filed under in its kicker. A note, which has no title, is
|
|
9
9
|
printed whole as its `e-content`, and its date in the kicker is the link to
|
|
10
10
|
it. A reply is a note that first cites what it answers, and a reply with a
|
|
11
|
-
title is an article that
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
title is an article that cites it after its title and summary; a like, a
|
|
12
|
+
repost and a bookmark cite theirs the same way. Tags are deliberately not
|
|
13
|
+
here: an entry's tags belong under the entry, and a feed of twenty posts
|
|
14
|
+
listing everyone's would be a wall of links rather than a list of writing.
|
|
14
15
|
|
|
15
16
|
`feedHeading` is the heading level, which belongs to the layout rather than
|
|
16
17
|
to the list: a listing is a page of entries and heads each one at 2, and a
|
|
@@ -32,16 +33,17 @@
|
|
|
32
33
|
{% else %}
|
|
33
34
|
{{ kicker.line(post.postType | capitalize, post.date, post.url, [], post.label, lang=post.lang) }}
|
|
34
35
|
{% endif %}
|
|
35
|
-
{
|
|
36
|
+
{% set cited %}
|
|
36
37
|
{% if post.inReplyTo %}
|
|
37
38
|
{% set inReplyTo = post.inReplyTo %}
|
|
38
39
|
{% set replyContext = post.replyContext %}
|
|
39
40
|
{% set lang = post.lang %}
|
|
40
41
|
{% include "partials/reply-context.njk" %}
|
|
41
42
|
{% endif %}
|
|
42
|
-
{#- What it reposts, likes or bookmarks, from the partial an entry uses. -#}
|
|
43
43
|
{% set citations = post.citations %}
|
|
44
44
|
{% include "partials/citations.njk" %}
|
|
45
|
+
{% endset %}
|
|
46
|
+
{% if not post.named %}{{ cited | safe }}{% endif %}
|
|
45
47
|
{% set read = post.read %}
|
|
46
48
|
{% include "partials/read.njk" %}
|
|
47
49
|
{% if post.photos.length %}
|
|
@@ -62,6 +64,7 @@
|
|
|
62
64
|
<p>{{ post.summary | truncate(280) }}</p>
|
|
63
65
|
</div>
|
|
64
66
|
{% endif %}
|
|
67
|
+
{{ cited | safe }}
|
|
65
68
|
<p class="feed-more">
|
|
66
69
|
<a href="{{ post.url | url }}" aria-label="Continue reading: {{ post.title }}">Continue reading<span aria-hidden="true"> →</span></a>
|
|
67
70
|
</p>
|
|
@@ -16,18 +16,11 @@
|
|
|
16
16
|
written in `lang`, the language of the entry it sits in (TASK-189), so a
|
|
17
17
|
listing sets `lang` from each entry as it sets `replyContext`.
|
|
18
18
|
#}
|
|
19
|
+
{% import "partials/cited-page.njk" as cited %}
|
|
19
20
|
{% if inReplyTo %}
|
|
20
21
|
<div class="reply-context cite u-in-reply-to h-cite">
|
|
21
22
|
<p class="cite-line small">In reply to
|
|
22
|
-
{
|
|
23
|
-
{%- elif replyContext.author %} <a class="u-url" href="{{ inReplyTo }}">a post</a>
|
|
24
|
-
{%- else %} <a class="u-url" href="{{ inReplyTo }}">{{ inReplyTo }}</a>
|
|
25
|
-
{%- endif %}
|
|
26
|
-
{%- if replyContext.author %} by <span class="p-author h-card">
|
|
27
|
-
{%- if replyContext.author.url %}<a class="u-url p-name" href="{{ replyContext.author.url }}">{{ replyContext.author.name }}</a>
|
|
28
|
-
{%- else %}<span class="p-name">{{ replyContext.author.name }}</span>{% endif -%}
|
|
29
|
-
</span>
|
|
30
|
-
{%- endif %}
|
|
23
|
+
{{- cited.page(inReplyTo, replyContext) }}
|
|
31
24
|
{%- if replyContext.published %}, <time class="dt-published" datetime="{{ replyContext.published | date("iso") }}">{{ replyContext.published | date("readable", none, lang) }}</time>
|
|
32
25
|
{%- endif -%}
|
|
33
26
|
</p>
|