@geekity/cms 0.35.0 → 0.36.1

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 (85) hide show
  1. package/admin/components/job-status.njk +15 -10
  2. package/admin/components/upload.njk +26 -0
  3. package/admin/pages/documents/editor.njk +34 -19
  4. package/admin/pages/federation/followers.njk +2 -1
  5. package/admin/pages/media/file.njk +5 -4
  6. package/admin/pages/media/library.njk +7 -3
  7. package/admin/pages/settings/general.njk +4 -1
  8. package/admin/pages/tools/export.njk +54 -51
  9. package/admin/pages/tools/maintenance.njk +2 -1
  10. package/admin/pages/users/edit.njk +3 -0
  11. package/admin/src/admin.css +1 -0
  12. package/admin/static/admin.css +74 -0
  13. package/admin/static/job-status.js +158 -0
  14. package/admin/static/upload-drop.js +225 -0
  15. package/dist/admin/documents.d.ts.map +1 -1
  16. package/dist/admin/documents.js +0 -2
  17. package/dist/admin/documents.js.map +1 -1
  18. package/dist/admin/index.d.ts +1 -1
  19. package/dist/admin/index.d.ts.map +1 -1
  20. package/dist/admin/index.js +1 -1
  21. package/dist/admin/index.js.map +1 -1
  22. package/dist/admin/job-status.d.ts +1 -0
  23. package/dist/admin/job-status.d.ts.map +1 -1
  24. package/dist/admin/job-status.js +1 -0
  25. package/dist/admin/job-status.js.map +1 -1
  26. package/dist/admin/media.d.ts +6 -9
  27. package/dist/admin/media.d.ts.map +1 -1
  28. package/dist/admin/media.js +85 -27
  29. package/dist/admin/media.js.map +1 -1
  30. package/dist/admin/routes.d.ts.map +1 -1
  31. package/dist/admin/routes.js +1 -0
  32. package/dist/admin/routes.js.map +1 -1
  33. package/dist/admin/uploads.d.ts +2 -1
  34. package/dist/admin/uploads.d.ts.map +1 -1
  35. package/dist/admin/uploads.js +5 -2
  36. package/dist/admin/uploads.js.map +1 -1
  37. package/dist/media/library.d.ts +9 -0
  38. package/dist/media/library.d.ts.map +1 -1
  39. package/dist/media/library.js +25 -1
  40. package/dist/media/library.js.map +1 -1
  41. package/package.json +6 -1
  42. package/dist/comments/routes.d.ts +0 -65
  43. package/dist/comments/routes.d.ts.map +0 -1
  44. package/dist/comments/routes.js +0 -235
  45. package/dist/comments/routes.js.map +0 -1
  46. package/dist/content/media.d.ts +0 -85
  47. package/dist/content/media.d.ts.map +0 -1
  48. package/dist/content/media.js +0 -237
  49. package/dist/content/media.js.map +0 -1
  50. package/dist/content/read-form.d.ts +0 -31
  51. package/dist/content/read-form.d.ts.map +0 -1
  52. package/dist/content/read-form.js +0 -157
  53. package/dist/content/read-form.js.map +0 -1
  54. package/dist/content/read.d.ts +0 -29
  55. package/dist/content/read.d.ts.map +0 -1
  56. package/dist/content/read.js +0 -82
  57. package/dist/content/read.js.map +0 -1
  58. package/dist/export/export-archives.d.ts +0 -29
  59. package/dist/export/export-archives.d.ts.map +0 -1
  60. package/dist/export/export-archives.js +0 -88
  61. package/dist/export/export-archives.js.map +0 -1
  62. package/dist/federation/mount.d.ts +0 -53
  63. package/dist/federation/mount.d.ts.map +0 -1
  64. package/dist/federation/mount.js +0 -344
  65. package/dist/federation/mount.js.map +0 -1
  66. package/dist/mail/credentials.d.ts +0 -62
  67. package/dist/mail/credentials.d.ts.map +0 -1
  68. package/dist/mail/credentials.js +0 -86
  69. package/dist/mail/credentials.js.map +0 -1
  70. package/dist/site/setting-rows.d.ts +0 -45
  71. package/dist/site/setting-rows.d.ts.map +0 -1
  72. package/dist/site/setting-rows.js +0 -361
  73. package/dist/site/setting-rows.js.map +0 -1
  74. package/dist/site/settings-form.d.ts +0 -30
  75. package/dist/site/settings-form.d.ts.map +0 -1
  76. package/dist/site/settings-form.js +0 -54
  77. package/dist/site/settings-form.js.map +0 -1
  78. package/dist/site/site-json.d.ts +0 -38
  79. package/dist/site/site-json.d.ts.map +0 -1
  80. package/dist/site/site-json.js +0 -69
  81. package/dist/site/site-json.js.map +0 -1
  82. package/dist/webmention/routes.d.ts +0 -37
  83. package/dist/webmention/routes.d.ts.map +0 -1
  84. package/dist/webmention/routes.js +0 -75
  85. package/dist/webmention/routes.js.map +0 -1
