@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.
- package/admin/components/job-status.njk +15 -10
- package/admin/components/upload.njk +26 -0
- package/admin/pages/documents/editor.njk +34 -19
- package/admin/pages/federation/followers.njk +2 -1
- package/admin/pages/media/file.njk +5 -4
- package/admin/pages/media/library.njk +7 -3
- package/admin/pages/settings/general.njk +4 -1
- package/admin/pages/tools/export.njk +54 -51
- package/admin/pages/tools/maintenance.njk +2 -1
- package/admin/pages/users/edit.njk +3 -0
- package/admin/src/admin.css +1 -0
- package/admin/static/admin.css +74 -0
- package/admin/static/job-status.js +158 -0
- package/admin/static/upload-drop.js +225 -0
- package/dist/admin/documents.d.ts.map +1 -1
- package/dist/admin/documents.js +0 -2
- package/dist/admin/documents.js.map +1 -1
- package/dist/admin/index.d.ts +1 -1
- package/dist/admin/index.d.ts.map +1 -1
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/job-status.d.ts +1 -0
- package/dist/admin/job-status.d.ts.map +1 -1
- package/dist/admin/job-status.js +1 -0
- package/dist/admin/job-status.js.map +1 -1
- package/dist/admin/media.d.ts +6 -9
- package/dist/admin/media.d.ts.map +1 -1
- package/dist/admin/media.js +85 -27
- package/dist/admin/media.js.map +1 -1
- package/dist/admin/routes.d.ts.map +1 -1
- package/dist/admin/routes.js +1 -0
- package/dist/admin/routes.js.map +1 -1
- package/dist/admin/uploads.d.ts +2 -1
- package/dist/admin/uploads.d.ts.map +1 -1
- package/dist/admin/uploads.js +5 -2
- package/dist/admin/uploads.js.map +1 -1
- package/dist/media/library.d.ts +9 -0
- package/dist/media/library.d.ts.map +1 -1
- package/dist/media/library.js +25 -1
- package/dist/media/library.js.map +1 -1
- package/package.json +6 -1
- package/dist/comments/routes.d.ts +0 -65
- package/dist/comments/routes.d.ts.map +0 -1
- package/dist/comments/routes.js +0 -235
- package/dist/comments/routes.js.map +0 -1
- package/dist/content/media.d.ts +0 -85
- package/dist/content/media.d.ts.map +0 -1
- package/dist/content/media.js +0 -237
- package/dist/content/media.js.map +0 -1
- package/dist/content/read-form.d.ts +0 -31
- package/dist/content/read-form.d.ts.map +0 -1
- package/dist/content/read-form.js +0 -157
- package/dist/content/read-form.js.map +0 -1
- package/dist/content/read.d.ts +0 -29
- package/dist/content/read.d.ts.map +0 -1
- package/dist/content/read.js +0 -82
- package/dist/content/read.js.map +0 -1
- package/dist/export/export-archives.d.ts +0 -29
- package/dist/export/export-archives.d.ts.map +0 -1
- package/dist/export/export-archives.js +0 -88
- package/dist/export/export-archives.js.map +0 -1
- package/dist/federation/mount.d.ts +0 -53
- package/dist/federation/mount.d.ts.map +0 -1
- package/dist/federation/mount.js +0 -344
- package/dist/federation/mount.js.map +0 -1
- package/dist/mail/credentials.d.ts +0 -62
- package/dist/mail/credentials.d.ts.map +0 -1
- package/dist/mail/credentials.js +0 -86
- package/dist/mail/credentials.js.map +0 -1
- package/dist/site/setting-rows.d.ts +0 -45
- package/dist/site/setting-rows.d.ts.map +0 -1
- package/dist/site/setting-rows.js +0 -361
- package/dist/site/setting-rows.js.map +0 -1
- package/dist/site/settings-form.d.ts +0 -30
- package/dist/site/settings-form.d.ts.map +0 -1
- package/dist/site/settings-form.js +0 -54
- package/dist/site/settings-form.js.map +0 -1
- package/dist/site/site-json.d.ts +0 -38
- package/dist/site/site-json.d.ts.map +0 -1
- package/dist/site/site-json.js +0 -69
- package/dist/site/site-json.js.map +0 -1
- package/dist/webmention/routes.d.ts +0 -37
- package/dist/webmention/routes.d.ts.map +0 -1
- package/dist/webmention/routes.js +0 -75
- package/dist/webmention/routes.js.map +0 -1
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import type { FieldError } from './form-error.ts';
|
|
2
|
-
import type { Read, ReadOf } from './read.ts';
|
|
3
|
-
export interface ReadOfForm {
|
|
4
|
-
name: string;
|
|
5
|
-
author: string;
|
|
6
|
-
uid: string;
|
|
7
|
-
url: string;
|
|
8
|
-
photo: string;
|
|
9
|
-
photoAlt: string;
|
|
10
|
-
}
|
|
11
|
-
export declare const READ_FIELDS: {
|
|
12
|
-
readonly status: 'read-status';
|
|
13
|
-
readonly name: 'read-of-name';
|
|
14
|
-
readonly author: 'read-of-author';
|
|
15
|
-
readonly uid: 'read-of-uid';
|
|
16
|
-
readonly url: 'read-of-url';
|
|
17
|
-
readonly photo: 'read-of-photo';
|
|
18
|
-
readonly photoAlt: 'read-of-photo-alt';
|
|
19
|
-
};
|
|
20
|
-
export declare function submittedReadOfForm(body: Readonly<Record<string, unknown>>): ReadOfForm;
|
|
21
|
-
export declare const BLANK_READ_OF_FORM: ReadOfForm;
|
|
22
|
-
export declare function readOfForm(of: ReadOf | undefined): ReadOfForm;
|
|
23
|
-
export declare function resolveRead(status: string, of: ReadOfForm, contentDir: string): {
|
|
24
|
-
read: Read | undefined;
|
|
25
|
-
} | FieldError;
|
|
26
|
-
export declare function readOfFromMicropub(values: readonly unknown[], refuse: (message: string) => void, baseUrl: string): ReadOfForm;
|
|
27
|
-
export declare function readCite({ photo, ...of }: ReadOf, baseUrl: string): {
|
|
28
|
-
type: string[];
|
|
29
|
-
properties: Record<string, unknown[]>;
|
|
30
|
-
};
|
|
31
|
-
//# sourceMappingURL=read-form.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"read-form.d.ts","sourceRoot":"","sources":["../../src/content/read-form.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAGlD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAE9C,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,WAAW;aACtB,MAAM,EAAE,aAAa;aACrB,IAAI,EAAE,cAAc;aACpB,MAAM,EAAE,gBAAgB;aACxB,GAAG,EAAE,aAAa;aAClB,GAAG,EAAE,aAAa;aAClB,KAAK,EAAE,eAAe;aACtB,QAAQ,EAAE,mBAAmB;CACrB,CAAC;AAEX,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,UAAU,CASvF;AAED,eAAO,MAAM,kBAAkB,EAAE,UAOhC,CAAC;AAEF,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,CAS7D;AAED,wBAAgB,WAAW,CACzB,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,UAAU,EACd,UAAU,EAAE,MAAM,GACjB;IAAE,IAAI,EAAE,IAAI,GAAG,SAAS,CAAA;CAAE,GAAG,UAAU,CAmDzC;AAKD,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,SAAS,OAAO,EAAE,EAC1B,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,EACjC,OAAO,EAAE,MAAM,GACd,UAAU,CAiDZ;AAED,wBAAgB,QAAQ,CACtB,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,EACxB,OAAO,EAAE,MAAM,GACd;IACD,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;CACvC,CAWA"}
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
import { trimmedField } from '../util/forms.js';
|
|
2
|
-
import { isUploadUrl, isWebUrl } from './enclosure.js';
|
|
3
|
-
import { isLibraryImage, photoRowFromMicropub, photoToMicropub } from './photo-form.js';
|
|
4
|
-
import { isReadStatus, READ_STATUSES } from './read.js';
|
|
5
|
-
export const READ_FIELDS = {
|
|
6
|
-
status: 'read-status',
|
|
7
|
-
name: 'read-of-name',
|
|
8
|
-
author: 'read-of-author',
|
|
9
|
-
uid: 'read-of-uid',
|
|
10
|
-
url: 'read-of-url',
|
|
11
|
-
photo: 'read-of-photo',
|
|
12
|
-
photoAlt: 'read-of-photo-alt',
|
|
13
|
-
};
|
|
14
|
-
export function submittedReadOfForm(body) {
|
|
15
|
-
return {
|
|
16
|
-
name: trimmedField(body, READ_FIELDS.name),
|
|
17
|
-
author: trimmedField(body, READ_FIELDS.author),
|
|
18
|
-
uid: trimmedField(body, READ_FIELDS.uid),
|
|
19
|
-
url: trimmedField(body, READ_FIELDS.url),
|
|
20
|
-
photo: trimmedField(body, READ_FIELDS.photo),
|
|
21
|
-
photoAlt: trimmedField(body, READ_FIELDS.photoAlt),
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
export const BLANK_READ_OF_FORM = {
|
|
25
|
-
name: '',
|
|
26
|
-
author: '',
|
|
27
|
-
uid: '',
|
|
28
|
-
url: '',
|
|
29
|
-
photo: '',
|
|
30
|
-
photoAlt: '',
|
|
31
|
-
};
|
|
32
|
-
export function readOfForm(of) {
|
|
33
|
-
return {
|
|
34
|
-
name: of?.name ?? '',
|
|
35
|
-
author: of?.author ?? '',
|
|
36
|
-
uid: of?.uid ?? '',
|
|
37
|
-
url: of?.url ?? '',
|
|
38
|
-
photo: of?.photo?.url ?? '',
|
|
39
|
-
photoAlt: of?.photo?.alt ?? '',
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
export function resolveRead(status, of, contentDir) {
|
|
43
|
-
const filled = Object.values(of).some((value) => value !== '');
|
|
44
|
-
if (status === '' && !filled)
|
|
45
|
-
return { read: undefined };
|
|
46
|
-
if (status !== '' && !isReadStatus(status)) {
|
|
47
|
-
return {
|
|
48
|
-
error: `A read status is ${READ_STATUSES.join(', ')}, not ${status}.`,
|
|
49
|
-
field: 'editor-read-status',
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
if (of.name === '') {
|
|
53
|
-
return { error: 'A read needs the title of what was read.', field: 'editor-read-of-name' };
|
|
54
|
-
}
|
|
55
|
-
if (!isReadStatus(status)) {
|
|
56
|
-
return {
|
|
57
|
-
error: 'A read needs a read status: want to read, currently reading or finished.',
|
|
58
|
-
field: 'editor-read-status',
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
if (of.url !== '' && !isWebUrl(of.url)) {
|
|
62
|
-
return {
|
|
63
|
-
error: 'The address of what was read has to be a web address, like https://example.com/a-book/.',
|
|
64
|
-
field: 'editor-read-of-url',
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
if (isUploadUrl(of.photo)) {
|
|
68
|
-
if (!isLibraryImage(of.photo, contentDir)) {
|
|
69
|
-
return {
|
|
70
|
-
error: `The cover ${of.photo} is not an image in the media library.`,
|
|
71
|
-
field: 'editor-read-of-photo',
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
else if (of.photo !== '' && !isWebUrl(of.photo)) {
|
|
76
|
-
return {
|
|
77
|
-
error: `A cover is an image in the media library or a web address, not ${of.photo}.`,
|
|
78
|
-
field: 'editor-read-of-photo',
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
const word = (value) => (value === '' ? undefined : value);
|
|
82
|
-
return {
|
|
83
|
-
read: {
|
|
84
|
-
status,
|
|
85
|
-
of: {
|
|
86
|
-
name: of.name,
|
|
87
|
-
author: word(of.author),
|
|
88
|
-
uid: word(of.uid),
|
|
89
|
-
url: word(of.url),
|
|
90
|
-
...(of.photo === '' ? {} : { photo: { url: of.photo, alt: word(of.photoAlt) } }),
|
|
91
|
-
},
|
|
92
|
-
},
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
const READ_OF_TEXT_PROPERTIES = ['name', 'author', 'uid', 'url'];
|
|
96
|
-
const READ_OF_PROPERTIES = [...READ_OF_TEXT_PROPERTIES, 'photo'];
|
|
97
|
-
export function readOfFromMicropub(values, refuse, baseUrl) {
|
|
98
|
-
if (values.length > 1)
|
|
99
|
-
refuse('read-of takes one value.');
|
|
100
|
-
const [value] = values;
|
|
101
|
-
if (value === undefined)
|
|
102
|
-
return BLANK_READ_OF_FORM;
|
|
103
|
-
const { type, properties } = typeof value === 'object' && value !== null ? value : {};
|
|
104
|
-
if (!Array.isArray(type) ||
|
|
105
|
-
!type.includes('h-cite') ||
|
|
106
|
-
typeof properties !== 'object' ||
|
|
107
|
-
properties === null) {
|
|
108
|
-
refuse('read-of is an h-cite, { "type": ["h-cite"], "properties": { "name": ["…"] } }.');
|
|
109
|
-
return BLANK_READ_OF_FORM;
|
|
110
|
-
}
|
|
111
|
-
const given = properties;
|
|
112
|
-
const unknown = Object.keys(given).filter((name) => !READ_OF_PROPERTIES.includes(name));
|
|
113
|
-
if (unknown.length > 0)
|
|
114
|
-
refuse(`read-of does not understand ${unknown.join(', ')}.`);
|
|
115
|
-
const field = (name) => {
|
|
116
|
-
const values = given[name] ?? [];
|
|
117
|
-
if (!Array.isArray(values) ||
|
|
118
|
-
values.length > 1 ||
|
|
119
|
-
!values.every((v) => typeof v === 'string')) {
|
|
120
|
-
refuse(`read-of ${name} takes one text value.`);
|
|
121
|
-
return '';
|
|
122
|
-
}
|
|
123
|
-
return (values[0] ?? '').trim();
|
|
124
|
-
};
|
|
125
|
-
const photos = given.photo ?? [];
|
|
126
|
-
let photo = { url: '', alt: '' };
|
|
127
|
-
if (!Array.isArray(photos) || photos.length > 1)
|
|
128
|
-
refuse('read-of photo takes one value.');
|
|
129
|
-
else if (photos.length === 1) {
|
|
130
|
-
const row = photoRowFromMicropub(photos[0], baseUrl);
|
|
131
|
-
if (row === undefined)
|
|
132
|
-
refuse('read-of photo is a web address or { "value": "…", "alt": "…" }.');
|
|
133
|
-
else
|
|
134
|
-
photo = row;
|
|
135
|
-
}
|
|
136
|
-
return {
|
|
137
|
-
name: field('name'),
|
|
138
|
-
author: field('author'),
|
|
139
|
-
uid: field('uid'),
|
|
140
|
-
url: field('url'),
|
|
141
|
-
photo: photo.url,
|
|
142
|
-
photoAlt: photo.alt,
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
export function readCite({ photo, ...of }, baseUrl) {
|
|
146
|
-
const fields = Object.entries(of).filter(([, value]) => value !== undefined);
|
|
147
|
-
return {
|
|
148
|
-
type: ['h-cite'],
|
|
149
|
-
properties: {
|
|
150
|
-
...Object.fromEntries(fields.map(([name, value]) => [name, [value]])),
|
|
151
|
-
...(photo === undefined
|
|
152
|
-
? {}
|
|
153
|
-
: { photo: [photoToMicropub({ url: photo.url, alt: photo.alt ?? '' }, baseUrl)] }),
|
|
154
|
-
},
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
//# sourceMappingURL=read-form.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"read-form.js","sourceRoot":"","sources":["../../src/content/read-form.ts"],"names":[],"mappings":"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"}
|
package/dist/content/read.d.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import type { AltTextLibrary } from './alt-text.ts';
|
|
2
|
-
import type { Photo } from './photo.ts';
|
|
3
|
-
export declare const READ_OF_FRONT_MATTER_KEY = "read-of";
|
|
4
|
-
export declare const READ_STATUS_FRONT_MATTER_KEY = "read-status";
|
|
5
|
-
export declare const READ_STATUSES: readonly ['to-read', 'reading', 'finished'];
|
|
6
|
-
export type ReadStatus = (typeof READ_STATUSES)[number];
|
|
7
|
-
export declare const READ_STATUS_LABELS: Readonly<Record<ReadStatus, string>>;
|
|
8
|
-
export interface ReadOf {
|
|
9
|
-
readonly name: string;
|
|
10
|
-
readonly author?: string | undefined;
|
|
11
|
-
readonly uid?: string | undefined;
|
|
12
|
-
readonly url?: string | undefined;
|
|
13
|
-
readonly photo?: Photo | undefined;
|
|
14
|
-
}
|
|
15
|
-
export interface Read {
|
|
16
|
-
readonly status: ReadStatus;
|
|
17
|
-
readonly of: ReadOf;
|
|
18
|
-
}
|
|
19
|
-
export declare function isReadStatus(value: unknown): value is ReadStatus;
|
|
20
|
-
export declare function readOf(extra: Readonly<Record<string, unknown>>): Read | undefined;
|
|
21
|
-
export declare function readWork(value: unknown): ReadOf | undefined;
|
|
22
|
-
export declare function uidLabel(uid: string): string;
|
|
23
|
-
export declare function readWorkFrontMatter({ name, author, uid, url, photo }: ReadOf): ReadOf;
|
|
24
|
-
export interface ReadLineOptions {
|
|
25
|
-
readonly library?: AltTextLibrary | undefined;
|
|
26
|
-
readonly baseUrl?: string | undefined;
|
|
27
|
-
}
|
|
28
|
-
export declare function readLine(read: Read | undefined, options?: ReadLineOptions): string;
|
|
29
|
-
//# sourceMappingURL=read.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../src/content/read.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGpD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC,eAAO,MAAM,wBAAwB,YAAY,CAAC;AAClD,eAAO,MAAM,4BAA4B,gBAAgB,CAAC;AAE1D,eAAO,MAAM,aAAa,YAAI,SAAS,EAAE,SAAS,EAAE,UAAU,CAAU,CAAC;AAEzE,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAExD,eAAO,MAAM,kBAAkB,EAAE,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAInE,CAAC;AAEF,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,SAAS,CAAC;CACpC;AAED,MAAM,WAAW,IAAI;IACnB,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,UAAU,CAEhE;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,IAAI,GAAG,SAAS,CAKjF;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAkB3D;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED,wBAAgB,mBAAmB,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,MAAM,GAAG,MAAM,CAUrF;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IAC9C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACvC;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,SAAS,EAAE,OAAO,GAAE,eAAoB,GAAG,MAAM,CAiBtF"}
|
package/dist/content/read.js
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import { escapeAttribute, escapeText } from '../util/html.js';
|
|
2
|
-
import { absoluteUrl } from '../util/url.js';
|
|
3
|
-
import { isWebUrl } from './enclosure.js';
|
|
4
|
-
import { photoAlt, photoOf } from './photo.js';
|
|
5
|
-
export const READ_OF_FRONT_MATTER_KEY = 'read-of';
|
|
6
|
-
export const READ_STATUS_FRONT_MATTER_KEY = 'read-status';
|
|
7
|
-
export const READ_STATUSES = ['to-read', 'reading', 'finished'];
|
|
8
|
-
export const READ_STATUS_LABELS = {
|
|
9
|
-
'to-read': 'Want to read',
|
|
10
|
-
reading: 'Currently reading',
|
|
11
|
-
finished: 'Finished reading',
|
|
12
|
-
};
|
|
13
|
-
export function isReadStatus(value) {
|
|
14
|
-
return READ_STATUSES.includes(value);
|
|
15
|
-
}
|
|
16
|
-
export function readOf(extra) {
|
|
17
|
-
const status = extra[READ_STATUS_FRONT_MATTER_KEY];
|
|
18
|
-
const of = readWork(extra[READ_OF_FRONT_MATTER_KEY]);
|
|
19
|
-
if (!isReadStatus(status) || of === undefined)
|
|
20
|
-
return undefined;
|
|
21
|
-
return { status, of: isWebUrl(of.url ?? '') ? of : { ...of, url: undefined } };
|
|
22
|
-
}
|
|
23
|
-
export function readWork(value) {
|
|
24
|
-
if (typeof value === 'string')
|
|
25
|
-
return value.trim() === '' ? undefined : { name: value.trim() };
|
|
26
|
-
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
27
|
-
return undefined;
|
|
28
|
-
const fields = value;
|
|
29
|
-
const word = (key) => {
|
|
30
|
-
const field = fields[key];
|
|
31
|
-
return typeof field === 'string' && field.trim() !== '' ? field.trim() : undefined;
|
|
32
|
-
};
|
|
33
|
-
const name = word('name');
|
|
34
|
-
if (name === undefined)
|
|
35
|
-
return undefined;
|
|
36
|
-
const photo = Array.isArray(fields.photo) ? undefined : photoOf(fields.photo);
|
|
37
|
-
return readWorkFrontMatter({
|
|
38
|
-
name,
|
|
39
|
-
author: word('author'),
|
|
40
|
-
uid: word('uid'),
|
|
41
|
-
url: word('url'),
|
|
42
|
-
photo,
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
export function uidLabel(uid) {
|
|
46
|
-
return /^isbn:/i.test(uid) ? `ISBN: ${uid.slice('isbn:'.length)}` : uid;
|
|
47
|
-
}
|
|
48
|
-
export function readWorkFrontMatter({ name, author, uid, url, photo }) {
|
|
49
|
-
return {
|
|
50
|
-
name,
|
|
51
|
-
...(author ? { author } : {}),
|
|
52
|
-
...(uid ? { uid } : {}),
|
|
53
|
-
...(url ? { url } : {}),
|
|
54
|
-
...(photo
|
|
55
|
-
? { photo: photo.alt ? { url: photo.url, alt: photo.alt } : { url: photo.url } }
|
|
56
|
-
: {}),
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
export function readLine(read, options = {}) {
|
|
60
|
-
if (read === undefined)
|
|
61
|
-
return '';
|
|
62
|
-
const { status, of } = read;
|
|
63
|
-
const cited = `<cite class="p-name">${escapeText(of.name)}</cite>`;
|
|
64
|
-
return (`<p class="read-line"><data class="p-read-status" value="${status}">` +
|
|
65
|
-
`${READ_STATUS_LABELS[status]}</data>: <span class="p-read-of h-cite">` +
|
|
66
|
-
(of.photo === undefined ? '' : cover(of.photo, options)) +
|
|
67
|
-
(of.url === undefined
|
|
68
|
-
? cited
|
|
69
|
-
: `<a class="u-url" href="${escapeAttribute(of.url)}">${cited}</a>`) +
|
|
70
|
-
(of.author === undefined ? '' : ` by <span class="p-author">${escapeText(of.author)}</span>`) +
|
|
71
|
-
(of.uid === undefined
|
|
72
|
-
? ''
|
|
73
|
-
: `, <data class="p-uid" value="${escapeAttribute(of.uid)}">${escapeText(uidLabel(of.uid))}</data>`) +
|
|
74
|
-
'</span></p>\n');
|
|
75
|
-
}
|
|
76
|
-
function cover(photo, { library, baseUrl }) {
|
|
77
|
-
const src = baseUrl === undefined ? photo.url : absoluteUrl(photo.url, baseUrl);
|
|
78
|
-
const alt = photoAlt(photo, library ?? new Map()) ?? '';
|
|
79
|
-
return (`<span class="read-cover"><img class="u-photo" src="${escapeAttribute(src)}"` +
|
|
80
|
-
` alt="${escapeAttribute(alt)}"></span>`);
|
|
81
|
-
}
|
|
82
|
-
//# sourceMappingURL=read.js.map
|
package/dist/content/read.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"read.js","sourceRoot":"","sources":["../../src/content/read.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The archives the admin's export job leaves in `data/exports/` for a
|
|
3
|
-
* download (decision-55, section 4). Each holds actor keys, password hashes
|
|
4
|
-
* and personal data, so only the newest is kept and it goes 24 hours after it
|
|
5
|
-
* was written. Its age comes from the time in its name, which the site's
|
|
6
|
-
* clock wrote.
|
|
7
|
-
*/
|
|
8
|
-
export declare const EXPORT_LIFETIME_MS: number;
|
|
9
|
-
export interface ExportArchive {
|
|
10
|
-
readonly name: string;
|
|
11
|
-
readonly path: string;
|
|
12
|
-
readonly writtenAt: Date;
|
|
13
|
-
readonly expiresAt: Date;
|
|
14
|
-
}
|
|
15
|
-
/** Delete the archives 24 hours old or older, and say how many went. */
|
|
16
|
-
export declare function expireExports(dataDir: string, now: Date): Promise<number>;
|
|
17
|
-
/** The archive a download serves: the newest, unless it has expired. Expired ones are deleted. */
|
|
18
|
-
export declare function currentExport(dataDir: string, now: Date): Promise<(ExportArchive & {
|
|
19
|
-
readonly size: number;
|
|
20
|
-
}) | undefined>;
|
|
21
|
-
/**
|
|
22
|
-
* Delete what an export a crash cut off left: everything that is not an
|
|
23
|
-
* archive. Only one export job runs at a time, so no other writer's temporary
|
|
24
|
-
* file is here.
|
|
25
|
-
*/
|
|
26
|
-
export declare function clearUnfinishedExports(dataDir: string): Promise<void>;
|
|
27
|
-
/** Empty the folder but for the archive just written. */
|
|
28
|
-
export declare function keepOnlyExport(dataDir: string, keep: string): Promise<void>;
|
|
29
|
-
//# sourceMappingURL=export-archives.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"export-archives.d.ts","sourceRoot":"","sources":["../../src/export/export-archives.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AAEH,eAAO,MAAM,kBAAkB,QAAsB,CAAC;AAItD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;CAC1B;AAmCD,wEAAwE;AACxE,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAS/E;AAED,kGAAkG;AAClG,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,IAAI,GACR,OAAO,CAAC,CAAC,aAAa,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,SAAS,CAAC,CAUlE;AAED;;;;GAIG;AACH,wBAAsB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAK3E;AAED,yDAAyD;AACzD,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIjF"}
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import { readdir, rm, stat } from 'node:fs/promises';
|
|
2
|
-
import { EXPORTS, dataPath } from '../files/data-files.js';
|
|
3
|
-
/**
|
|
4
|
-
* The archives the admin's export job leaves in `data/exports/` for a
|
|
5
|
-
* download (decision-55, section 4). Each holds actor keys, password hashes
|
|
6
|
-
* and personal data, so only the newest is kept and it goes 24 hours after it
|
|
7
|
-
* was written. Its age comes from the time in its name, which the site's
|
|
8
|
-
* clock wrote.
|
|
9
|
-
*/
|
|
10
|
-
export const EXPORT_LIFETIME_MS = 24 * 60 * 60 * 1000;
|
|
11
|
-
const ARCHIVE = /^geekity-.+-(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})(\d{2})Z\.tar\.gz$/;
|
|
12
|
-
function archiveOf(dataDir, name) {
|
|
13
|
-
const match = ARCHIVE.exec(name);
|
|
14
|
-
if (match === null)
|
|
15
|
-
return undefined;
|
|
16
|
-
const [, year, month, day, hour, minute, second] = match;
|
|
17
|
-
const writtenAt = new Date(`${year}-${month}-${day}T${hour}:${minute}:${second}Z`);
|
|
18
|
-
return {
|
|
19
|
-
name,
|
|
20
|
-
path: dataPath(dataDir, EXPORTS, name),
|
|
21
|
-
writtenAt,
|
|
22
|
-
expiresAt: new Date(writtenAt.getTime() + EXPORT_LIFETIME_MS),
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
async function namesIn(dataDir) {
|
|
26
|
-
try {
|
|
27
|
-
return await readdir(dataPath(dataDir, EXPORTS));
|
|
28
|
-
}
|
|
29
|
-
catch (error) {
|
|
30
|
-
if (error.code === 'ENOENT')
|
|
31
|
-
return [];
|
|
32
|
-
throw error;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
/** Every archive in the folder, newest first. */
|
|
36
|
-
async function archives(dataDir) {
|
|
37
|
-
return (await namesIn(dataDir))
|
|
38
|
-
.flatMap((name) => archiveOf(dataDir, name) ?? [])
|
|
39
|
-
.sort((a, b) => b.writtenAt.getTime() - a.writtenAt.getTime());
|
|
40
|
-
}
|
|
41
|
-
function expired(archive, now) {
|
|
42
|
-
return archive.expiresAt.getTime() <= now.getTime();
|
|
43
|
-
}
|
|
44
|
-
/** Delete the archives 24 hours old or older, and say how many went. */
|
|
45
|
-
export async function expireExports(dataDir, now) {
|
|
46
|
-
let deleted = 0;
|
|
47
|
-
for (const archive of await archives(dataDir)) {
|
|
48
|
-
if (expired(archive, now)) {
|
|
49
|
-
await rm(archive.path, { force: true });
|
|
50
|
-
deleted += 1;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
return deleted;
|
|
54
|
-
}
|
|
55
|
-
/** The archive a download serves: the newest, unless it has expired. Expired ones are deleted. */
|
|
56
|
-
export async function currentExport(dataDir, now) {
|
|
57
|
-
await expireExports(dataDir, now);
|
|
58
|
-
const [newest] = await archives(dataDir);
|
|
59
|
-
if (newest === undefined)
|
|
60
|
-
return undefined;
|
|
61
|
-
try {
|
|
62
|
-
return { ...newest, size: (await stat(newest.path)).size };
|
|
63
|
-
}
|
|
64
|
-
catch (error) {
|
|
65
|
-
if (error.code === 'ENOENT')
|
|
66
|
-
return undefined;
|
|
67
|
-
throw error;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Delete what an export a crash cut off left: everything that is not an
|
|
72
|
-
* archive. Only one export job runs at a time, so no other writer's temporary
|
|
73
|
-
* file is here.
|
|
74
|
-
*/
|
|
75
|
-
export async function clearUnfinishedExports(dataDir) {
|
|
76
|
-
for (const name of await namesIn(dataDir)) {
|
|
77
|
-
if (!ARCHIVE.test(name))
|
|
78
|
-
await rm(dataPath(dataDir, EXPORTS, name), { recursive: true, force: true });
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
/** Empty the folder but for the archive just written. */
|
|
82
|
-
export async function keepOnlyExport(dataDir, keep) {
|
|
83
|
-
for (const name of await namesIn(dataDir)) {
|
|
84
|
-
if (name !== keep)
|
|
85
|
-
await rm(dataPath(dataDir, EXPORTS, name), { recursive: true, force: true });
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
//# sourceMappingURL=export-archives.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"export-archives.js","sourceRoot":"","sources":["../../src/export/export-archives.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import type { Context, Hono, MiddlewareHandler } from 'hono';
|
|
2
|
-
import type { GeekityEnv } from '../web/env.ts';
|
|
3
|
-
import type { User } from '../site/users.ts';
|
|
4
|
-
import type { FederationContextData, SiteFederation } from './federation.ts';
|
|
5
|
-
/**
|
|
6
|
-
* Put Fedify in front of the rest of the app.
|
|
7
|
-
*
|
|
8
|
-
* The middleware only answers the paths Fedify registered — the actor, its
|
|
9
|
-
* collections, WebFinger and NodeInfo; everything else falls through to
|
|
10
|
-
* `next()` and reaches the admin and the public site as before. That is why it
|
|
11
|
-
* is mounted first: the public site claims every unmatched path in its
|
|
12
|
-
* not-found handler, so anything registered after it never sees a request.
|
|
13
|
-
*
|
|
14
|
-
* A post's object is not one of Fedify's paths at all. decision-13 makes a
|
|
15
|
-
* post's ActivityStreams id its permalink, so {@link activityStreamsDocument}
|
|
16
|
-
* is what serves the `Article`: one URL, answering a browser with the page and
|
|
17
|
-
* a peer with the object. The same handler answers at the `activitypub.id` a
|
|
18
|
-
* migrated post's file names, and sends a browser from there to the permalink.
|
|
19
|
-
*
|
|
20
|
-
* The dispatchers are handed the stores off the Hono context rather than
|
|
21
|
-
* closing over them, so one federation object could serve more than one CMS
|
|
22
|
-
* and so a dispatcher is never reading a store the request did not come with.
|
|
23
|
-
*/
|
|
24
|
-
export declare function mountFederation(app: Hono<GeekityEnv>, federation: SiteFederation, options?: MountFederationOptions): void;
|
|
25
|
-
/** What {@link mountFederation} takes beyond the site's own federation. */
|
|
26
|
-
export interface MountFederationOptions {
|
|
27
|
-
/** The phase plugins answer federation requests in. */
|
|
28
|
-
plugins?: MiddlewareHandler<GeekityEnv> | undefined;
|
|
29
|
-
}
|
|
30
|
-
/** Where WebFinger lives, which is defined on the host rather than under a site. */
|
|
31
|
-
export declare const WEBFINGER_PATH = "/.well-known/webfinger";
|
|
32
|
-
/** `acct:{username}@{host}`, the handle a person types into a search box. */
|
|
33
|
-
export declare function acctOf(username: string, baseUrl: string): string;
|
|
34
|
-
/**
|
|
35
|
-
* The user a WebFinger `resource` asks about, or `undefined` for one this site
|
|
36
|
-
* answers for nobody.
|
|
37
|
-
*
|
|
38
|
-
* Every spelling of a person resolves, and they are the ones decision-14 lists
|
|
39
|
-
* as their aliases: the `acct:` handle, the author archive, `/@{username}` and
|
|
40
|
-
* — for somebody who was published elsewhere first — the id they were
|
|
41
|
-
* published under. Matching every one of them is what lets a peer that holds
|
|
42
|
-
* any one URL for this person find the others, which is the whole job of
|
|
43
|
-
* WebFinger, and it is how a server holding only `?author=2` discovers that
|
|
44
|
-
* the account it follows is still here.
|
|
45
|
-
*
|
|
46
|
-
* Both sides of the comparison go through {@link canonicalResource} first, so
|
|
47
|
-
* the spellings that differ only in how they were typed are one spelling by
|
|
48
|
-
* the time they are matched, and no spelling needs a branch of its own.
|
|
49
|
-
*/
|
|
50
|
-
export declare function webFingerSubject(c: Context<GeekityEnv>, resource: string): User | undefined;
|
|
51
|
-
/** What the dispatchers are handed, off the Hono context. */
|
|
52
|
-
export declare function contextData(c: Context<GeekityEnv>): FederationContextData;
|
|
53
|
-
//# sourceMappingURL=mount.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mount.d.ts","sourceRoot":"","sources":["../../src/federation/mount.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAK7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEhD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAQ7C,OAAO,KAAK,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAG7E;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,IAAI,CAAC,UAAU,CAAC,EACrB,UAAU,EAAE,cAAc,EAC1B,OAAO,GAAE,sBAA2B,GACnC,IAAI,CAuGN;AAED,2EAA2E;AAC3E,MAAM,WAAW,sBAAsB;IACrC,uDAAuD;IACvD,OAAO,CAAC,EAAE,iBAAiB,CAAC,UAAU,CAAC,GAAG,SAAS,CAAC;CACrD;AA+JD,oFAAoF;AACpF,eAAO,MAAM,cAAc,2BAA2B,CAAC;AAEvD,6EAA6E;AAC7E,wBAAgB,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAa3F;AAoCD,6DAA6D;AAC7D,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,qBAAqB,CAQzE"}
|