@geekity/cms 0.21.0 → 0.23.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 +42 -4
- package/admin/components/admin-bar.njk +27 -6
- package/admin/components/alert.njk +28 -0
- package/admin/components/badge.njk +58 -0
- package/admin/components/button.njk +56 -0
- package/admin/components/card.njk +40 -0
- package/admin/components/collapse.njk +36 -0
- package/admin/components/copy.njk +20 -0
- package/admin/components/dropdown.njk +32 -0
- package/admin/components/fields.njk +81 -45
- package/admin/components/flash.njk +12 -5
- package/admin/components/menu.njk +51 -0
- package/admin/components/navbar.njk +23 -0
- package/admin/components/pagination.njk +47 -0
- package/admin/components/public-admin-bar.njk +4 -41
- package/admin/components/stat.njk +35 -0
- package/admin/components/table.njk +74 -0
- package/admin/components/tabs.njk +33 -0
- package/admin/components/theme-choice.njk +18 -0
- package/admin/layouts/base.njk +9 -16
- package/admin/layouts/settings-page.njk +15 -10
- package/admin/layouts/shell.njk +23 -31
- package/admin/pages/account/forgot.njk +39 -33
- package/admin/pages/account/login.njk +22 -16
- package/admin/pages/account/reset.njk +34 -25
- package/admin/pages/account/setup.njk +21 -15
- package/admin/pages/appearance/themes.njk +50 -44
- package/admin/pages/comments/all.njk +88 -106
- package/admin/pages/dashboard/home.njk +50 -62
- package/admin/pages/documents/conflict.njk +29 -24
- package/admin/pages/documents/editor.njk +173 -275
- package/admin/pages/documents/list.njk +60 -69
- package/admin/pages/documents/syndication.njk +98 -60
- package/admin/pages/documents/taxonomy.njk +36 -32
- package/admin/pages/error.njk +8 -5
- package/admin/pages/federation/followers.njk +91 -97
- package/admin/pages/federation/settings.njk +10 -11
- package/admin/pages/indieauth/consent.njk +60 -44
- package/admin/pages/indieauth/refused.njk +6 -3
- package/admin/pages/media/library.njk +86 -107
- package/admin/pages/messages/all.njk +71 -77
- package/admin/pages/navigation/menus.njk +90 -85
- package/admin/pages/placeholder.njk +13 -8
- package/admin/pages/settings/discussion.njk +30 -29
- package/admin/pages/settings/email.njk +26 -28
- package/admin/pages/settings/general.njk +10 -4
- package/admin/pages/settings/permalinks.njk +8 -9
- package/admin/pages/settings/privacy.njk +3 -3
- package/admin/pages/settings/reading.njk +3 -3
- package/admin/pages/tools/content-index.njk +79 -73
- package/admin/pages/tools/personal-data.njk +61 -55
- package/admin/pages/users/activity-entry.njk +12 -12
- package/admin/pages/users/activity.njk +13 -19
- package/admin/pages/users/apps.njk +112 -100
- package/admin/pages/users/edit.njk +65 -58
- package/admin/pages/users/list.njk +26 -24
- package/admin/pages/users/new.njk +11 -7
- package/admin/src/admin.css +174 -0
- package/admin/static/admin-bar.css +33 -31
- package/admin/static/admin-bar.js +22 -0
- package/admin/static/admin.css +7388 -1195
- package/admin/static/copy.js +1 -1
- package/admin/static/editor.js +18 -18
- package/dist/admin/accounts.d.ts +20 -0
- package/dist/admin/accounts.d.ts.map +1 -1
- package/dist/admin/accounts.js +25 -0
- package/dist/admin/accounts.js.map +1 -1
- package/dist/admin/admin-theme.d.ts +157 -0
- package/dist/admin/admin-theme.d.ts.map +1 -0
- package/dist/admin/admin-theme.js +52 -0
- package/dist/admin/admin-theme.js.map +1 -0
- package/dist/admin/assets.d.ts +4 -3
- package/dist/admin/assets.d.ts.map +1 -1
- package/dist/admin/assets.js +4 -3
- package/dist/admin/assets.js.map +1 -1
- package/dist/admin/comments.js +2 -2
- package/dist/admin/comments.js.map +1 -1
- package/dist/admin/documents.d.ts +36 -7
- package/dist/admin/documents.d.ts.map +1 -1
- package/dist/admin/documents.js +141 -30
- package/dist/admin/documents.js.map +1 -1
- package/dist/admin/editor-layout.d.ts +1 -1
- package/dist/admin/editor-layout.d.ts.map +1 -1
- package/dist/admin/editor-layout.js +6 -1
- package/dist/admin/editor-layout.js.map +1 -1
- package/dist/admin/event-field.d.ts +26 -0
- package/dist/admin/event-field.d.ts.map +1 -0
- package/dist/admin/event-field.js +74 -0
- package/dist/admin/event-field.js.map +1 -0
- package/dist/admin/federation.js +3 -3
- package/dist/admin/federation.js.map +1 -1
- package/dist/admin/headers.js +1 -1
- package/dist/admin/headers.js.map +1 -1
- package/dist/admin/media.js +2 -2
- package/dist/admin/media.js.map +1 -1
- package/dist/admin/preview.d.ts.map +1 -1
- package/dist/admin/preview.js +16 -1
- package/dist/admin/preview.js.map +1 -1
- package/dist/admin/routes.d.ts.map +1 -1
- package/dist/admin/routes.js +17 -8
- package/dist/admin/routes.js.map +1 -1
- package/dist/admin/store.d.ts +9 -0
- package/dist/admin/store.d.ts.map +1 -1
- package/dist/admin/store.js +16 -5
- package/dist/admin/store.js.map +1 -1
- package/dist/admin/templates.d.ts +6 -3
- package/dist/admin/templates.d.ts.map +1 -1
- package/dist/admin/templates.js +25 -3
- package/dist/admin/templates.js.map +1 -1
- package/dist/admin/users.d.ts +4 -0
- package/dist/admin/users.d.ts.map +1 -1
- package/dist/admin/users.js +37 -1
- package/dist/admin/users.js.map +1 -1
- package/dist/avatars/avatars.js +1 -1
- package/dist/avatars/avatars.js.map +1 -1
- package/dist/comments/policy.d.ts +10 -0
- package/dist/comments/policy.d.ts.map +1 -1
- package/dist/comments/policy.js +12 -0
- package/dist/comments/policy.js.map +1 -1
- package/dist/comments/records.d.ts +5 -1
- package/dist/comments/records.d.ts.map +1 -1
- package/dist/comments/records.js +16 -2
- package/dist/comments/records.js.map +1 -1
- package/dist/content/event.d.ts +40 -0
- package/dist/content/event.d.ts.map +1 -0
- package/dist/content/event.js +51 -0
- package/dist/content/event.js.map +1 -0
- package/dist/content/handles.d.ts +22 -0
- package/dist/content/handles.d.ts.map +1 -0
- package/dist/content/handles.js +68 -0
- package/dist/content/handles.js.map +1 -0
- package/dist/content/markdown.d.ts +8 -2
- package/dist/content/markdown.d.ts.map +1 -1
- package/dist/content/markdown.js +55 -5
- package/dist/content/markdown.js.map +1 -1
- package/dist/content/parser.d.ts +3 -0
- package/dist/content/parser.d.ts.map +1 -1
- package/dist/content/parser.js +1 -1
- package/dist/content/parser.js.map +1 -1
- package/dist/content/post-type.d.ts +12 -8
- package/dist/content/post-type.d.ts.map +1 -1
- package/dist/content/post-type.js +19 -4
- package/dist/content/post-type.js.map +1 -1
- package/dist/content/rsvp.d.ts +29 -0
- package/dist/content/rsvp.d.ts.map +1 -0
- package/dist/content/rsvp.js +49 -0
- package/dist/content/rsvp.js.map +1 -0
- package/dist/content/save.d.ts +2 -1
- package/dist/content/save.d.ts.map +1 -1
- package/dist/content/save.js +10 -3
- package/dist/content/save.js.map +1 -1
- package/dist/content/store.d.ts +11 -4
- package/dist/content/store.d.ts.map +1 -1
- package/dist/content/store.js +15 -4
- package/dist/content/store.js.map +1 -1
- package/dist/content/sync.d.ts.map +1 -1
- package/dist/content/sync.js +7 -6
- package/dist/content/sync.js.map +1 -1
- package/dist/env.d.ts +3 -0
- package/dist/env.d.ts.map +1 -1
- package/dist/federation/article.d.ts +9 -3
- package/dist/federation/article.d.ts.map +1 -1
- package/dist/federation/article.js +90 -34
- package/dist/federation/article.js.map +1 -1
- package/dist/federation/cited-post.d.ts +13 -0
- package/dist/federation/cited-post.d.ts.map +1 -0
- package/dist/federation/cited-post.js +75 -0
- package/dist/federation/cited-post.js.map +1 -0
- package/dist/federation/delivery.d.ts.map +1 -1
- package/dist/federation/delivery.js +31 -2
- package/dist/federation/delivery.js.map +1 -1
- package/dist/federation/handles.d.ts +28 -0
- package/dist/federation/handles.d.ts.map +1 -0
- package/dist/federation/handles.js +65 -0
- package/dist/federation/handles.js.map +1 -0
- package/dist/federation/inbox.d.ts +2 -1
- package/dist/federation/inbox.d.ts.map +1 -1
- package/dist/federation/inbox.js +11 -3
- package/dist/federation/inbox.js.map +1 -1
- package/dist/federation/mount.d.ts.map +1 -1
- package/dist/federation/mount.js +18 -2
- package/dist/federation/mount.js.map +1 -1
- package/dist/federation/profiles.d.ts.map +1 -1
- package/dist/federation/profiles.js +2 -8
- package/dist/federation/profiles.js.map +1 -1
- package/dist/federation/site-loaders.d.ts +15 -0
- package/dist/federation/site-loaders.d.ts.map +1 -0
- package/dist/federation/site-loaders.js +19 -0
- package/dist/federation/site-loaders.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23 -1
- package/dist/index.js.map +1 -1
- package/dist/indieauth/client.js +2 -2
- package/dist/indieauth/client.js.map +1 -1
- package/dist/micropub/create.d.ts +2 -1
- package/dist/micropub/create.d.ts.map +1 -1
- package/dist/micropub/create.js +57 -8
- package/dist/micropub/create.js.map +1 -1
- package/dist/micropub/endpoint.d.ts.map +1 -1
- package/dist/micropub/endpoint.js +12 -4
- package/dist/micropub/endpoint.js.map +1 -1
- package/dist/micropub/update.d.ts +3 -0
- package/dist/micropub/update.d.ts.map +1 -1
- package/dist/micropub/update.js +29 -4
- package/dist/micropub/update.js.map +1 -1
- package/dist/web/admin-bar.d.ts +4 -4
- package/dist/web/admin-bar.d.ts.map +1 -1
- package/dist/web/admin-bar.js +11 -34
- package/dist/web/admin-bar.js.map +1 -1
- package/dist/web/context.d.ts +32 -4
- package/dist/web/context.d.ts.map +1 -1
- package/dist/web/context.js +28 -1
- package/dist/web/context.js.map +1 -1
- package/dist/web/conversation.d.ts +26 -1
- package/dist/web/conversation.d.ts.map +1 -1
- package/dist/web/conversation.js +67 -10
- package/dist/web/conversation.js.map +1 -1
- package/dist/web/documents.d.ts +12 -0
- package/dist/web/documents.d.ts.map +1 -1
- package/dist/web/documents.js +20 -0
- package/dist/web/documents.js.map +1 -1
- package/dist/web/feed-item.d.ts.map +1 -1
- package/dist/web/feed-item.js +8 -3
- package/dist/web/feed-item.js.map +1 -1
- package/dist/web/render.d.ts +3 -0
- package/dist/web/render.d.ts.map +1 -1
- package/dist/web/render.js +39 -6
- package/dist/web/render.js.map +1 -1
- package/dist/web/routes.d.ts.map +1 -1
- package/dist/web/routes.js +16 -3
- package/dist/web/routes.js.map +1 -1
- package/dist/web/templates.d.ts +4 -1
- package/dist/web/templates.d.ts.map +1 -1
- package/dist/web/templates.js +11 -0
- package/dist/web/templates.js.map +1 -1
- package/dist/webmention/cited-picture.d.ts +11 -4
- package/dist/webmention/cited-picture.d.ts.map +1 -1
- package/dist/webmention/cited-picture.js +22 -13
- package/dist/webmention/cited-picture.js.map +1 -1
- package/dist/webmention/cited-start.d.ts +10 -0
- package/dist/webmention/cited-start.d.ts.map +1 -0
- package/dist/webmention/cited-start.js +21 -0
- package/dist/webmention/cited-start.js.map +1 -0
- package/dist/webmention/fetch-public.d.ts +2 -2
- 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/dist/webmention/html.d.ts +2 -0
- package/dist/webmention/html.d.ts.map +1 -1
- package/dist/webmention/html.js +6 -0
- package/dist/webmention/html.js.map +1 -1
- package/dist/webmention/index.d.ts +2 -1
- package/dist/webmention/index.d.ts.map +1 -1
- package/dist/webmention/index.js +1 -0
- package/dist/webmention/index.js.map +1 -1
- package/dist/webmention/microformats.d.ts +25 -2
- package/dist/webmention/microformats.d.ts.map +1 -1
- package/dist/webmention/microformats.js +38 -4
- package/dist/webmention/microformats.js.map +1 -1
- package/dist/webmention/pingback.d.ts +42 -0
- package/dist/webmention/pingback.d.ts.map +1 -0
- package/dist/webmention/pingback.js +229 -0
- package/dist/webmention/pingback.js.map +1 -0
- package/dist/webmention/receive.d.ts +20 -2
- package/dist/webmention/receive.d.ts.map +1 -1
- package/dist/webmention/receive.js +25 -16
- package/dist/webmention/receive.js.map +1 -1
- package/dist/webmention/reply-context.d.ts +65 -18
- package/dist/webmention/reply-context.d.ts.map +1 -1
- package/dist/webmention/reply-context.js +403 -99
- package/dist/webmention/reply-context.js.map +1 -1
- package/dist/webmention/reply-contexts.d.ts +3 -1
- package/dist/webmention/reply-contexts.d.ts.map +1 -1
- package/dist/webmention/reply-contexts.js +53 -17
- package/dist/webmention/reply-contexts.js.map +1 -1
- package/dist/webmention/routes.d.ts.map +1 -1
- package/dist/webmention/routes.js +2 -0
- package/dist/webmention/routes.js.map +1 -1
- package/dist/webmention/service.d.ts +11 -0
- package/dist/webmention/service.d.ts.map +1 -1
- package/dist/webmention/service.js +27 -6
- package/dist/webmention/service.js.map +1 -1
- package/dist/webmention/syndication.d.ts +6 -0
- package/dist/webmention/syndication.d.ts.map +1 -1
- package/dist/webmention/syndication.js +12 -0
- package/dist/webmention/syndication.js.map +1 -1
- package/package.json +10 -6
- package/themes/default/README.md +130 -38
- package/themes/default/layouts/410.njk +10 -0
- package/themes/default/layouts/base.njk +3 -0
- package/themes/default/layouts/page.njk +7 -0
- package/themes/default/layouts/post.njk +7 -4
- package/themes/default/layouts/search.njk +1 -1
- package/themes/default/partials/cited-page.njk +7 -0
- package/themes/default/partials/conversation.njk +25 -5
- package/themes/default/partials/event.njk +27 -0
- package/themes/default/partials/jsonld.njk +28 -0
- package/themes/default/partials/post-list.njk +5 -2
- package/themes/default/partials/reply-context.njk +24 -4
- package/themes/default/partials/rsvp.njk +7 -0
- package/themes/default/src/style.css +20 -0
- package/themes/default/static/style.css +35 -0
|
@@ -7,48 +7,33 @@
|
|
|
7
7
|
{% block title %}{{ heading }}{% endblock %}
|
|
8
8
|
|
|
9
9
|
{% import "components/fields.njk" as field %}
|
|
10
|
+
{% from "components/alert.njk" import alert %}
|
|
11
|
+
{% from "components/button.njk" import button, buttonLink %}
|
|
12
|
+
{% from "components/card.njk" import card, cardActions %}
|
|
13
|
+
{% from "components/collapse.njk" import collapse %}
|
|
10
14
|
|
|
11
|
-
{
|
|
12
|
-
|
|
13
|
-
{% macro group(name, open, class='admin-editor-group') %}
|
|
14
|
-
<details class="{{ class }}"{% if open %} open{% endif %}>
|
|
15
|
-
<summary>{{ name }}</summary>
|
|
16
|
-
<fieldset>
|
|
17
|
-
<legend class="admin-visually-hidden">{{ name }}</legend>
|
|
18
|
-
{{ caller() }}
|
|
19
|
-
</fieldset>
|
|
20
|
-
</details>
|
|
21
|
-
{% endmacro %}
|
|
22
|
-
|
|
23
|
-
{% macro invalid(id, hint='') -%}
|
|
24
|
-
{% if errorField == id %} aria-invalid="true" aria-describedby="{{ id }}-error{% if hint %} {{ hint }}{% endif %}"{% elif hint %} aria-describedby="{{ hint }}"{% endif %}
|
|
25
|
-
{%- endmacro %}
|
|
26
|
-
|
|
27
|
-
{% macro problem(id) %}
|
|
28
|
-
{% if errorField == id %}<p class="admin-field-error" id="{{ id }}-error">{{ error }}</p>{% endif %}
|
|
29
|
-
{% endmacro %}
|
|
15
|
+
{% set ACTION_COLORS = { 'publish': 'primary', 'update': 'primary', 'trash': 'error' } %}
|
|
16
|
+
{% set ACTION_STYLES = { 'trash': 'ghost' } %}
|
|
30
17
|
|
|
31
18
|
{% macro citedCard(property) %}
|
|
32
|
-
{% set
|
|
33
|
-
{% if
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
<
|
|
37
|
-
<
|
|
38
|
-
<
|
|
39
|
-
<p class="
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
{
|
|
44
|
-
|
|
45
|
-
{%- endif %}
|
|
46
|
-
</div>
|
|
19
|
+
{% set cited = citedPreviews[property] %}
|
|
20
|
+
{% if cited %}
|
|
21
|
+
{% call card(size='sm', style='border') %}
|
|
22
|
+
{# First: Tailwind's `peer-*` variants reach later siblings only. #}
|
|
23
|
+
<input class="peer sr-only" type="checkbox" id="editor-preview-{{ property }}" name="preview" value="hide"{% if form.previewHidden %} checked{% endif %}>
|
|
24
|
+
<label class="btn btn-circle btn-xs absolute end-2 top-2 peer-checked:btn-neutral peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-base-content" for="editor-preview-{{ property }}"><span aria-hidden="true">×</span><span class="sr-only">Remove the preview of {{ cited.name }}</span></label>
|
|
25
|
+
<img class="h-auto max-h-32 w-full rounded-box object-cover peer-checked:opacity-40" src="{{ cited.picture.src }}" alt="" width="{{ cited.picture.width }}" height="{{ cited.picture.height }}" loading="lazy">
|
|
26
|
+
<p class="break-words pe-8 peer-checked:opacity-40">{{ cited.name }}</p>
|
|
27
|
+
<p class="label hidden whitespace-normal peer-checked:block">Removed. The post shows the plain citation until you select the X again.</p>
|
|
28
|
+
{% if cited.described %}
|
|
29
|
+
{{ field.text('editor-cited-alt', 'cited-alt', 'Alt text of the reposted image', value=(form.citedAlt or form.title), error=(error if errorField == 'editor-cited-alt' else ''), hint='What the image shows, for readers who cannot see it. It starts as the post’s title.', hintId='editor-cited-alt-hint') }}
|
|
30
|
+
{% endif %}
|
|
31
|
+
{% endcall %}
|
|
47
32
|
{% endif %}
|
|
48
33
|
{% endmacro %}
|
|
49
34
|
|
|
50
35
|
{% block content %}
|
|
51
|
-
<h1>{{ heading }}</h1>
|
|
36
|
+
<h1 class="mb-6 text-2xl font-bold">{{ heading }}</h1>
|
|
52
37
|
|
|
53
38
|
{% if error and errorField %}
|
|
54
39
|
{% call field.summary('Nothing was saved. Fix the field marked below and try again.') %}
|
|
@@ -58,15 +43,22 @@
|
|
|
58
43
|
{{ field.summary(error) }}
|
|
59
44
|
{% endif %}
|
|
60
45
|
|
|
61
|
-
{% if trashed %}
|
|
62
|
-
<
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
46
|
+
{% if trashed or scheduledFor %}
|
|
47
|
+
<div class="my-6 flex flex-col gap-2">
|
|
48
|
+
{% if trashed %}
|
|
49
|
+
{% call alert(color='warning', polite=true) %}
|
|
50
|
+
<span>This {{ kind.singular }} is in the trash. The public site is not serving it.</span>
|
|
51
|
+
{% endcall %}
|
|
52
|
+
{% endif %}
|
|
53
|
+
{% if scheduledFor %}
|
|
54
|
+
{% call alert(color='info', polite=true) %}
|
|
55
|
+
<span>Scheduled for {{ scheduledFor }}. The public site starts serving it then, and the followers are told then.</span>
|
|
56
|
+
{% endcall %}
|
|
57
|
+
{% endif %}
|
|
58
|
+
</div>
|
|
67
59
|
{% endif %}
|
|
68
60
|
|
|
69
|
-
<form class="
|
|
61
|
+
<form class="grid items-start gap-6 xl:grid-cols-[minmax(0,1fr)_20rem]" method="post" action="{{ saveUrl }}">
|
|
70
62
|
<input type="hidden" name="csrf_token" value="{{ csrfToken }}" />
|
|
71
63
|
{# The hash of the file this form was filled in from. A save whose hash no
|
|
72
64
|
longer matches what is on disk is refused rather than overwriting
|
|
@@ -75,54 +67,42 @@
|
|
|
75
67
|
{# Which layout the preview renders through. The save handler ignores it. #}
|
|
76
68
|
<input type="hidden" name="type" value="{{ kind.type }}" />
|
|
77
69
|
|
|
78
|
-
<div class="
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
<button
|
|
103
|
-
type="submit"
|
|
104
|
-
id="editor-preview-fallback"
|
|
105
|
-
class="admin-button-quiet"
|
|
106
|
-
formaction="{{ previewUrl }}"
|
|
107
|
-
formtarget="_blank"
|
|
108
|
-
formnovalidate
|
|
109
|
-
>Preview</button>
|
|
110
|
-
</div>
|
|
70
|
+
<div class="flex min-w-0 flex-col gap-4">
|
|
71
|
+
{% call card() %}
|
|
72
|
+
{% set titleHint %}{% if kind.type == "post" %}Leave it empty to write a note: the post is then its words, and takes its slug from the first of them.{% endif %}{% endset %}
|
|
73
|
+
{#- A post may go without one, and is then a note; a page is always named. -#}
|
|
74
|
+
{{ field.text('editor-title', 'title', 'Title', value=form.title, required=(kind.type == "page"), autofocus=true, error=(error if errorField == 'editor-title' else ''), hint=titleHint) }}
|
|
75
|
+
|
|
76
|
+
{{ field.textarea('editor-body', 'body', 'Body', value=form.body, rows=24) }}
|
|
77
|
+
|
|
78
|
+
{# Everything the editor's own script needs, on the element it hangs
|
|
79
|
+
off. With JavaScript off this is one button that posts the form to
|
|
80
|
+
the preview in a new tab, which is a preview. With it on, editor.js
|
|
81
|
+
takes the button over, puts CodeMirror on the textarea above and
|
|
82
|
+
adds the Write and Preview tabs, the upload control and its status
|
|
83
|
+
line here. #}
|
|
84
|
+
<div
|
|
85
|
+
class="flex flex-wrap items-center gap-2"
|
|
86
|
+
id="editor-enhance"
|
|
87
|
+
data-preview-url="{{ previewUrl }}"
|
|
88
|
+
data-upload-url="{{ uploadUrl }}"
|
|
89
|
+
data-kind="{{ kind.type }}"
|
|
90
|
+
>
|
|
91
|
+
{{ button('Preview', type='submit', id='editor-preview-fallback', style='soft', formaction=previewUrl, formtarget='_blank', formnovalidate=true) }}
|
|
92
|
+
</div>
|
|
93
|
+
{% endcall %}
|
|
111
94
|
|
|
112
95
|
{% if kind.type == "post" %}
|
|
113
|
-
{% call
|
|
114
|
-
<p class="
|
|
96
|
+
{% call collapse('Photos', open.photos, fields=true) %}
|
|
97
|
+
<p class="label block whitespace-normal text-xs">
|
|
115
98
|
Each is an image in the media library or an address starting https://. Leave the alt text
|
|
116
99
|
empty to use the media library’s. Empty an address to remove that photo.
|
|
117
100
|
</p>
|
|
118
101
|
{% for row in photoRows %}
|
|
119
102
|
{% set n = loop.index0 %}
|
|
120
|
-
{% call
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
{{ problem('editor-photo-url-' + n) }}
|
|
124
|
-
<label for="editor-photo-alt-{{ n }}">Alt text</label>
|
|
125
|
-
<input id="editor-photo-alt-{{ n }}" name="{{ photoFields.alt }}{{ n }}" type="text" value="{{ row.alt }}"{% if row.libraryAlt %} placeholder="{{ row.libraryAlt }}"{% endif %} />
|
|
103
|
+
{% call collapse(('Photo ' + loop.index) if row.url else 'Add a photo', row.url, fields=true) %}
|
|
104
|
+
{{ field.text('editor-photo-url-' + n, photoFields.url + n, 'Address', value=row.url, list='editor-photo-uploads', autocomplete='off', error=(error if errorField == ('editor-photo-url-' + n) else '')) }}
|
|
105
|
+
{{ field.text('editor-photo-alt-' + n, photoFields.alt + n, 'Alt text', value=row.alt, placeholder=row.libraryAlt) }}
|
|
126
106
|
{% endcall %}
|
|
127
107
|
{% endfor %}
|
|
128
108
|
<datalist id="editor-photo-uploads">
|
|
@@ -132,100 +112,61 @@
|
|
|
132
112
|
</datalist>
|
|
133
113
|
{% endcall %}
|
|
134
114
|
|
|
135
|
-
{% call
|
|
136
|
-
<p class="
|
|
115
|
+
{% call collapse('Location', open.location, fields=true) %}
|
|
116
|
+
<p class="label block whitespace-normal text-xs">
|
|
137
117
|
Kept in <code>data/locations.json</code>, not in the post’s file. What readers see of it
|
|
138
118
|
is chosen on Settings > Privacy. Empty every box to remove it.
|
|
139
119
|
</p>
|
|
140
|
-
<
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
<
|
|
144
|
-
{{
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
{{
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
<input id="editor-location-name" name="{{ locationFields.name }}" type="text" value="{{ form.location.name }}" />
|
|
152
|
-
<label for="editor-location-locality">Locality</label>
|
|
153
|
-
<input id="editor-location-locality" name="{{ locationFields.locality }}" type="text" value="{{ form.location.locality }}" />
|
|
154
|
-
<label for="editor-location-region">Region</label>
|
|
155
|
-
<input id="editor-location-region" name="{{ locationFields.region }}" type="text" value="{{ form.location.region }}" />
|
|
156
|
-
<label for="editor-location-country">Country</label>
|
|
157
|
-
<input id="editor-location-country" name="{{ locationFields.country }}" type="text" value="{{ form.location.country }}" />
|
|
158
|
-
<p class="admin-check">
|
|
159
|
-
<input id="editor-location-checkin" name="{{ locationFields.checkin }}" type="checkbox" value="1"{% if form.location.checkin %} checked{% endif %} aria-describedby="editor-location-checkin-hint" />
|
|
160
|
-
<label for="editor-location-checkin">A check-in</label>
|
|
161
|
-
</p>
|
|
162
|
-
<p class="admin-hint" id="editor-location-checkin-hint">A Micropub app sent it as a checkin, and reads it back as one. Readers see it as any other location.</p>
|
|
120
|
+
<div>
|
|
121
|
+
{{ button('Use my location', id='editor-location-here', style='soft', hidden=true) }}
|
|
122
|
+
</div>
|
|
123
|
+
<p id="editor-location-status" class="label block whitespace-normal text-xs" role="status"></p>
|
|
124
|
+
{{ field.text('editor-location-geo', locationFields.geo, 'Coordinates', value=form.location.geo, placeholder='48.85837, 2.29448', autocomplete='off', spellcheck='false', error=(error if errorField == 'editor-location-geo' else ''), hint='Latitude, longitude, as decimal degrees. A <code>geo:</code> URI works too.', hintId='editor-location-geo-hint') }}
|
|
125
|
+
{{ field.text('editor-location-accuracy', locationFields.accuracy, 'Accuracy', value=form.location.accuracy, inputmode='numeric', autocomplete='off', error=(error if errorField == 'editor-location-accuracy' else ''), hint='Metres. Leave it empty if you do not know.', hintId='editor-location-accuracy-hint') }}
|
|
126
|
+
{{ field.text('editor-location-name', locationFields.name, 'Place', value=form.location.name) }}
|
|
127
|
+
{{ field.text('editor-location-locality', locationFields.locality, 'Locality', value=form.location.locality) }}
|
|
128
|
+
{{ field.text('editor-location-region', locationFields.region, 'Region', value=form.location.region) }}
|
|
129
|
+
{{ field.text('editor-location-country', locationFields.country, 'Country', value=form.location.country) }}
|
|
130
|
+
{{ field.checkbox('editor-location-checkin', locationFields.checkin, 'A check-in', checked=form.location.checkin, hint='A Micropub app sent it as a checkin, and reads it back as one. Readers see it as any other location.', hintId='editor-location-checkin-hint') }}
|
|
163
131
|
{% endcall %}
|
|
164
132
|
|
|
165
|
-
{% call
|
|
166
|
-
|
|
167
|
-
<select id="editor-enclosure-url" name="{{ enclosureFields.url }}"{{ invalid('editor-enclosure-url', 'editor-enclosure-url-hint') }}>
|
|
133
|
+
{% call collapse('Recording', open.recording, fields=true) %}
|
|
134
|
+
{% call field.select('editor-enclosure-url', enclosureFields.url, 'Audio or video file', error=(error if errorField == 'editor-enclosure-url' else ''), hint='Upload the file to the media library first. Feeds carry it as the post’s enclosure and the post page plays it. None removes the recording, its transcript and its other versions.', hintId='editor-enclosure-url-hint') %}
|
|
168
135
|
<option value=""{% if form.enclosure.url == "" %} selected{% endif %}>None</option>
|
|
169
136
|
{% for choice in enclosureChoices.media %}
|
|
170
137
|
<option value="{{ choice.url }}"{% if choice.url == form.enclosure.url %} selected{% endif %}>{{ choice.label }}</option>
|
|
171
138
|
{% endfor %}
|
|
172
|
-
|
|
173
|
-
{{ problem('editor-enclosure-url') }}
|
|
174
|
-
<p class="admin-hint" id="editor-enclosure-url-hint">
|
|
175
|
-
Upload the file to the media library first. Feeds carry it as the post’s enclosure and the
|
|
176
|
-
post page plays it. None removes the recording, its transcript and its other versions.
|
|
177
|
-
</p>
|
|
139
|
+
{% endcall %}
|
|
178
140
|
|
|
179
|
-
|
|
180
|
-
<input id="editor-enclosure-duration" name="{{ enclosureFields.duration }}" type="text" inputmode="numeric" value="{{ form.enclosure.duration }}" autocomplete="off"{{ invalid('editor-enclosure-duration', 'editor-enclosure-duration-hint') }} />
|
|
181
|
-
{{ problem('editor-enclosure-duration') }}
|
|
182
|
-
<p class="admin-hint" id="editor-enclosure-duration-hint">Seconds, or 30:34, or 1:02:03. Leave it empty if you do not know.</p>
|
|
141
|
+
{{ field.text('editor-enclosure-duration', enclosureFields.duration, 'Duration', value=form.enclosure.duration, inputmode='numeric', autocomplete='off', error=(error if errorField == 'editor-enclosure-duration' else ''), hint='Seconds, or 30:34, or 1:02:03. Leave it empty if you do not know.', hintId='editor-enclosure-duration-hint') }}
|
|
183
142
|
|
|
184
|
-
|
|
185
|
-
<input id="editor-enclosure-transcript" name="{{ enclosureFields.transcriptUrl }}" type="text" value="{{ form.enclosure.transcriptUrl }}" list="editor-transcript-uploads" autocomplete="off"{{ invalid('editor-enclosure-transcript', 'editor-enclosure-transcript-hint') }} />
|
|
186
|
-
{{ problem('editor-enclosure-transcript') }}
|
|
143
|
+
{{ field.text('editor-enclosure-transcript', enclosureFields.transcriptUrl, 'Transcript or captions', value=form.enclosure.transcriptUrl, list='editor-transcript-uploads', autocomplete='off', error=(error if errorField == 'editor-enclosure-transcript' else ''), hintId='editor-enclosure-transcript-hint') }}
|
|
187
144
|
<datalist id="editor-transcript-uploads">
|
|
188
145
|
{% for url in enclosureChoices.transcripts %}
|
|
189
146
|
<option value="{{ url }}"></option>
|
|
190
147
|
{% endfor %}
|
|
191
148
|
</datalist>
|
|
192
|
-
|
|
193
|
-
<select id="editor-enclosure-transcript-type" name="{{ enclosureFields.transcriptType }}"{{ invalid('editor-enclosure-transcript-type', 'editor-enclosure-transcript-hint') }}>
|
|
149
|
+
{% call field.select('editor-enclosure-transcript-type', enclosureFields.transcriptType, 'Transcript type', error=(error if errorField == 'editor-enclosure-transcript-type' else ''), hint='A .vtt, .srt or .txt file in the media library, or an address starting https://. A linked transcript needs its type.', hintId='editor-enclosure-transcript-hint') %}
|
|
194
150
|
<option value=""{% if form.enclosure.transcriptType == "" %} selected{% endif %}>From the file</option>
|
|
195
151
|
{% for type in transcriptTypes %}
|
|
196
152
|
<option value="{{ type }}"{% if type == form.enclosure.transcriptType %} selected{% endif %}>{{ type }}</option>
|
|
197
153
|
{% endfor %}
|
|
198
|
-
|
|
199
|
-
{{ problem('editor-enclosure-transcript-type') }}
|
|
200
|
-
<p class="admin-hint" id="editor-enclosure-transcript-hint">
|
|
201
|
-
A .vtt, .srt or .txt file in the media library, or an address starting https://. A linked
|
|
202
|
-
transcript needs its type.
|
|
203
|
-
</p>
|
|
154
|
+
{% endcall %}
|
|
204
155
|
|
|
205
|
-
{% call
|
|
206
|
-
<p class="
|
|
156
|
+
{% call collapse('Other versions', open.versions, fields=true) %}
|
|
157
|
+
<p class="label block whitespace-normal text-xs">
|
|
207
158
|
A video of an audio episode, a smaller file, another language. Each is a file in the media
|
|
208
159
|
library or an address starting https://, which needs its type. Empty an address to remove
|
|
209
160
|
that version.
|
|
210
161
|
</p>
|
|
211
162
|
{% for row in alternateRows %}
|
|
212
163
|
{% set n = loop.index0 %}
|
|
213
|
-
{% call
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
{{
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
{{ problem('editor-alternate-type-' + n) }}
|
|
220
|
-
<label for="editor-alternate-title-{{ n }}">Title</label>
|
|
221
|
-
<input id="editor-alternate-title-{{ n }}" name="{{ enclosureFields.alternate.title }}{{ n }}" type="text" value="{{ row.title }}" maxlength="32"{{ invalid('editor-alternate-title-' + n) }} />
|
|
222
|
-
{{ problem('editor-alternate-title-' + n) }}
|
|
223
|
-
<label for="editor-alternate-height-{{ n }}">Height</label>
|
|
224
|
-
<input id="editor-alternate-height-{{ n }}" name="{{ enclosureFields.alternate.height }}{{ n }}" type="text" inputmode="numeric" value="{{ row.height }}" autocomplete="off"{{ invalid('editor-alternate-height-' + n) }} />
|
|
225
|
-
{{ problem('editor-alternate-height-' + n) }}
|
|
226
|
-
<label for="editor-alternate-lang-{{ n }}">Language</label>
|
|
227
|
-
<input id="editor-alternate-lang-{{ n }}" name="{{ enclosureFields.alternate.lang }}{{ n }}" type="text" value="{{ row.lang }}" autocomplete="off" spellcheck="false"{{ invalid('editor-alternate-lang-' + n) }} />
|
|
228
|
-
{{ problem('editor-alternate-lang-' + n) }}
|
|
164
|
+
{% call collapse(('Version ' + loop.index) if row.url else 'Add a version', row.url, fields=true) %}
|
|
165
|
+
{{ field.text('editor-alternate-url-' + n, enclosureFields.alternate.url + n, 'Address', value=row.url, list='editor-media-uploads', autocomplete='off', error=(error if errorField == ('editor-alternate-url-' + n) else '')) }}
|
|
166
|
+
{{ field.text('editor-alternate-type-' + n, enclosureFields.alternate.type + n, 'Type', value=row.type, placeholder='video/mp4', autocomplete='off', spellcheck='false', error=(error if errorField == ('editor-alternate-type-' + n) else '')) }}
|
|
167
|
+
{{ field.text('editor-alternate-title-' + n, enclosureFields.alternate.title + n, 'Title', value=row.title, maxlength='32', error=(error if errorField == ('editor-alternate-title-' + n) else '')) }}
|
|
168
|
+
{{ field.text('editor-alternate-height-' + n, enclosureFields.alternate.height + n, 'Height', value=row.height, inputmode='numeric', autocomplete='off', error=(error if errorField == ('editor-alternate-height-' + n) else '')) }}
|
|
169
|
+
{{ field.text('editor-alternate-lang-' + n, enclosureFields.alternate.lang + n, 'Language', value=row.lang, autocomplete='off', spellcheck='false', error=(error if errorField == ('editor-alternate-lang-' + n) else '')) }}
|
|
229
170
|
{% endcall %}
|
|
230
171
|
{% endfor %}
|
|
231
172
|
<datalist id="editor-media-uploads">
|
|
@@ -238,31 +179,29 @@
|
|
|
238
179
|
{% endif %}
|
|
239
180
|
</div>
|
|
240
181
|
|
|
241
|
-
<div class="
|
|
242
|
-
{% call
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
182
|
+
<div class="flex min-w-0 flex-col gap-4">
|
|
183
|
+
{% call card(size='sm') %}
|
|
184
|
+
{% call cardActions() %}
|
|
185
|
+
{% for action in actions %}
|
|
186
|
+
{{ button(action.label, type='submit', name='action', value=action.value, color=ACTION_COLORS[action.value], style=ACTION_STYLES[action.value]) }}
|
|
187
|
+
{% endfor %}
|
|
188
|
+
{% if viewUrl %}
|
|
189
|
+
{{ buttonLink('View', viewUrl, style='ghost') }}
|
|
190
|
+
{% endif %}
|
|
191
|
+
{% endcall %}
|
|
192
|
+
{% endcall %}
|
|
193
|
+
|
|
194
|
+
{% call collapse('Publishing', open.publishing, fields=true) %}
|
|
195
|
+
{{ field.checkbox('editor-draft', 'draft', 'Draft', checked=form.draft) }}
|
|
247
196
|
|
|
248
197
|
{% if kind.dated %}
|
|
249
|
-
<label for="editor-date">Date</label>
|
|
250
|
-
<input id="editor-date" name="date" type="text" value="{{ form.date }}"{{ invalid('editor-date') }} />
|
|
251
|
-
{{ problem('editor-date') }}
|
|
252
198
|
{# The file holds a UTC instant; this field is that instant as the
|
|
253
199
|
site's own clock reads it, so the zone has to be on the screen. #}
|
|
254
|
-
|
|
200
|
+
{% set dateHint %}Wall-clock time in {{ dateZone }}. Stored as UTC.{% endset %}
|
|
201
|
+
{{ field.text('editor-date', 'date', 'Date', value=form.date, error=(error if errorField == 'editor-date' else ''), hint=dateHint) }}
|
|
255
202
|
{% endif %}
|
|
256
203
|
|
|
257
|
-
|
|
258
|
-
<select id="editor-visibility" name="visibility" aria-describedby="editor-visibility-hint">
|
|
259
|
-
{% if form.visibility.unrecognized is defined %}
|
|
260
|
-
<option value="{{ form.visibility.unrecognized }}" selected>{{ form.visibility.unrecognized }} (not recognized)</option>
|
|
261
|
-
{% endif %}
|
|
262
|
-
<option value="public"{% if form.visibility == "public" %} selected{% endif %}>Public</option>
|
|
263
|
-
<option value="unlisted"{% if form.visibility == "unlisted" %} selected{% endif %}>Unlisted</option>
|
|
264
|
-
</select>
|
|
265
|
-
<p class="admin-hint" id="editor-visibility-hint">
|
|
204
|
+
{% set visibilityHint %}
|
|
266
205
|
{% if form.visibility.unrecognized is defined %}
|
|
267
206
|
The front matter says <code>visibility: {{ form.visibility.unrecognized }}</code>, which this
|
|
268
207
|
site does not recognize. The {{ kind.singular }} is hidden until you choose Public or Unlisted:
|
|
@@ -271,20 +210,19 @@
|
|
|
271
210
|
Unlisted writes <code>visibility: unlisted</code> into the front matter. The {{ kind.singular }}
|
|
272
211
|
keeps its page and still goes to your followers, but is left off the home page, archives,
|
|
273
212
|
feeds, the sitemap, search and llms.txt, and asks search engines not to index it.
|
|
274
|
-
|
|
213
|
+
{% endset %}
|
|
214
|
+
{% call field.select('editor-visibility', 'visibility', 'Visibility', hint=visibilityHint, hintId='editor-visibility-hint') %}
|
|
215
|
+
{% if form.visibility.unrecognized is defined %}
|
|
216
|
+
<option value="{{ form.visibility.unrecognized }}" selected>{{ form.visibility.unrecognized }} (not recognized)</option>
|
|
217
|
+
{% endif %}
|
|
218
|
+
<option value="public"{% if form.visibility == "public" %} selected{% endif %}>Public</option>
|
|
219
|
+
<option value="unlisted"{% if form.visibility == "unlisted" %} selected{% endif %}>Unlisted</option>
|
|
220
|
+
{% endcall %}
|
|
275
221
|
|
|
276
222
|
{% if kind.type == "post" %}
|
|
277
223
|
{# TASK-207: shown at the top of the author's fediverse profile, from
|
|
278
224
|
the featured collection their actor links. #}
|
|
279
|
-
|
|
280
|
-
<input id="editor-pinned" name="pinned" type="checkbox" value="1"{% if form.pinned %} checked{% endif %}{{ invalid('editor-pinned') }} />
|
|
281
|
-
<label for="editor-pinned">Pinned</label>
|
|
282
|
-
</p>
|
|
283
|
-
{{ problem('editor-pinned') }}
|
|
284
|
-
<p class="admin-hint">
|
|
285
|
-
Writes <code>pinned:</code> and the moment you pinned it into the front matter. Pinned posts
|
|
286
|
-
show first on your fediverse profile, newest pin first, up to five.
|
|
287
|
-
</p>
|
|
225
|
+
{{ field.checkbox('editor-pinned', 'pinned', 'Pinned', checked=form.pinned, error=(error if errorField == 'editor-pinned' else ''), hint='Writes <code>pinned:</code> and the moment you pinned it into the front matter. Pinned posts show first on your fediverse profile, newest pin first, up to five.') }}
|
|
288
226
|
{% endif %}
|
|
289
227
|
|
|
290
228
|
{# Who the front matter says wrote this (TASK-67). A select of the site's
|
|
@@ -293,65 +231,57 @@
|
|
|
293
231
|
and, once the actors land, whose followers hear about it. A file that
|
|
294
232
|
still names somebody who has no account keeps an option of its own, so
|
|
295
233
|
opening the editor cannot silently reattribute it. #}
|
|
296
|
-
|
|
297
|
-
<select id="editor-author" name="author">
|
|
234
|
+
{% call field.select('editor-author', 'author', 'Author') %}
|
|
298
235
|
{% for choice in authors %}
|
|
299
236
|
<option value="{{ choice.value }}"{% if choice.chosen %} selected{% endif %}>{{ choice.label }}</option>
|
|
300
237
|
{% endfor %}
|
|
301
|
-
|
|
238
|
+
{% endcall %}
|
|
302
239
|
{% endcall %}
|
|
303
240
|
|
|
304
241
|
{% if kind.tagged or kind.categorised %}
|
|
305
|
-
{% call
|
|
242
|
+
{% call collapse('Tags and categories', open.taxonomy, fields=true) %}
|
|
306
243
|
{% if kind.tagged %}
|
|
307
|
-
|
|
308
|
-
<input id="editor-tags" name="tags" type="text" value="{{ form.tags }}" />
|
|
309
|
-
<p class="admin-hint">Separated by commas.</p>
|
|
244
|
+
{{ field.text('editor-tags', 'tags', 'Tags', value=form.tags, hint='Separated by commas.') }}
|
|
310
245
|
{% endif %}
|
|
311
|
-
|
|
312
246
|
{% if kind.categorised %}
|
|
313
|
-
|
|
314
|
-
<input id="editor-categories" name="categories" type="text" value="{{ form.categories }}" />
|
|
315
|
-
<p class="admin-hint">Separated by commas.</p>
|
|
247
|
+
{{ field.text('editor-categories', 'categories', 'Categories', value=form.categories, hint='Separated by commas.') }}
|
|
316
248
|
{% endif %}
|
|
317
249
|
{% endcall %}
|
|
318
250
|
{% endif %}
|
|
319
251
|
|
|
320
|
-
{% call
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
{{
|
|
324
|
-
|
|
325
|
-
<label for="editor-permalink">Permalink</label>
|
|
326
|
-
<input id="editor-permalink" name="permalink" type="text" value="{{ form.permalink }}" />
|
|
327
|
-
<p class="admin-hint">Leave it empty to let the {{ kind.singular }} take the URL its slug implies.</p>
|
|
252
|
+
{% call collapse('Address', open.address, fields=true) %}
|
|
253
|
+
{{ field.text('editor-slug', 'slug', 'Slug', value=form.slug, error=(error if errorField == 'editor-slug' else '')) }}
|
|
254
|
+
{% set permalinkHint %}Leave it empty to let the {{ kind.singular }} take the URL its slug implies.{% endset %}
|
|
255
|
+
{{ field.text('editor-permalink', 'permalink', 'Permalink', value=form.permalink, hint=permalinkHint) }}
|
|
328
256
|
{% endcall %}
|
|
329
257
|
|
|
330
258
|
{% if kind.type == "post" %}
|
|
331
|
-
{% call
|
|
259
|
+
{% call collapse('Responding to', open.responding, fields=true) %}
|
|
332
260
|
{#- The mf2 `in-reply-to`: a URL here makes the post a reply, threads
|
|
333
261
|
it in the fediverse and sends that page a webmention. -#}
|
|
334
|
-
|
|
335
|
-
<input id="editor-in-reply-to" name="in-reply-to" type="url" value="{{ form.inReplyTo }}"{{ invalid('editor-in-reply-to') }} />
|
|
336
|
-
{{ problem('editor-in-reply-to') }}
|
|
262
|
+
{{ field.text('editor-in-reply-to', 'in-reply-to', 'In reply to', value=form.inReplyTo, type='url', error=(error if errorField == 'editor-in-reply-to' else '')) }}
|
|
337
263
|
{{ citedCard('in-reply-to') }}
|
|
338
|
-
<p class="
|
|
264
|
+
<p class="label block whitespace-normal text-xs">The address of the post this one answers. Leave it empty for a post that answers nobody.</p>
|
|
265
|
+
|
|
266
|
+
{% call field.select('editor-rsvp', 'rsvp', 'RSVP', error=(error if errorField == 'editor-rsvp' else '')) %}
|
|
267
|
+
<option value=""{% if form.rsvp == "" %} selected{% endif %}>Not an RSVP</option>
|
|
268
|
+
{% for choice in rsvpChoices %}
|
|
269
|
+
<option value="{{ choice.value }}"{% if form.rsvp == choice.value %} selected{% endif %}>{{ choice.label }}</option>
|
|
270
|
+
{% endfor %}
|
|
271
|
+
{% if unrecognizedRsvp %}
|
|
272
|
+
<option value="{{ unrecognizedRsvp }}" selected>{{ unrecognizedRsvp }} (not recognized)</option>
|
|
273
|
+
{% endif %}
|
|
274
|
+
{% endcall %}
|
|
339
275
|
|
|
340
276
|
{#- The mf2 `like-of`, `repost-of` and `bookmark-of` (TASK-169): each
|
|
341
277
|
cites a page the way a reply does, and sends it a webmention. -#}
|
|
342
|
-
|
|
343
|
-
<input id="editor-like-of" name="like-of" type="url" value="{{ form.likeOf }}"{{ invalid('editor-like-of') }} />
|
|
344
|
-
{{ problem('editor-like-of') }}
|
|
278
|
+
{{ field.text('editor-like-of', 'like-of', 'Like of', value=form.likeOf, type='url', error=(error if errorField == 'editor-like-of' else '')) }}
|
|
345
279
|
{{ citedCard('like-of') }}
|
|
346
|
-
|
|
347
|
-
<input id="editor-repost-of" name="repost-of" type="url" value="{{ form.repostOf }}"{{ invalid('editor-repost-of') }} />
|
|
348
|
-
{{ problem('editor-repost-of') }}
|
|
280
|
+
{{ field.text('editor-repost-of', 'repost-of', 'Repost of', value=form.repostOf, type='url', error=(error if errorField == 'editor-repost-of' else '')) }}
|
|
349
281
|
{{ citedCard('repost-of') }}
|
|
350
|
-
|
|
351
|
-
<input id="editor-bookmark-of" name="bookmark-of" type="url" value="{{ form.bookmarkOf }}"{{ invalid('editor-bookmark-of') }} />
|
|
352
|
-
{{ problem('editor-bookmark-of') }}
|
|
282
|
+
{{ field.text('editor-bookmark-of', 'bookmark-of', 'Bookmark of', value=form.bookmarkOf, type='url', error=(error if errorField == 'editor-bookmark-of' else '')) }}
|
|
353
283
|
{{ citedCard('bookmark-of') }}
|
|
354
|
-
<p class="
|
|
284
|
+
<p class="label block whitespace-normal text-xs">The address of a post this one likes, reposts or bookmarks. Leave them empty for a post that cites nothing.</p>
|
|
355
285
|
{% if form.previewHidden and not (citedPreviews | length) %}
|
|
356
286
|
<input type="hidden" name="preview" value="hide">
|
|
357
287
|
{% endif %}
|
|
@@ -360,9 +290,16 @@
|
|
|
360
290
|
{% endif %}
|
|
361
291
|
{% endcall %}
|
|
362
292
|
|
|
363
|
-
{% call
|
|
364
|
-
|
|
365
|
-
|
|
293
|
+
{% call collapse('Event', open.event, fields=true) %}
|
|
294
|
+
{% set eventTimeHint %}Wall-clock time in {{ dateZone }}. Stored as UTC.{% endset %}
|
|
295
|
+
{{ field.text('editor-event-start', eventFields.start, 'Starts', value=form.event.start, placeholder='2026-10-10 09:00', autocomplete='off', error=(error if errorField == 'editor-event-start' else ''), hint=eventTimeHint, hintId='editor-event-time-hint') }}
|
|
296
|
+
{{ field.text('editor-event-end', eventFields.end, 'Ends', value=form.event.end, placeholder='2026-10-10 17:00', autocomplete='off', error=(error if errorField == 'editor-event-end' else ''), hintId='editor-event-time-hint') }}
|
|
297
|
+
{{ field.text('editor-event-location', eventFields.location, 'Where', value=form.event.location, error=(error if errorField == 'editor-event-location' else ''), hint='The place, or the address to join an online event at.', hintId='editor-event-location-hint') }}
|
|
298
|
+
<p class="label block whitespace-normal text-xs">A post with a start is an event, named by its Title and described by its Body. Empty every box to make it a post again.</p>
|
|
299
|
+
{% endcall %}
|
|
300
|
+
|
|
301
|
+
{% call collapse('Read', open.read, fields=true) %}
|
|
302
|
+
{% call field.select('editor-read-status', readFields.status, 'Read status', error=(error if errorField == 'editor-read-status' else '')) %}
|
|
366
303
|
<option value=""{% if form.readStatus == "" %} selected{% endif %}>Not a read post</option>
|
|
367
304
|
{% for status in readStatuses %}
|
|
368
305
|
<option value="{{ status.value }}"{% if form.readStatus == status.value %} selected{% endif %}>{{ status.label }}</option>
|
|
@@ -370,47 +307,33 @@
|
|
|
370
307
|
{% if unrecognizedReadStatus %}
|
|
371
308
|
<option value="{{ unrecognizedReadStatus }}" selected>{{ unrecognizedReadStatus }} (not recognized)</option>
|
|
372
309
|
{% endif %}
|
|
373
|
-
|
|
374
|
-
{{
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
{{
|
|
378
|
-
<
|
|
379
|
-
<input id="editor-read-of-author" name="{{ readFields.author }}" type="text" value="{{ form.readOf.author }}" />
|
|
380
|
-
<label for="editor-read-of-uid">Identifier</label>
|
|
381
|
-
<input id="editor-read-of-uid" name="{{ readFields.uid }}" type="text" value="{{ form.readOf.uid }}" placeholder="isbn:9780441478125" autocomplete="off" spellcheck="false" />
|
|
382
|
-
<label for="editor-read-of-url">Address</label>
|
|
383
|
-
<input id="editor-read-of-url" name="{{ readFields.url }}" type="url" value="{{ form.readOf.url }}"{{ invalid('editor-read-of-url') }} />
|
|
384
|
-
{{ problem('editor-read-of-url') }}
|
|
385
|
-
<p class="admin-hint">A book or paper this post says its author read. An identifier is an ISBN or a DOI, written isbn:… or doi:…. Choose Not a read post and empty every box to remove it. A read is described by what it says, so leave its Description empty.</p>
|
|
310
|
+
{% endcall %}
|
|
311
|
+
{{ field.text('editor-read-of-name', readFields.name, 'Title', value=form.readOf.name, error=(error if errorField == 'editor-read-of-name' else '')) }}
|
|
312
|
+
{{ field.text('editor-read-of-author', readFields.author, 'Author', value=form.readOf.author) }}
|
|
313
|
+
{{ field.text('editor-read-of-uid', readFields.uid, 'Identifier', value=form.readOf.uid, placeholder='isbn:9780441478125', autocomplete='off', spellcheck='false') }}
|
|
314
|
+
{{ field.text('editor-read-of-url', readFields.url, 'Address', value=form.readOf.url, type='url', error=(error if errorField == 'editor-read-of-url' else '')) }}
|
|
315
|
+
<p class="label block whitespace-normal text-xs">A book or paper this post says its author read. An identifier is an ISBN or a DOI, written isbn:… or doi:…. Choose Not a read post and empty every box to remove it. A read is described by what it says, so leave its Description empty.</p>
|
|
386
316
|
{% endcall %}
|
|
387
317
|
{% endif %}
|
|
388
318
|
|
|
389
|
-
{% call
|
|
390
|
-
|
|
391
|
-
<input id="editor-description" name="description" type="text" value="{{ form.description }}"{{ invalid('editor-description') }} />
|
|
392
|
-
{{ problem('editor-description') }}
|
|
319
|
+
{% call collapse('Summary and language', open.summary, fields=true) %}
|
|
320
|
+
{{ field.text('editor-description', 'description', 'Description', value=form.description, error=(error if errorField == 'editor-description' else '')) }}
|
|
393
321
|
|
|
394
322
|
{#- The `lang` front matter (TASK-154): a post or page written in another
|
|
395
323
|
language than the site's says so, for screen readers, translation
|
|
396
324
|
and fediverse language filters. -#}
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
{{ problem('editor-lang') }}
|
|
400
|
-
<p class="admin-hint" id="editor-lang-hint">A language tag, such as fr or pt-BR. Leave it empty for the site’s language, {{ siteLanguage }}.</p>
|
|
325
|
+
{% set langHint %}A language tag, such as fr or pt-BR. Leave it empty for the site’s language, {{ siteLanguage }}.{% endset %}
|
|
326
|
+
{{ field.text('editor-lang', 'lang', 'Language', value=form.lang, autocomplete='off', spellcheck='false', error=(error if errorField == 'editor-lang' else ''), hint=langHint, hintId='editor-lang-hint') }}
|
|
401
327
|
{% endcall %}
|
|
402
328
|
|
|
403
329
|
{% if kind.type == "post" and syndicationTargets.length %}
|
|
404
330
|
{# TASK-155: the targets content/_data/syndicationTargets.json declares.
|
|
405
331
|
A target whose tag the post carries is selected without a tick. #}
|
|
406
|
-
{% call
|
|
332
|
+
{% call collapse('Syndicate to', open.syndication, fields=true) %}
|
|
407
333
|
{% for target in syndicationTargets %}
|
|
408
|
-
|
|
409
|
-
<input id="editor-{{ target.field }}" name="{{ target.field }}" type="checkbox" value="1"{% if target.checked %} checked{% endif %} />
|
|
410
|
-
<label for="editor-{{ target.field }}">{{ target.name }}</label>
|
|
411
|
-
</p>
|
|
334
|
+
{{ field.checkbox('editor-' + target.field, target.field, target.name | escape, checked=target.checked) }}
|
|
412
335
|
{% endfor %}
|
|
413
|
-
<p class="
|
|
336
|
+
<p class="label block whitespace-normal text-xs">
|
|
414
337
|
Writes <code>syndicate-to:</code> into the front matter. The post links to each target and
|
|
415
338
|
sends it a webmention when it is published or updated. A post tagged with a target’s tag is
|
|
416
339
|
sent there without a tick.
|
|
@@ -418,55 +341,30 @@
|
|
|
418
341
|
{% endcall %}
|
|
419
342
|
{% endif %}
|
|
420
343
|
|
|
421
|
-
{% call
|
|
344
|
+
{% call collapse('Display and discussion', open.display, fields=true) %}
|
|
422
345
|
{# What this document says about comments, if anything. Three answers
|
|
423
346
|
rather than two: the site's own rules, always open, always closed. #}
|
|
424
|
-
|
|
425
|
-
<select id="editor-comments" name="comments">
|
|
347
|
+
{% call field.select('editor-comments', 'comments', 'Comments', hint='Writes <code>comments: true</code> or <code>comments: false</code> into the front matter, which beats the site’s switch and its closing window in both directions. Fediverse replies are shown either way.') %}
|
|
426
348
|
<option value="{{ commentSettings.site }}"{% if form.comments == commentSettings.site %} selected{% endif %}>Follow the site settings</option>
|
|
427
349
|
<option value="{{ commentSettings.open }}"{% if form.comments == commentSettings.open %} selected{% endif %}>Open</option>
|
|
428
350
|
<option value="{{ commentSettings.closed }}"{% if form.comments == commentSettings.closed %} selected{% endif %}>Closed</option>
|
|
429
|
-
|
|
430
|
-
<p class="admin-hint">
|
|
431
|
-
Writes <code>comments: true</code> or <code>comments: false</code> into the front matter,
|
|
432
|
-
which beats the site's switch and its closing window in both directions. Fediverse replies
|
|
433
|
-
are shown either way.
|
|
434
|
-
</p>
|
|
351
|
+
{% endcall %}
|
|
435
352
|
|
|
436
353
|
{% if kind.excludable %}
|
|
437
354
|
{# doc-2's eleventyExcludeFromCollections: still published and still at
|
|
438
355
|
its URL, but out of every collection a template lists from. #}
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
<label for="editor-exclude">Hide from collections</label>
|
|
442
|
-
</p>
|
|
443
|
-
<p class="admin-hint">Keeps the {{ kind.singular }} out of listings that gather content, without unpublishing it.</p>
|
|
356
|
+
{% set excludeHint %}Keeps the {{ kind.singular }} out of listings that gather content, without unpublishing it.{% endset %}
|
|
357
|
+
{{ field.checkbox('editor-exclude', 'exclude', 'Hide from collections', checked=form.exclude, hint=excludeHint) }}
|
|
444
358
|
{% endif %}
|
|
445
359
|
|
|
446
360
|
{% if kind.contactable %}
|
|
447
361
|
{# The page offers a contact form under its content (TASK-56). Where a
|
|
448
362
|
message goes is the contact address on the Settings screen; it is
|
|
449
363
|
never on this page or in its HTML. #}
|
|
450
|
-
<
|
|
451
|
-
|
|
452
|
-
<label for="editor-contact">Contact form</label>
|
|
453
|
-
</p>
|
|
454
|
-
<p class="admin-hint">
|
|
455
|
-
Writes <code>contact: true</code> into the front matter and puts a name, email, subject
|
|
456
|
-
and message form under this {{ kind.singular }}. Messages arrive on the Messages screen
|
|
457
|
-
and are emailed to the contact address on Settings.
|
|
458
|
-
</p>
|
|
364
|
+
{% set contactHint %}Writes <code>contact: true</code> into the front matter and puts a name, email, subject and message form under this {{ kind.singular }}. Messages arrive on the Messages screen and are emailed to the contact address on Settings.{% endset %}
|
|
365
|
+
{{ field.checkbox('editor-contact', 'contact', 'Contact form', checked=form.contact, hint=contactHint) }}
|
|
459
366
|
{% endif %}
|
|
460
367
|
{% endcall %}
|
|
461
|
-
|
|
462
|
-
<p class="admin-editor-buttons">
|
|
463
|
-
{% for button in actions %}
|
|
464
|
-
<button type="submit" name="action" value="{{ button.value }}">{{ button.label }}</button>
|
|
465
|
-
{% endfor %}
|
|
466
|
-
{% if viewUrl %}
|
|
467
|
-
<a class="admin-button admin-button-quiet" href="{{ viewUrl }}">View</a>
|
|
468
|
-
{% endif %}
|
|
469
|
-
</p>
|
|
470
368
|
</div>
|
|
471
369
|
</form>
|
|
472
370
|
|