@@ -1,361 +0,0 @@
1
- import path from 'node:path';
2
- import { LANGUAGE_TAG_PATTERN } from '../content/language.js';
3
- import { isLocationSharing, LOCATION_SHARING } from '../content/location.js';
4
- import { parseIconSetting } from '../images/icons.js';
5
- import { sourceFile } from '../images/paths.js';
6
- import { MAIL_PROVIDERS } from '../mail/provider.js';
7
- import { isFileSync } from '../util/files.js';
8
- import { DEFAULT_FEED_CADENCE, isUpdatePeriod, UPDATE_PERIODS } from './feed-settings.js';
9
- import { generateIndexNowKey } from './indexnow-key.js';
10
- import { isLicenseUrl } from '../content/license.js';
11
- import { canonicalLocale } from '../content/locale.js';
12
- import { AI_CRAWLER_POLICIES, robotsRuleLines, robotsRuleProblem } from './robots.js';
13
- import { taxonomyBaseProblems } from '../content/taxonomy.js';
14
- import { PACKAGED_THEME, readTheme, themeNameProblem } from '../theme/themes.js';
15
- import { EMAIL_PATTERN, isAiCrawlerPolicy, isContentSignalChoice, isLicenseChoice, isMailProvider, isPollCount, isValidTimezone, isWholeDays, normalizeBaseUrl, normalizeLanguageList, normalizeRelayInbox, normalizeSecurityContact, normalizeSecurityPolicy, relayLines, relayList, securityContactList, } from './setting-values.js';
16
- import { DEFAULT_SITE_SETTINGS } from './settings.js';
17
- const checkbox = (value) => (value ? '1' : '');
18
- const ticked = (value) => value !== '';
19
- const asIs = (value) => value;
20
- const lines = (value) => value.join('\n');
21
- const nothingWrong = () => undefined;
22
- function text(key, field, options = {}) {
23
- return {
24
- field,
25
- submitted: (form) => form[key].trim(),
26
- shown: asIs,
27
- check: options.check ?? nothingWrong,
28
- };
29
- }
30
- /** A checkbox, which submits nothing at all when it is clear. */
31
- function flag(key, field) {
32
- return {
33
- field,
34
- submitted: (form) => ticked(form[key]),
35
- shown: checkbox,
36
- check: nothingWrong,
37
- };
38
- }
39
- function choice(key, field, guard, fallback, problem) {
40
- return {
41
- field,
42
- submitted: (form) => (guard(form[key]) ? form[key] : fallback),
43
- shown: (value) => value,
44
- check: (form) => (guard(form[key]) ? undefined : problem),
45
- };
46
- }
47
- export function requiredWholeDays(typed) {
48
- const trimmed = typed.trim();
49
- if (trimmed === '')
50
- return undefined;
51
- const days = Number(trimmed);
52
- return isWholeDays(days) ? days : undefined;
53
- }
54
- function retention(key, field) {
55
- return {
56
- field,
57
- submitted: (form) => Number(form[key]),
58
- shown: String,
59
- check: (form) => requiredWholeDays(form[key]) === undefined
60
- ? 'Keep it for a whole number of days, or 0 to keep it forever.'
61
- : undefined,
62
- };
63
- }
64
- function contentSignal(key, field) {
65
- return choice(key, field, isContentSignalChoice, '', 'A content signal is yes, no, or not said.');
66
- }
67
- function list(key, field, parse, check) {
68
- return {
69
- field,
70
- submitted: (form) => parse(form[key]),
71
- shown: lines,
72
- check,
73
- };
74
- }
75
- const isCustomLicense = (form) => form.license.trim() === 'custom';
76
- const PAGE_SLUG_PATTERN = /^[A-Za-z0-9._~-]{1,200}$/;
77
- /** What is wrong with one page pick, or `undefined`. Empty is a value. */
78
- function slugProblem(value, what) {
79
- const slug = value.trim();
80
- return slug === '' || PAGE_SLUG_PATTERN.test(slug)
81
- ? undefined
82
- : `${what} is the slug of one of the site's pages, such as about.`;
83
- }
84
- function iconProblem(icon) {
85
- if (icon === '')
86
- return undefined;
87
- const parsed = parseIconSetting(icon);
88
- if (!('problem' in parsed))
89
- return undefined;
90
- return parsed.problem === 'not-an-upload'
91
- ? 'The site icon has to be a file in the media library, a path such as /uploads/2026/10/icon.png.'
92
- : 'The site icon has to be an image: PNG, JPEG, GIF, WebP, AVIF, TIFF or SVG.';
93
- }
94
- const ICON_UPLOADED = {
95
- dir: 'contentDir',
96
- problem: (icon, contentDir) => {
97
- const parsed = parseIconSetting(icon);
98
- if ('problem' in parsed)
99
- return undefined;
100
- const file = sourceFile({ contentDir }, parsed.source);
101
- return file !== undefined && isFileSync(file)
102
- ? undefined
103
- : `There is no upload at ${icon}. Upload the picture on the Media screen first.`;
104
- },
105
- };
106
- export function frontPageOf(form) {
107
- const homepage = form.homepage.trim();
108
- return { homepage, posts_page: homepage === '' ? '' : form.posts_page.trim() };
109
- }
110
- export function frontPageProblems(form) {
111
- const homepage = form.homepage.trim();
112
- return {
113
- homepage: slugProblem(homepage, 'A homepage'),
114
- posts_page: postsPageProblem(homepage, form.posts_page.trim()),
115
- };
116
- }
117
- function postsPageProblem(homepage, posts_page) {
118
- if (posts_page === '')
119
- return undefined;
120
- if (homepage === '') {
121
- return 'A posts page needs a homepage: pick the page the front page shows first.';
122
- }
123
- if (posts_page === homepage) {
124
- return 'The homepage and the posts page have to be two different pages.';
125
- }
126
- return slugProblem(posts_page, 'A posts page');
127
- }
128
- function frontPageRows() {
129
- const row = (key, field) => ({
130
- ...text(key, field),
131
- submitted: (form) => frontPageOf(form)[key],
132
- check: (form) => frontPageProblems(form)[key],
133
- });
134
- return { homepage: row('homepage', 'homepage'), posts_page: row('posts_page', 'posts_page') };
135
- }
136
- function emailCheck(key, problem) {
137
- return (form) => form[key].trim() !== '' && !EMAIL_PATTERN.test(form[key].trim()) ? problem : undefined;
138
- }
139
- const THEME_INSTALLED = {
140
- dir: 'themesDir',
141
- problem: (name, themesDir) => {
142
- if (name === PACKAGED_THEME)
143
- return undefined;
144
- const read = readTheme(path.join(themesDir, name));
145
- return read.ok ? undefined : `There is no theme called "${name}": ${read.reason}`;
146
- },
147
- };
148
- const SETTING_ROWS = {
149
- title: text('title', 'title', {
150
- check: (form) => (form.title.trim() === '' ? 'The site needs a title.' : undefined),
151
- }),
152
- tagline: text('tagline', 'tagline'),
153
- base_url: {
154
- field: 'base_url',
155
- submitted: (form) => normalizeBaseUrl(form.base_url) ?? '',
156
- shown: asIs,
157
- check: (form) => normalizeBaseUrl(form.base_url) === undefined
158
- ? 'The base URL has to be an absolute http:// or https:// URL.'
159
- : undefined,
160
- },
161
- posts_per_page: {
162
- field: 'posts_per_page',
163
- submitted: (form) => Number(form.posts_per_page),
164
- shown: String,
165
- check: (form) => {
166
- const perPage = Number(form.posts_per_page);
167
- return !Number.isInteger(perPage) || perPage < 1
168
- ? 'Posts per page has to be a whole number of one or more.'
169
- : undefined;
170
- },
171
- },
172
- timezone: text('timezone', 'timezone', {
173
- check: (form) => isValidTimezone(form.timezone)
174
- ? undefined
175
- : 'That is not an IANA time zone name, such as Europe/London.',
176
- }),
177
- language: text('language', 'language', {
178
- check: (form) => LANGUAGE_TAG_PATTERN.test(form.language.trim())
179
- ? undefined
180
- : 'That is not a language tag, such as en, en-GB or pt-BR.',
181
- }),
182
- // The two archive bases are checked as a pair, because two of the rules —
183
- // that they differ, and that neither takes a path the site already answers
184
- // on — are about the pair rather than either one. They are on one page for
185
- // exactly that reason.
186
- tag_base: text('tag_base', 'tag_base', {
187
- check: (form) => taxonomyBaseProblems({ tag: form.tag_base, category: form.category_base }).tag,
188
- }),
189
- category_base: text('category_base', 'category_base', {
190
- check: (form) => taxonomyBaseProblems({ tag: form.tag_base, category: form.category_base }).category,
191
- }),
192
- comments: flag('comments', 'comments'),
193
- // The empty string is refused rather than read as zero, which is what
194
- // `Number('')` would make it: a cleared field is a mistake, and "never close
195
- // comments" should have to be typed.
196
- comments_close_after_days: {
197
- field: 'comments_close_after_days',
198
- submitted: (form) => Number(form.comments_close_after_days),
199
- shown: String,
200
- check: (form) => {
201
- const typed = form.comments_close_after_days.trim();
202
- const days = Number(typed);
203
- return typed === '' || !Number.isInteger(days) || days < 0
204
- ? 'Comments close after a whole number of days, or 0 for never.'
205
- : undefined;
206
- },
207
- },
208
- comment_email_retention_days: retention('comment_email_retention_days', 'comment_email_retention_days'),
209
- address_hash_retention_days: retention('address_hash_retention_days', 'address_hash_retention_days'),
210
- contact_message_retention_days: retention('contact_message_retention_days', 'contact_message_retention_days'),
211
- webmentions_send: flag('webmentions_send', 'webmentions_send'),
212
- webmentions_receive: flag('webmentions_receive', 'webmentions_receive'),
213
- // Empty is a value here — it is how a site turns real-time notification off
214
- // — so only a non-empty one has to be a URL. http as well as https, because
215
- // a notify server on a private network or a loopback port is a real one.
216
- notify_server: {
217
- ...text('notify_server', 'notify_server'),
218
- submitted: (form) => normalizeBaseUrl(form.notify_server) ?? '',
219
- check: (form) => form.notify_server.trim() !== '' && normalizeBaseUrl(form.notify_server) === undefined
220
- ? 'A notify server is an absolute http:// or https:// URL, or empty for none.'
221
- : undefined,
222
- },
223
- feed_update_period: choice('feed_update_period', 'feed_update_period', isUpdatePeriod, DEFAULT_FEED_CADENCE.period, `An update period is one of ${UPDATE_PERIODS.join(', ')}.`),
224
- feed_update_frequency: {
225
- field: 'feed_update_frequency',
226
- submitted: (form) => Number(form.feed_update_frequency),
227
- shown: String,
228
- check: (form) => form.feed_update_frequency.trim() !== '' && isPollCount(Number(form.feed_update_frequency))
229
- ? undefined
230
- : 'Polls per period is a whole number, 1 or more.',
231
- },
232
- ai_crawlers: choice('ai_crawlers', 'ai_crawlers', isAiCrawlerPolicy, 'allow', `An AI-crawler policy is one of ${AI_CRAWLER_POLICIES.join(', ')}.`),
233
- content_signal_search: contentSignal('content_signal_search', 'content_signal_search'),
234
- content_signal_ai_input: contentSignal('content_signal_ai_input', 'content_signal_ai_input'),
235
- content_signal_ai_train: contentSignal('content_signal_ai_train', 'content_signal_ai_train'),
236
- robots_rules: list('robots_rules', 'robots_rules', (typed) => robotsRuleLines([typed]), (form) => robotsRuleProblem([form.robots_rules])),
237
- llms_txt: flag('llms_txt', 'llms_txt'),
238
- index_now: flag('index_now', 'index_now'),
239
- mail_provider: choice('mail_provider', 'mail_provider', isMailProvider, 'none', `A mail provider is one of ${MAIL_PROVIDERS.join(', ')}.`),
240
- mail_from_name: text('mail_from_name', 'mail_from_name'),
241
- mail_from_address: text('mail_from_address', 'mail_from_address', {
242
- check: emailCheck('mail_from_address', 'A From address is an email address, such as blog@example.com, or empty for the default.'),
243
- }),
244
- mail_reply_to: text('mail_reply_to', 'mail_reply_to', {
245
- check: emailCheck('mail_reply_to', 'A reply-to is an email address, such as hello@example.com, or empty to reply to the From address.'),
246
- }),
247
- contact_email: text('contact_email', 'contact_email', {
248
- check: emailCheck('contact_email', 'A contact address is an email address, such as hello@example.com, or empty for the first admin with one.'),
249
- }),
250
- // These three are printed line by line into security.txt, so a hand edit
251
- // with a line break in it must not become a field nobody set.
252
- security_contacts: list('security_contacts', 'security_contacts', securityContactList, (form) => {
253
- const bad = relayLines(form.security_contacts).find((line) => normalizeSecurityContact(line) === undefined);
254
- return bad === undefined
255
- ? undefined
256
- : 'A security contact is an email address, an https:// URL or a tel: number, one per line. ' +
257
- `"${bad}" is not one.`;
258
- }),
259
- // RFC 9116 wants every web URI in the file to be https.
260
- security_policy: {
261
- ...text('security_policy', 'security_policy'),
262
- submitted: (form) => normalizeSecurityPolicy(form.security_policy) ?? '',
263
- check: (form) => form.security_policy.trim() !== '' &&
264
- normalizeSecurityPolicy(form.security_policy) === undefined
265
- ? 'A security policy is an https:// URL, or empty for none.'
266
- : undefined,
267
- },
268
- security_languages: {
269
- ...text('security_languages', 'security_languages'),
270
- submitted: (form) => normalizeLanguageList(form.security_languages) ?? '',
271
- check: (form) => normalizeLanguageList(form.security_languages) === undefined
272
- ? 'Preferred languages are language tags separated by commas, such as en, fr, or empty for none.'
273
- : undefined,
274
- },
275
- relays: list('relays', 'relays', relayList, (form) => {
276
- const bad = relayLines(form.relays).find((line) => normalizeRelayInbox(line) === undefined);
277
- return bad === undefined
278
- ? undefined
279
- : `A relay is its inbox as an absolute http:// or https:// URL, one per line. ` +
280
- `"${bad}" is not one.`;
281
- }),
282
- location_sharing: choice('location_sharing', 'location_sharing', isLocationSharing, 'none', `Location sharing is one of ${LOCATION_SHARING.join(', ')}.`),
283
- menus: { submitted: (_form, onFile) => onFile.menus ?? DEFAULT_SITE_SETTINGS.menus },
284
- taxonomy_redirects: {
285
- submitted: (_form, onFile) => onFile.taxonomy_redirects ?? DEFAULT_SITE_SETTINGS.taxonomy_redirects,
286
- },
287
- ...frontPageRows(),
288
- theme: {
289
- ...text('theme', 'theme', { check: (form) => themeNameProblem(form.theme) }),
290
- onDisk: THEME_INSTALLED,
291
- },
292
- locale: text('locale', 'locale', {
293
- check: (form) => {
294
- const locale = form.locale.trim();
295
- return locale === '' ||
296
- (LANGUAGE_TAG_PATTERN.test(locale) && canonicalLocale(locale) !== undefined)
297
- ? undefined
298
- : 'That is not a locale, such as en-US, fr-CA or pt-BR, or empty for the language.';
299
- },
300
- }),
301
- author: text('author', 'author'),
302
- icon: {
303
- ...text('icon', 'icon', { check: (form) => iconProblem(form.icon.trim()) }),
304
- onDisk: ICON_UPLOADED,
305
- },
306
- avatar: { submitted: (_form, onFile) => onFile.avatar ?? DEFAULT_SITE_SETTINGS.avatar },
307
- license: {
308
- field: 'license',
309
- submitted: (form) => {
310
- const choice = form.license.trim();
311
- if (!isLicenseChoice(choice) || choice === '')
312
- return DEFAULT_SITE_SETTINGS.license;
313
- return choice === 'custom'
314
- ? { choice, url: form.license_url.trim(), name: form.license_name.trim() }
315
- : { choice, url: '', name: '' };
316
- },
317
- shown: (value) => value.choice,
318
- check: (form) => isLicenseChoice(form.license.trim()) ? undefined : 'Choose a license from the list.',
319
- },
320
- index_now_key: {
321
- submitted: (form, onFile) => onFile.index_now_key !== undefined && onFile.index_now_key !== ''
322
- ? onFile.index_now_key
323
- : ticked(form.index_now)
324
- ? generateIndexNowKey()
325
- : '',
326
- },
327
- clients_without_pkce: {
328
- submitted: (_form, onFile) => onFile.clients_without_pkce ?? DEFAULT_SITE_SETTINGS.clients_without_pkce,
329
- },
330
- };
331
- const LICENSE_FIELD_ROWS = {
332
- license_url: {
333
- field: 'license_url',
334
- shown: (value) => value.url,
335
- check: (form) => isCustomLicense(form) && !isLicenseUrl(form.license_url.trim())
336
- ? 'A custom license needs the URL of its terms, starting http:// or https://.'
337
- : undefined,
338
- },
339
- license_name: {
340
- field: 'license_name',
341
- shown: (value) => value.name,
342
- check: (form) => isCustomLicense(form) && form.license_name.trim() === ''
343
- ? 'A custom license needs a name for the footer to show.'
344
- : undefined,
345
- },
346
- };
347
- export const ROWS = SETTING_ROWS;
348
- export const FORM_ROWS = {
349
- ...SETTING_ROWS,
350
- ...LICENSE_FIELD_ROWS,
351
- };
352
- export const SETTING_KEYS = Object.keys(SETTING_ROWS);
353
- function isFormKey(key) {
354
- return 'field' in SETTING_ROWS[key];
355
- }
356
- export const SETTINGS_FIELD_NAMES = [
357
- ...SETTING_KEYS.filter(isFormKey),
358
- 'license_url',
359
- 'license_name',
360
- ];
361
- //# sourceMappingURL=setting-rows.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"setting-rows.js","sourceRoot":"","sources":["../../src/site/setting-rows.ts"],"names":[],"mappings":"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"}
@@ -1,30 +0,0 @@
1
- import type { CarriedSettings, SettingsContext, SettingsField, SettingsForm } from './setting-rows.ts';
2
- import type { SiteSettings } from './settings.ts';
3
- export { SETTINGS_FIELD_NAMES } from './setting-rows.ts';
4
- export type { CarriedSettings, SettingsContext, SettingsField, SettingsForm, } from './setting-rows.ts';
5
- /** One message per field that is wrong. An empty object is a valid form. */
6
- export type SettingsProblems = Partial<Record<SettingsField, string>>;
7
- /** The form field each setting is submitted under. */
8
- export declare const SETTINGS_FIELDS: Readonly<Record<SettingsField, string>>;
9
- /**
10
- * What is wrong with a submitted settings form, one message per field.
11
- *
12
- * `fields` is what a page carries: it validates its own fields and says
13
- * nothing about the rest, so a page cannot refuse a save over a field it does
14
- * not show and gives no way to fix. `context` names the directories the
15
- * on-disk checks read, and an on-disk check runs only when its directory is
16
- * named.
17
- */
18
- export declare function settingsProblems(form: SettingsForm, fields?: readonly SettingsField[], context?: SettingsContext): SettingsProblems;
19
- /**
20
- * A validated form as settings. Only call it on a form
21
- * {@link settingsProblems} found nothing wrong with.
22
- *
23
- * The settings no form carries are passed in rather than read off the form:
24
- * a save of the fields that are on the form keeps whatever is stored, so
25
- * passing the settings read inside the write is all a caller has to do.
26
- */
27
- export declare function settingsFromForm(form: SettingsForm, carriedOnFile?: CarriedSettings): SiteSettings;
28
- /** The settings as the form shows them. */
29
- export declare function formFromSettings(settings: SiteSettings): SettingsForm;
30
- //# sourceMappingURL=settings-form.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"settings-form.d.ts","sourceRoot":"","sources":["../../src/site/settings-form.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,eAAe,EAEf,eAAe,EACf,aAAa,EACb,YAAY,EACb,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,YAAY,EACV,eAAe,EACf,eAAe,EACf,aAAa,EACb,YAAY,GACb,MAAM,mBAAmB,CAAC;AAE3B,4EAA4E;AAC5E,MAAM,MAAM,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC;AAStE,sDAAsD;AACtD,eAAO,MAAM,eAAe,EAAE,QAAQ,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAEnE,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,YAAY,EAClB,MAAM,GAAE,SAAS,aAAa,EAAyB,EACvD,OAAO,GAAE,eAAoB,GAC5B,gBAAgB,CASlB;AAaD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,YAAY,EAClB,aAAa,GAAE,eAAoB,GAClC,YAAY,CAId;AAWD,2CAA2C;AAC3C,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,YAAY,GAAG,YAAY,CAErE"}
@@ -1,54 +0,0 @@
1
- import { FORM_ROWS, ROWS, SETTING_KEYS, SETTINGS_FIELD_NAMES } from './setting-rows.js';
2
- export { SETTINGS_FIELD_NAMES } from './setting-rows.js';
3
- function perField(value) {
4
- return Object.fromEntries(SETTINGS_FIELD_NAMES.map((name) => [name, value(name)]));
5
- }
6
- /** The form field each setting is submitted under. */
7
- export const SETTINGS_FIELDS = perField((name) => FORM_ROWS[name].field);
8
- /**
9
- * What is wrong with a submitted settings form, one message per field.
10
- *
11
- * `fields` is what a page carries: it validates its own fields and says
12
- * nothing about the rest, so a page cannot refuse a save over a field it does
13
- * not show and gives no way to fix. `context` names the directories the
14
- * on-disk checks read, and an on-disk check runs only when its directory is
15
- * named.
16
- */
17
- export function settingsProblems(form, fields = SETTINGS_FIELD_NAMES, context = {}) {
18
- const problems = {};
19
- for (const name of fields) {
20
- const problem = FORM_ROWS[name].check(form) ?? onDiskProblem(name, form, context);
21
- if (problem !== undefined)
22
- problems[name] = problem;
23
- }
24
- return problems;
25
- }
26
- function onDiskProblem(name, form, context) {
27
- const onDisk = FORM_ROWS[name].onDisk;
28
- if (onDisk === undefined)
29
- return undefined;
30
- const dir = context[onDisk.dir];
31
- return dir === undefined ? undefined : onDisk.problem(form[name].trim(), dir);
32
- }
33
- /**
34
- * A validated form as settings. Only call it on a form
35
- * {@link settingsProblems} found nothing wrong with.
36
- *
37
- * The settings no form carries are passed in rather than read off the form:
38
- * a save of the fields that are on the form keeps whatever is stored, so
39
- * passing the settings read inside the write is all a caller has to do.
40
- */
41
- export function settingsFromForm(form, carriedOnFile = {}) {
42
- return Object.fromEntries(SETTING_KEYS.map((key) => [key, ROWS[key].submitted(form, carriedOnFile)]));
43
- }
44
- function shownSetting(settings, name) {
45
- const value = (name === 'license_url' || name === 'license_name'
46
- ? settings.license
47
- : settings[name]);
48
- return FORM_ROWS[name].shown(value);
49
- }
50
- /** The settings as the form shows them. */
51
- export function formFromSettings(settings) {
52
- return perField((name) => shownSetting(settings, name));
53
- }
54
- //# sourceMappingURL=settings-form.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"settings-form.js","sourceRoot":"","sources":["../../src/site/settings-form.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAUxF,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAWzD,SAAS,QAAQ,CAAI,KAAiC;IACpD,OAAO,MAAM,CAAC,WAAW,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAGhF,CAAC;AACJ,CAAC;AAED,sDAAsD;AACtD,MAAM,CAAC,MAAM,eAAe,GAA4C,QAAQ,CAC9E,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,KAAK,CAChC,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,UAAU,gBAAgB,CAC9B,IAAkB,EAClB,MAAM,GAA6B,oBAAoB,EACvD,OAAO,GAAoB,EAAE;IAE7B,MAAM,QAAQ,GAAqB,EAAE,CAAC;IAEtC,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;QAC1B,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QAClF,IAAI,OAAO,KAAK,SAAS;YAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC;IACtD,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,aAAa,CACpB,IAAmB,EACnB,IAAkB,EAClB,OAAwB;IAExB,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;IACtC,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC3C,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAChC,OAAO,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC;AAChF,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAC9B,IAAkB,EAClB,aAAa,GAAoB,EAAE;IAEnC,OAAO,MAAM,CAAC,WAAW,CACvB,YAAY,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC,CAC3D,CAAC;AACpB,CAAC;AAED,SAAS,YAAY,CAA0B,QAAsB,EAAE,IAAO;IAC5E,MAAM,KAAK,GAAG,CACZ,IAAI,KAAK,aAAa,IAAI,IAAI,KAAK,cAAc;QAC/C,CAAC,CAAC,QAAQ,CAAC,OAAO;QAClB,CAAC,CAAC,QAAQ,CAAC,IAA0B,CAAC,CACxB,CAAC;IACnB,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AACtC,CAAC;AAED,2CAA2C;AAC3C,MAAM,UAAU,gBAAgB,CAAC,QAAsB;IACrD,OAAO,QAAQ,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC;AAC1D,CAAC"}
@@ -1,38 +0,0 @@
1
- import type { SiteSettings } from './settings.ts';
2
- export declare function parseSiteJson(source: string): Record<string, unknown>;
3
- /** The absolute path of one site's `content/_data/site.json`. */
4
- export declare function siteDataPath(contentDir: string): string;
5
- export declare function settingsFromSiteJson(file: Record<string, unknown>): SiteSettings;
6
- export declare function siteJsonFor(settings: SiteSettings, existing?: Record<string, unknown>): Record<string, unknown>;
7
- /** The bytes of one settings object, as the file holds them. */
8
- export declare function siteJsonText(settings: SiteSettings, existing: Record<string, unknown>): string;
9
- /**
10
- * Rewrite `content/_data/site.json` as these settings, keeping the keys they
11
- * do not model.
12
- *
13
- * {@link updateSiteSettings} for a caller whose new settings depend on the old
14
- * ones, which every screen's is: this is for the callers that have the whole
15
- * object already, a test's set-up among them.
16
- */
17
- export declare function writeSiteJson(options: {
18
- contentDir: string;
19
- settings: SiteSettings;
20
- }): Promise<void>;
21
- /**
22
- * Change the settings: re-read the file, apply the change, write it back, with
23
- * nothing able to write that file in between ({@link updateFileAtomically}).
24
- *
25
- * The re-read is what makes the file win the way it wins for a post
26
- * (decision-9). Two people with the settings screen open both save what they
27
- * see, and the second save is applied to what the first one actually wrote
28
- * rather than to what the second one had on screen — so a change to a field
29
- * the second person did not touch survives. The write is a temporary file and
30
- * a rename, so a reader — an Eleventy build, the site data source, another
31
- * process entirely — never sees a half-written file. Keys the settings do not
32
- * model, `feedSize` and anything a site added, are kept.
33
- */
34
- export declare function updateSiteSettings(options: {
35
- contentDir: string;
36
- change: (current: SiteSettings) => SiteSettings;
37
- }): Promise<SiteSettings>;
38
- //# sourceMappingURL=site-json.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"site-json.d.ts","sourceRoot":"","sources":["../../src/site/site-json.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAIlD,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQrE;AAED,iEAAiE;AACjE,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,YAAY,CAEhF;AAED,wBAAgB,WAAW,CACzB,QAAQ,EAAE,YAAY,EACtB,QAAQ,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GACrC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAIzB;AAED,gEAAgE;AAChE,wBAAgB,YAAY,CAAC,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAE9F;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE;IAC3C,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,YAAY,CAAC;CACxB,GAAG,OAAO,CAAC,IAAI,CAAC,CAEhB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE;IAChD,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,YAAY,CAAC;CACjD,GAAG,OAAO,CAAC,YAAY,CAAC,CAUxB"}
@@ -1,69 +0,0 @@
1
- import path from 'node:path';
2
- import { updateFileAtomically } from '../files/atomic.js';
3
- import { fileWith, storedValues } from '../settings/registry.js';
4
- import { isRecord } from '../util/guards.js';
5
- import { SITE_DATA_FILE } from '../theme/site-data.js';
6
- import { SITE } from './namespace.js';
7
- import { DEFAULT_SITE_SETTINGS } from './settings.js';
8
- const RETIRED_KEYS = ['navigation', 'soloAuthor'];
9
- export function parseSiteJson(source) {
10
- let parsed;
11
- try {
12
- parsed = JSON.parse(source);
13
- }
14
- catch {
15
- return {};
16
- }
17
- return isRecord(parsed) ? parsed : {};
18
- }
19
- /** The absolute path of one site's `content/_data/site.json`. */
20
- export function siteDataPath(contentDir) {
21
- return path.join(contentDir, ...SITE_DATA_FILE.split('/'));
22
- }
23
- export function settingsFromSiteJson(file) {
24
- return storedValues(SITE, file);
25
- }
26
- export function siteJsonFor(settings, existing = {}) {
27
- const file = fileWith(SITE, settings, existing);
28
- for (const key of RETIRED_KEYS)
29
- delete file[key];
30
- return file;
31
- }
32
- /** The bytes of one settings object, as the file holds them. */
33
- export function siteJsonText(settings, existing) {
34
- return `${JSON.stringify(siteJsonFor(settings, existing), null, 2)}\n`;
35
- }
36
- /**
37
- * Rewrite `content/_data/site.json` as these settings, keeping the keys they
38
- * do not model.
39
- *
40
- * {@link updateSiteSettings} for a caller whose new settings depend on the old
41
- * ones, which every screen's is: this is for the callers that have the whole
42
- * object already, a test's set-up among them.
43
- */
44
- export async function writeSiteJson(options) {
45
- await updateSiteSettings({ contentDir: options.contentDir, change: () => options.settings });
46
- }
47
- /**
48
- * Change the settings: re-read the file, apply the change, write it back, with
49
- * nothing able to write that file in between ({@link updateFileAtomically}).
50
- *
51
- * The re-read is what makes the file win the way it wins for a post
52
- * (decision-9). Two people with the settings screen open both save what they
53
- * see, and the second save is applied to what the first one actually wrote
54
- * rather than to what the second one had on screen — so a change to a field
55
- * the second person did not touch survives. The write is a temporary file and
56
- * a rename, so a reader — an Eleventy build, the site data source, another
57
- * process entirely — never sees a half-written file. Keys the settings do not
58
- * model, `feedSize` and anything a site added, are kept.
59
- */
60
- export async function updateSiteSettings(options) {
61
- let written = DEFAULT_SITE_SETTINGS;
62
- await updateFileAtomically(siteDataPath(options.contentDir), (current) => {
63
- const existing = parseSiteJson(current ?? '');
64
- written = options.change(settingsFromSiteJson(existing));
65
- return siteJsonText(written, existing);
66
- });
67
- return written;
68
- }
69
- //# sourceMappingURL=site-json.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"site-json.js","sourceRoot":"","sources":["../../src/site/site-json.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAGtD,MAAM,YAAY,GAAG,CAAC,YAAY,EAAE,YAAY,CAAU,CAAC;AAE3D,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;AACxC,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,YAAY,CAAC,UAAkB;IAC7C,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,cAAc,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,IAA6B;IAChE,OAAO,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,WAAW,CACzB,QAAsB,EACtB,QAAQ,GAA4B,EAAE;IAEtC,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAChD,KAAK,MAAM,GAAG,IAAI,YAAY;QAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;IACjD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,YAAY,CAAC,QAAsB,EAAE,QAAiC;IACpF,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;AACzE,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAGnC;IACC,MAAM,kBAAkB,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;AAC/F,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,OAGxC;IACC,IAAI,OAAO,GAAG,qBAAqB,CAAC;IAEpC,MAAM,oBAAoB,CAAC,YAAY,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE;QACvE,MAAM,QAAQ,GAAG,aAAa,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;QAC9C,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC,CAAC;QACzD,OAAO,YAAY,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -1,37 +0,0 @@
1
- import type { Hono } from 'hono';
2
- import type { GeekityEnv } from '../web/env.ts';
3
- /**
4
- * The one public endpoint webmentions add.
5
- *
6
- * A single path under `/_geekity/`, like the comment form's, so it is out of
7
- * the way of every permalink a site might ever mint and the route table does
8
- * not grow with the site. It is what the `Link` header and the `<link>` in
9
- * every post's head point at, and it takes nothing but a form with a `source`
10
- * and a `target` in it.
11
- */
12
- /** Where a webmention is sent. */
13
- export declare const WEBMENTION_PATH = "/_geekity/webmention";
14
- /** The fields a webmention carries, which the spec fixes. */
15
- export declare const WEBMENTION_FIELDS: {
16
- readonly source: 'source';
17
- readonly target: 'target';
18
- };
19
- /**
20
- * The endpoint a page should advertise, or `undefined` when the site is not
21
- * taking webmentions.
22
- *
23
- * Read off the site data the renderer already has rather than the settings, so
24
- * a template asks one question and gets the same answer the endpoint gives.
25
- * A file that does not mention the setting is a site that takes them: that is
26
- * the default, and an older `site.json` should not quietly stop.
27
- */
28
- export declare function webmentionEndpointFor(site: Record<string, unknown>): string | undefined;
29
- /**
30
- * Register the webmention endpoint. Mounted by the public site.
31
- *
32
- * The answer is a 202 for anything worth going and looking at and a 400 for
33
- * anything that is not, and the looking happens afterwards — see
34
- * `receive.ts` for why that split is the whole design.
35
- */
36
- export declare function mountWebmentions(app: Hono<GeekityEnv>): void;
37
- //# sourceMappingURL=routes.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/webmention/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAGjC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAOhD;;;;;;;;GAQG;AAEH,kCAAkC;AAClC,eAAO,MAAM,eAAe,yBAAyB,CAAC;AAEtD,6DAA6D;AAC7D,eAAO,MAAM,iBAAiB;aAAK,MAAM,EAAE,QAAQ;aAAE,MAAM,EAAE,QAAQ;CAAW,CAAC;AAEjF;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,GAAG,SAAS,CAEvF;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,IAAI,CAAC,UAAU,CAAC,GAAG,IAAI,CA4C5D"}