@geekity/cms 0.3.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/LICENSE +21 -0
- package/README.md +870 -0
- package/admin/layouts/_flash.njk +5 -0
- package/admin/layouts/base.njk +27 -0
- package/admin/layouts/dashboard.njk +78 -0
- package/admin/layouts/document-conflict.njk +49 -0
- package/admin/layouts/document-editor.njk +167 -0
- package/admin/layouts/document-list.njk +92 -0
- package/admin/layouts/federation.njk +145 -0
- package/admin/layouts/login.njk +23 -0
- package/admin/layouts/placeholder.njk +10 -0
- package/admin/layouts/settings.njk +116 -0
- package/admin/layouts/setup.njk +27 -0
- package/admin/layouts/shell.njk +37 -0
- package/admin/layouts/users.njk +91 -0
- package/admin/static/admin.css +726 -0
- package/admin/static/editor.js +30 -0
- package/dist/admin/assets.d.ts +26 -0
- package/dist/admin/assets.d.ts.map +1 -0
- package/dist/admin/assets.js +38 -0
- package/dist/admin/assets.js.map +1 -0
- package/dist/admin/credentials.d.ts +28 -0
- package/dist/admin/credentials.d.ts.map +1 -0
- package/dist/admin/credentials.js +39 -0
- package/dist/admin/credentials.js.map +1 -0
- package/dist/admin/documents.d.ts +134 -0
- package/dist/admin/documents.d.ts.map +1 -0
- package/dist/admin/documents.js +613 -0
- package/dist/admin/documents.js.map +1 -0
- package/dist/admin/federation.d.ts +194 -0
- package/dist/admin/federation.d.ts.map +1 -0
- package/dist/admin/federation.js +299 -0
- package/dist/admin/federation.js.map +1 -0
- package/dist/admin/flash.d.ts +24 -0
- package/dist/admin/flash.d.ts.map +1 -0
- package/dist/admin/flash.js +31 -0
- package/dist/admin/flash.js.map +1 -0
- package/dist/admin/index.d.ts +23 -0
- package/dist/admin/index.d.ts.map +1 -0
- package/dist/admin/index.js +15 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/admin/passwords.d.ts +49 -0
- package/dist/admin/passwords.d.ts.map +1 -0
- package/dist/admin/passwords.js +122 -0
- package/dist/admin/passwords.js.map +1 -0
- package/dist/admin/preview.d.ts +18 -0
- package/dist/admin/preview.d.ts.map +1 -0
- package/dist/admin/preview.js +83 -0
- package/dist/admin/preview.js.map +1 -0
- package/dist/admin/routes.d.ts +54 -0
- package/dist/admin/routes.d.ts.map +1 -0
- package/dist/admin/routes.js +383 -0
- package/dist/admin/routes.js.map +1 -0
- package/dist/admin/session.d.ts +44 -0
- package/dist/admin/session.d.ts.map +1 -0
- package/dist/admin/session.js +69 -0
- package/dist/admin/session.js.map +1 -0
- package/dist/admin/settings.d.ts +194 -0
- package/dist/admin/settings.d.ts.map +1 -0
- package/dist/admin/settings.js +470 -0
- package/dist/admin/settings.js.map +1 -0
- package/dist/admin/store.d.ts +407 -0
- package/dist/admin/store.d.ts.map +1 -0
- package/dist/admin/store.js +704 -0
- package/dist/admin/store.js.map +1 -0
- package/dist/admin/templates.d.ts +36 -0
- package/dist/admin/templates.d.ts.map +1 -0
- package/dist/admin/templates.js +43 -0
- package/dist/admin/templates.js.map +1 -0
- package/dist/admin/uploads.d.ts +96 -0
- package/dist/admin/uploads.d.ts.map +1 -0
- package/dist/admin/uploads.js +179 -0
- package/dist/admin/uploads.js.map +1 -0
- package/dist/admin/users.d.ts +95 -0
- package/dist/admin/users.d.ts.map +1 -0
- package/dist/admin/users.js +233 -0
- package/dist/admin/users.js.map +1 -0
- package/dist/cli.d.ts +85 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +424 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +172 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +184 -0
- package/dist/config.js.map +1 -0
- package/dist/content/document.d.ts +66 -0
- package/dist/content/document.d.ts.map +1 -0
- package/dist/content/document.js +13 -0
- package/dist/content/document.js.map +1 -0
- package/dist/content/index.d.ts +17 -0
- package/dist/content/index.d.ts.map +1 -0
- package/dist/content/index.js +10 -0
- package/dist/content/index.js.map +1 -0
- package/dist/content/markdown.d.ts +3 -0
- package/dist/content/markdown.d.ts.map +1 -0
- package/dist/content/markdown.js +39 -0
- package/dist/content/markdown.js.map +1 -0
- package/dist/content/media.d.ts +65 -0
- package/dist/content/media.d.ts.map +1 -0
- package/dist/content/media.js +143 -0
- package/dist/content/media.js.map +1 -0
- package/dist/content/parser.d.ts +24 -0
- package/dist/content/parser.d.ts.map +1 -0
- package/dist/content/parser.js +165 -0
- package/dist/content/parser.js.map +1 -0
- package/dist/content/save.d.ts +60 -0
- package/dist/content/save.d.ts.map +1 -0
- package/dist/content/save.js +103 -0
- package/dist/content/save.js.map +1 -0
- package/dist/content/slug.d.ts +25 -0
- package/dist/content/slug.d.ts.map +1 -0
- package/dist/content/slug.js +75 -0
- package/dist/content/slug.js.map +1 -0
- package/dist/content/store.d.ts +133 -0
- package/dist/content/store.d.ts.map +1 -0
- package/dist/content/store.js +411 -0
- package/dist/content/store.js.map +1 -0
- package/dist/content/sync.d.ts +146 -0
- package/dist/content/sync.d.ts.map +1 -0
- package/dist/content/sync.js +421 -0
- package/dist/content/sync.js.map +1 -0
- package/dist/content/writer.d.ts +37 -0
- package/dist/content/writer.d.ts.map +1 -0
- package/dist/content/writer.js +97 -0
- package/dist/content/writer.js.map +1 -0
- package/dist/env.d.ts +48 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +2 -0
- package/dist/env.js.map +1 -0
- package/dist/federation/actor.d.ts +55 -0
- package/dist/federation/actor.d.ts.map +1 -0
- package/dist/federation/actor.js +101 -0
- package/dist/federation/actor.js.map +1 -0
- package/dist/federation/article.d.ts +83 -0
- package/dist/federation/article.d.ts.map +1 -0
- package/dist/federation/article.js +169 -0
- package/dist/federation/article.js.map +1 -0
- package/dist/federation/delivery.d.ts +90 -0
- package/dist/federation/delivery.d.ts.map +1 -0
- package/dist/federation/delivery.js +289 -0
- package/dist/federation/delivery.js.map +1 -0
- package/dist/federation/federation.d.ts +75 -0
- package/dist/federation/federation.d.ts.map +1 -0
- package/dist/federation/federation.js +190 -0
- package/dist/federation/federation.js.map +1 -0
- package/dist/federation/followers.d.ts +43 -0
- package/dist/federation/followers.d.ts.map +1 -0
- package/dist/federation/followers.js +69 -0
- package/dist/federation/followers.js.map +1 -0
- package/dist/federation/inbox.d.ts +68 -0
- package/dist/federation/inbox.d.ts.map +1 -0
- package/dist/federation/inbox.js +171 -0
- package/dist/federation/inbox.js.map +1 -0
- package/dist/federation/index.d.ts +14 -0
- package/dist/federation/index.d.ts.map +1 -0
- package/dist/federation/index.js +10 -0
- package/dist/federation/index.js.map +1 -0
- package/dist/federation/keys.d.ts +27 -0
- package/dist/federation/keys.d.ts.map +1 -0
- package/dist/federation/keys.js +60 -0
- package/dist/federation/keys.js.map +1 -0
- package/dist/federation/mount.d.ts +23 -0
- package/dist/federation/mount.d.ts.map +1 -0
- package/dist/federation/mount.js +71 -0
- package/dist/federation/mount.js.map +1 -0
- package/dist/federation/paths.d.ts +85 -0
- package/dist/federation/paths.d.ts.map +1 -0
- package/dist/federation/paths.js +97 -0
- package/dist/federation/paths.js.map +1 -0
- package/dist/index.d.ts +106 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +148 -0
- package/dist/index.js.map +1 -0
- package/dist/init.d.ts +71 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.js +125 -0
- package/dist/init.js.map +1 -0
- package/dist/web/assets.d.ts +65 -0
- package/dist/web/assets.d.ts.map +1 -0
- package/dist/web/assets.js +152 -0
- package/dist/web/assets.js.map +1 -0
- package/dist/web/context.d.ts +121 -0
- package/dist/web/context.d.ts.map +1 -0
- package/dist/web/context.js +112 -0
- package/dist/web/context.js.map +1 -0
- package/dist/web/documents.d.ts +28 -0
- package/dist/web/documents.d.ts.map +1 -0
- package/dist/web/documents.js +39 -0
- package/dist/web/documents.js.map +1 -0
- package/dist/web/feeds.d.ts +122 -0
- package/dist/web/feeds.d.ts.map +1 -0
- package/dist/web/feeds.js +229 -0
- package/dist/web/feeds.js.map +1 -0
- package/dist/web/index.d.ts +17 -0
- package/dist/web/index.d.ts.map +1 -0
- package/dist/web/index.js +10 -0
- package/dist/web/index.js.map +1 -0
- package/dist/web/negotiate.d.ts +219 -0
- package/dist/web/negotiate.d.ts.map +1 -0
- package/dist/web/negotiate.js +409 -0
- package/dist/web/negotiate.js.map +1 -0
- package/dist/web/pagination.d.ts +48 -0
- package/dist/web/pagination.d.ts.map +1 -0
- package/dist/web/pagination.js +30 -0
- package/dist/web/pagination.js.map +1 -0
- package/dist/web/render.d.ts +72 -0
- package/dist/web/render.d.ts.map +1 -0
- package/dist/web/render.js +73 -0
- package/dist/web/render.js.map +1 -0
- package/dist/web/routes.d.ts +31 -0
- package/dist/web/routes.d.ts.map +1 -0
- package/dist/web/routes.js +366 -0
- package/dist/web/routes.js.map +1 -0
- package/dist/web/templates.d.ts +34 -0
- package/dist/web/templates.d.ts.map +1 -0
- package/dist/web/templates.js +106 -0
- package/dist/web/templates.js.map +1 -0
- package/package.json +68 -0
- package/templates/site/content/_data/site.json +8 -0
- package/templates/site/content/pages/about.md +11 -0
- package/templates/site/content/pages/pages.json +3 -0
- package/templates/site/content/posts/2026-01-01-hello-world.md +34 -0
- package/templates/site/content/posts/posts.json +4 -0
- package/templates/site/geekity.config.ts +11 -0
- package/templates/site/gitignore +3 -0
- package/templates/site/server.ts +20 -0
- package/templates/site/tsconfig.json +18 -0
- package/themes/default/README.md +148 -0
- package/themes/default/layouts/404.njk +9 -0
- package/themes/default/layouts/base.njk +59 -0
- package/themes/default/layouts/home.njk +9 -0
- package/themes/default/layouts/page.njk +13 -0
- package/themes/default/layouts/post.njk +30 -0
- package/themes/default/layouts/tag.njk +19 -0
- package/themes/default/partials/pagination.njk +14 -0
- package/themes/default/partials/post-list.njk +24 -0
- package/themes/default/partials/tags.njk +12 -0
- package/themes/default/static/style.css +327 -0
|
@@ -0,0 +1,613 @@
|
|
|
1
|
+
import { mkdir, readFile, rename, rm } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { parseDocument } from '../content/parser.js';
|
|
4
|
+
import { contentFilePath, freeSlug, saveDocument } from '../content/save.js';
|
|
5
|
+
import { defaultPermalink, slugify } from '../content/slug.js';
|
|
6
|
+
import { DuplicatePermalinkError, isTrashedPath, TRASH_DIRECTORY } from '../content/store.js';
|
|
7
|
+
import { normalizeBody, serializeDocument } from '../content/writer.js';
|
|
8
|
+
import { isPublicDocument } from '../web/documents.js';
|
|
9
|
+
import { flash } from './flash.js';
|
|
10
|
+
import { PREVIEW_PATH } from './preview.js';
|
|
11
|
+
import { ADMIN_PREFIX } from './session.js';
|
|
12
|
+
import { ADMIN_TEMPLATES } from './templates.js';
|
|
13
|
+
import { UPLOADS_PATH } from './uploads.js';
|
|
14
|
+
/**
|
|
15
|
+
* The Eleventy key that keeps a document out of every collection.
|
|
16
|
+
*
|
|
17
|
+
* The CMS does not model it — it is not in `KNOWN_FRONT_MATTER_KEYS` — so the
|
|
18
|
+
* parser leaves it in {@link Document.extra} and the editor reads and writes it
|
|
19
|
+
* there, alongside every other key somebody added by hand.
|
|
20
|
+
*/
|
|
21
|
+
export const EXCLUDE_KEY = 'eleventyExcludeFromCollections';
|
|
22
|
+
/** The posts screens: dated, tagged, filed under `posts/`. */
|
|
23
|
+
export const POST_KIND = {
|
|
24
|
+
type: 'post',
|
|
25
|
+
section: 'posts',
|
|
26
|
+
basePath: `${ADMIN_PREFIX}/posts`,
|
|
27
|
+
singular: 'post',
|
|
28
|
+
plural: 'Posts',
|
|
29
|
+
dated: true,
|
|
30
|
+
tagged: true,
|
|
31
|
+
excludable: false,
|
|
32
|
+
};
|
|
33
|
+
/** The pages screens: standing content, no date prefix and no taxonomy. */
|
|
34
|
+
export const PAGE_KIND = {
|
|
35
|
+
type: 'page',
|
|
36
|
+
section: 'pages',
|
|
37
|
+
basePath: `${ADMIN_PREFIX}/pages`,
|
|
38
|
+
singular: 'page',
|
|
39
|
+
plural: 'Pages',
|
|
40
|
+
dated: false,
|
|
41
|
+
tagged: false,
|
|
42
|
+
excludable: true,
|
|
43
|
+
};
|
|
44
|
+
/** The URL of the editor for one document. */
|
|
45
|
+
export function editorPath(kind, slug) {
|
|
46
|
+
return `${kind.basePath}/${encodeURIComponent(slug)}`;
|
|
47
|
+
}
|
|
48
|
+
/** The URL of the editor for a document that does not exist yet. */
|
|
49
|
+
export function newEditorPath(kind) {
|
|
50
|
+
return `${kind.basePath}/new`;
|
|
51
|
+
}
|
|
52
|
+
/** The filters, in the order they are shown. */
|
|
53
|
+
export const DOCUMENT_FILTERS = ['all', 'published', 'draft', 'trash'];
|
|
54
|
+
/** How many rows one page of a listing holds. */
|
|
55
|
+
export const DOCUMENTS_PER_PAGE = 25;
|
|
56
|
+
/** The filter a query string asked for, defaulting to everything live. */
|
|
57
|
+
export function documentFilter(value) {
|
|
58
|
+
return DOCUMENT_FILTERS.includes(value) ? value : 'all';
|
|
59
|
+
}
|
|
60
|
+
/** {@link ContentStore.listAll} options for one kind and one filter. */
|
|
61
|
+
export function listOptionsFor(kind, filter) {
|
|
62
|
+
return {
|
|
63
|
+
type: kind.type,
|
|
64
|
+
trashed: filter === 'trash',
|
|
65
|
+
...(filter === 'published' ? { draft: false } : {}),
|
|
66
|
+
...(filter === 'draft' ? { draft: true } : {}),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Register the listing and the editor for one kind of document.
|
|
71
|
+
*
|
|
72
|
+
* Both `/admin/posts` and `/admin/pages` are this function with a different
|
|
73
|
+
* {@link DocumentKind}: the screens, the templates and the write path are
|
|
74
|
+
* shared, and the kind decides what a file is called, whether the form has a
|
|
75
|
+
* date and tags, and which section of the navigation marks itself.
|
|
76
|
+
*/
|
|
77
|
+
export function mountDocumentScreens(app, options) {
|
|
78
|
+
const { kind, render } = options;
|
|
79
|
+
app.get(kind.basePath, (c) => {
|
|
80
|
+
const filter = documentFilter(c.req.query('status'));
|
|
81
|
+
const pageNumber = Math.max(1, Number(c.req.query('page') ?? '1') || 1);
|
|
82
|
+
const offset = (pageNumber - 1) * DOCUMENTS_PER_PAGE;
|
|
83
|
+
// One row more than fits, so "is there another page" costs no second query.
|
|
84
|
+
const found = c.var.store.listAll({
|
|
85
|
+
...listOptionsFor(kind, filter),
|
|
86
|
+
limit: DOCUMENTS_PER_PAGE + 1,
|
|
87
|
+
offset,
|
|
88
|
+
});
|
|
89
|
+
const rows = found.slice(0, DOCUMENTS_PER_PAGE);
|
|
90
|
+
return render(c, ADMIN_TEMPLATES.documentList, {
|
|
91
|
+
section: kind.section,
|
|
92
|
+
kind,
|
|
93
|
+
filter,
|
|
94
|
+
filters: DOCUMENT_FILTERS.map((name) => ({
|
|
95
|
+
name,
|
|
96
|
+
label: FILTER_LABELS[name],
|
|
97
|
+
url: listingUrl(kind, name, 1),
|
|
98
|
+
current: name === filter,
|
|
99
|
+
})),
|
|
100
|
+
documents: rows.map((document) => listRow(kind, document)),
|
|
101
|
+
newUrl: newEditorPath(kind),
|
|
102
|
+
returnUrl: listingUrl(kind, filter, pageNumber),
|
|
103
|
+
page: pageNumber,
|
|
104
|
+
previousUrl: pageNumber > 1 ? listingUrl(kind, filter, pageNumber - 1) : undefined,
|
|
105
|
+
nextUrl: found.length > rows.length ? listingUrl(kind, filter, pageNumber + 1) : undefined,
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
// Registered before the slug route, so a document can never take the URL of
|
|
109
|
+
// the form that makes a new one.
|
|
110
|
+
app.get(newEditorPath(kind), (c) => renderEditor(c, {
|
|
111
|
+
kind,
|
|
112
|
+
render,
|
|
113
|
+
document: undefined,
|
|
114
|
+
form: blankForm(kind),
|
|
115
|
+
}));
|
|
116
|
+
app.post(newEditorPath(kind), async (c) => saveFromForm(c, { kind, render, document: undefined, body: await c.req.parseBody() }));
|
|
117
|
+
app.get(`${kind.basePath}/:slug`, (c) => {
|
|
118
|
+
const document = findBySlug(c.var.store, kind, c.req.param('slug'));
|
|
119
|
+
if (document === undefined)
|
|
120
|
+
return c.notFound();
|
|
121
|
+
return renderEditor(c, { kind, render, document, form: formFor(document) });
|
|
122
|
+
});
|
|
123
|
+
app.post(`${kind.basePath}/:slug`, async (c) => {
|
|
124
|
+
const document = findBySlug(c.var.store, kind, c.req.param('slug'));
|
|
125
|
+
if (document === undefined)
|
|
126
|
+
return c.notFound();
|
|
127
|
+
const body = await c.req.parseBody();
|
|
128
|
+
const action = text(body['action']);
|
|
129
|
+
if (action === 'trash' || action === 'restore') {
|
|
130
|
+
return moveDocument(c, { kind, document, action, returnTo: text(body['return']) });
|
|
131
|
+
}
|
|
132
|
+
return saveFromForm(c, { kind, render, document, body });
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Write what the editor submitted.
|
|
137
|
+
*
|
|
138
|
+
* The order matters: the form is read and checked before anything is touched,
|
|
139
|
+
* the on-disk file is re-hashed and compared with the hash the form loaded with
|
|
140
|
+
* (doc-1's conflict rule), and only then is a file written. A save that is
|
|
141
|
+
* refused — no title, an unreadable date, a stale hash, a URL another document
|
|
142
|
+
* already holds — leaves the content directory exactly as it was.
|
|
143
|
+
*/
|
|
144
|
+
async function saveFromForm(c, options) {
|
|
145
|
+
const { kind, render, document, body } = options;
|
|
146
|
+
const store = c.var.store;
|
|
147
|
+
const contentDir = c.var.config.contentDir;
|
|
148
|
+
const form = {
|
|
149
|
+
title: text(body['title']).trim(),
|
|
150
|
+
slug: text(body['slug']).trim(),
|
|
151
|
+
permalink: text(body['permalink']).trim(),
|
|
152
|
+
date: text(body['date']).trim(),
|
|
153
|
+
tags: text(body['tags']).trim(),
|
|
154
|
+
description: text(body['description']).trim(),
|
|
155
|
+
draft: body['draft'] !== undefined,
|
|
156
|
+
exclude: body['exclude'] !== undefined,
|
|
157
|
+
body: normalizeBody(text(body['body'])),
|
|
158
|
+
hash: text(body['hash']),
|
|
159
|
+
};
|
|
160
|
+
const action = text(body['action']);
|
|
161
|
+
// The buttons doc-5 names are shortcuts past the checkbox: Save draft and
|
|
162
|
+
// Publish say what they do, and Update leaves the decision to the checkbox.
|
|
163
|
+
const draft = action === 'save-draft' ? true : action === 'publish' ? false : form.draft;
|
|
164
|
+
function refuse(message) {
|
|
165
|
+
return renderEditor(c, {
|
|
166
|
+
kind,
|
|
167
|
+
render,
|
|
168
|
+
document,
|
|
169
|
+
form: { ...form, draft },
|
|
170
|
+
error: message,
|
|
171
|
+
status: 400,
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
if (form.title === '')
|
|
175
|
+
return refuse(`A ${kind.singular} needs a title.`);
|
|
176
|
+
const date = kind.dated ? (form.date === '' ? new Date().toISOString() : form.date) : undefined;
|
|
177
|
+
if (date !== undefined && !/^\d{4}-\d{2}-\d{2}/.test(date)) {
|
|
178
|
+
return refuse('A date has to start with a year, a month and a day, like 2026-03-04.');
|
|
179
|
+
}
|
|
180
|
+
const slug = slugify(form.slug) || slugify(form.title) || (document?.slug ?? '') || 'untitled';
|
|
181
|
+
const trashed = document !== undefined && isTrashedPath(document.path);
|
|
182
|
+
// A new document gets out of the way of anything that already holds its
|
|
183
|
+
// name; an existing one keeps the slug it was given.
|
|
184
|
+
const finalSlug = document === undefined
|
|
185
|
+
? await freeSlug({ contentDir, store, type: kind.type, slug, date })
|
|
186
|
+
: slug;
|
|
187
|
+
const permalink = resolvePermalink({ kind, form, slug: finalSlug, date, document });
|
|
188
|
+
const target = documentPath({ kind, slug: finalSlug, date, trashed });
|
|
189
|
+
if (document !== undefined) {
|
|
190
|
+
const conflict = await conflictWith(contentDir, document, form.hash);
|
|
191
|
+
if (conflict !== undefined) {
|
|
192
|
+
return renderConflict(c, { kind, render, document, form: { ...form, draft }, conflict });
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
if (target !== document?.path && store.getByPath(target) !== undefined) {
|
|
196
|
+
return refuse(`Another ${kind.singular} already lives in ${target}.`);
|
|
197
|
+
}
|
|
198
|
+
const content = {
|
|
199
|
+
title: form.title,
|
|
200
|
+
...(date === undefined ? {} : { date }),
|
|
201
|
+
updated: new Date().toISOString(),
|
|
202
|
+
permalink,
|
|
203
|
+
tags: kind.tagged ? splitTags(form.tags) : [],
|
|
204
|
+
draft,
|
|
205
|
+
...(form.description === '' ? {} : { description: form.description }),
|
|
206
|
+
...optional('author', document?.author ?? currentUsername(c)),
|
|
207
|
+
...optional('activitypub', document?.activitypub),
|
|
208
|
+
extra: resolveExtra(kind, document, form.exclude),
|
|
209
|
+
body: form.body,
|
|
210
|
+
};
|
|
211
|
+
// The row for the old path goes first: a rename briefly leaves two rows
|
|
212
|
+
// claiming one permalink, and the index refuses that.
|
|
213
|
+
const renamedFrom = document !== undefined && document.path !== target ? document : undefined;
|
|
214
|
+
if (renamedFrom !== undefined)
|
|
215
|
+
store.remove(renamedFrom.path);
|
|
216
|
+
let saved;
|
|
217
|
+
try {
|
|
218
|
+
saved = await saveDocument({ contentDir, store, path: target, content });
|
|
219
|
+
}
|
|
220
|
+
catch (error) {
|
|
221
|
+
// Nothing was written, so the row that was taken out of the way goes back.
|
|
222
|
+
if (renamedFrom !== undefined)
|
|
223
|
+
store.upsert(renamedFrom);
|
|
224
|
+
if (error instanceof DuplicatePermalinkError)
|
|
225
|
+
return refuse(error.message);
|
|
226
|
+
throw error;
|
|
227
|
+
}
|
|
228
|
+
if (renamedFrom !== undefined) {
|
|
229
|
+
await rm(path.join(contentDir, ...renamedFrom.path.split('/')), { force: true });
|
|
230
|
+
}
|
|
231
|
+
// Announced rather than left to the watcher: the index already holds what
|
|
232
|
+
// was written, so the watcher's re-read is a no-op and nobody would ever
|
|
233
|
+
// hear that this post was published. Awaited, so a subscriber that writes
|
|
234
|
+
// back to the file — the federation stamping `activitypub` into a post it
|
|
235
|
+
// has just announced — has finished before the editor is reloaded with a
|
|
236
|
+
// hash that would otherwise be one save behind.
|
|
237
|
+
await c.var.announce({
|
|
238
|
+
type: document === undefined ? 'created' : 'updated',
|
|
239
|
+
path: saved.path,
|
|
240
|
+
previous: document,
|
|
241
|
+
next: saved,
|
|
242
|
+
origin: 'admin',
|
|
243
|
+
});
|
|
244
|
+
flash(c, 'notice', savedMessage(kind, document, saved));
|
|
245
|
+
return c.redirect(editorPath(kind, saved.slug), 303);
|
|
246
|
+
}
|
|
247
|
+
/** What the flash says after a save, which depends on what the save did. */
|
|
248
|
+
function savedMessage(kind, previous, saved) {
|
|
249
|
+
if (saved.draft)
|
|
250
|
+
return `Draft saved: ${saved.title}`;
|
|
251
|
+
if (previous === undefined || previous.draft)
|
|
252
|
+
return `Published: ${saved.title}`;
|
|
253
|
+
return `Updated: ${saved.title}`;
|
|
254
|
+
}
|
|
255
|
+
/** Where a document's file goes, trash included. */
|
|
256
|
+
function documentPath(input) {
|
|
257
|
+
const relative = contentFilePath({ type: input.kind.type, slug: input.slug, date: input.date });
|
|
258
|
+
return input.trashed ? `${TRASH_DIRECTORY}/${relative}` : relative;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* The permalink to write.
|
|
262
|
+
*
|
|
263
|
+
* A permalink is explicit in the file and the stored value is what counts
|
|
264
|
+
* (doc-2), so one that was customised is never quietly rewritten. One that is
|
|
265
|
+
* still the URL its old slug and date implied follows them to the new ones,
|
|
266
|
+
* which is what makes renaming a slug in the editor do what it looks like it
|
|
267
|
+
* does.
|
|
268
|
+
*/
|
|
269
|
+
function resolvePermalink(input) {
|
|
270
|
+
const fallback = defaultPermalink({
|
|
271
|
+
type: input.kind.type,
|
|
272
|
+
slug: input.slug,
|
|
273
|
+
date: input.date,
|
|
274
|
+
});
|
|
275
|
+
const submitted = normalizePermalink(input.form.permalink);
|
|
276
|
+
if (submitted === undefined)
|
|
277
|
+
return fallback;
|
|
278
|
+
const document = input.document;
|
|
279
|
+
if (document !== undefined && submitted === previousDefaultPermalink(input.kind, document)) {
|
|
280
|
+
return fallback;
|
|
281
|
+
}
|
|
282
|
+
return submitted;
|
|
283
|
+
}
|
|
284
|
+
/** The permalink a document would have had if it had never been customised. */
|
|
285
|
+
function previousDefaultPermalink(kind, document) {
|
|
286
|
+
try {
|
|
287
|
+
return defaultPermalink({ type: kind.type, slug: document.slug, date: document.date });
|
|
288
|
+
}
|
|
289
|
+
catch {
|
|
290
|
+
return undefined;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
/** A submitted permalink as a URL path, or `undefined` when the field is empty. */
|
|
294
|
+
function normalizePermalink(value) {
|
|
295
|
+
const trimmed = value.trim();
|
|
296
|
+
if (trimmed === '')
|
|
297
|
+
return undefined;
|
|
298
|
+
const withLeading = trimmed.startsWith('/') ? trimmed : `/${trimmed}`;
|
|
299
|
+
const last = withLeading.split('/').at(-1) ?? '';
|
|
300
|
+
// `/feed.xml` is a file and keeps its name; everything else is a directory
|
|
301
|
+
// and gets the trailing slash that is canonical here.
|
|
302
|
+
if (last === '' || last.includes('.'))
|
|
303
|
+
return withLeading;
|
|
304
|
+
return `${withLeading}/`;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* The front matter to write that the CMS does not model.
|
|
308
|
+
*
|
|
309
|
+
* What the file already carried comes back out untouched, so a key somebody
|
|
310
|
+
* added by hand survives every admin save (doc-2). The one such key the editor
|
|
311
|
+
* has a field for is `eleventyExcludeFromCollections`: ticking the box writes
|
|
312
|
+
* it, and clearing the box takes the key back out rather than leaving a
|
|
313
|
+
* `false` behind — unless the file spelled the key out itself, in which case
|
|
314
|
+
* the `false` is written, because a key somebody wrote by hand is not the
|
|
315
|
+
* editor's to delete.
|
|
316
|
+
*/
|
|
317
|
+
function resolveExtra(kind, document, exclude) {
|
|
318
|
+
const extra = { ...(document?.extra ?? {}) };
|
|
319
|
+
if (!kind.excludable)
|
|
320
|
+
return extra;
|
|
321
|
+
if (exclude)
|
|
322
|
+
extra[EXCLUDE_KEY] = true;
|
|
323
|
+
else if (EXCLUDE_KEY in extra)
|
|
324
|
+
extra[EXCLUDE_KEY] = false;
|
|
325
|
+
return extra;
|
|
326
|
+
}
|
|
327
|
+
/** A comma-separated tag field as a list, without the blanks and the repeats. */
|
|
328
|
+
export function splitTags(value) {
|
|
329
|
+
const tags = [];
|
|
330
|
+
for (const tag of value.split(',')) {
|
|
331
|
+
const trimmed = tag.trim();
|
|
332
|
+
if (trimmed !== '' && !tags.includes(trimmed))
|
|
333
|
+
tags.push(trimmed);
|
|
334
|
+
}
|
|
335
|
+
return tags;
|
|
336
|
+
}
|
|
337
|
+
/** The signed-in user's login, which is what doc-2's `author` holds. */
|
|
338
|
+
function currentUsername(c) {
|
|
339
|
+
const userId = c.var.session?.userId;
|
|
340
|
+
if (userId == null)
|
|
341
|
+
return undefined;
|
|
342
|
+
return c.var.admin.getUserById(userId)?.username;
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Whether the file has moved on since the form loaded, per doc-1: files win,
|
|
346
|
+
* and an edit made behind the editor's back is never silently overwritten.
|
|
347
|
+
*
|
|
348
|
+
* The file is read and re-parsed rather than trusted to the index, so the
|
|
349
|
+
* check is right even when the watcher is off or has not caught up.
|
|
350
|
+
*/
|
|
351
|
+
async function conflictWith(contentDir, document, submittedHash) {
|
|
352
|
+
const file = path.join(contentDir, ...document.path.split('/'));
|
|
353
|
+
let source;
|
|
354
|
+
try {
|
|
355
|
+
source = await readFile(file, 'utf8');
|
|
356
|
+
}
|
|
357
|
+
catch {
|
|
358
|
+
// The file is gone. There is nothing to lose by writing it again.
|
|
359
|
+
return undefined;
|
|
360
|
+
}
|
|
361
|
+
let hash;
|
|
362
|
+
try {
|
|
363
|
+
hash = parseDocument(source, { path: document.path, type: document.type }).hash;
|
|
364
|
+
}
|
|
365
|
+
catch {
|
|
366
|
+
// A file that will not parse cannot be compared, and overwriting it would
|
|
367
|
+
// throw away whatever is wrong with it before anyone has seen it.
|
|
368
|
+
hash = '';
|
|
369
|
+
}
|
|
370
|
+
if (hash === submittedHash)
|
|
371
|
+
return undefined;
|
|
372
|
+
return { current: source, hash };
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* The refused save, side by side with the file it would have overwritten.
|
|
376
|
+
*
|
|
377
|
+
* Nothing has been written at this point. The form is offered back with the
|
|
378
|
+
* fresh hash, so the way out is to read both versions and decide, rather than
|
|
379
|
+
* to lose the edit.
|
|
380
|
+
*/
|
|
381
|
+
function renderConflict(c, options) {
|
|
382
|
+
const { kind, document, form, conflict } = options;
|
|
383
|
+
const submitted = serializeDocument({
|
|
384
|
+
title: form.title,
|
|
385
|
+
...(form.date === '' ? {} : { date: form.date }),
|
|
386
|
+
permalink: form.permalink === '' ? document.permalink : form.permalink,
|
|
387
|
+
tags: kind.tagged ? splitTags(form.tags) : [],
|
|
388
|
+
draft: form.draft,
|
|
389
|
+
...(form.description === '' ? {} : { description: form.description }),
|
|
390
|
+
...optional('author', document.author),
|
|
391
|
+
...optional('activitypub', document.activitypub),
|
|
392
|
+
extra: resolveExtra(kind, document, form.exclude),
|
|
393
|
+
body: form.body,
|
|
394
|
+
});
|
|
395
|
+
c.status(409);
|
|
396
|
+
return options.render(c, ADMIN_TEMPLATES.documentConflict, {
|
|
397
|
+
section: kind.section,
|
|
398
|
+
kind,
|
|
399
|
+
form,
|
|
400
|
+
// The hash the file has now, so resubmitting this form is a deliberate
|
|
401
|
+
// overwrite of a version its author has been shown.
|
|
402
|
+
freshHash: conflict.hash,
|
|
403
|
+
submitted,
|
|
404
|
+
current: conflict.current,
|
|
405
|
+
editUrl: editorPath(kind, document.slug),
|
|
406
|
+
saveUrl: editorPath(kind, document.slug),
|
|
407
|
+
action: form.draft ? 'save-draft' : 'publish',
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Move a document into `content/_trash/` or back out of it.
|
|
412
|
+
*
|
|
413
|
+
* The trash mirrors the content tree — `posts/2026-03-04-x.md` becomes
|
|
414
|
+
* `_trash/posts/2026-03-04-x.md` — so restoring is the same move backwards and
|
|
415
|
+
* needs to remember nothing. The index is corrected as soon as the file has
|
|
416
|
+
* landed rather than waiting for the watcher, so the public site stops or
|
|
417
|
+
* starts serving the document with this request (doc-1).
|
|
418
|
+
*/
|
|
419
|
+
async function moveDocument(c, options) {
|
|
420
|
+
const { kind, document, action } = options;
|
|
421
|
+
const store = c.var.store;
|
|
422
|
+
const contentDir = c.var.config.contentDir;
|
|
423
|
+
const trashed = isTrashedPath(document.path);
|
|
424
|
+
if (action === 'trash' && trashed)
|
|
425
|
+
return backTo(c, options, `It is already in the trash.`);
|
|
426
|
+
if (action === 'restore' && !trashed)
|
|
427
|
+
return backTo(c, options, `It is not in the trash.`);
|
|
428
|
+
const target = action === 'trash'
|
|
429
|
+
? `${TRASH_DIRECTORY}/${document.path}`
|
|
430
|
+
: document.path
|
|
431
|
+
.split('/')
|
|
432
|
+
.filter((segment) => segment !== TRASH_DIRECTORY)
|
|
433
|
+
.join('/');
|
|
434
|
+
const from = path.join(contentDir, ...document.path.split('/'));
|
|
435
|
+
const to = path.join(contentDir, ...target.split('/'));
|
|
436
|
+
let source;
|
|
437
|
+
try {
|
|
438
|
+
source = await readFile(from, 'utf8');
|
|
439
|
+
await mkdir(path.dirname(to), { recursive: true });
|
|
440
|
+
await rename(from, to);
|
|
441
|
+
}
|
|
442
|
+
catch {
|
|
443
|
+
return backTo(c, options, `Could not move ${document.path}. Is the file still there?`);
|
|
444
|
+
}
|
|
445
|
+
const moved = parseDocument(source, { path: target, type: document.type });
|
|
446
|
+
store.remove(document.path);
|
|
447
|
+
store.upsert(moved);
|
|
448
|
+
// Trashing takes a post off the public site and restoring puts it back, so
|
|
449
|
+
// both are visibility changes a subscriber has to hear about.
|
|
450
|
+
await c.var.announce({
|
|
451
|
+
type: 'updated',
|
|
452
|
+
path: target,
|
|
453
|
+
previous: document,
|
|
454
|
+
next: moved,
|
|
455
|
+
origin: 'admin',
|
|
456
|
+
});
|
|
457
|
+
const message = action === 'trash' ? `Moved to the trash: ${document.title}` : `Restored: ${document.title}`;
|
|
458
|
+
flash(c, 'notice', message);
|
|
459
|
+
return c.redirect(returnPath(options.returnTo) ??
|
|
460
|
+
(action === 'trash' ? kind.basePath : editorPath(kind, document.slug)), 303);
|
|
461
|
+
}
|
|
462
|
+
/** Report a move that did not happen and go back where the form came from. */
|
|
463
|
+
function backTo(c, options, message) {
|
|
464
|
+
flash(c, 'error', message);
|
|
465
|
+
return c.redirect(returnPath(options.returnTo) ?? editorPath(options.kind, options.document.slug), 303);
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* A submitted return path, when it is one this admin could have rendered.
|
|
469
|
+
*
|
|
470
|
+
* Only paths under `/admin/` are honoured, and only ones that cannot be read
|
|
471
|
+
* as another host, so the value cannot be used to bounce somebody off the site.
|
|
472
|
+
*/
|
|
473
|
+
export function returnPath(value) {
|
|
474
|
+
const trimmed = value.trim();
|
|
475
|
+
if (!trimmed.startsWith(`${ADMIN_PREFIX}/`) && trimmed !== ADMIN_PREFIX)
|
|
476
|
+
return undefined;
|
|
477
|
+
if (trimmed.startsWith('//') || trimmed.includes('\\'))
|
|
478
|
+
return undefined;
|
|
479
|
+
return trimmed;
|
|
480
|
+
}
|
|
481
|
+
function optional(key, value) {
|
|
482
|
+
return value === undefined ? {} : { [key]: value };
|
|
483
|
+
}
|
|
484
|
+
/** A form field as a string. A file upload, or a missing field, is the empty one. */
|
|
485
|
+
function text(value) {
|
|
486
|
+
return typeof value === 'string' ? value : '';
|
|
487
|
+
}
|
|
488
|
+
/** The editor for a document that does not exist yet. */
|
|
489
|
+
export function blankForm(kind) {
|
|
490
|
+
return {
|
|
491
|
+
title: '',
|
|
492
|
+
slug: '',
|
|
493
|
+
permalink: '',
|
|
494
|
+
date: kind.dated ? new Date().toISOString() : '',
|
|
495
|
+
tags: '',
|
|
496
|
+
description: '',
|
|
497
|
+
draft: false,
|
|
498
|
+
exclude: false,
|
|
499
|
+
body: '',
|
|
500
|
+
hash: '',
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
/** The editor for a document that does. */
|
|
504
|
+
export function formFor(document) {
|
|
505
|
+
return {
|
|
506
|
+
title: document.title,
|
|
507
|
+
slug: document.slug,
|
|
508
|
+
permalink: document.permalink,
|
|
509
|
+
date: document.date ?? '',
|
|
510
|
+
tags: document.tags.join(', '),
|
|
511
|
+
description: document.description ?? '',
|
|
512
|
+
draft: document.draft,
|
|
513
|
+
exclude: document.extra[EXCLUDE_KEY] === true,
|
|
514
|
+
body: document.body,
|
|
515
|
+
hash: document.hash,
|
|
516
|
+
};
|
|
517
|
+
}
|
|
518
|
+
/**
|
|
519
|
+
* The editor screen.
|
|
520
|
+
*
|
|
521
|
+
* The buttons follow doc-5 and the document's state: something unwritten or
|
|
522
|
+
* still a draft offers Save draft and Publish, something published offers
|
|
523
|
+
* Update, and anything that exists can be thrown away or, if it already has
|
|
524
|
+
* been, restored.
|
|
525
|
+
*/
|
|
526
|
+
function renderEditor(c, options) {
|
|
527
|
+
const { kind, document, form } = options;
|
|
528
|
+
const trashed = document !== undefined && isTrashedPath(document.path);
|
|
529
|
+
const actions = [];
|
|
530
|
+
if (document === undefined || document.draft) {
|
|
531
|
+
actions.push({ value: 'save-draft', label: 'Save draft' });
|
|
532
|
+
actions.push({ value: 'publish', label: 'Publish' });
|
|
533
|
+
}
|
|
534
|
+
else {
|
|
535
|
+
actions.push({ value: 'update', label: 'Update' });
|
|
536
|
+
}
|
|
537
|
+
if (trashed)
|
|
538
|
+
actions.push({ value: 'restore', label: 'Restore' });
|
|
539
|
+
else if (document !== undefined)
|
|
540
|
+
actions.push({ value: 'trash', label: 'Move to trash' });
|
|
541
|
+
if (options.status !== undefined)
|
|
542
|
+
c.status(options.status);
|
|
543
|
+
return options.render(c, ADMIN_TEMPLATES.documentEditor, {
|
|
544
|
+
section: kind.section,
|
|
545
|
+
kind,
|
|
546
|
+
form,
|
|
547
|
+
actions,
|
|
548
|
+
trashed,
|
|
549
|
+
heading: document === undefined ? `Add ${kind.singular}` : `Edit ${kind.singular}: ${document.title}`,
|
|
550
|
+
saveUrl: document === undefined ? newEditorPath(kind) : editorPath(kind, document.slug),
|
|
551
|
+
listUrl: kind.basePath,
|
|
552
|
+
previewUrl: PREVIEW_PATH,
|
|
553
|
+
uploadUrl: UPLOADS_PATH,
|
|
554
|
+
viewUrl: document !== undefined && isPublicDocument(document) ? document.permalink : undefined,
|
|
555
|
+
...(options.error === undefined ? {} : { error: options.error }),
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* The document of this kind with this slug.
|
|
560
|
+
*
|
|
561
|
+
* The index's slug lookup is across both kinds and is not unique, so a direct
|
|
562
|
+
* hit is only taken when it is of the right kind; otherwise the listing is
|
|
563
|
+
* searched, trash included, because the editor is where a trashed document is
|
|
564
|
+
* restored from.
|
|
565
|
+
*/
|
|
566
|
+
export function findBySlug(store, kind, slug) {
|
|
567
|
+
const direct = store.getBySlug(slug);
|
|
568
|
+
if (direct?.type === kind.type)
|
|
569
|
+
return direct;
|
|
570
|
+
for (const trashed of [false, true]) {
|
|
571
|
+
const found = store
|
|
572
|
+
.listAll({ type: kind.type, trashed })
|
|
573
|
+
.find((document) => document.slug === slug);
|
|
574
|
+
if (found !== undefined)
|
|
575
|
+
return found;
|
|
576
|
+
}
|
|
577
|
+
return undefined;
|
|
578
|
+
}
|
|
579
|
+
function listRow(kind, document) {
|
|
580
|
+
const isPublic = isPublicDocument(document);
|
|
581
|
+
return {
|
|
582
|
+
title: document.title,
|
|
583
|
+
slug: document.slug,
|
|
584
|
+
author: document.author,
|
|
585
|
+
tags: document.tags.join(', '),
|
|
586
|
+
date: document.date,
|
|
587
|
+
// Both come out of the index, so the listing costs no reads of its own.
|
|
588
|
+
// A page that has never been saved through the admin has no `updated`, and
|
|
589
|
+
// its date, when it has one, is the closest thing to one.
|
|
590
|
+
updated: document.updated ?? document.date,
|
|
591
|
+
draft: document.draft,
|
|
592
|
+
trashed: isTrashedPath(document.path),
|
|
593
|
+
editUrl: editorPath(kind, document.slug),
|
|
594
|
+
viewUrl: isPublic ? document.permalink : undefined,
|
|
595
|
+
};
|
|
596
|
+
}
|
|
597
|
+
const FILTER_LABELS = {
|
|
598
|
+
all: 'All',
|
|
599
|
+
published: 'Published',
|
|
600
|
+
draft: 'Drafts',
|
|
601
|
+
trash: 'Trash',
|
|
602
|
+
};
|
|
603
|
+
/** The URL of one view of a listing. Page one is the listing's own URL. */
|
|
604
|
+
export function listingUrl(kind, filter, page = 1) {
|
|
605
|
+
const query = new URLSearchParams();
|
|
606
|
+
if (filter !== 'all')
|
|
607
|
+
query.set('status', filter);
|
|
608
|
+
if (page > 1)
|
|
609
|
+
query.set('page', String(page));
|
|
610
|
+
const search = query.toString();
|
|
611
|
+
return search === '' ? kind.basePath : `${kind.basePath}?${search}`;
|
|
612
|
+
}
|
|
613
|
+
//# sourceMappingURL=documents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documents.js","sourceRoot":"","sources":["../../src/admin/documents.ts"],"names":[],"mappings":"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"}
|