@geekity/cms 0.12.0 → 0.13.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 +170 -4
- package/admin/pages/account/login.njk +3 -0
- package/admin/pages/documents/editor.njk +7 -0
- package/admin/pages/indieauth/consent.njk +51 -0
- package/admin/pages/indieauth/refused.njk +11 -0
- package/admin/pages/settings/general.njk +9 -0
- package/admin/pages/settings/reading.njk +93 -0
- package/admin/pages/users/apps.njk +74 -0
- package/admin/pages/users/edit.njk +12 -0
- package/admin/static/admin.css +27 -0
- package/dist/admin/accounts.d.ts +3 -0
- package/dist/admin/accounts.d.ts.map +1 -1
- package/dist/admin/accounts.js +5 -0
- package/dist/admin/accounts.js.map +1 -1
- package/dist/admin/documents.d.ts +2 -0
- package/dist/admin/documents.d.ts.map +1 -1
- package/dist/admin/documents.js +17 -1
- package/dist/admin/documents.js.map +1 -1
- package/dist/admin/headers.d.ts +5 -1
- package/dist/admin/headers.d.ts.map +1 -1
- package/dist/admin/headers.js +7 -3
- package/dist/admin/headers.js.map +1 -1
- package/dist/admin/menu.d.ts.map +1 -1
- package/dist/admin/menu.js +2 -1
- package/dist/admin/menu.js.map +1 -1
- package/dist/admin/routes.d.ts.map +1 -1
- package/dist/admin/routes.js +48 -5
- package/dist/admin/routes.js.map +1 -1
- package/dist/admin/settings-general.js +1 -1
- package/dist/admin/settings-general.js.map +1 -1
- package/dist/admin/settings-reading.d.ts.map +1 -1
- package/dist/admin/settings-reading.js +15 -1
- package/dist/admin/settings-reading.js.map +1 -1
- package/dist/admin/settings.d.ts +79 -2
- package/dist/admin/settings.d.ts.map +1 -1
- package/dist/admin/settings.js +168 -2
- package/dist/admin/settings.js.map +1 -1
- package/dist/admin/templates.d.ts +3 -0
- package/dist/admin/templates.d.ts.map +1 -1
- package/dist/admin/templates.js +3 -0
- package/dist/admin/templates.js.map +1 -1
- package/dist/admin/users.d.ts +8 -0
- package/dist/admin/users.d.ts.map +1 -1
- package/dist/admin/users.js +9 -0
- package/dist/admin/users.js.map +1 -1
- package/dist/config.d.ts +30 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/env.d.ts +14 -0
- package/dist/env.d.ts.map +1 -1
- package/dist/federation/article.d.ts.map +1 -1
- package/dist/federation/article.js +18 -5
- package/dist/federation/article.js.map +1 -1
- package/dist/images/icons.d.ts +44 -25
- package/dist/images/icons.d.ts.map +1 -1
- package/dist/images/icons.js +205 -60
- package/dist/images/icons.js.map +1 -1
- package/dist/images/index.d.ts +2 -2
- package/dist/images/index.d.ts.map +1 -1
- package/dist/images/index.js +1 -1
- package/dist/images/index.js.map +1 -1
- package/dist/images/markup.d.ts +14 -0
- package/dist/images/markup.d.ts.map +1 -1
- package/dist/images/markup.js +16 -11
- package/dist/images/markup.js.map +1 -1
- package/dist/images/variants.d.ts.map +1 -1
- package/dist/images/variants.js +3 -4
- package/dist/images/variants.js.map +1 -1
- package/dist/index.d.ts +14 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +28 -1
- package/dist/index.js.map +1 -1
- package/dist/indexnow.d.ts +34 -0
- package/dist/indexnow.d.ts.map +1 -0
- package/dist/indexnow.js +141 -0
- package/dist/indexnow.js.map +1 -0
- package/dist/indieauth/bearer.d.ts +39 -0
- package/dist/indieauth/bearer.d.ts.map +1 -0
- package/dist/indieauth/bearer.js +63 -0
- package/dist/indieauth/bearer.js.map +1 -0
- package/dist/indieauth/client.d.ts +61 -0
- package/dist/indieauth/client.d.ts.map +1 -0
- package/dist/indieauth/client.js +139 -0
- package/dist/indieauth/client.js.map +1 -0
- package/dist/indieauth/connected-apps.d.ts +23 -0
- package/dist/indieauth/connected-apps.d.ts.map +1 -0
- package/dist/indieauth/connected-apps.js +73 -0
- package/dist/indieauth/connected-apps.js.map +1 -0
- package/dist/indieauth/consent.d.ts +28 -0
- package/dist/indieauth/consent.d.ts.map +1 -0
- package/dist/indieauth/consent.js +185 -0
- package/dist/indieauth/consent.js.map +1 -0
- package/dist/indieauth/discovery.d.ts +87 -0
- package/dist/indieauth/discovery.d.ts.map +1 -0
- package/dist/indieauth/discovery.js +127 -0
- package/dist/indieauth/discovery.js.map +1 -0
- package/dist/indieauth/grants.d.ts +57 -0
- package/dist/indieauth/grants.d.ts.map +1 -0
- package/dist/indieauth/grants.js +35 -0
- package/dist/indieauth/grants.js.map +1 -0
- package/dist/indieauth/identity.d.ts +36 -0
- package/dist/indieauth/identity.d.ts.map +1 -0
- package/dist/indieauth/identity.js +78 -0
- package/dist/indieauth/identity.js.map +1 -0
- package/dist/indieauth/redeem.d.ts +47 -0
- package/dist/indieauth/redeem.d.ts.map +1 -0
- package/dist/indieauth/redeem.js +69 -0
- package/dist/indieauth/redeem.js.map +1 -0
- package/dist/indieauth/request.d.ts +47 -0
- package/dist/indieauth/request.d.ts.map +1 -0
- package/dist/indieauth/request.js +104 -0
- package/dist/indieauth/request.js.map +1 -0
- package/dist/indieauth/token.d.ts +19 -0
- package/dist/indieauth/token.d.ts.map +1 -0
- package/dist/indieauth/token.js +110 -0
- package/dist/indieauth/token.js.map +1 -0
- package/dist/indieauth/tokens.d.ts +131 -0
- package/dist/indieauth/tokens.d.ts.map +1 -0
- package/dist/indieauth/tokens.js +205 -0
- package/dist/indieauth/tokens.js.map +1 -0
- package/dist/web/archive.d.ts +1 -1
- package/dist/web/archive.d.ts.map +1 -1
- package/dist/web/archive.js +3 -2
- package/dist/web/archive.js.map +1 -1
- package/dist/web/context.d.ts +25 -0
- package/dist/web/context.d.ts.map +1 -1
- package/dist/web/context.js +18 -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 +3 -1
- package/dist/web/feed-atom.js.map +1 -1
- package/dist/web/feed-item.d.ts +11 -2
- package/dist/web/feed-item.d.ts.map +1 -1
- package/dist/web/feed-item.js +9 -3
- package/dist/web/feed-item.js.map +1 -1
- package/dist/web/feed-json.d.ts +4 -0
- package/dist/web/feed-json.d.ts.map +1 -1
- package/dist/web/feed-json.js +4 -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 +16 -3
- package/dist/web/feed-rss.js.map +1 -1
- package/dist/web/feed-source.d.ts +28 -0
- package/dist/web/feed-source.d.ts.map +1 -1
- package/dist/web/feed-source.js +31 -0
- package/dist/web/feed-source.js.map +1 -1
- package/dist/web/feed-xml.d.ts +2 -0
- package/dist/web/feed-xml.d.ts.map +1 -1
- package/dist/web/feed-xml.js +2 -0
- package/dist/web/feed-xml.js.map +1 -1
- package/dist/web/feeds.d.ts.map +1 -1
- package/dist/web/feeds.js +8 -1
- package/dist/web/feeds.js.map +1 -1
- package/dist/web/index.d.ts +3 -1
- package/dist/web/index.d.ts.map +1 -1
- package/dist/web/index.js +2 -1
- package/dist/web/index.js.map +1 -1
- package/dist/web/indexnow.d.ts +9 -0
- package/dist/web/indexnow.d.ts.map +1 -0
- package/dist/web/indexnow.js +27 -0
- package/dist/web/indexnow.js.map +1 -0
- package/dist/web/llms.d.ts +58 -0
- package/dist/web/llms.d.ts.map +1 -0
- package/dist/web/llms.js +91 -0
- package/dist/web/llms.js.map +1 -0
- package/dist/web/locale.d.ts +41 -0
- package/dist/web/locale.d.ts.map +1 -0
- package/dist/web/locale.js +56 -0
- package/dist/web/locale.js.map +1 -0
- package/dist/web/manifest.d.ts +50 -0
- package/dist/web/manifest.d.ts.map +1 -0
- package/dist/web/manifest.js +56 -0
- package/dist/web/manifest.js.map +1 -0
- package/dist/web/negotiate.d.ts.map +1 -1
- package/dist/web/negotiate.js +6 -0
- package/dist/web/negotiate.js.map +1 -1
- package/dist/web/render.d.ts +6 -1
- package/dist/web/render.d.ts.map +1 -1
- package/dist/web/render.js +41 -10
- package/dist/web/render.js.map +1 -1
- package/dist/web/robots.d.ts +89 -0
- package/dist/web/robots.d.ts.map +1 -0
- package/dist/web/robots.js +259 -0
- package/dist/web/robots.js.map +1 -0
- package/dist/web/routes.d.ts.map +1 -1
- package/dist/web/routes.js +105 -6
- package/dist/web/routes.js.map +1 -1
- package/dist/web/share-image.d.ts +51 -0
- package/dist/web/share-image.d.ts.map +1 -0
- package/dist/web/share-image.js +43 -0
- package/dist/web/share-image.js.map +1 -0
- package/dist/web/sitemap.d.ts +0 -26
- package/dist/web/sitemap.d.ts.map +1 -1
- package/dist/web/sitemap.js +0 -44
- package/dist/web/sitemap.js.map +1 -1
- package/dist/web/templates.d.ts +16 -9
- package/dist/web/templates.d.ts.map +1 -1
- package/dist/web/templates.js +83 -55
- package/dist/web/templates.js.map +1 -1
- package/dist/web/themes.d.ts +33 -0
- package/dist/web/themes.d.ts.map +1 -1
- package/dist/web/themes.js +57 -0
- package/dist/web/themes.js.map +1 -1
- package/dist/webmention/discovery.d.ts +4 -2
- package/dist/webmention/discovery.d.ts.map +1 -1
- package/dist/webmention/discovery.js +14 -8
- package/dist/webmention/discovery.js.map +1 -1
- package/dist/webmention/fetch-public.d.ts +2 -0
- package/dist/webmention/fetch-public.d.ts.map +1 -1
- package/dist/webmention/fetch-public.js +1 -1
- package/dist/webmention/fetch-public.js.map +1 -1
- package/package.json +1 -1
- package/themes/default/README.md +119 -29
- package/themes/default/layouts/base.njk +95 -16
- package/themes/default/layouts/front-page.njk +6 -1
- package/themes/default/layouts/home.njk +10 -0
- package/themes/default/layouts/page.njk +4 -3
- package/themes/default/layouts/post.njk +5 -4
- package/themes/default/layouts/search.njk +4 -5
- package/themes/default/partials/archive.njk +3 -1
- package/themes/default/partials/bio.njk +9 -2
- package/themes/default/partials/breadcrumbs.njk +20 -0
- package/themes/default/partials/conversation.njk +4 -1
- package/themes/default/partials/jsonld.njk +19 -4
- package/themes/default/partials/kicker.njk +6 -4
- package/themes/default/partials/lang.njk +7 -0
- package/themes/default/partials/post-list.njk +5 -3
- package/themes/default/partials/reply-context.njk +4 -2
- package/themes/default/src/style.css +14 -0
- package/themes/default/static/style.css +53 -0
- package/themes/default/theme.json +2 -0
|
@@ -23,6 +23,8 @@
|
|
|
23
23
|
adds to it.
|
|
24
24
|
alternates <link rel="alternate"> tags, where the feeds go
|
|
25
25
|
header the site header, with the site menu
|
|
26
|
+
breadcrumbs the trail at the top of <main>; empty it to print none
|
|
27
|
+
(the JSON-LD keeps its BreadcrumbList)
|
|
26
28
|
content the page body
|
|
27
29
|
footer the site footer
|
|
28
30
|
scripts scripts at the end of <body>
|
|
@@ -38,8 +40,10 @@
|
|
|
38
40
|
|
|
39
41
|
`metaDescription` is the page's own description, else the entry's summary
|
|
40
42
|
— the very line the feeds publish — else the site's tagline. `metaImage` is
|
|
41
|
-
the picture the front matter names, else the site's
|
|
42
|
-
nothing is printed rather than an empty tag.
|
|
43
|
+
`shareImage.url`: the picture the front matter names, else the site's
|
|
44
|
+
avatar; with neither, nothing is printed rather than an empty tag. The CMS
|
|
45
|
+
works out `shareImage` because its alt text and its size live in files a
|
|
46
|
+
template cannot read. `isEntry` is a rendered post
|
|
43
47
|
or page, which is what Open Graph calls an article: a listing has
|
|
44
48
|
`pagination`, and the posts page is a listing carrying a page's front
|
|
45
49
|
matter, so it is a website like every other listing. -#}
|
|
@@ -48,13 +52,51 @@
|
|
|
48
52
|
{% set pageTitle = title or label %}
|
|
49
53
|
{% set metaTitle = pageTitle or site.title %}
|
|
50
54
|
{% set metaUrl = (page.url or "/") | absoluteUrl %}
|
|
51
|
-
{% set metaImage =
|
|
55
|
+
{% set metaImage = shareImage.url if shareImage else "" %}
|
|
52
56
|
{% set isEntry = (type == "post" or type == "page") and not pagination %}
|
|
57
|
+
{#- An author archive is the only page that is about a person: a listing whose
|
|
58
|
+
`author` is whose page this is, rather than the posts page's writer. -#}
|
|
59
|
+
{% set isAuthorArchive = pagination and author.url and url and (author.url in url) %}
|
|
60
|
+
{#- Where this page sits, as `{ name, url }` from the front page down to it
|
|
61
|
+
(TASK-150): a post under its first category, and an archive under the
|
|
62
|
+
front page, with a crumb of its own past page one. The visible breadcrumb
|
|
63
|
+
and the JSON-LD both print this list, so they cannot say different things.
|
|
64
|
+
Every other page has no hierarchy worth showing and an empty trail. -#}
|
|
65
|
+
{% set crumbs = [] %}
|
|
66
|
+
{% if pagination and category %}
|
|
67
|
+
{% set _ = crumbs.push({ "name": category, "url": "/" + (site.categoryBase or "category") + "/" + (category | urlencode) + "/" }) %}
|
|
68
|
+
{% elif pagination and tag %}
|
|
69
|
+
{% set _ = crumbs.push({ "name": tag, "url": "/" + (site.tagBase or "tag") + "/" + (tag | urlencode) + "/" }) %}
|
|
70
|
+
{% elif isAuthorArchive %}
|
|
71
|
+
{% set _ = crumbs.push({ "name": author.name, "url": author.url }) %}
|
|
72
|
+
{% elif type == "post" and isEntry and categories.length %}
|
|
73
|
+
{% set _ = crumbs.push({ "name": categories[0], "url": "/" + (site.categoryBase or "category") + "/" + (categories[0] | urlencode) + "/" }) %}
|
|
74
|
+
{% set _ = crumbs.push({ "name": pageTitle, "url": page.url or url }) %}
|
|
75
|
+
{% endif %}
|
|
76
|
+
{% if crumbs.length and pagination.pageNumber > 0 %}
|
|
77
|
+
{% set _ = crumbs.push({ "name": "Page " + (pagination.pageNumber + 1), "url": page.url or url }) %}
|
|
78
|
+
{% endif %}
|
|
79
|
+
{% set breadcrumbs = [{ "name": "Home", "url": "/" }].concat(crumbs) if crumbs.length else [] %}
|
|
53
80
|
<!doctype html>
|
|
54
81
|
<html lang="{{ site.language | default("en") }}">
|
|
55
82
|
<head>
|
|
56
83
|
<meta charset="utf-8">
|
|
57
84
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
85
|
+
{#
|
|
86
|
+
The colours the theme's `theme.json` declares (TASK-146). The colour
|
|
87
|
+
scheme goes before the stylesheet, so a reader in dark mode gets a dark
|
|
88
|
+
canvas while the stylesheet is still on its way rather than a white
|
|
89
|
+
flash. The theme colour tints the browser around the page, one per
|
|
90
|
+
scheme, and is the page's own background so the two meet without a seam.
|
|
91
|
+
#}
|
|
92
|
+
{% if theme.colorScheme %}
|
|
93
|
+
<meta name="color-scheme" content="{{ theme.colorScheme }}">
|
|
94
|
+
{% endif %}
|
|
95
|
+
{% for scheme in ["light", "dark"] %}
|
|
96
|
+
{% if theme.themeColor[scheme] %}
|
|
97
|
+
<meta name="theme-color" content="{{ theme.themeColor[scheme] }}" media="(prefers-color-scheme: {{ scheme }})">
|
|
98
|
+
{% endif %}
|
|
99
|
+
{% endfor %}
|
|
58
100
|
<title>{% block title %}{% if pageTitle %}{{ pageTitle }} · {% endif %}{{ site.title }}{% endblock %}</title>
|
|
59
101
|
{% if metaDescription %}
|
|
60
102
|
<meta name="description" content="{{ metaDescription }}">
|
|
@@ -110,13 +152,23 @@
|
|
|
110
152
|
{% if webmention %}
|
|
111
153
|
<link rel="webmention" href="{{ webmention | url }}">
|
|
112
154
|
{% endif %}
|
|
155
|
+
{#- The site's index for language models (TASK-149), from the front page,
|
|
156
|
+
which is where a tool that found the site looks for it. #}
|
|
157
|
+
{% if llmsTxt and atRoot %}
|
|
158
|
+
<link rel="describedby" type="text/markdown" href="{{ llmsTxt | url }}">
|
|
159
|
+
{% endif %}
|
|
113
160
|
{% block head %}
|
|
114
161
|
{#
|
|
115
162
|
What a link to this page looks like when somebody posts it: the same
|
|
116
163
|
title, description and picture to Open Graph and to a Twitter card,
|
|
117
|
-
which is the pair every reader of this markup understands. The
|
|
118
|
-
always
|
|
119
|
-
|
|
164
|
+
which is the pair every reader of this markup understands. The image
|
|
165
|
+
always carries its alt text, and its size when the CMS knows it. The
|
|
166
|
+
card is `summary_large_image` only for a picture wide enough to fill
|
|
167
|
+
one, and `summary` — a small picture beside the words — for the site's
|
|
168
|
+
avatar and anything else.
|
|
169
|
+
|
|
170
|
+
An entry is an article, with its times, its author and its tags: the
|
|
171
|
+
author is their profile here when they have one, else their name.
|
|
120
172
|
#}
|
|
121
173
|
<meta property="og:title" content="{{ metaTitle }}">
|
|
122
174
|
{% if metaDescription %}
|
|
@@ -125,25 +177,49 @@
|
|
|
125
177
|
<meta property="og:url" content="{{ metaUrl }}">
|
|
126
178
|
<meta property="og:type" content="{% if isEntry %}article{% else %}website{% endif %}">
|
|
127
179
|
<meta property="og:site_name" content="{{ site.title }}">
|
|
128
|
-
{% if
|
|
129
|
-
<meta property="og:image" content="{{
|
|
180
|
+
{% if shareImage %}
|
|
181
|
+
<meta property="og:image" content="{{ shareImage.url | absoluteUrl }}">
|
|
182
|
+
<meta property="og:image:alt" content="{{ shareImage.alt }}">
|
|
183
|
+
{% if shareImage.size %}
|
|
184
|
+
<meta property="og:image:width" content="{{ shareImage.size.width }}">
|
|
185
|
+
<meta property="og:image:height" content="{{ shareImage.size.height }}">
|
|
186
|
+
{% endif %}
|
|
187
|
+
{% endif %}
|
|
188
|
+
{% if isEntry %}
|
|
189
|
+
{% if date %}
|
|
190
|
+
<meta property="article:published_time" content="{{ date | date("iso") }}">
|
|
191
|
+
{% endif %}
|
|
192
|
+
{% if updated or date %}
|
|
193
|
+
<meta property="article:modified_time" content="{{ (updated or date) | date("iso") }}">
|
|
194
|
+
{% endif %}
|
|
195
|
+
{% if siteAuthor.url %}
|
|
196
|
+
<meta property="article:author" content="{{ siteAuthor.url | absoluteUrl }}">
|
|
197
|
+
{% elif siteAuthor.name or author.name or author or site.author %}
|
|
198
|
+
<meta property="article:author" content="{{ siteAuthor.name or author.name or author or site.author }}">
|
|
199
|
+
{% endif %}
|
|
200
|
+
{% for tag in tags %}
|
|
201
|
+
<meta property="article:tag" content="{{ tag }}">
|
|
202
|
+
{% endfor %}
|
|
130
203
|
{% endif %}
|
|
131
|
-
<meta name="twitter:card" content="summary">
|
|
204
|
+
<meta name="twitter:card" content="{{ shareImage.card if shareImage else "summary" }}">
|
|
132
205
|
<meta name="twitter:title" content="{{ metaTitle }}">
|
|
133
206
|
{% if metaDescription %}
|
|
134
207
|
<meta name="twitter:description" content="{{ metaDescription }}">
|
|
135
208
|
{% endif %}
|
|
136
|
-
{% if
|
|
137
|
-
<meta name="twitter:image" content="{{
|
|
209
|
+
{% if shareImage %}
|
|
210
|
+
<meta name="twitter:image" content="{{ shareImage.url | absoluteUrl }}">
|
|
211
|
+
<meta name="twitter:image:alt" content="{{ shareImage.alt }}">
|
|
138
212
|
{% endif %}
|
|
139
213
|
{#
|
|
140
|
-
The site's icons, derived from its
|
|
141
|
-
lines print nothing — until a site has one,
|
|
142
|
-
links no icon rather than
|
|
214
|
+
The site's icons, derived from its `icon` setting, else its avatar.
|
|
215
|
+
`icons` is empty — and these lines print nothing — until a site has one,
|
|
216
|
+
so a site with neither links no icon rather than links that answer 404.
|
|
217
|
+
An SVG icon has every size, so it carries no `sizes`.
|
|
143
218
|
#}
|
|
144
219
|
{% for icon in icons %}
|
|
145
|
-
<link rel="{{ icon.rel }}" type="
|
|
220
|
+
<link rel="{{ icon.rel }}" type="{{ icon.type }}"{% if icon.sizes %} sizes="{{ icon.sizes }}"{% endif %} href="{{ icon.href | url }}">
|
|
146
221
|
{% endfor %}
|
|
222
|
+
<link rel="manifest" href="{{ "/manifest.webmanifest" | url }}">
|
|
147
223
|
{% include "partials/jsonld.njk" %}
|
|
148
224
|
{% endblock %}
|
|
149
225
|
</head>
|
|
@@ -170,13 +246,16 @@
|
|
|
170
246
|
<p class="site-tagline">{{ site.tagline }}</p>
|
|
171
247
|
{% endif %}
|
|
172
248
|
{% else %}
|
|
173
|
-
|
|
249
|
+
{#- The solo author's own archive claims the homepage back, so the
|
|
250
|
+
two URLs are provably one person (TASK-180). -#}
|
|
251
|
+
<a class="header-link-home"{% if isAuthorArchive and soloAuthor.url == author.url %} rel="me"{% endif %} href="{{ "/" | url }}">{{ site.title }}</a>
|
|
174
252
|
{% endif %}
|
|
175
253
|
{{ nav.list(menus.primary, "Site") }}
|
|
176
254
|
</header>
|
|
177
255
|
{% endblock %}
|
|
178
256
|
|
|
179
257
|
<main id="main">
|
|
258
|
+
{% block breadcrumbs %}{% include "partials/breadcrumbs.njk" %}{% endblock %}
|
|
180
259
|
{% block content %}{% endblock %}
|
|
181
260
|
</main>
|
|
182
261
|
|
|
@@ -10,13 +10,18 @@
|
|
|
10
10
|
over the same feed a listing is made of, headed at 3 so the outline never
|
|
11
11
|
skips a level, then the line of links, then the bio.
|
|
12
12
|
|
|
13
|
+
The bio is the site's author's on a solo author blog, with the `rel="me"`
|
|
14
|
+
claims that make this page their identity (TASK-180). On any other site it is
|
|
15
|
+
whoever the page is by, and it claims nothing: the homepage speaks for nobody.
|
|
16
|
+
|
|
13
17
|
A theme that wants a different front page replaces this file; a site that
|
|
14
18
|
wants no front page of its own sets no homepage, and `/` is the listing.
|
|
15
19
|
#}
|
|
16
20
|
{% extends "layouts/base.njk" %}
|
|
17
21
|
|
|
18
22
|
{#- Who the bio credits: the person the site's author setting names. -#}
|
|
19
|
-
{% set bioAuthor = siteAuthor %}
|
|
23
|
+
{% set bioAuthor = soloAuthor or siteAuthor %}
|
|
24
|
+
{% set bioRelMe = true if soloAuthor else false %}
|
|
20
25
|
|
|
21
26
|
{% block content %}
|
|
22
27
|
<div class="page-body e-content">
|
|
@@ -22,4 +22,14 @@
|
|
|
22
22
|
{% endif %}
|
|
23
23
|
{% include "partials/post-list.njk" %}
|
|
24
24
|
{% include "partials/pagination.njk" %}
|
|
25
|
+
{#- On a solo author blog the homepage speaks for the site's author, so it
|
|
26
|
+
ends with their card, as the front page does (TASK-180). Any other
|
|
27
|
+
listing, and the homepage of any other site, is nobody's. -#}
|
|
28
|
+
{% if atRoot and soloAuthor %}
|
|
29
|
+
{% set bioAuthor = soloAuthor %}
|
|
30
|
+
<hr>
|
|
31
|
+
<footer>
|
|
32
|
+
{% include "partials/bio.njk" %}
|
|
33
|
+
</footer>
|
|
34
|
+
{% endif %}
|
|
25
35
|
{% endblock %}
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
#}
|
|
15
15
|
{% extends "layouts/base.njk" %}
|
|
16
16
|
{% import "partials/kicker.njk" as kicker with context %}
|
|
17
|
+
{% import "partials/lang.njk" as language with context %}
|
|
17
18
|
|
|
18
19
|
{#- Who the bio credits, and what tells `layouts/base.njk` the site menu is in
|
|
19
20
|
the bio rather than in the page footer. -#}
|
|
@@ -21,7 +22,7 @@
|
|
|
21
22
|
|
|
22
23
|
{% block content %}
|
|
23
24
|
{% set entryUrl = page.url or url %}
|
|
24
|
-
<article class="blog-post h-entry">
|
|
25
|
+
<article class="blog-post h-entry"{{ language.attr(lang) }}>
|
|
25
26
|
<header class="post-header">
|
|
26
27
|
{{ kicker.line("Page") }}
|
|
27
28
|
<h1 class="p-name">{{ title }}</h1>
|
|
@@ -35,10 +36,10 @@
|
|
|
35
36
|
deciding twice whether there is anything to say. -#}
|
|
36
37
|
<p class="page-meta">
|
|
37
38
|
{%- if date %}
|
|
38
|
-
<a href="{{ entryUrl | url }}" class="u-url"><time class="small dt-published" datetime="{{ date | date("iso") }}">Published {{ date | date }}</time></a>
|
|
39
|
+
<a href="{{ entryUrl | url }}" class="u-url"><time class="small dt-published" datetime="{{ date | date("iso") }}">Published {{ date | date("readable", none, lang) }}</time></a>
|
|
39
40
|
{%- endif %}
|
|
40
41
|
{%- if updated and (not date or (updated | date("html")) != (date | date("html"))) %}
|
|
41
|
-
{% if date %}<span aria-hidden="true">·</span> {% endif %}<time class="small dt-updated" datetime="{{ updated | date("iso") }}">Updated {{ updated | date }}</time>
|
|
42
|
+
{% if date %}<span aria-hidden="true">·</span> {% endif %}<time class="small dt-updated" datetime="{{ updated | date("iso") }}">Updated {{ updated | date("readable", none, lang) }}</time>
|
|
42
43
|
{%- endif -%}
|
|
43
44
|
</p>
|
|
44
45
|
</section>
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
{% extends "layouts/base.njk" %}
|
|
18
18
|
{% import "partials/tags.njk" as taxonomy with context %}
|
|
19
19
|
{% import "partials/kicker.njk" as kicker with context %}
|
|
20
|
+
{% import "partials/lang.njk" as language with context %}
|
|
20
21
|
|
|
21
22
|
{#- Who the bio credits: the person the file names, and otherwise whoever the
|
|
22
23
|
site is by, which is what the source theme's bio reads. A post naming
|
|
@@ -28,7 +29,7 @@
|
|
|
28
29
|
|
|
29
30
|
{% block content %}
|
|
30
31
|
{% set entryUrl = page.url or url %}
|
|
31
|
-
<article class="blog-post h-entry">
|
|
32
|
+
<article class="blog-post h-entry"{{ language.attr(lang) }}>
|
|
32
33
|
{#- A post with no name of its own (a note, or a reply without a title) is
|
|
33
34
|
its words, so it opens on them in sight. Its page still needs one h1 to
|
|
34
35
|
navigate by, so it gets one that says what it is, who wrote it and when,
|
|
@@ -49,7 +50,7 @@
|
|
|
49
50
|
<h1 class="screen-reader-text">
|
|
50
51
|
{{- "Reply" if postType == "reply" else "Note" }}
|
|
51
52
|
{%- if bioAuthor.name %} by {{ bioAuthor.name }}{% endif %}
|
|
52
|
-
{%- if date %}, {{ date | date }}{% endif -%}
|
|
53
|
+
{%- if date %}, {{ date | date("readable", none, lang) }}{% endif -%}
|
|
53
54
|
</h1>
|
|
54
55
|
{{ kicker.line(postType | capitalize, false, false, categories) }}
|
|
55
56
|
{% include "partials/reply-context.njk" %}
|
|
@@ -64,12 +65,12 @@
|
|
|
64
65
|
<a class="u-category small" href="https://news.indieweb.org/en">#indienews</a>
|
|
65
66
|
{%- endif %}
|
|
66
67
|
{%- if date %}
|
|
67
|
-
<a href="{{ entryUrl | url }}" class="u-url"><time class="small dt-published" datetime="{{ date | date("iso") }}">Published {{ date | date }}</time></a>
|
|
68
|
+
<a href="{{ entryUrl | url }}" class="u-url"><time class="small dt-published" datetime="{{ date | date("iso") }}">Published {{ date | date("readable", none, lang) }}</time></a>
|
|
68
69
|
{%- endif %}
|
|
69
70
|
{#- Updated only when it is a different day in the site's own timezone:
|
|
70
71
|
a typo fixed an hour after publishing is not news. -#}
|
|
71
72
|
{%- if updated and (not date or (updated | date("html")) != (date | date("html"))) %}
|
|
72
|
-
{% if date %}<span aria-hidden="true">·</span> {% endif %}<time class="small dt-updated" datetime="{{ updated | date("iso") }}">Updated {{ updated | date }}</time>
|
|
73
|
+
{% if date %}<span aria-hidden="true">·</span> {% endif %}<time class="small dt-updated" datetime="{{ updated | date("iso") }}">Updated {{ updated | date("readable", none, lang) }}</time>
|
|
73
74
|
{%- endif -%}
|
|
74
75
|
</p>
|
|
75
76
|
</section>
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
{% endblock %}
|
|
22
22
|
|
|
23
23
|
{% import "partials/kicker.njk" as kicker with context %}
|
|
24
|
+
{% import "partials/lang.njk" as language with context %}
|
|
24
25
|
{% block content %}
|
|
25
26
|
<h1 class="page-title">Search</h1>
|
|
26
27
|
{% include "partials/search-form.njk" %}
|
|
@@ -28,17 +29,15 @@
|
|
|
28
29
|
<p class="search-summary" role="status">
|
|
29
30
|
{%- if pagination.total == 0 -%}
|
|
30
31
|
Nothing found for “{{ query }}”.
|
|
31
|
-
{%- elif pagination.total == 1 -%}
|
|
32
|
-
One result for “{{ query }}”.
|
|
33
32
|
{%- else -%}
|
|
34
|
-
{{ pagination.total }}
|
|
33
|
+
{{ pagination.total | plural({ one: "One result", other: "# results" }, "en") }} for “{{ query }}”.
|
|
35
34
|
{%- endif -%}
|
|
36
35
|
</p>
|
|
37
36
|
{% if posts.length %}
|
|
38
37
|
<div class="search-results">
|
|
39
38
|
{% for post in posts %}
|
|
40
|
-
<article class="search-result h-entry">
|
|
41
|
-
{{ kicker.line(("Page" if post.type == "page" else post.postType) | capitalize, post.date) }}
|
|
39
|
+
<article class="search-result h-entry"{{ language.attr(post.lang) }}>
|
|
40
|
+
{{ kicker.line(("Page" if post.type == "page" else post.postType) | capitalize, post.date, lang=post.lang) }}
|
|
42
41
|
{#- A post with no name of its own has none to claim, so its first words
|
|
43
42
|
link it without being marked up as one. -#}
|
|
44
43
|
<h2 class="feed-title{% if post.named %} p-name{% endif %}">
|
|
@@ -14,7 +14,9 @@
|
|
|
14
14
|
rather than an index.
|
|
15
15
|
#}
|
|
16
16
|
{% if archiveMonths.length %}
|
|
17
|
-
|
|
17
|
+
{#- The month headings are in the site's locale, so a page in another
|
|
18
|
+
language hands the section back to the site's language. -#}
|
|
19
|
+
<section class="archive"{% if lang and lang != (site.language | default("en")) %} lang="{{ site.language | default("en") }}"{% endif %}>
|
|
18
20
|
{% for group in archiveMonths %}
|
|
19
21
|
<h2>{{ group.month }}</h2>
|
|
20
22
|
<ol class="list-none">
|
|
@@ -33,6 +33,11 @@
|
|
|
33
33
|
Links box typed it — followed by whatever else that line carried, so this
|
|
34
34
|
prints one attribute rather than one of its own beside one of theirs.
|
|
35
35
|
|
|
36
|
+
`bioRelMe` set to `false` keeps the card and drops its claims: the name is
|
|
37
|
+
linked `rel="author"` alone and `me` comes off every profile link. The
|
|
38
|
+
homepage of a site that is not a solo author blog sets it (TASK-180), because
|
|
39
|
+
that page speaks for nobody even when it shows the site author's card.
|
|
40
|
+
|
|
36
41
|
The `p-note` and the `rel="me"` links are printed wherever the card is, which
|
|
37
42
|
is what `bioProfile` used to ask for on an author archive alone. An entry
|
|
38
43
|
left that switch unset because the page footer carried the site's identity
|
|
@@ -40,6 +45,7 @@
|
|
|
40
45
|
wrote rather than one page further on.
|
|
41
46
|
#}
|
|
42
47
|
{% if bioAuthor %}
|
|
48
|
+
{%- set bioClaims = bioRelMe !== false %}
|
|
43
49
|
<div class="bio p-author h-card">
|
|
44
50
|
{%- if bioAuthor.avatar %}
|
|
45
51
|
<div class="bio-avatar">
|
|
@@ -51,7 +57,7 @@
|
|
|
51
57
|
<p>
|
|
52
58
|
{{ bioLead | default("Written by") }}
|
|
53
59
|
{%- if bioAuthor.url %}
|
|
54
|
-
<a class="u-url p-name" rel="author me" href="{{ bioAuthor.url | url }}">{{ bioAuthor.name }}</a>
|
|
60
|
+
<a class="u-url p-name" rel="author{% if bioClaims %} me{% endif %}" href="{{ bioAuthor.url | url }}">{{ bioAuthor.name }}</a>
|
|
55
61
|
{%- else %}
|
|
56
62
|
<strong class="p-name">{{ bioAuthor.name }}</strong>
|
|
57
63
|
{%- endif %}
|
|
@@ -66,7 +72,8 @@
|
|
|
66
72
|
{%- if bioAuthor.links.length %}
|
|
67
73
|
<ul class="hlist bio-links">
|
|
68
74
|
{%- for link in bioAuthor.links %}
|
|
69
|
-
|
|
75
|
+
{%- set linkRel = link.rel if bioClaims else (link.rel.split(" ") | reject("equalto", "me") | join(" ")) %}
|
|
76
|
+
<li><a class="u-url"{% if linkRel %} rel="{{ linkRel }}"{% endif %} href="{{ link.href }}">{{ link.label }}</a></li>
|
|
70
77
|
{%- endfor %}
|
|
71
78
|
</ul>
|
|
72
79
|
{%- endif %}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{#
|
|
2
|
+
The trail from the front page down to this one (TASK-150), printed from
|
|
3
|
+
`breadcrumbs`, the list `layouts/base.njk` builds and `partials/jsonld.njk`
|
|
4
|
+
prints as a BreadcrumbList. Every crumb but the last is a link; the last is
|
|
5
|
+
the page the reader is on, so it is text marked as the current page. The
|
|
6
|
+
separators are decoration and a screen reader skips them: the list already
|
|
7
|
+
says there are steps.
|
|
8
|
+
#}
|
|
9
|
+
{% if breadcrumbs.length %}
|
|
10
|
+
<nav class="breadcrumbs" aria-label="Breadcrumb">
|
|
11
|
+
<ol class="hlist">
|
|
12
|
+
{% for crumb in breadcrumbs %}
|
|
13
|
+
<li>
|
|
14
|
+
{%- if not loop.first %}<span class="breadcrumbs-sep" aria-hidden="true">›</span>{% endif -%}
|
|
15
|
+
{%- if loop.last %}<span aria-current="page">{{ crumb.name }}</span>{% else %}<a href="{{ crumb.url | url }}">{{ crumb.name }}</a>{% endif -%}
|
|
16
|
+
</li>
|
|
17
|
+
{% endfor %}
|
|
18
|
+
</ol>
|
|
19
|
+
</nav>
|
|
20
|
+
{% endif %}
|
|
@@ -120,6 +120,9 @@
|
|
|
120
120
|
And the thread. The title counts the whole of it rather than the top level,
|
|
121
121
|
which is what `counts.replies` is. It does not quote the post's title: the
|
|
122
122
|
post is the page it sits under, and a note has no title to quote (TASK-186).
|
|
123
|
+
The count goes through `plural` with "en" because the words are English: a
|
|
124
|
+
theme that translates them drops the "en" and gives the forms its language
|
|
125
|
+
has, so the site's locale picks between them.
|
|
123
126
|
|
|
124
127
|
"Comments are closed." is printed under a post that has been answered and is
|
|
125
128
|
no longer taking comments. That a post is closed is what the absence of
|
|
@@ -130,7 +133,7 @@
|
|
|
130
133
|
{% if conversation.replies.length %}
|
|
131
134
|
<div id="comments" class="comments-area">
|
|
132
135
|
<h2 class="comments-title">
|
|
133
|
-
{
|
|
136
|
+
{{- conversation.counts.replies | plural({ one: "One reply", other: "# replies" }, "en") -}}
|
|
134
137
|
</h2>
|
|
135
138
|
|
|
136
139
|
<ol class="comment-list">
|
|
@@ -42,9 +42,6 @@
|
|
|
42
42
|
{% for link in siteAuthor.links %}{% set _ = sameAs.push(link.href) %}{% endfor %}
|
|
43
43
|
{% if personUrl %}{% set _ = sameAs.push(personUrl) %}{% endif %}
|
|
44
44
|
{% set address = { "@type": "PostalAddress", "addressLocality": siteAuthor.location } if siteAuthor.location else "" %}
|
|
45
|
-
{#- An author archive is the only page that is about a person: a listing whose
|
|
46
|
-
`author` is whose page this is. -#}
|
|
47
|
-
{% set isProfilePage = pagination and author.url and url and (author.url in url) %}
|
|
48
45
|
{% set entryType = "BlogPosting" if type == "post" else "Article" %}
|
|
49
46
|
{% set nodes = [] %}
|
|
50
47
|
{% set website %}
|
|
@@ -67,6 +64,9 @@
|
|
|
67
64
|
"query-input": "required name=search_term_string"
|
|
68
65
|
}) }}
|
|
69
66
|
{{- member("publisher", person) }}
|
|
67
|
+
{#- What the site is about, on the homepage of a solo author blog
|
|
68
|
+
(TASK-180): the site's author, and nobody on any other site. #}
|
|
69
|
+
{{- member("about", { "@id": (soloAuthor.url | absoluteUrl) + "#person" } if atRoot and soloAuthor.url else "") }}
|
|
70
70
|
}{% endset %}
|
|
71
71
|
{% set _ = nodes.push(website) %}
|
|
72
72
|
{% if personId %}
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
}{% endset %}
|
|
85
85
|
{% set _ = nodes.push(profile) %}
|
|
86
86
|
{% endif %}
|
|
87
|
-
{% if
|
|
87
|
+
{% if isAuthorArchive %}
|
|
88
88
|
{% set profilePage %}
|
|
89
89
|
{
|
|
90
90
|
"@type": "ProfilePage"
|
|
@@ -110,6 +110,21 @@
|
|
|
110
110
|
}{% endset %}
|
|
111
111
|
{% set _ = nodes.push(entry) %}
|
|
112
112
|
{% endif %}
|
|
113
|
+
{#- Where the page sits, from the trail `layouts/base.njk` builds and the
|
|
114
|
+
visible breadcrumb prints (TASK-150). -#}
|
|
115
|
+
{% if breadcrumbs.length %}
|
|
116
|
+
{% set trail = [] %}
|
|
117
|
+
{% for crumb in breadcrumbs %}
|
|
118
|
+
{% set _ = trail.push({ "@type": "ListItem", "position": loop.index, "name": crumb.name, "item": crumb.url | absoluteUrl }) %}
|
|
119
|
+
{% endfor %}
|
|
120
|
+
{% set breadcrumbList %}
|
|
121
|
+
{
|
|
122
|
+
"@type": "BreadcrumbList"
|
|
123
|
+
{{- member("@id", metaUrl + "#breadcrumb") }}
|
|
124
|
+
{{- member("itemListElement", trail) }}
|
|
125
|
+
}{% endset %}
|
|
126
|
+
{% set _ = nodes.push(breadcrumbList) %}
|
|
127
|
+
{% endif %}
|
|
113
128
|
<script type="application/ld+json">
|
|
114
129
|
{
|
|
115
130
|
"@context": "https://schema.org",
|
|
@@ -14,17 +14,19 @@
|
|
|
14
14
|
an error page. `date` is the entry's `dt-published`, printed long. With
|
|
15
15
|
`href` the date is the entry's `u-url`, which is how a feed links an entry
|
|
16
16
|
that has no title to link; an entry with no date links `label` instead.
|
|
17
|
-
`categories` are printed as `p-category` links.
|
|
17
|
+
`categories` are printed as `p-category` links. `lang` is the entry's own
|
|
18
|
+
language when it names one, so its date is written in that language rather
|
|
19
|
+
than the site's (TASK-189); a listing passes `lang=post.lang`.
|
|
18
20
|
#}
|
|
19
|
-
{% macro line(kind, date=false, href=false, categories=[], label="") %}
|
|
21
|
+
{% macro line(kind, date=false, href=false, categories=[], label="", lang=false) %}
|
|
20
22
|
<p class="kicker">
|
|
21
23
|
<span class="kicker-kind">{{ kind }}</span>
|
|
22
24
|
{%- if href %}
|
|
23
25
|
<span class="kicker-dot" aria-hidden="true">·</span>
|
|
24
|
-
<a href="{{ href | url }}" class="u-url">{% if date %}<time class="feed-date dt-published" datetime="{{ date | date("iso") }}">{{ date | date }}</time>{% else %}{{ label }}{% endif %}</a>
|
|
26
|
+
<a href="{{ href | url }}" class="u-url">{% if date %}<time class="feed-date dt-published" datetime="{{ date | date("iso") }}">{{ date | date("readable", none, lang) }}</time>{% else %}{{ label }}{% endif %}</a>
|
|
25
27
|
{%- elif date %}
|
|
26
28
|
<span class="kicker-dot" aria-hidden="true">·</span>
|
|
27
|
-
<time class="feed-date dt-published" datetime="{{ date | date("iso") }}">{{ date | date }}</time>
|
|
29
|
+
<time class="feed-date dt-published" datetime="{{ date | date("iso") }}">{{ date | date("readable", none, lang) }}</time>
|
|
28
30
|
{%- endif %}
|
|
29
31
|
{%- for category in categories %}
|
|
30
32
|
<span class="kicker-dot" aria-hidden="true">·</span>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{#- The `lang` attribute of an article written in a language other than the
|
|
2
|
+
site's (TASK-154), with its leading space, and nothing for one in the
|
|
3
|
+
site's own: the `<html lang>` already names that. Imported with context,
|
|
4
|
+
since the site's language is what it compares against. -#}
|
|
5
|
+
{% macro attr(tag) -%}
|
|
6
|
+
{%- if tag and tag != (site.language | default("en")) %} lang="{{ tag }}"{% endif -%}
|
|
7
|
+
{%- endmacro %}
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
never skips a level.
|
|
19
19
|
#}
|
|
20
20
|
{% import "partials/kicker.njk" as kicker with context %}
|
|
21
|
+
{% import "partials/lang.njk" as language with context %}
|
|
21
22
|
{% set feedTitleTag = "h" + (feedHeading | default(2)) %}
|
|
22
23
|
{% if posts.length %}
|
|
23
24
|
<div class="feed h-feed">
|
|
@@ -25,16 +26,17 @@
|
|
|
25
26
|
{% if not loop.first %}
|
|
26
27
|
<hr class="feed-separator">
|
|
27
28
|
{% endif %}
|
|
28
|
-
<article class="feed-item h-entry">
|
|
29
|
+
<article class="feed-item h-entry"{{ language.attr(post.lang) }}>
|
|
29
30
|
{% if post.named %}
|
|
30
|
-
{{ kicker.line(post.postType | capitalize, post.date, false, post.categories) }}
|
|
31
|
+
{{ kicker.line(post.postType | capitalize, post.date, false, post.categories, lang=post.lang) }}
|
|
31
32
|
{% else %}
|
|
32
|
-
{{ kicker.line(post.postType | capitalize, post.date, post.url, [], post.label) }}
|
|
33
|
+
{{ kicker.line(post.postType | capitalize, post.date, post.url, [], post.label, lang=post.lang) }}
|
|
33
34
|
{% endif %}
|
|
34
35
|
{#- What a reply answers, from the same partial an entry cites it with. -#}
|
|
35
36
|
{% if post.inReplyTo %}
|
|
36
37
|
{% set inReplyTo = post.inReplyTo %}
|
|
37
38
|
{% set replyContext = post.replyContext %}
|
|
39
|
+
{% set lang = post.lang %}
|
|
38
40
|
{% include "partials/reply-context.njk" %}
|
|
39
41
|
{% endif %}
|
|
40
42
|
{% if not post.named %}
|
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
or synced: its name, a short excerpt, its author and its date, each only when
|
|
13
13
|
it said so. It is somebody else's words, so every piece is printed through
|
|
14
14
|
autoescaping and none of it with `safe`. With a name, the name is the link;
|
|
15
|
-
with only an author, "a post" is; with neither, the bare URL.
|
|
15
|
+
with only an author, "a post" is; with neither, the bare URL. Its date is
|
|
16
|
+
written in `lang`, the language of the entry it sits in (TASK-189), so a
|
|
17
|
+
listing sets `lang` from each entry as it sets `replyContext`.
|
|
16
18
|
#}
|
|
17
19
|
{% if inReplyTo %}
|
|
18
20
|
<div class="reply-context cite u-in-reply-to h-cite">
|
|
@@ -26,7 +28,7 @@
|
|
|
26
28
|
{%- else %}<span class="p-name">{{ replyContext.author.name }}</span>{% endif -%}
|
|
27
29
|
</span>
|
|
28
30
|
{%- endif %}
|
|
29
|
-
{%- if replyContext.published %}, <time class="dt-published" datetime="{{ replyContext.published | date("iso") }}">{{ replyContext.published | date }}</time>
|
|
31
|
+
{%- if replyContext.published %}, <time class="dt-published" datetime="{{ replyContext.published | date("iso") }}">{{ replyContext.published | date("readable", none, lang) }}</time>
|
|
30
32
|
{%- endif -%}
|
|
31
33
|
</p>
|
|
32
34
|
{% if replyContext.text %}
|
|
@@ -323,6 +323,20 @@
|
|
|
323
323
|
@apply font-semibold text-accent;
|
|
324
324
|
}
|
|
325
325
|
|
|
326
|
+
/* The breadcrumb: where the page sits, on one quiet line above it. The
|
|
327
|
+
crumbs are links like the kicker's; the last is the page itself. */
|
|
328
|
+
.breadcrumbs ol {
|
|
329
|
+
@apply mb-6 gap-x-2 font-sans text-sm text-muted;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
.breadcrumbs a {
|
|
333
|
+
@apply target quiet-link text-muted;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
.breadcrumbs-sep {
|
|
337
|
+
@apply me-2;
|
|
338
|
+
}
|
|
339
|
+
|
|
326
340
|
/* Titles: what heads a listing, an archive, search and an error page. */
|
|
327
341
|
.page-title {
|
|
328
342
|
@apply mt-1 mb-8 text-4xl leading-[1.08] sm:text-[2.75rem];
|
|
@@ -687,6 +687,59 @@
|
|
|
687
687
|
color: var(--color-primary);
|
|
688
688
|
}
|
|
689
689
|
|
|
690
|
+
.breadcrumbs ol {
|
|
691
|
+
margin-bottom: calc(var(--spacing) * 6);
|
|
692
|
+
column-gap: calc(var(--spacing) * 2);
|
|
693
|
+
font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
|
|
694
|
+
font-size: var(--text-sm);
|
|
695
|
+
line-height: var(--tw-leading, var(--text-sm--line-height));
|
|
696
|
+
color: var(--color-muted);
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
.breadcrumbs a {
|
|
700
|
+
align-items: center;
|
|
701
|
+
min-block-size: 24px;
|
|
702
|
+
min-inline-size: 24px;
|
|
703
|
+
text-decoration-line: underline;
|
|
704
|
+
text-decoration-color: currentColor;
|
|
705
|
+
display: inline-flex;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
709
|
+
.breadcrumbs a {
|
|
710
|
+
-webkit-text-decoration-color: color-mix(in oklab, currentcolor 50%, transparent);
|
|
711
|
+
-webkit-text-decoration-color: color-mix(in oklab, currentcolor 50%, transparent);
|
|
712
|
+
text-decoration-color: color-mix(in oklab, currentcolor 50%, transparent);
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
.breadcrumbs a {
|
|
717
|
+
text-underline-offset: 4px;
|
|
718
|
+
text-decoration-thickness: 1px;
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
@media (hover: hover) {
|
|
722
|
+
.breadcrumbs a:hover {
|
|
723
|
+
color: var(--color-primary);
|
|
724
|
+
-webkit-text-decoration-color: var(--color-primary);
|
|
725
|
+
-webkit-text-decoration-color: var(--color-primary);
|
|
726
|
+
text-decoration-color: var(--color-primary);
|
|
727
|
+
text-decoration-thickness: 2px;
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
.breadcrumbs a:focus-visible {
|
|
732
|
+
text-decoration-thickness: 2px;
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
.breadcrumbs a {
|
|
736
|
+
color: var(--color-muted);
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
.breadcrumbs-sep {
|
|
740
|
+
margin-inline-end: calc(var(--spacing) * 2);
|
|
741
|
+
}
|
|
742
|
+
|
|
690
743
|
.page-title {
|
|
691
744
|
margin-top: var(--spacing);
|
|
692
745
|
margin-bottom: calc(var(--spacing) * 8);
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
"name": "Default",
|
|
3
3
|
"kind": "site",
|
|
4
4
|
"description": "The theme that ships with Geekity: Nunjucks and one stylesheet compiled from Tailwind, in the Paper design, and the layer every other theme is laid over.",
|
|
5
|
+
"colorScheme": "light dark",
|
|
6
|
+
"themeColor": { "light": "#faf7f2", "dark": "#171412" },
|
|
5
7
|
"areas": [
|
|
6
8
|
{ "name": "primary", "label": "Site menu" },
|
|
7
9
|
{ "name": "footer", "label": "Footer links" }
|