@geekity/cms 0.14.0 → 0.16.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.
Files changed (209) hide show
  1. package/README.md +270 -52
  2. package/admin/pages/documents/editor.njk +120 -0
  3. package/admin/pages/documents/syndication.njk +110 -0
  4. package/admin/pages/federation/followers.njk +7 -0
  5. package/admin/pages/media/library.njk +4 -3
  6. package/admin/pages/settings/general.njk +44 -0
  7. package/admin/static/admin.css +44 -0
  8. package/dist/admin/documents.d.ts +104 -0
  9. package/dist/admin/documents.d.ts.map +1 -1
  10. package/dist/admin/documents.js +220 -55
  11. package/dist/admin/documents.js.map +1 -1
  12. package/dist/admin/enclosure-field.d.ts +91 -0
  13. package/dist/admin/enclosure-field.d.ts.map +1 -0
  14. package/dist/admin/enclosure-field.js +282 -0
  15. package/dist/admin/enclosure-field.js.map +1 -0
  16. package/dist/admin/federation.d.ts +15 -0
  17. package/dist/admin/federation.d.ts.map +1 -1
  18. package/dist/admin/federation.js +19 -0
  19. package/dist/admin/federation.js.map +1 -1
  20. package/dist/admin/media.d.ts +7 -2
  21. package/dist/admin/media.d.ts.map +1 -1
  22. package/dist/admin/media.js +4 -2
  23. package/dist/admin/media.js.map +1 -1
  24. package/dist/admin/menu.d.ts.map +1 -1
  25. package/dist/admin/menu.js +3 -0
  26. package/dist/admin/menu.js.map +1 -1
  27. package/dist/admin/photo-field.d.ts +39 -0
  28. package/dist/admin/photo-field.d.ts.map +1 -0
  29. package/dist/admin/photo-field.js +91 -0
  30. package/dist/admin/photo-field.js.map +1 -0
  31. package/dist/admin/preview.d.ts.map +1 -1
  32. package/dist/admin/preview.js +6 -1
  33. package/dist/admin/preview.js.map +1 -1
  34. package/dist/admin/routes.d.ts.map +1 -1
  35. package/dist/admin/routes.js +4 -0
  36. package/dist/admin/routes.js.map +1 -1
  37. package/dist/admin/settings-general.d.ts.map +1 -1
  38. package/dist/admin/settings-general.js +36 -2
  39. package/dist/admin/settings-general.js.map +1 -1
  40. package/dist/admin/settings-page.d.ts.map +1 -1
  41. package/dist/admin/settings-page.js +1 -2
  42. package/dist/admin/settings-page.js.map +1 -1
  43. package/dist/admin/settings.d.ts +26 -0
  44. package/dist/admin/settings.d.ts.map +1 -1
  45. package/dist/admin/settings.js +88 -2
  46. package/dist/admin/settings.js.map +1 -1
  47. package/dist/admin/syndication-targets.d.ts +57 -0
  48. package/dist/admin/syndication-targets.d.ts.map +1 -0
  49. package/dist/admin/syndication-targets.js +266 -0
  50. package/dist/admin/syndication-targets.js.map +1 -0
  51. package/dist/admin/templates.d.ts +1 -0
  52. package/dist/admin/templates.d.ts.map +1 -1
  53. package/dist/admin/templates.js +1 -0
  54. package/dist/admin/templates.js.map +1 -1
  55. package/dist/admin/uploads.d.ts +13 -2
  56. package/dist/admin/uploads.d.ts.map +1 -1
  57. package/dist/admin/uploads.js +23 -5
  58. package/dist/admin/uploads.js.map +1 -1
  59. package/dist/config.d.ts +17 -3
  60. package/dist/config.d.ts.map +1 -1
  61. package/dist/config.js +11 -7
  62. package/dist/config.js.map +1 -1
  63. package/dist/content/citation.d.ts +36 -0
  64. package/dist/content/citation.d.ts.map +1 -0
  65. package/dist/content/citation.js +31 -0
  66. package/dist/content/citation.js.map +1 -0
  67. package/dist/content/enclosure.d.ts +69 -0
  68. package/dist/content/enclosure.d.ts.map +1 -0
  69. package/dist/content/enclosure.js +165 -0
  70. package/dist/content/enclosure.js.map +1 -0
  71. package/dist/content/index.d.ts +5 -1
  72. package/dist/content/index.d.ts.map +1 -1
  73. package/dist/content/index.js +2 -0
  74. package/dist/content/index.js.map +1 -1
  75. package/dist/content/media.d.ts +15 -2
  76. package/dist/content/media.d.ts.map +1 -1
  77. package/dist/content/media.js +92 -9
  78. package/dist/content/media.js.map +1 -1
  79. package/dist/content/photo.d.ts +45 -0
  80. package/dist/content/photo.d.ts.map +1 -0
  81. package/dist/content/photo.js +55 -0
  82. package/dist/content/photo.js.map +1 -0
  83. package/dist/content/post-type.d.ts +20 -8
  84. package/dist/content/post-type.d.ts.map +1 -1
  85. package/dist/content/post-type.js +17 -0
  86. package/dist/content/post-type.js.map +1 -1
  87. package/dist/federation/article.d.ts.map +1 -1
  88. package/dist/federation/article.js +93 -10
  89. package/dist/federation/article.js.map +1 -1
  90. package/dist/federation/citations.d.ts +38 -0
  91. package/dist/federation/citations.d.ts.map +1 -0
  92. package/dist/federation/citations.js +98 -0
  93. package/dist/federation/citations.js.map +1 -0
  94. package/dist/federation/delivery.d.ts.map +1 -1
  95. package/dist/federation/delivery.js +79 -31
  96. package/dist/federation/delivery.js.map +1 -1
  97. package/dist/images/alt-text.d.ts +6 -0
  98. package/dist/images/alt-text.d.ts.map +1 -1
  99. package/dist/images/alt-text.js +10 -0
  100. package/dist/images/alt-text.js.map +1 -1
  101. package/dist/images/icons.d.ts +5 -0
  102. package/dist/images/icons.d.ts.map +1 -1
  103. package/dist/images/icons.js +13 -8
  104. package/dist/images/icons.js.map +1 -1
  105. package/dist/images/paths.d.ts +1 -1
  106. package/dist/images/paths.d.ts.map +1 -1
  107. package/dist/images/paths.js.map +1 -1
  108. package/dist/index.d.ts +7 -7
  109. package/dist/index.d.ts.map +1 -1
  110. package/dist/index.js +25 -4
  111. package/dist/index.js.map +1 -1
  112. package/dist/indieauth/bearer.d.ts +6 -1
  113. package/dist/indieauth/bearer.d.ts.map +1 -1
  114. package/dist/indieauth/bearer.js +39 -12
  115. package/dist/indieauth/bearer.js.map +1 -1
  116. package/dist/indieauth/discovery.d.ts +9 -4
  117. package/dist/indieauth/discovery.d.ts.map +1 -1
  118. package/dist/indieauth/discovery.js +18 -7
  119. package/dist/indieauth/discovery.js.map +1 -1
  120. package/dist/micropub/create.d.ts +56 -0
  121. package/dist/micropub/create.d.ts.map +1 -0
  122. package/dist/micropub/create.js +200 -0
  123. package/dist/micropub/create.js.map +1 -0
  124. package/dist/micropub/endpoint.d.ts +21 -0
  125. package/dist/micropub/endpoint.d.ts.map +1 -0
  126. package/dist/micropub/endpoint.js +353 -0
  127. package/dist/micropub/endpoint.js.map +1 -0
  128. package/dist/micropub/media.d.ts +14 -0
  129. package/dist/micropub/media.d.ts.map +1 -0
  130. package/dist/micropub/media.js +93 -0
  131. package/dist/micropub/media.js.map +1 -0
  132. package/dist/micropub/update.d.ts +44 -0
  133. package/dist/micropub/update.d.ts.map +1 -0
  134. package/dist/micropub/update.js +133 -0
  135. package/dist/micropub/update.js.map +1 -0
  136. package/dist/web/assets.d.ts +14 -0
  137. package/dist/web/assets.d.ts.map +1 -1
  138. package/dist/web/assets.js +56 -1
  139. package/dist/web/assets.js.map +1 -1
  140. package/dist/web/context.d.ts +68 -3
  141. package/dist/web/context.d.ts.map +1 -1
  142. package/dist/web/context.js +56 -1
  143. package/dist/web/context.js.map +1 -1
  144. package/dist/web/feed-atom.d.ts.map +1 -1
  145. package/dist/web/feed-atom.js +20 -0
  146. package/dist/web/feed-atom.js.map +1 -1
  147. package/dist/web/feed-item.d.ts +19 -0
  148. package/dist/web/feed-item.d.ts.map +1 -1
  149. package/dist/web/feed-item.js +22 -0
  150. package/dist/web/feed-item.js.map +1 -1
  151. package/dist/web/feed-json.d.ts +13 -0
  152. package/dist/web/feed-json.d.ts.map +1 -1
  153. package/dist/web/feed-json.js +15 -0
  154. package/dist/web/feed-json.js.map +1 -1
  155. package/dist/web/feed-rss.d.ts.map +1 -1
  156. package/dist/web/feed-rss.js +59 -2
  157. package/dist/web/feed-rss.js.map +1 -1
  158. package/dist/web/feed-xml.d.ts +7 -1
  159. package/dist/web/feed-xml.d.ts.map +1 -1
  160. package/dist/web/feed-xml.js +8 -2
  161. package/dist/web/feed-xml.js.map +1 -1
  162. package/dist/web/feeds.d.ts +1 -1
  163. package/dist/web/feeds.d.ts.map +1 -1
  164. package/dist/web/feeds.js +6 -0
  165. package/dist/web/feeds.js.map +1 -1
  166. package/dist/web/index.d.ts +4 -1
  167. package/dist/web/index.d.ts.map +1 -1
  168. package/dist/web/index.js +2 -0
  169. package/dist/web/index.js.map +1 -1
  170. package/dist/web/license.d.ts +94 -0
  171. package/dist/web/license.d.ts.map +1 -0
  172. package/dist/web/license.js +116 -0
  173. package/dist/web/license.js.map +1 -0
  174. package/dist/web/oembed.d.ts.map +1 -1
  175. package/dist/web/oembed.js +1 -2
  176. package/dist/web/oembed.js.map +1 -1
  177. package/dist/web/render.d.ts +15 -0
  178. package/dist/web/render.d.ts.map +1 -1
  179. package/dist/web/render.js +27 -2
  180. package/dist/web/render.js.map +1 -1
  181. package/dist/web/routes.d.ts.map +1 -1
  182. package/dist/web/routes.js +10 -6
  183. package/dist/web/routes.js.map +1 -1
  184. package/dist/web/share-image.d.ts +7 -7
  185. package/dist/web/share-image.d.ts.map +1 -1
  186. package/dist/web/share-image.js +8 -7
  187. package/dist/web/share-image.js.map +1 -1
  188. package/dist/webmention/index.d.ts +2 -0
  189. package/dist/webmention/index.d.ts.map +1 -1
  190. package/dist/webmention/index.js +1 -0
  191. package/dist/webmention/index.js.map +1 -1
  192. package/dist/webmention/service.d.ts.map +1 -1
  193. package/dist/webmention/service.js +96 -18
  194. package/dist/webmention/service.js.map +1 -1
  195. package/dist/webmention/syndication.d.ts +135 -0
  196. package/dist/webmention/syndication.d.ts.map +1 -0
  197. package/dist/webmention/syndication.js +337 -0
  198. package/dist/webmention/syndication.js.map +1 -0
  199. package/package.json +1 -1
  200. package/themes/default/README.md +121 -37
  201. package/themes/default/layouts/base.njk +3 -4
  202. package/themes/default/layouts/post.njk +23 -6
  203. package/themes/default/partials/citations.njk +17 -0
  204. package/themes/default/partials/jsonld.njk +15 -6
  205. package/themes/default/partials/photos.njk +10 -0
  206. package/themes/default/partials/post-list.njk +7 -0
  207. package/themes/default/partials/recording.njk +41 -0
  208. package/themes/default/src/style.css +25 -0
  209. package/themes/default/static/style.css +41 -0
