@geekity/cms 0.13.0 → 0.15.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 +181 -57
- package/admin/pages/documents/editor.njk +82 -0
- package/admin/pages/media/library.njk +4 -3
- package/admin/pages/settings/general.njk +51 -6
- package/admin/static/admin.css +33 -0
- package/dist/admin/documents.d.ts +5 -0
- package/dist/admin/documents.d.ts.map +1 -1
- package/dist/admin/documents.js +63 -6
- package/dist/admin/documents.js.map +1 -1
- package/dist/admin/enclosure-field.d.ts +91 -0
- package/dist/admin/enclosure-field.d.ts.map +1 -0
- package/dist/admin/enclosure-field.js +282 -0
- package/dist/admin/enclosure-field.js.map +1 -0
- package/dist/admin/federation.js +2 -2
- package/dist/admin/federation.js.map +1 -1
- package/dist/admin/headers.d.ts +4 -1
- package/dist/admin/headers.d.ts.map +1 -1
- package/dist/admin/headers.js +9 -4
- package/dist/admin/headers.js.map +1 -1
- package/dist/admin/media.d.ts +7 -2
- package/dist/admin/media.d.ts.map +1 -1
- package/dist/admin/media.js +4 -2
- package/dist/admin/media.js.map +1 -1
- package/dist/admin/settings-general.d.ts.map +1 -1
- package/dist/admin/settings-general.js +63 -4
- package/dist/admin/settings-general.js.map +1 -1
- package/dist/admin/settings-page.d.ts.map +1 -1
- package/dist/admin/settings-page.js +1 -2
- package/dist/admin/settings-page.js.map +1 -1
- package/dist/admin/settings.d.ts +37 -9
- package/dist/admin/settings.d.ts.map +1 -1
- package/dist/admin/settings.js +93 -11
- package/dist/admin/settings.js.map +1 -1
- package/dist/admin/uploads.d.ts +7 -2
- package/dist/admin/uploads.d.ts.map +1 -1
- package/dist/admin/uploads.js +23 -5
- package/dist/admin/uploads.js.map +1 -1
- package/dist/config.d.ts +21 -3
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +11 -7
- package/dist/config.js.map +1 -1
- package/dist/content/enclosure.d.ts +69 -0
- package/dist/content/enclosure.d.ts.map +1 -0
- package/dist/content/enclosure.js +165 -0
- package/dist/content/enclosure.js.map +1 -0
- package/dist/content/index.d.ts +3 -1
- package/dist/content/index.d.ts.map +1 -1
- package/dist/content/index.js +1 -0
- package/dist/content/index.js.map +1 -1
- package/dist/content/media.d.ts +15 -2
- package/dist/content/media.d.ts.map +1 -1
- package/dist/content/media.js +92 -9
- package/dist/content/media.js.map +1 -1
- package/dist/content/pinned.d.ts +26 -0
- package/dist/content/pinned.d.ts.map +1 -0
- package/dist/content/pinned.js +42 -0
- package/dist/content/pinned.js.map +1 -0
- package/dist/content/store.d.ts +7 -0
- package/dist/content/store.d.ts.map +1 -1
- package/dist/content/store.js +20 -0
- package/dist/content/store.js.map +1 -1
- package/dist/env.d.ts +7 -0
- package/dist/env.d.ts.map +1 -1
- package/dist/federation/actor.d.ts +15 -0
- package/dist/federation/actor.d.ts.map +1 -1
- package/dist/federation/actor.js +94 -3
- package/dist/federation/actor.js.map +1 -1
- package/dist/federation/article.d.ts +13 -1
- package/dist/federation/article.d.ts.map +1 -1
- package/dist/federation/article.js +62 -7
- package/dist/federation/article.js.map +1 -1
- package/dist/federation/delivery.d.ts.map +1 -1
- package/dist/federation/delivery.js +36 -4
- package/dist/federation/delivery.js.map +1 -1
- package/dist/federation/federation.d.ts.map +1 -1
- package/dist/federation/federation.js +24 -2
- package/dist/federation/federation.js.map +1 -1
- package/dist/federation/mount.js +2 -2
- package/dist/federation/mount.js.map +1 -1
- package/dist/federation/paths.d.ts +30 -0
- package/dist/federation/paths.d.ts.map +1 -1
- package/dist/federation/paths.js +36 -0
- package/dist/federation/paths.js.map +1 -1
- package/dist/images/icons.d.ts +5 -0
- package/dist/images/icons.d.ts.map +1 -1
- package/dist/images/icons.js +13 -8
- package/dist/images/icons.js.map +1 -1
- package/dist/images/paths.d.ts +1 -1
- package/dist/images/paths.d.ts.map +1 -1
- package/dist/images/paths.js.map +1 -1
- package/dist/images/variants.d.ts +11 -0
- package/dist/images/variants.d.ts.map +1 -1
- package/dist/images/variants.js +21 -0
- package/dist/images/variants.js.map +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -3
- package/dist/index.js.map +1 -1
- package/dist/indieauth/identity.d.ts +3 -3
- package/dist/indieauth/identity.d.ts.map +1 -1
- package/dist/indieauth/identity.js +6 -7
- package/dist/indieauth/identity.js.map +1 -1
- package/dist/web/admin-bar.d.ts +3 -1
- package/dist/web/admin-bar.d.ts.map +1 -1
- package/dist/web/admin-bar.js +5 -1
- package/dist/web/admin-bar.js.map +1 -1
- package/dist/web/assets.d.ts +14 -0
- package/dist/web/assets.d.ts.map +1 -1
- package/dist/web/assets.js +56 -1
- package/dist/web/assets.js.map +1 -1
- package/dist/web/authors.d.ts +19 -0
- package/dist/web/authors.d.ts.map +1 -1
- package/dist/web/authors.js +25 -0
- package/dist/web/authors.js.map +1 -1
- package/dist/web/context.d.ts +26 -0
- package/dist/web/context.d.ts.map +1 -1
- package/dist/web/context.js +15 -0
- package/dist/web/context.js.map +1 -1
- package/dist/web/feed-atom.d.ts.map +1 -1
- package/dist/web/feed-atom.js +22 -1
- package/dist/web/feed-atom.js.map +1 -1
- package/dist/web/feed-item.d.ts +34 -6
- package/dist/web/feed-item.d.ts.map +1 -1
- package/dist/web/feed-item.js +31 -7
- package/dist/web/feed-item.js.map +1 -1
- package/dist/web/feed-json.d.ts +15 -2
- package/dist/web/feed-json.d.ts.map +1 -1
- package/dist/web/feed-json.js +17 -1
- package/dist/web/feed-json.js.map +1 -1
- package/dist/web/feed-rss.d.ts.map +1 -1
- package/dist/web/feed-rss.js +60 -3
- package/dist/web/feed-rss.js.map +1 -1
- package/dist/web/feed-source.d.ts +3 -0
- package/dist/web/feed-source.d.ts.map +1 -1
- package/dist/web/feed-source.js.map +1 -1
- package/dist/web/feed-xml.d.ts +7 -1
- package/dist/web/feed-xml.d.ts.map +1 -1
- package/dist/web/feed-xml.js +8 -2
- package/dist/web/feed-xml.js.map +1 -1
- package/dist/web/feeds.d.ts +1 -1
- package/dist/web/feeds.d.ts.map +1 -1
- package/dist/web/feeds.js +13 -2
- package/dist/web/feeds.js.map +1 -1
- package/dist/web/index.d.ts +5 -2
- package/dist/web/index.d.ts.map +1 -1
- package/dist/web/index.js +3 -1
- package/dist/web/index.js.map +1 -1
- package/dist/web/license.d.ts +94 -0
- package/dist/web/license.d.ts.map +1 -0
- package/dist/web/license.js +116 -0
- package/dist/web/license.js.map +1 -0
- package/dist/web/oembed.d.ts +104 -0
- package/dist/web/oembed.d.ts.map +1 -0
- package/dist/web/oembed.js +289 -0
- package/dist/web/oembed.js.map +1 -0
- package/dist/web/opensearch.d.ts +35 -0
- package/dist/web/opensearch.d.ts.map +1 -0
- package/dist/web/opensearch.js +65 -0
- package/dist/web/opensearch.js.map +1 -0
- package/dist/web/render.d.ts.map +1 -1
- package/dist/web/render.js +16 -8
- package/dist/web/render.js.map +1 -1
- package/dist/web/routes.d.ts.map +1 -1
- package/dist/web/routes.js +82 -6
- package/dist/web/routes.js.map +1 -1
- package/dist/web/share-image.d.ts +7 -7
- package/dist/web/share-image.d.ts.map +1 -1
- package/dist/web/share-image.js +8 -7
- package/dist/web/share-image.js.map +1 -1
- package/dist/web/templates.d.ts.map +1 -1
- package/dist/web/templates.js +5 -0
- package/dist/web/templates.js.map +1 -1
- package/package.json +2 -1
- package/templates/site/content/_data/site.json +0 -1
- package/themes/default/README.md +142 -48
- package/themes/default/layouts/base.njk +25 -6
- package/themes/default/layouts/front-page.njk +1 -0
- package/themes/default/layouts/home.njk +1 -0
- package/themes/default/layouts/post.njk +4 -0
- package/themes/default/partials/bio.njk +7 -0
- package/themes/default/partials/jsonld.njk +30 -7
- package/themes/default/partials/recording.njk +41 -0
- package/themes/default/src/style.css +16 -0
- package/themes/default/static/style.css +29 -0
package/dist/web/templates.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Environment, FileSystemLoader } from 'nunjucks';
|
|
2
2
|
import { calendarDayIn, DEFAULT_TIMEZONE } from '../content/time.js';
|
|
3
|
+
import { accountOf } from '../federation/paths.js';
|
|
3
4
|
import { themeAssetUrl } from './assets.js';
|
|
4
5
|
import { siteLocale, siteTimezone } from './context.js';
|
|
5
6
|
import { canonicalLocale, DEFAULT_LOCALE, pluralForm } from './locale.js';
|
|
@@ -113,6 +114,10 @@ function addFilters(environment, baseUrl, loader) {
|
|
|
113
114
|
return pathname;
|
|
114
115
|
}
|
|
115
116
|
});
|
|
117
|
+
// `{{ siteAuthor.username | fediverseHandle }}`: a user's own account on
|
|
118
|
+
// this site, `@ada@example.com`, exactly as WebFinger answers for it
|
|
119
|
+
// (TASK-202), so a theme never spells the host.
|
|
120
|
+
environment.addFilter('fediverseHandle', (value) => typeof value === 'string' && value !== '' ? `@${accountOf(value, baseUrl)}` : '');
|
|
116
121
|
return environment;
|
|
117
122
|
}
|
|
118
123
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/web/templates.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/web/templates.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.15.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",
|
|
@@ -55,6 +55,7 @@
|
|
|
55
55
|
"codemirror": "^6.0.2",
|
|
56
56
|
"esbuild": "^0.28.2",
|
|
57
57
|
"highlight.js": "11.12.0",
|
|
58
|
+
"microformats-parser": "^2.0.6",
|
|
58
59
|
"tailwindcss": "^4.3.3",
|
|
59
60
|
"tsx": "^4.23.15",
|
|
60
61
|
"typescript": "^7.0.2"
|
package/themes/default/README.md
CHANGED
|
@@ -204,8 +204,11 @@ stylesheet tells the two apart. `menus.primary` is printed inside the
|
|
|
204
204
|
tagline, and everywhere else the stylesheet lays the header out as one line so
|
|
205
205
|
it sits beside the link home. See [Navigation](#navigation).
|
|
206
206
|
|
|
207
|
-
**The footer** prints the copyright with the current year and
|
|
208
|
-
|
|
207
|
+
**The footer** prints the copyright with the current year and the site
|
|
208
|
+
author's display name, `soloAuthor.name`, or the site title on a site with
|
|
209
|
+
several authors,
|
|
210
|
+
then the page's license, when it has one, as `<a rel="license">` with its name,
|
|
211
|
+
then `Published with Geekity`, and then `menus.footer` — the `footer` area this
|
|
209
212
|
theme declares, and the whole of what the footer links. A site that wants its
|
|
210
213
|
feed there types an `RSS | /feed/` line into it, the way the starter site does.
|
|
211
214
|
Nothing in the footer is read off an account: it used to hold one `rel="me"`
|
|
@@ -214,7 +217,9 @@ presented as the site's. An empty or missing footer menu prints no list at all,
|
|
|
214
217
|
and the copyright line stands on its own. The year is
|
|
215
218
|
`{{ "now" | date("year") }}` — `now` is the one word the `date` filter reads
|
|
216
219
|
rather than parses — so it is the year at the moment the page is rendered, in
|
|
217
|
-
the site's own timezone.
|
|
220
|
+
the site's own timezone. The license is `license`: a post's own from its
|
|
221
|
+
`license` front matter, else the site's from Settings > General, and nothing
|
|
222
|
+
on a site with none.
|
|
218
223
|
|
|
219
224
|
**The breadcrumb** opens `<main>` on a page with a place in the site's
|
|
220
225
|
hierarchy (TASK-150): a post filed under a category, and a category, tag or
|
|
@@ -228,8 +233,8 @@ two cannot disagree. Every other page has an empty trail and prints nothing. A
|
|
|
228
233
|
site that wants no visible breadcrumb empties the `breadcrumbs` block, and the
|
|
229
234
|
`BreadcrumbList` stays in the graph.
|
|
230
235
|
|
|
231
|
-
Webrings, badges
|
|
232
|
-
|
|
236
|
+
Webrings, badges and anything else that is markup rather than a link are
|
|
237
|
+
deliberately not in the package. They go in a site theme's `footer`
|
|
233
238
|
block:
|
|
234
239
|
|
|
235
240
|
```njk
|
|
@@ -398,6 +403,41 @@ is a `p-category` of this entry, as one `p.post-categories` from
|
|
|
398
403
|
`partials/tags.njk`. The stylesheet draws the `#` in front of each, so the
|
|
399
404
|
category a parser reads is the tag and not the hash.
|
|
400
405
|
|
|
406
|
+
**A post with a recording plays it** (TASK-213), from
|
|
407
|
+
`partials/recording.njk`, between the header and the `e-content`. The main file
|
|
408
|
+
is the browser's own player, `<audio controls>` or `<video controls>` as
|
|
409
|
+
`enclosure.player` says, with `preload="metadata"` so a reader who never presses
|
|
410
|
+
play downloads nothing, and a download link inside it for a browser that plays
|
|
411
|
+
neither. The `<source>` carries `u-audio` or `u-video`, so a microformats parser
|
|
412
|
+
finds the file on the entry. A video whose transcript is WebVTT also gets it as
|
|
413
|
+
a `<track kind="captions">`. Under the player a `figcaption` links the
|
|
414
|
+
transcript, as Captions for VTT or SRT and Transcript otherwise, and lists the
|
|
415
|
+
other versions by their title, else their media type. A post without a
|
|
416
|
+
recording, or whose front matter is missing what a player needs, prints none of
|
|
417
|
+
it.
|
|
418
|
+
|
|
419
|
+
```html
|
|
420
|
+
<figure class="post-recording">
|
|
421
|
+
<audio controls preload="metadata" aria-label="Recording of Episode twelve">
|
|
422
|
+
<source
|
|
423
|
+
class="u-audio"
|
|
424
|
+
src="/uploads/2026/10/episode-12.mp3"
|
|
425
|
+
type="audio/mpeg"
|
|
426
|
+
/>
|
|
427
|
+
<a href="/uploads/2026/10/episode-12.mp3">Download the recording</a>
|
|
428
|
+
</audio>
|
|
429
|
+
<figcaption class="post-recording-links">
|
|
430
|
+
<p><a href="/uploads/2026/10/episode-12.vtt">Captions</a></p>
|
|
431
|
+
<p id="post-recording-versions">Other versions</p>
|
|
432
|
+
<ul aria-labelledby="post-recording-versions">
|
|
433
|
+
<li>
|
|
434
|
+
<a href="/uploads/2026/10/episode-12.mp4" type="video/mp4">Video</a>
|
|
435
|
+
</li>
|
|
436
|
+
</ul>
|
|
437
|
+
</figcaption>
|
|
438
|
+
</figure>
|
|
439
|
+
```
|
|
440
|
+
|
|
401
441
|
After the entry a post prints `nav.blog-post-nav`: the `previous` and `next`
|
|
402
442
|
posts as two cards, `rel="prev"` and `rel="next"`, each opening on a
|
|
403
443
|
`span.blog-post-nav-label`, and nothing at all at the ends of the archive; then
|
|
@@ -431,12 +471,17 @@ Links box typed. Set `bioRelMe` to `false` to keep the card and drop its
|
|
|
431
471
|
claims: the name is linked `rel="author"` alone and `me` comes off every
|
|
432
472
|
link.
|
|
433
473
|
|
|
434
|
-
**The homepage** speaks for the site's author only on a
|
|
435
|
-
which `soloAuthor` on the context says. Then both
|
|
436
|
-
`layouts/front-page.njk` end with that person's
|
|
437
|
-
claims, and their author archive's link home carries
|
|
438
|
-
homepage and the archive name each other.
|
|
439
|
-
|
|
474
|
+
**The homepage** speaks for the site's author only on a site whose Site author
|
|
475
|
+
setting names a user, which `soloAuthor` on the context says. Then both
|
|
476
|
+
`layouts/home.njk` at `/` and `layouts/front-page.njk` end with that person's
|
|
477
|
+
card, with its `rel="me"` claims, and their author archive's link home carries
|
|
478
|
+
`rel="me"` back, so the homepage and the archive name each other. Those two
|
|
479
|
+
layouts also set `bioHome` to the homepage's absolute URL, which puts a
|
|
480
|
+
`data.u-url.u-uid` holding it first in the card, so a parser running the
|
|
481
|
+
[representative h-card algorithm](https://microformats.org/wiki/representative-h-card-parsing)
|
|
482
|
+
on the homepage finds this card as the site's (TASK-193). The archive stays a
|
|
483
|
+
second `u-url`. No other page sets `bioHome`. On a site
|
|
484
|
+
with several authors neither homepage prints a card. Each of
|
|
440
485
|
those is printed only when the profile says it, so a profile holding a name
|
|
441
486
|
alone prints a name alone. A name this site has no account for is printed
|
|
442
487
|
unlinked, because the file still said somebody wrote this.
|
|
@@ -459,7 +504,7 @@ an overridden layout — either includes this partial instead or writes the line
|
|
|
459
504
|
itself. It was four lines of markup, and the object behind it has not changed:
|
|
460
505
|
|
|
461
506
|
```njk
|
|
462
|
-
{% set writer = author or { name: site.
|
|
507
|
+
{% set writer = author or { name: site.title } %}
|
|
463
508
|
<span class="p-author h-card">
|
|
464
509
|
{%- if writer.url %}<a class="u-url" href="{{ writer.url | url }}">{{ writer.name }}</a>
|
|
465
510
|
{%- else %}{{ writer.name }}{% endif %}
|
|
@@ -702,17 +747,28 @@ included. `og:url` is the canonical URL. An article also carries
|
|
|
702
747
|
publish date), `article:author` (the author's profile URL here, else their
|
|
703
748
|
name) and one `article:tag` per tag.
|
|
704
749
|
|
|
705
|
-
**The picture** is the
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
750
|
+
**The picture** is the first of these that the page has, on the context as
|
|
751
|
+
`shareImage`:
|
|
752
|
+
|
|
753
|
+
1. The `image` in the entry's front matter.
|
|
754
|
+
2. `site.avatar`, which only a hand edit of `site.json` sets.
|
|
755
|
+
3. The profile photo of the person the page is by: the writer of a post or page
|
|
756
|
+
that names an author, the user of an author archive, and the site's author
|
|
757
|
+
on a solo-author site's homepage and other pages about nobody in particular.
|
|
758
|
+
4. The site icon, from `icon` in `site.json`.
|
|
759
|
+
|
|
760
|
+
A page with none of these prints no `og:image` and no `twitter:image` rather
|
|
761
|
+
than an empty one. The picture always carries `og:image:alt` and
|
|
762
|
+
`twitter:image:alt`. The alt text is what the media library says about the
|
|
763
|
+
upload, else words for what it shows. For the entry's own picture, its
|
|
764
|
+
`imageAlt` front matter comes first, and the entry's title last. For the
|
|
765
|
+
avatar, the last resort is the site's author; for a photo, that person's
|
|
766
|
+
display name; for the icon, the site's title. `og:image:width` and
|
|
767
|
+
`og:image:height` are printed when the image's variants have been derived,
|
|
768
|
+
because the size is read from their sidecar rather than from the file.
|
|
769
|
+
`twitter:card` is `summary_large_image` for a picture at least 1200 pixels wide
|
|
770
|
+
and wider than it is tall. Everything else, a square photo included, is
|
|
771
|
+
`summary`, the small picture beside the words.
|
|
716
772
|
|
|
717
773
|
**The icons** come from the site's `icon` setting in `site.json`, else
|
|
718
774
|
`site.avatar`, through the derived images (decision-10). `icon` exists for a
|
|
@@ -734,26 +790,63 @@ site with no icon. `/manifest.webmanifest` gives the site's title as `name` and
|
|
|
734
790
|
pixels plus a maskable 512 whose picture sits inside the middle 80%, padded
|
|
735
791
|
with its own dominant colour. The head links it on every page.
|
|
736
792
|
|
|
793
|
+
**The search description** is a route too. `/opensearch.xml` is an OpenSearch
|
|
794
|
+
1.1 description that names the site by its title (cut to the 16 characters
|
|
795
|
+
`ShortName` allows), describes it by its tagline, else its title, shows
|
|
796
|
+
`/favicon.ico` as its `Image` when the site has an icon, and searches
|
|
797
|
+
`/search/?q={searchTerms}`. Every URL in it is absolute and carries the base
|
|
798
|
+
path. The head links it on every page with `<link rel="search"
|
|
799
|
+
type="application/opensearchdescription+xml">`, outside the `head` block, so a
|
|
800
|
+
browser offers the site as a search engine. A theme that replaces `base.njk`
|
|
801
|
+
copies that line to keep the offer.
|
|
802
|
+
|
|
803
|
+
**The embed card** is a route too. `/_geekity/oembed?url=…` is an oEmbed
|
|
804
|
+
provider: for the URL of a published post or page it answers a `rich` embed
|
|
805
|
+
with the title, the author and their archive, the site as provider, a
|
|
806
|
+
thumbnail when the post's own `image` has a recorded size, and an `html`
|
|
807
|
+
card that is a blockquote of escaped text and links with no script, followed
|
|
808
|
+
by a hidden, sandboxed `<iframe>` of `/_geekity/embed?url=…`. That route is
|
|
809
|
+
the same card as a page of its own, and it is the one response another site may
|
|
810
|
+
frame. WordPress keeps a card from a provider it does not know only when the
|
|
811
|
+
card has an iframe, and it shows the frame once the page inside reports its
|
|
812
|
+
height. A consumer that strips iframes still has the blockquote. `maxwidth`
|
|
813
|
+
and `maxheight` are honoured, `format=xml` gives the same fields as XML, and
|
|
814
|
+
any other URL is a 404. The head of each post and page links it with
|
|
815
|
+
`<link rel="alternate" type="application/json+oembed">` and its `text/xml+oembed`
|
|
816
|
+
twin, outside the `head` block. A theme that replaces `base.njk` copies those
|
|
817
|
+
lines to keep the card.
|
|
818
|
+
|
|
737
819
|
**The structured data** is `partials/jsonld.njk`, one `<script
|
|
738
820
|
type="application/ld+json">` holding one `@graph` per page, and it is the only
|
|
739
821
|
structured data the theme emits — there is no Microdata anywhere, by
|
|
740
822
|
decision-16, because the visible markup already carries microformats2 for the
|
|
741
823
|
IndieWeb. The graph holds:
|
|
742
824
|
|
|
743
|
-
- `WebSite`, always, with the site's title, tagline and URL, and a
|
|
744
|
-
|
|
745
|
-
`/search/?q={search_term_string}`. On
|
|
746
|
-
|
|
825
|
+
- `WebSite`, always, with the site's title, tagline and URL, and a
|
|
826
|
+
`potentialAction` that is a `SearchAction` on
|
|
827
|
+
`/search/?q={search_term_string}`. On a site whose author is a user, its
|
|
828
|
+
`publisher` and `about` both point at that user's Person, on every page. On
|
|
829
|
+
a site with several authors its `publisher` is the Organization below and it
|
|
830
|
+
has no `about`. With a site license, `license` is its URL.
|
|
831
|
+
- `Organization`, on a site with several authors only: the site itself, named
|
|
832
|
+
for its title, at `{baseUrl}/#organization`. It publishes the `WebSite` and
|
|
833
|
+
every entry.
|
|
747
834
|
- `Person`, from `siteAuthor`: their name, archive URL, avatar, bio, job title
|
|
748
835
|
and location, and a `sameAs` of their profile links and their actor id, which
|
|
749
836
|
is what asserts that the schema.org Person and the fediverse actor are one
|
|
750
837
|
identity. Identity comes from a user profile, so a site — or a byline —
|
|
751
|
-
naming nobody with an account here prints no Person, and the `author`
|
|
752
|
-
|
|
838
|
+
naming nobody with an account here prints no Person, and the `author`
|
|
839
|
+
reference goes with it. A site with several authors prints no Person on a
|
|
840
|
+
page about nobody in particular.
|
|
753
841
|
- `ProfilePage` on an author archive, whose `mainEntity` is that Person.
|
|
754
842
|
- `BlogPosting` on a post and `Article` on a page, with the headline, URL,
|
|
755
843
|
`mainEntityOfPage`, `datePublished`, `dateModified`, description, image,
|
|
756
|
-
`author
|
|
844
|
+
`author`, and the site's `publisher`: the site author's Person, or the
|
|
845
|
+
Organization. A post with no title is headed by the words its `<title>`
|
|
846
|
+
names it by, its `label`, cut on a word boundary to at most 110 characters.
|
|
847
|
+
Its `image` is the picture the Open Graph tags print, so the two always
|
|
848
|
+
agree (see [The head](#the-head)). Its `license` is the page's license URL,
|
|
849
|
+
the front matter's over the site's, and absent with none.
|
|
757
850
|
- `BreadcrumbList` wherever the page prints a breadcrumb (see
|
|
758
851
|
[The page shell](#the-page-shell)): one `ListItem` per crumb with its
|
|
759
852
|
`position`, `name` and absolute URL as `item`.
|
|
@@ -1012,16 +1105,18 @@ an Eleventy build needs few edits. It is part of the package's semver contract.
|
|
|
1012
1105
|
|
|
1013
1106
|
Every template gets:
|
|
1014
1107
|
|
|
1015
|
-
| Key
|
|
1016
|
-
|
|
|
1017
|
-
| `site`
|
|
1018
|
-
| `menus`
|
|
1019
|
-
| `siteAuthor`
|
|
1020
|
-
| `soloAuthor`
|
|
1021
|
-
| `icons`
|
|
1022
|
-
| `theme`
|
|
1023
|
-
| `shareImage`
|
|
1024
|
-
| `llmsTxt`
|
|
1108
|
+
| Key | What it holds |
|
|
1109
|
+
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1110
|
+
| `site` | `content/_data/site.json`, if the site has one, over the defaults `title` and `url`. Any key in the file is readable, so `site.tagline`, `site.author` and anything else a site adds are all available. |
|
|
1111
|
+
| `menus` | Every menu the site stores, by name, marked for this page: `menus.primary`, `menus.footer`, and any other name. See [Navigation](#navigation). |
|
|
1112
|
+
| `siteAuthor` | Who the page is by, as a profile. **Absent** when nobody matches. See [Bylines and author archives](#bylines-and-author-archives). |
|
|
1113
|
+
| `soloAuthor` | The site author's profile, on every page of a site whose Site author setting names a user. **Absent** on a site with several authors. See [The bio](#the-bio). |
|
|
1114
|
+
| `icons` | The site's icons, as `{ rel, sizes, type, href }`. Empty until the site has an icon or an avatar to derive them from. See [The head](#the-head). |
|
|
1115
|
+
| `theme` | The colours the theme declares, as `{ colorScheme, themeColor: { light, dark } }`, each absent when no theme declares it. See [The manifest](#the-manifest). |
|
|
1116
|
+
| `shareImage` | The picture a shared link shows, as `{ url, alt, size: { width, height }, card }`. `size` is absent when it is not known. **Absent** when there is no picture. See [The head](#the-head). |
|
|
1117
|
+
| `llmsTxt` | The path of `/llms.txt`, while the site serves it. **Absent** when the site has turned it off. The default theme links it from the front page only. |
|
|
1118
|
+
| `license` | The page's license as `{ name, url }`: the page's `license` front matter, else the site's. **Undefined** with none. It replaces the raw front matter value on the context. |
|
|
1119
|
+
| `siteLicense` | The site's own license as `{ name, url }`, whatever the page says. **Undefined** with none. |
|
|
1025
1120
|
|
|
1026
1121
|
A document — one post, one page, or one entry of a listing — adds:
|
|
1027
1122
|
|
|
@@ -1042,6 +1137,7 @@ A document — one post, one page, or one entry of a listing — adds:
|
|
|
1042
1137
|
| `type` | `post` or `page`. |
|
|
1043
1138
|
| `permalink`, `slug`, `draft`, `description` | Straight from the front matter. |
|
|
1044
1139
|
| `lang` | The `lang` front matter as a canonical tag, such as `fr-CA`. Absent when it names none or no tag. |
|
|
1140
|
+
| `enclosure` | The post's recording, parsed, with `player` (`audio` or `video`) and `transcript.captions`. Absent with none. |
|
|
1045
1141
|
| `author` | Who wrote it, as a profile rather than a string. See [Bylines and author archives](#bylines-and-author-archives). |
|
|
1046
1142
|
| `activityStreams` | The post's ActivityPub object id, absolute. Only on a rendered published post. |
|
|
1047
1143
|
| `previous` | The published post before this one by date, as `{ title, url }`. Absent on the oldest post. |
|
|
@@ -1121,14 +1217,12 @@ account. It resolves in this order:
|
|
|
1121
1217
|
|
|
1122
1218
|
- the document's own `author`, on a post or a page that names one;
|
|
1123
1219
|
- the person whose archive it is, on an author archive;
|
|
1124
|
-
- the
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
It is **absent** when none of those name anybody this site has
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
behind it has no picture, no bio and nowhere to link, so there is nothing to
|
|
1131
|
-
print and the key is not there. Write `{% if siteAuthor %}` around the bio.
|
|
1220
|
+
- the site author, `soloAuthor`, everywhere else — the home page, a taxonomy
|
|
1221
|
+
archive, a page that names nobody, the 404.
|
|
1222
|
+
|
|
1223
|
+
It is **absent** when none of those name anybody this site has, which on a
|
|
1224
|
+
site with several authors is every page about nobody in particular. Write
|
|
1225
|
+
`{% if siteAuthor %}` around the bio.
|
|
1132
1226
|
|
|
1133
1227
|
The URL is not only a page. Each user is an ActivityPub actor at that address,
|
|
1134
1228
|
so it is the page a follower lands on when they click through from the
|
|
@@ -40,9 +40,8 @@
|
|
|
40
40
|
|
|
41
41
|
`metaDescription` is the page's own description, else the entry's summary
|
|
42
42
|
— the very line the feeds publish — else the site's tagline. `metaImage` is
|
|
43
|
-
`shareImage.url
|
|
44
|
-
|
|
45
|
-
works out `shareImage` because its alt text and its size live in files a
|
|
43
|
+
`shareImage.url`; with none, nothing is printed rather than an empty tag.
|
|
44
|
+
The CMS works out `shareImage` because its alt text and its size live in files a
|
|
46
45
|
template cannot read. `isEntry` is a rendered post
|
|
47
46
|
or page, which is what Open Graph calls an article: a listing has
|
|
48
47
|
`pagination`, and the posts page is a listing carrying a page's front
|
|
@@ -152,6 +151,16 @@
|
|
|
152
151
|
{% if webmention %}
|
|
153
152
|
<link rel="webmention" href="{{ webmention | url }}">
|
|
154
153
|
{% endif %}
|
|
154
|
+
{#- The site's search, for a browser to offer from its address bar
|
|
155
|
+
(TASK-204). #}
|
|
156
|
+
<link rel="search" type="application/opensearchdescription+xml" title="{{ site.title }}" href="{{ "/opensearch.xml" | url }}">
|
|
157
|
+
{#- Where a tool that is pasted this post's URL asks for its card
|
|
158
|
+
(TASK-205), as JSON and as XML. #}
|
|
159
|
+
{% if isEntry %}
|
|
160
|
+
{% set oembed = "/_geekity/oembed?url=" + (metaUrl | urlencode) + "&format=" %}
|
|
161
|
+
<link rel="alternate" type="application/json+oembed" href="{{ (oembed + "json") | absoluteUrl }}" title="{{ metaTitle }}">
|
|
162
|
+
<link rel="alternate" type="text/xml+oembed" href="{{ (oembed + "xml") | absoluteUrl }}" title="{{ metaTitle }}">
|
|
163
|
+
{% endif %}
|
|
155
164
|
{#- The site's index for language models (TASK-149), from the front page,
|
|
156
165
|
which is where a tool that found the site looks for it. #}
|
|
157
166
|
{% if llmsTxt and atRoot %}
|
|
@@ -194,13 +203,23 @@
|
|
|
194
203
|
{% endif %}
|
|
195
204
|
{% if siteAuthor.url %}
|
|
196
205
|
<meta property="article:author" content="{{ siteAuthor.url | absoluteUrl }}">
|
|
197
|
-
{% elif siteAuthor.name or author.name or author
|
|
198
|
-
<meta property="article:author" content="{{ siteAuthor.name or author.name or author
|
|
206
|
+
{% elif siteAuthor.name or author.name or author %}
|
|
207
|
+
<meta property="article:author" content="{{ siteAuthor.name or author.name or author }}">
|
|
199
208
|
{% endif %}
|
|
200
209
|
{% for tag in tags %}
|
|
201
210
|
<meta property="article:tag" content="{{ tag }}">
|
|
202
211
|
{% endfor %}
|
|
203
212
|
{% endif %}
|
|
213
|
+
{#
|
|
214
|
+
Who a Mastodon link preview credits, with a follow button (TASK-202):
|
|
215
|
+
the user's own account here, on an entry by them and on the homepage of
|
|
216
|
+
a site one person writes. Mastodon shows it only when that account lists
|
|
217
|
+
this site's domain under author attribution.
|
|
218
|
+
#}
|
|
219
|
+
{% set creator = siteAuthor if isEntry else (soloAuthor if atRoot) %}
|
|
220
|
+
{% if creator.username %}
|
|
221
|
+
<meta name="fediverse:creator" content="{{ creator.username | fediverseHandle }}">
|
|
222
|
+
{% endif %}
|
|
204
223
|
<meta name="twitter:card" content="{{ shareImage.card if shareImage else "summary" }}">
|
|
205
224
|
<meta name="twitter:title" content="{{ metaTitle }}">
|
|
206
225
|
{% if metaDescription %}
|
|
@@ -261,7 +280,7 @@
|
|
|
261
280
|
|
|
262
281
|
{% block footer %}
|
|
263
282
|
<footer>
|
|
264
|
-
<p>© {{ "now" | date("year") }}{
|
|
283
|
+
<p>© {{ "now" | date("year") }}, {{ soloAuthor.name or site.title }}{% if license %} · <a rel="license" href="{{ license.url }}">{{ license.name }}</a>{% endif %} · Published with Geekity</p>
|
|
265
284
|
{#
|
|
266
285
|
The footer menu: the `footer` area this theme declares in its
|
|
267
286
|
`theme.json`, which a site fills in on the Navigation screen, and the
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
{#- Who the bio credits: the person the site's author setting names. -#}
|
|
23
23
|
{% set bioAuthor = soloAuthor or siteAuthor %}
|
|
24
24
|
{% set bioRelMe = true if soloAuthor else false %}
|
|
25
|
+
{% set bioHome = "/" | absoluteUrl if soloAuthor else "" %}
|
|
25
26
|
|
|
26
27
|
{% block content %}
|
|
27
28
|
<div class="page-body e-content">
|
|
@@ -38,6 +38,12 @@
|
|
|
38
38
|
homepage of a site that is not a solo author blog sets it (TASK-180), because
|
|
39
39
|
that page speaks for nobody even when it shows the site author's card.
|
|
40
40
|
|
|
41
|
+
`bioHome` set to the homepage's absolute URL makes the card the site's
|
|
42
|
+
representative h-card (TASK-193): its first `u-url` and its `u-uid` are that
|
|
43
|
+
URL, which is what a parser reading the homepage looks for to learn who the
|
|
44
|
+
site is. The name keeps its link to the archive, as a second `u-url`. Only
|
|
45
|
+
the homepage of a solo author blog sets it; every other card is unchanged.
|
|
46
|
+
|
|
41
47
|
The `p-note` and the `rel="me"` links are printed wherever the card is, which
|
|
42
48
|
is what `bioProfile` used to ask for on an author archive alone. An entry
|
|
43
49
|
left that switch unset because the page footer carried the site's identity
|
|
@@ -55,6 +61,7 @@
|
|
|
55
61
|
|
|
56
62
|
<div>
|
|
57
63
|
<p>
|
|
64
|
+
{%- if bioHome %}<data class="u-url u-uid" value="{{ bioHome }}"></data>{% endif %}
|
|
58
65
|
{{ bioLead | default("Written by") }}
|
|
59
66
|
{%- if bioAuthor.url %}
|
|
60
67
|
<a class="u-url p-name" rel="author{% if bioClaims %} me{% endif %}" href="{{ bioAuthor.url | url }}">{{ bioAuthor.name }}</a>
|
|
@@ -12,7 +12,12 @@
|
|
|
12
12
|
`siteAuthor`: the site's own author on a page about nobody in particular, the
|
|
13
13
|
writer on a post, the archive's user on an author archive. Identity comes
|
|
14
14
|
from a user profile, so a name that answers to no account here has no Person
|
|
15
|
-
at all, and the author
|
|
15
|
+
at all, and the author reference goes with it.
|
|
16
|
+
|
|
17
|
+
Who publishes the site follows the Site author setting (TASK-192). A site
|
|
18
|
+
whose author is a user is published by that user's Person and is about
|
|
19
|
+
them, on every page. A site with several authors is published by an
|
|
20
|
+
Organization named for the site and is about nobody.
|
|
16
21
|
|
|
17
22
|
How it is printed: every value goes through `dump`, which is JSON.stringify,
|
|
18
23
|
with every `<` escaped to its `\u003C` form so nothing in a title or a
|
|
@@ -34,6 +39,10 @@
|
|
|
34
39
|
{#- What the author, publisher and mainEntity members hold: a reference to the
|
|
35
40
|
Person rather than a second copy of them. -#}
|
|
36
41
|
{% set person = { "@id": personId } if personId else "" %}
|
|
42
|
+
{#- Who publishes the site and everything on it: the site author, else the
|
|
43
|
+
site itself. -#}
|
|
44
|
+
{% set soloId = (soloAuthor.url | absoluteUrl) + "#person" if soloAuthor.url else "" %}
|
|
45
|
+
{% set publisher = { "@id": soloId or home + "#organization" } %}
|
|
37
46
|
{#- `sameAs` is everywhere else this person is: the profile links they listed,
|
|
38
47
|
and their actor id, which asserts that the schema.org Person and the
|
|
39
48
|
fediverse actor are one identity — decision-14 makes their archive URL the
|
|
@@ -43,6 +52,10 @@
|
|
|
43
52
|
{% if personUrl %}{% set _ = sameAs.push(personUrl) %}{% endif %}
|
|
44
53
|
{% set address = { "@type": "PostalAddress", "addressLocality": siteAuthor.location } if siteAuthor.location else "" %}
|
|
45
54
|
{% set entryType = "BlogPosting" if type == "post" else "Article" %}
|
|
55
|
+
{#- A post with no title is headed by the words its <title> names it by,
|
|
56
|
+
within the 110 characters Google reads, cut where a word ends (TASK-201).
|
|
57
|
+
A page keeps its title. -#}
|
|
58
|
+
{% set headline = title or (label | truncate(109, false, "…") if type == "post" else "") %}
|
|
46
59
|
{% set nodes = [] %}
|
|
47
60
|
{% set website %}
|
|
48
61
|
{
|
|
@@ -63,12 +76,21 @@
|
|
|
63
76
|
},
|
|
64
77
|
"query-input": "required name=search_term_string"
|
|
65
78
|
}) }}
|
|
66
|
-
{{- member("publisher",
|
|
67
|
-
{
|
|
68
|
-
|
|
69
|
-
{{- member("about", { "@id": (soloAuthor.url | absoluteUrl) + "#person" } if atRoot and soloAuthor.url else "") }}
|
|
79
|
+
{{- member("publisher", publisher) }}
|
|
80
|
+
{{- member("about", { "@id": soloId } if soloId else "") }}
|
|
81
|
+
{{- member("license", siteLicense.url if siteLicense else "") }}
|
|
70
82
|
}{% endset %}
|
|
71
83
|
{% set _ = nodes.push(website) %}
|
|
84
|
+
{% if not soloId %}
|
|
85
|
+
{% set organization %}
|
|
86
|
+
{
|
|
87
|
+
"@type": "Organization"
|
|
88
|
+
{{- member("@id", publisher["@id"]) }}
|
|
89
|
+
{{- member("name", site.title) }}
|
|
90
|
+
{{- member("url", home) }}
|
|
91
|
+
}{% endset %}
|
|
92
|
+
{% set _ = nodes.push(organization) %}
|
|
93
|
+
{% endif %}
|
|
72
94
|
{% if personId %}
|
|
73
95
|
{% set profile %}
|
|
74
96
|
{
|
|
@@ -98,7 +120,7 @@
|
|
|
98
120
|
{% set entry %}
|
|
99
121
|
{
|
|
100
122
|
"@type": {{ entryType | dump | safe }}
|
|
101
|
-
{{- member("headline",
|
|
123
|
+
{{- member("headline", headline) }}
|
|
102
124
|
{{- member("url", metaUrl) }}
|
|
103
125
|
{{- member("mainEntityOfPage", metaUrl) }}
|
|
104
126
|
{{- member("datePublished", date | date("iso") if date else "") }}
|
|
@@ -106,7 +128,8 @@
|
|
|
106
128
|
{{- member("description", metaDescription) }}
|
|
107
129
|
{{- member("image", metaImage | absoluteUrl if metaImage else "") }}
|
|
108
130
|
{{- member("author", person) }}
|
|
109
|
-
{{- member("publisher",
|
|
131
|
+
{{- member("publisher", publisher) }}
|
|
132
|
+
{{- member("license", license.url if license else "") }}
|
|
110
133
|
}{% endset %}
|
|
111
134
|
{% set _ = nodes.push(entry) %}
|
|
112
135
|
{% endif %}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{#
|
|
2
|
+
Timed captions in WebVTT go on a video as a track as well as in the links,
|
|
3
|
+
since that is the one format a browser shows over the picture. The source
|
|
4
|
+
carries `u-audio` or `u-video`, so a microformats parser finds the file on
|
|
5
|
+
the entry.
|
|
6
|
+
|
|
7
|
+
The `preload="metadata"` asks for the length and the first frame and no
|
|
8
|
+
more: a reader who never presses play does not download the episode.
|
|
9
|
+
#}
|
|
10
|
+
{% set recordingLabel = ("Recording of " ~ title) if named else "Recording" %}
|
|
11
|
+
<figure class="post-recording">
|
|
12
|
+
{% if enclosure.player == "video" %}
|
|
13
|
+
<video controls preload="metadata" aria-label="{{ recordingLabel }}">
|
|
14
|
+
<source class="u-video" src="{{ enclosure.url | url }}" type="{{ enclosure.type }}">
|
|
15
|
+
{% if enclosure.transcript and enclosure.transcript.type == "text/vtt" %}
|
|
16
|
+
<track kind="captions" src="{{ enclosure.transcript.url | url }}" srclang="{{ lang or (site.language | default("en")) }}" label="Captions" default>
|
|
17
|
+
{% endif %}
|
|
18
|
+
<a href="{{ enclosure.url | url }}">Download the video</a>
|
|
19
|
+
</video>
|
|
20
|
+
{% else %}
|
|
21
|
+
<audio controls preload="metadata" aria-label="{{ recordingLabel }}">
|
|
22
|
+
<source class="u-audio" src="{{ enclosure.url | url }}" type="{{ enclosure.type }}">
|
|
23
|
+
<a href="{{ enclosure.url | url }}">Download the recording</a>
|
|
24
|
+
</audio>
|
|
25
|
+
{% endif %}
|
|
26
|
+
{% if enclosure.alternates.length or enclosure.transcript %}
|
|
27
|
+
<figcaption class="post-recording-links">
|
|
28
|
+
{% if enclosure.transcript %}
|
|
29
|
+
<p><a href="{{ enclosure.transcript.url | url }}">{{ "Captions" if enclosure.transcript.captions else "Transcript" }}</a></p>
|
|
30
|
+
{% endif %}
|
|
31
|
+
{% if enclosure.alternates.length %}
|
|
32
|
+
<p id="post-recording-versions">Other versions</p>
|
|
33
|
+
<ul aria-labelledby="post-recording-versions">
|
|
34
|
+
{% for alternate in enclosure.alternates %}
|
|
35
|
+
<li><a href="{{ alternate.url | url }}" type="{{ alternate.type }}"{% if alternate.lang %} hreflang="{{ alternate.lang }}"{% endif %}>{{ alternate.title or alternate.type }}</a></li>
|
|
36
|
+
{% endfor %}
|
|
37
|
+
</ul>
|
|
38
|
+
{% endif %}
|
|
39
|
+
</figcaption>
|
|
40
|
+
{% endif %}
|
|
41
|
+
</figure>
|
|
@@ -660,6 +660,22 @@
|
|
|
660
660
|
@apply text-[1.08rem] leading-[1.65];
|
|
661
661
|
}
|
|
662
662
|
|
|
663
|
+
.post-recording {
|
|
664
|
+
@apply my-8;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
.post-recording :is(audio, video) {
|
|
668
|
+
@apply block w-full;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
.post-recording-links {
|
|
672
|
+
@apply mt-3 font-sans text-sm text-muted;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
.post-recording-links ul {
|
|
676
|
+
@apply mt-1 flex flex-wrap gap-x-4 gap-y-1;
|
|
677
|
+
}
|
|
678
|
+
|
|
663
679
|
/* An untitled post is its words, set larger. It is the one entry whose
|
|
664
680
|
heading is the hidden one TASK-144 gave it. */
|
|
665
681
|
.blog-post > .screen-reader-text ~ .e-content {
|