@@ -0,0 +1,110 @@
1
+ {# /admin/syndication: the services a post can be sent to, which is
2
+ content/_data/syndicationTargets.json itself.
3
+
4
+ One panel per entry the file holds, in file order, the broken ones too:
5
+ an entry that declares nothing says why, so it can be fixed or removed here.
6
+ Each panel saves or removes its own entry, and the Add form at the bottom
7
+ appends one. A file that is not a JSON list is shown with its problem and
8
+ no forms, because saving over it would lose what it holds. #}
9
+ {% extends "layouts/shell.njk" %}
10
+ {% import "components/fields.njk" as field %}
11
+
12
+ {% block title %}{{ heading }}{% endblock %}
13
+
14
+ {# The five boxes of one target, ids prefixed with the panel's key. #}
15
+ {% macro boxes(panel, fields) %}
16
+ {{ field.text(panel.key + '-id', fields.id, 'Id', panel.form.id, error=panel.problems.id,
17
+ spellcheck='false', required=true,
18
+ hint='What a post&rsquo;s <code>syndicate-to</code> lists and what Micropub offers as the uid. Letters, digits, <code>.</code>, <code>-</code> and <code>_</code>.') }}
19
+ {{ field.text(panel.key + '-name', fields.name, 'Name', panel.form.name, error=panel.problems.name,
20
+ required=true, hint='What the editor&rsquo;s checkbox and the post&rsquo;s link say.') }}
21
+ {{ field.text(panel.key + '-url', fields.url, 'URL', panel.form.url, error=panel.problems.url,
22
+ inputmode='url', spellcheck='false', required=true,
23
+ hint='The page the post links to and sends its webmention to. Put <code>{lang}</code> where the post&rsquo;s language goes, as in <code>https://news.indieweb.org/{lang}</code>.') }}
24
+ {{ field.text(panel.key + '-tag', fields.tag, 'Tag', panel.form.tag, error=panel.problems.tag,
25
+ spellcheck='false',
26
+ hint='Optional. A post carrying this tag is sent here without listing the target.') }}
27
+ {{ field.text(panel.key + '-languages', fields.languages, 'Languages', panel.form.languages,
28
+ error=panel.problems.languages, spellcheck='false',
29
+ hint='Optional. The language tags this target takes posts in, separated by commas, such as <code>en, de</code>. Empty takes every language.') }}
30
+ {% endmacro %}
31
+
32
+ {% block content %}
33
+ <h1>{{ heading }}</h1>
34
+
35
+ {% if hasProblems %}
36
+ {% call field.summary('Nothing was saved. Fix the fields marked below and try again.') %}
37
+ {% for panel in panels.concat([adding]) %}
38
+ {% if panel.key == refusedKey %}
39
+ {{ field.problem(panel.key + '-id', panel.problems.id) }}
40
+ {{ field.problem(panel.key + '-name', panel.problems.name) }}
41
+ {{ field.problem(panel.key + '-url', panel.problems.url) }}
42
+ {{ field.problem(panel.key + '-tag', panel.problems.tag) }}
43
+ {{ field.problem(panel.key + '-languages', panel.problems.languages) }}
44
+ {% endif %}
45
+ {% endfor %}
46
+ {% endcall %}
47
+ {% endif %}
48
+
49
+ <p class="admin-hint">
50
+ Services such as IndieNews and Bridgy Publish copy a post when it links to them and sends
51
+ them a webmention. Each target listed here gets a checkbox in the post editor and is offered
52
+ to Micropub clients. They are kept in <code>content/{{ file }}</code>, which this screen reads
53
+ and writes, so the file can still be edited by hand.
54
+ </p>
55
+
56
+ {% if fileProblem %}
57
+ <div class="admin-error" role="alert">
58
+ <p>{{ fileProblem }} No target is offered until it is fixed. Fix or remove the file by hand;
59
+ this screen will not save over it, because that would lose what it holds.</p>
60
+ </div>
61
+ {% else %}
62
+ <h2>Targets</h2>
63
+
64
+ {% if panels.length %}
65
+ <ul class="admin-menu-boxes">
66
+ {% for panel in panels %}
67
+ <li class="admin-menu-box">
68
+ <h3>{{ panel.form.name or ('Entry ' + (panel.index + 1)) }}</h3>
69
+ {% if panel.fileProblems.length %}
70
+ {% for problem in panel.fileProblems %}
71
+ <p class="admin-field-error">This entry is ignored. {{ problem }}</p>
72
+ {% endfor %}
73
+ {% else %}
74
+ <p class="admin-menu-name"><code>{{ panel.form.id }}</code></p>
75
+ {% endif %}
76
+
77
+ <form method="post" action="{{ saveUrl }}">
78
+ <input type="hidden" name="csrf_token" value="{{ csrfToken }}" />
79
+ <input type="hidden" name="{{ fields.entry }}" value="{{ panel.index }}" />
80
+ <input type="hidden" name="{{ fields.was }}" value="{{ panel.was }}" />
81
+ {{ boxes(panel, fields) }}
82
+ <p class="admin-menu-buttons">
83
+ <button type="submit">Save target</button>
84
+ </p>
85
+ </form>
86
+
87
+ <form class="admin-menu-delete" method="post" action="{{ deleteUrl }}">
88
+ <input type="hidden" name="csrf_token" value="{{ csrfToken }}" />
89
+ <input type="hidden" name="{{ fields.entry }}" value="{{ panel.index }}" />
90
+ <input type="hidden" name="{{ fields.was }}" value="{{ panel.was }}" />
91
+ <button type="submit">Remove this target</button>
92
+ </form>
93
+ </li>
94
+ {% endfor %}
95
+ </ul>
96
+ {% else %}
97
+ <p class="admin-hint">This site declares no targets, so the editor offers none.</p>
98
+ {% endif %}
99
+
100
+ <h2>Add a target</h2>
101
+
102
+ <form class="admin-menu-add" method="post" action="{{ addUrl }}">
103
+ <input type="hidden" name="csrf_token" value="{{ csrfToken }}" />
104
+ {{ boxes(adding, fields) }}
105
+ <p class="admin-menu-buttons">
106
+ <button type="submit">Add target</button>
107
+ </p>
108
+ </form>
109
+ {% endif %}
110
+ {% endblock %}
@@ -214,6 +214,13 @@
214
214
  {% else %}
215
215
  <span class="admin-empty">—</span>
216
216
  {% endif %}
217
+ {% if row.syndication.length %}
218
+ <ul class="admin-syndication">
219
+ {% for target in row.syndication %}
220
+ <li>{{ target.name }}: {% if target.status == "failed" %}<span class="admin-status admin-status-failed">failed</span>{% if target.error %} ({{ target.error }}){% endif %}{% elif target.status == "none" %}takes none{% elif target.status %}sent{% else %}not sent yet{% endif %}{% if target.copy %}, <a href="{{ target.copy }}">copy</a>{% endif %}</li>
221
+ {% endfor %}
222
+ </ul>
223
+ {% endif %}
217
224
  </td>
218
225
  <td class="admin-actions">
219
226
  <form method="post" action="{{ resendUrl }}">
@@ -48,7 +48,8 @@
48
48
  <label for="media-file">Add a file</label>
49
49
  <input id="media-file" name="{{ fields.file }}" type="file" accept="{{ accepts }}" required />
50
50
  <p class="admin-hint">
51
- This site accepts {{ accepts | replace(',', ', ') }}, up to {{ maxBytes }} bytes. The same
51
+ This site accepts {{ accepts | replace(',', ', ') }}, up to {{ maxBytes }} bytes, or
52
+ {{ mediaMaxBytes }} bytes for audio and video. The same
52
53
  rules the editor’s upload control enforces.
53
54
  </p>
54
55
  <p class="admin-settings-buttons">
@@ -76,7 +77,7 @@
76
77
  {% for file in files %}
77
78
  <tr>
78
79
  <td class="admin-media-file">
79
- {% if file.image %}
80
+ {% if file.kind == 'image' %}
80
81
  <a href="{{ file.url }}">
81
82
  <img class="admin-media-thumbnail" src="{{ file.url }}" alt="" width="60" height="60" />
82
83
  </a>
@@ -86,7 +87,7 @@
86
87
  <a href="{{ file.url }}">{{ file.path }}</a>
87
88
  </td>
88
89
  <td class="admin-media-alt">
89
- {% if file.image %}
90
+ {% if file.kind == 'image' %}
90
91
  <form method="post" action="{{ altUrl }}">
91
92
  <input type="hidden" name="csrf_token" value="{{ csrfToken }}" />
92
93
  <input type="hidden" name="{{ fields.path }}" value="{{ file.path }}" />
@@ -8,6 +8,10 @@
8
8
  {{ field.problem('settings-timezone', problems.timezone) }}
9
9
  {{ field.problem('settings-language', problems.language) }}
10
10
  {{ field.problem('settings-locale', problems.locale) }}
11
+ {{ field.problem('settings-icon', problems.icon) }}
12
+ {{ field.problem('settings-license', problems.license) }}
13
+ {{ field.problem('settings-license-url', problems.licenseUrl) }}
14
+ {{ field.problem('settings-license-name', problems.licenseName) }}
11
15
  {% endblock %}
12
16
 
13
17
  {% block settingsFields %}
@@ -41,6 +45,46 @@
41
45
  {% set localeHint %}How the public site writes dates and counts, such as <code>en-US</code> for <code>September 2, 2026</code>. Leave it empty to follow the language.{% endset %}
42
46
  {{ field.text('settings-locale', fields.locale, 'Locale', form.locale,
43
47
  error=problems.locale, hint=localeHint) }}
48
+
49
+ {% set iconHint %}A square image at least 512 pixels wide, uploaded on <a href="{{ adminUrl }}/media">Media</a>: a path such as <code>/uploads/2026/10/icon.png</code>. It is the favicon, the home screen icon, <code>/favicon.ico</code> and the web app manifest's icon. Anything not square is cropped to its middle.{% endset %}
50
+ {{ field.text('settings-icon', fields.icon, 'Site icon', form.icon,
51
+ error=problems.icon, hint=iconHint) }}
52
+
53
+ <div class="admin-avatar-current">
54
+ {% if iconPreview %}
55
+ <img class="admin-icon-preview" src="{{ iconPreview }}" alt="The current site icon" width="96" height="96" />
56
+ {% else %}
57
+ <span class="admin-icon-preview admin-avatar-blank"></span>
58
+ {% endif %}
59
+ <p class="admin-hint">
60
+ {% if iconUnderived and not imageOptimization %}
61
+ Image optimization is off, so no icons are derived and the site links none.
62
+ {% elif iconUnderived %}
63
+ The site cannot derive icons from <code>{{ iconInEffect }}</code>, so it links none.
64
+ {% elif iconPreview and iconFromAvatar %}
65
+ The current icon, from the <code>avatar</code> in <code>site.json</code>. Saving this page writes it as the icon; clearing the field leaves the avatar in use.
66
+ {% elif iconPreview %}
67
+ The current icon, as a browser tab and a home screen show it.
68
+ {% else %}
69
+ The site has no icon yet, so browsers show their own.
70
+ {% endif %}
71
+ </p>
72
+ </div>
73
+
74
+ {% set licenseHint %}What readers may do with your posts. The footer links it, and the structured data and the feeds declare it. A post can name its own with <code>license</code> in its front matter.{% endset %}
75
+ {% call field.select('settings-license', fields.license, 'License', error=problems.license, hint=licenseHint) %}
76
+ <option value=""{% if not form.license %} selected{% endif %}>No license (all rights reserved)</option>
77
+ {% for choice in licenseChoices %}
78
+ <option value="{{ choice.key }}"{% if choice.key == form.license %} selected{% endif %}>{{ choice.name }}</option>
79
+ {% endfor %}
80
+ <option value="custom"{% if form.license == 'custom' %} selected{% endif %}>Custom license</option>
81
+ {% endcall %}
82
+
83
+ {{ field.text('settings-license-url', fields.licenseUrl, 'Custom license URL', form.licenseUrl,
84
+ error=problems.licenseUrl, inputmode='url', hint='Where its terms are. Only read for a custom license.') }}
85
+
86
+ {{ field.text('settings-license-name', fields.licenseName, 'Custom license name', form.licenseName,
87
+ error=problems.licenseName, hint='What the footer calls it. Only read for a custom license.') }}
44
88
  {% endblock %}
45
89
 
46
90
  {% block settingsPanels %}{% endblock %}
@@ -490,6 +490,37 @@ button[type='submit']:hover,
490
490
  min-height: 28rem;
491
491
  }
492
492
 
493
+ .admin-editor-enclosure {
494
+ margin: 1.25rem 0 0;
495
+ padding: 0.75rem 1rem 1rem;
496
+ border: 1px solid var(--admin-border);
497
+ }
498
+
499
+ .admin-editor-syndication {
500
+ margin: 1.25rem 0 0;
501
+ padding: 0.75rem 1rem 1rem;
502
+ border: 1px solid var(--admin-border);
503
+ }
504
+
505
+ .admin-editor-enclosure-heading {
506
+ margin: 1.25rem 0 0;
507
+ font-size: 1em;
508
+ }
509
+
510
+ .admin-editor-alternate {
511
+ display: grid;
512
+ grid-template-columns: max-content minmax(0, 1fr);
513
+ gap: 0.4rem 0.75rem;
514
+ align-items: center;
515
+ margin: 0.75rem 0 0;
516
+ padding: 0.5rem 0.75rem 0.75rem;
517
+ border: 1px solid var(--admin-border);
518
+ }
519
+
520
+ .admin-editor-alternate label {
521
+ margin: 0;
522
+ }
523
+
493
524
  .admin-hint {
494
525
  margin: 0.25rem 0 0;
495
526
  color: var(--admin-muted);
@@ -792,6 +823,14 @@ button[type='submit']:hover,
792
823
  border: 1px solid var(--admin-border);
793
824
  }
794
825
 
826
+ .admin-icon-preview {
827
+ flex: none;
828
+ width: 6rem;
829
+ height: 6rem;
830
+ border: 1px solid var(--admin-border);
831
+ border-radius: 0.75rem;
832
+ }
833
+
795
834
  .admin-avatar-current {
796
835
  display: flex;
797
836
  gap: 1rem;
@@ -847,6 +886,11 @@ button[type='submit']:hover,
847
886
  font-weight: 600;
848
887
  }
849
888
 
889
+ .admin-syndication {
890
+ margin: 0.25rem 0 0;
891
+ padding-left: 1rem;
892
+ }
893
+
850
894
  .admin-inbox-when {
851
895
  color: var(--admin-muted);
852
896
  }
@@ -1,7 +1,14 @@
1
1
  import type { Context, Hono } from 'hono';
2
2
  import type { Document, DocumentType } from '../content/document.ts';
3
+ import type { Enclosure } from '../content/enclosure.ts';
4
+ import type { Photo } from '../content/photo.ts';
3
5
  import type { ContentStore, ListAllOptions } from '../content/store.ts';
6
+ import type { ResolvedConfig } from '../config.ts';
7
+ import type { DocumentChange } from '../content/sync.ts';
4
8
  import type { GeekityEnv } from '../env.ts';
9
+ import type { UndescribedImage } from '../images/alt-text.ts';
10
+ import type { EnclosureForm } from './enclosure-field.ts';
11
+ import type { PhotoRow } from './photo-field.ts';
5
12
  /**
6
13
  * Everything that differs between the posts screens and the pages screens.
7
14
  *
@@ -106,6 +113,55 @@ export interface MountDocumentScreensOptions {
106
113
  * date and a taxonomy, and which section of the navigation marks itself.
107
114
  */
108
115
  export declare function mountDocumentScreens(app: Hono<GeekityEnv>, options: MountDocumentScreensOptions): void;
116
+ /** What a write needs from the site, as plain values rather than a request. */
117
+ export interface DocumentSite {
118
+ readonly store: ContentStore;
119
+ readonly config: ResolvedConfig;
120
+ readonly announce: (change: DocumentChange) => Promise<void>;
121
+ /** The username of whoever is writing: the author a new document starts on. */
122
+ readonly writer: string | undefined;
123
+ }
124
+ /** What {@link writeDocument} is asked to write. */
125
+ export interface DocumentWrite {
126
+ readonly kind: DocumentKind;
127
+ /** The document being replaced, or `undefined` when one is being made. */
128
+ readonly document: Document | undefined;
129
+ readonly form: EditorForm;
130
+ /** Whether it is saved as a draft, which the editor's buttons decide. */
131
+ readonly draft: boolean;
132
+ }
133
+ /** What came of a {@link writeDocument}. */
134
+ export type WriteOutcome = {
135
+ readonly outcome: 'saved';
136
+ readonly saved: Document;
137
+ /** Images published without alt text, which the editor warns about. */
138
+ readonly undescribed: readonly UndescribedImage[];
139
+ } | {
140
+ readonly outcome: 'refused';
141
+ readonly message: string;
142
+ } | {
143
+ readonly outcome: 'conflict';
144
+ /** The document as the form loaded it, which only an edit has. */
145
+ readonly document: Document;
146
+ /** The recording and the photos the form resolved to. */
147
+ readonly media: ResolvedMedia;
148
+ readonly conflict: Conflict;
149
+ };
150
+ /** The post's recording and photos, as a form resolved them against the media library. */
151
+ interface ResolvedMedia {
152
+ readonly recording: Enclosure | undefined;
153
+ readonly photos: readonly Photo[];
154
+ }
155
+ /**
156
+ * The write path behind the editor and Micropub (TASK-164): one form in, one
157
+ * file out, announced to every subscriber.
158
+ *
159
+ * The order matters: the form is checked before anything is touched, the
160
+ * on-disk file is re-hashed and compared with the hash the form loaded with
161
+ * (doc-1's conflict rule), and only then is a file written. A write that is
162
+ * refused leaves the content directory exactly as it was.
163
+ */
164
+ export declare function writeDocument(site: DocumentSite, write: DocumentWrite): Promise<WriteOutcome>;
109
165
  /**
110
166
  * A comma-separated taxonomy field as a list, without the blanks and the
111
167
  * repeats. Tags and categories are both entered this way.
@@ -134,6 +190,32 @@ export interface AuthorChoice {
134
190
  * editor does and what {@link blankForm} deliberately leaves to a request.
135
191
  */
136
192
  export declare function authorChoices(c: Context<GeekityEnv>, current: string): AuthorChoice[];
193
+ /** The file as it is now, when it is not the file the form was filled in from. */
194
+ interface Conflict {
195
+ /** The text of the file on disk. */
196
+ current: string;
197
+ /** Its hash, which is what a resubmission has to carry to go through. */
198
+ hash: string;
199
+ }
200
+ /** What moving a document's file needs from the site. */
201
+ export interface MoveSite {
202
+ readonly store: ContentStore;
203
+ readonly contentDir: string;
204
+ readonly announce: (change: DocumentChange) => Promise<void>;
205
+ }
206
+ /**
207
+ * Move a document into `content/_trash/` or back out of it, the move behind
208
+ * the editor's trash and restore and Micropub's delete and undelete
209
+ * (TASK-167). The document is the moved one, or `undefined` when its file
210
+ * could not be moved.
211
+ *
212
+ * The trash mirrors the content tree — `posts/2026-03-04-x.md` becomes
213
+ * `_trash/posts/2026-03-04-x.md` — so restoring is the same move backwards and
214
+ * needs to remember nothing. The index is corrected as soon as the file has
215
+ * landed rather than waiting for the watcher, so the public site stops or
216
+ * starts serving the document with this request (doc-1).
217
+ */
218
+ export declare function moveDocumentFile(site: MoveSite, document: Document, action: 'trash' | 'restore'): Promise<Document | undefined>;
137
219
  /**
138
220
  * A submitted return path, when it is one this admin could have rendered.
139
221
  *
@@ -141,6 +223,15 @@ export declare function authorChoices(c: Context<GeekityEnv>, current: string):
141
223
  * as another host, so the value cannot be used to bounce somebody off the site.
142
224
  */
143
225
  export declare function returnPath(value: string): string | undefined;
226
+ /**
227
+ * The editor field each citing property fills (TASK-169). The form submits it
228
+ * under the property's own name, as `in-reply-to` is.
229
+ */
230
+ export declare const CITATION_FIELDS: {
231
+ readonly 'repost-of': 'repostOf';
232
+ readonly 'like-of': 'likeOf';
233
+ readonly 'bookmark-of': 'bookmarkOf';
234
+ };
144
235
  /** The editor's fields, as strings, which is what a form has. */
145
236
  export interface EditorForm {
146
237
  title: string;
@@ -161,6 +252,12 @@ export interface EditorForm {
161
252
  author: string;
162
253
  /** The post this one replies to, the mf2 `in-reply-to`. Posts only. */
163
254
  inReplyTo: string;
255
+ /** The post this one reposts, the mf2 `repost-of` (TASK-169). Posts only. */
256
+ repostOf: string;
257
+ /** The post this one likes, the mf2 `like-of` (TASK-169). Posts only. */
258
+ likeOf: string;
259
+ /** The page this one bookmarks, the mf2 `bookmark-of` (TASK-169). Posts only. */
260
+ bookmarkOf: string;
164
261
  /** The language it is written in, the `lang` key; empty for the site's. */
165
262
  lang: string;
166
263
  draft: boolean;
@@ -179,6 +276,12 @@ export interface EditorForm {
179
276
  * lose is the default every document starts at.
180
277
  */
181
278
  comments: string;
279
+ /** The post's recording (TASK-213). Posts only; blank on a page. */
280
+ enclosure: EnclosureForm;
281
+ /** The post's photos (TASK-166), without the blank row the editor adds. Posts only. */
282
+ photos: PhotoRow[];
283
+ /** The ids of the declared syndication targets it selects (TASK-155). Posts only. */
284
+ syndicateTo: string[];
182
285
  body: string;
183
286
  /** The hash of the file the form was filled in from; empty for a new one. */
184
287
  hash: string;
@@ -245,4 +348,5 @@ export declare const PAGE_ROLE_LABELS: {
245
348
  };
246
349
  /** The URL of one view of a listing. Page one is the listing's own URL. */
247
350
  export declare function listingUrl(kind: DocumentKind, filter: DocumentFilter, page?: number): string;
351
+ export {};
248
352
  //# sourceMappingURL=documents.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"documents.d.ts","sourceRoot":"","sources":["../../src/admin/documents.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"documents.d.ts","sourceRoot":"","sources":["../../src/admin/documents.ts"],"names":[],"mappings":"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"}