@geekity/cms 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +71 -21
- package/admin/components/admin-bar.njk +26 -0
- package/admin/components/public-admin-bar.njk +41 -0
- package/admin/layouts/base.njk +1 -0
- package/admin/layouts/shell.njk +8 -19
- package/admin/static/admin-bar.css +137 -0
- package/admin/static/admin.css +1 -102
- package/dist/admin/comments.js +2 -1
- package/dist/admin/comments.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.map +1 -1
- package/dist/admin/personal-data.d.ts.map +1 -1
- package/dist/admin/personal-data.js +5 -1
- package/dist/admin/personal-data.js.map +1 -1
- package/dist/admin/preview.d.ts.map +1 -1
- package/dist/admin/preview.js +1 -1
- package/dist/admin/preview.js.map +1 -1
- package/dist/admin/routes.d.ts.map +1 -1
- package/dist/admin/routes.js +2 -1
- package/dist/admin/routes.js.map +1 -1
- package/dist/admin/store.d.ts +35 -0
- package/dist/admin/store.d.ts.map +1 -1
- package/dist/admin/store.js +62 -0
- package/dist/admin/store.js.map +1 -1
- package/dist/admin/templates.d.ts +1 -0
- package/dist/admin/templates.d.ts.map +1 -1
- package/dist/admin/templates.js +1 -0
- package/dist/admin/templates.js.map +1 -1
- package/dist/admin/tools.d.ts +2 -0
- package/dist/admin/tools.d.ts.map +1 -1
- package/dist/admin/tools.js +3 -2
- package/dist/admin/tools.js.map +1 -1
- package/dist/comments/index.d.ts +2 -2
- package/dist/comments/index.d.ts.map +1 -1
- package/dist/comments/index.js +1 -1
- package/dist/comments/index.js.map +1 -1
- package/dist/comments/records.d.ts +43 -2
- package/dist/comments/records.d.ts.map +1 -1
- package/dist/comments/records.js +201 -54
- package/dist/comments/records.js.map +1 -1
- package/dist/comments/routes.js +1 -1
- package/dist/comments/routes.js.map +1 -1
- package/dist/comments/viewer.d.ts +13 -0
- package/dist/comments/viewer.d.ts.map +1 -1
- package/dist/comments/viewer.js +13 -1
- package/dist/comments/viewer.js.map +1 -1
- package/dist/config.d.ts +11 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/env.d.ts +19 -0
- package/dist/env.d.ts.map +1 -1
- package/dist/federation/delivery.d.ts +3 -1
- package/dist/federation/delivery.d.ts.map +1 -1
- package/dist/federation/delivery.js +6 -1
- package/dist/federation/delivery.js.map +1 -1
- package/dist/federation/federation.d.ts +3 -0
- package/dist/federation/federation.d.ts.map +1 -1
- package/dist/federation/federation.js.map +1 -1
- package/dist/federation/inbox.d.ts +7 -5
- package/dist/federation/inbox.d.ts.map +1 -1
- package/dist/federation/inbox.js +15 -32
- package/dist/federation/inbox.js.map +1 -1
- package/dist/federation/index.d.ts +2 -0
- package/dist/federation/index.d.ts.map +1 -1
- package/dist/federation/index.js +1 -0
- package/dist/federation/index.js.map +1 -1
- package/dist/federation/mount.js +6 -1
- package/dist/federation/mount.js.map +1 -1
- package/dist/federation/profiles.d.ts +95 -0
- package/dist/federation/profiles.d.ts.map +1 -0
- package/dist/federation/profiles.js +171 -0
- package/dist/federation/profiles.js.map +1 -0
- package/dist/federation/relays.d.ts +3 -1
- package/dist/federation/relays.d.ts.map +1 -1
- package/dist/federation/relays.js +6 -1
- package/dist/federation/relays.js.map +1 -1
- package/dist/federation/replies.d.ts +13 -4
- package/dist/federation/replies.d.ts.map +1 -1
- package/dist/federation/replies.js +25 -6
- package/dist/federation/replies.js.map +1 -1
- package/dist/images/icons.d.ts.map +1 -1
- package/dist/images/icons.js +3 -2
- package/dist/images/icons.js.map +1 -1
- package/dist/images/index.d.ts +2 -2
- package/dist/images/index.d.ts.map +1 -1
- package/dist/images/markup.d.ts +15 -4
- package/dist/images/markup.d.ts.map +1 -1
- package/dist/images/markup.js +24 -15
- package/dist/images/markup.js.map +1 -1
- package/dist/images/paths.d.ts +11 -0
- package/dist/images/paths.d.ts.map +1 -1
- package/dist/images/paths.js +17 -1
- package/dist/images/paths.js.map +1 -1
- package/dist/images/variants.d.ts +13 -3
- package/dist/images/variants.d.ts.map +1 -1
- package/dist/images/variants.js +13 -11
- package/dist/images/variants.js.map +1 -1
- package/dist/index.d.ts +11 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +50 -11
- package/dist/index.js.map +1 -1
- package/dist/notifications/routes.js +1 -1
- package/dist/notifications/routes.js.map +1 -1
- package/dist/privacy/erase.d.ts.map +1 -1
- package/dist/privacy/erase.js +2 -3
- package/dist/privacy/erase.js.map +1 -1
- package/dist/privacy/retention.js +1 -1
- package/dist/privacy/retention.js.map +1 -1
- package/dist/web/admin-bar.d.ts +21 -0
- package/dist/web/admin-bar.d.ts.map +1 -0
- package/dist/web/admin-bar.js +145 -0
- package/dist/web/admin-bar.js.map +1 -0
- package/dist/web/assets.d.ts +29 -1
- package/dist/web/assets.d.ts.map +1 -1
- package/dist/web/assets.js +48 -3
- package/dist/web/assets.js.map +1 -1
- package/dist/web/compression.d.ts +19 -0
- package/dist/web/compression.d.ts.map +1 -0
- package/dist/web/compression.js +160 -0
- package/dist/web/compression.js.map +1 -0
- package/dist/web/context.d.ts +5 -1
- package/dist/web/context.d.ts.map +1 -1
- package/dist/web/context.js +5 -2
- package/dist/web/context.js.map +1 -1
- package/dist/web/conversation.d.ts.map +1 -1
- package/dist/web/conversation.js +13 -12
- package/dist/web/conversation.js.map +1 -1
- package/dist/web/render.d.ts +27 -0
- package/dist/web/render.d.ts.map +1 -1
- package/dist/web/render.js +77 -38
- package/dist/web/render.js.map +1 -1
- package/dist/web/routes.d.ts.map +1 -1
- package/dist/web/routes.js +63 -28
- package/dist/web/routes.js.map +1 -1
- package/dist/web/templates.d.ts.map +1 -1
- package/dist/web/templates.js +9 -2
- package/dist/web/templates.js.map +1 -1
- package/dist/webmention/service.d.ts.map +1 -1
- package/dist/webmention/service.js +5 -1
- package/dist/webmention/service.js.map +1 -1
- package/package.json +1 -1
- package/themes/default/README.md +143 -19
- package/themes/default/layouts/base.njk +51 -10
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { editorPath, newEditorPath, PAGE_KIND, POST_KIND } from '../admin/documents.js';
|
|
2
|
+
import { LOGOUT_PATH } from '../admin/routes.js';
|
|
3
|
+
import { ADMIN_PREFIX } from '../admin/session.js';
|
|
4
|
+
import { ADMIN_TEMPLATES, createAdminTemplateEnvironment } from '../admin/templates.js';
|
|
5
|
+
import { editUserPath } from '../admin/users.js';
|
|
6
|
+
import { signedInAccount } from '../comments/viewer.js';
|
|
7
|
+
import { PRIVATE_CACHE_CONTROL } from './negotiate.js';
|
|
8
|
+
import { requestPath } from './routes.js';
|
|
9
|
+
/** The editor screens each kind of document is written in. */
|
|
10
|
+
const KINDS = { post: POST_KIND, page: PAGE_KIND };
|
|
11
|
+
/** Built on the first signed-in page; the admin's own is closed over by its mount. */
|
|
12
|
+
let environment;
|
|
13
|
+
/**
|
|
14
|
+
* The admin bar across the top of the public site, for a signed-in user
|
|
15
|
+
* (TASK-183).
|
|
16
|
+
*
|
|
17
|
+
* Where the public site's pages learn who is reading them. An anonymous request
|
|
18
|
+
* goes through untouched, so what everybody else is sent, headers and bytes, is what
|
|
19
|
+
* it was before the bar existed. For a signed-in one the account is put on the
|
|
20
|
+
* context for the handlers, and whatever HTML they answer with, a document, a
|
|
21
|
+
* listing, a search, the 404 or the 500, gets the bar straight after its
|
|
22
|
+
* `<body>` tag, the stylesheet that makes room for it in `<head>`, the
|
|
23
|
+
* `geekity-admin-bar` class on `<html>`, and the headers of a page drawn for
|
|
24
|
+
* one reader: private, no-store, and no validator. Anything that is not HTML, the JSON, the
|
|
25
|
+
* Markdown, the feeds, ActivityPub, is left exactly as it was.
|
|
26
|
+
*
|
|
27
|
+
* Not inside `/admin`, which has a bar of its own and a CSP that would refuse
|
|
28
|
+
* this one's inline stylesheet.
|
|
29
|
+
*/
|
|
30
|
+
export const publicAdminBar = async (c, next) => {
|
|
31
|
+
const pathname = requestPath(c);
|
|
32
|
+
if (pathname === ADMIN_PREFIX || pathname.startsWith(`${ADMIN_PREFIX}/`))
|
|
33
|
+
return await next();
|
|
34
|
+
const account = signedInAccount(c);
|
|
35
|
+
if (account === undefined)
|
|
36
|
+
return await next();
|
|
37
|
+
c.set('signedIn', account);
|
|
38
|
+
await next();
|
|
39
|
+
if (!(c.res.headers.get('content-type') ?? '').startsWith('text/html'))
|
|
40
|
+
return;
|
|
41
|
+
const headers = new Headers(c.res.headers);
|
|
42
|
+
headers.set('cache-control', PRIVATE_CACHE_CONTROL);
|
|
43
|
+
headers.delete('etag');
|
|
44
|
+
headers.delete('last-modified');
|
|
45
|
+
headers.delete('content-length');
|
|
46
|
+
const { status } = c.res;
|
|
47
|
+
const body = withAdminBar(withoutSpeculationRules(await c.res.text()), renderBar(c, account));
|
|
48
|
+
// Cleared first, because assigning over a response copies its headers onto
|
|
49
|
+
// the new one, and the validators being dropped would come straight back.
|
|
50
|
+
c.res = undefined;
|
|
51
|
+
c.res = new Response(body, { status, headers });
|
|
52
|
+
};
|
|
53
|
+
/** The bar's markup for this reader and this page. */
|
|
54
|
+
function renderBar(c, account) {
|
|
55
|
+
environment ??= createAdminTemplateEnvironment({ noCache: c.var.config.watch });
|
|
56
|
+
const { user } = account;
|
|
57
|
+
const shown = c.var.shownDocument;
|
|
58
|
+
return environment
|
|
59
|
+
.render(ADMIN_TEMPLATES.publicAdminBar, {
|
|
60
|
+
site: c.var.renderer.site(),
|
|
61
|
+
adminUrl: ADMIN_PREFIX,
|
|
62
|
+
barLinks: [
|
|
63
|
+
{ label: '+ New', url: newEditorPath(POST_KIND) },
|
|
64
|
+
...(shown === undefined
|
|
65
|
+
? []
|
|
66
|
+
: [
|
|
67
|
+
{
|
|
68
|
+
label: `Edit ${capitalized(KINDS[shown.type].singular)}`,
|
|
69
|
+
url: editorPath(KINDS[shown.type], shown.slug),
|
|
70
|
+
},
|
|
71
|
+
]),
|
|
72
|
+
],
|
|
73
|
+
me: { name: user.profile?.displayName ?? user.username, url: editUserPath(user.id) },
|
|
74
|
+
logoutUrl: LOGOUT_PATH,
|
|
75
|
+
csrfToken: account.csrfToken,
|
|
76
|
+
})
|
|
77
|
+
.trim();
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* `html` with every `<script type="speculationrules">` taken out (TASK-140).
|
|
81
|
+
*
|
|
82
|
+
* A signed-in reader's pages are drawn for them alone and never stored, so a
|
|
83
|
+
* prefetch is a second render nobody may see, and a speculative request that
|
|
84
|
+
* carries a session is one the site would rather not be sent. Removed here
|
|
85
|
+
* rather than left to each theme, so a theme's rules stay one static block and
|
|
86
|
+
* the anonymous page keeps its bytes.
|
|
87
|
+
*/
|
|
88
|
+
function withoutSpeculationRules(html) {
|
|
89
|
+
return html.replace(/<script\b[^>]*\btype\s*=\s*(["']?)speculationrules\1[^>]*>[\s\S]*?<\/script\s*>/gi, '');
|
|
90
|
+
}
|
|
91
|
+
/** The class on `<html>` of a page that carries the bar, for a theme to key off. */
|
|
92
|
+
const ROOT_CLASS = 'geekity-admin-bar';
|
|
93
|
+
/**
|
|
94
|
+
* The room the bar takes at the top of the page, set from outside its shadow
|
|
95
|
+
* root because the bar is fixed and takes none by itself.
|
|
96
|
+
*
|
|
97
|
+
* `--geekity-admin-bar-height` is the bar's height, for a theme's own sticky
|
|
98
|
+
* or fixed header to sit under it. The script in the bar replaces it with the
|
|
99
|
+
* height it measures; until then, or without script, it is one 40px line, and
|
|
100
|
+
* two on a screen narrow enough for the bar to wrap.
|
|
101
|
+
*
|
|
102
|
+
* The page moves down by a margin on `<html>`, as it does under WordPress's
|
|
103
|
+
* bar: a theme's padding on `<html>` or `<body>` is left alone, `!important`
|
|
104
|
+
* outlasts a reset such as `html, body { margin: 0 }`, and the root's
|
|
105
|
+
* background still fills the canvas behind the bar. `scroll-padding-top` is
|
|
106
|
+
* under `:where()` so that a theme that sets its own, for a sticky header of
|
|
107
|
+
* its own, keeps it.
|
|
108
|
+
*/
|
|
109
|
+
const OFFSET_STYLE = `<style id="geekity-admin-bar-offset">
|
|
110
|
+
:root { --geekity-admin-bar-height: 40px; }
|
|
111
|
+
@media (max-width: 600px) { :root { --geekity-admin-bar-height: 80px; } }
|
|
112
|
+
html { margin-top: var(--geekity-admin-bar-height) !important; }
|
|
113
|
+
:where(html) { scroll-padding-top: var(--geekity-admin-bar-height); }
|
|
114
|
+
</style>`;
|
|
115
|
+
/**
|
|
116
|
+
* `html` with `bar` straight after its opening `<body>` tag, the offset
|
|
117
|
+
* stylesheet before `</head>`, and the root class on `<html>`; unchanged when
|
|
118
|
+
* it has no `<body>` tag to put the bar after.
|
|
119
|
+
*/
|
|
120
|
+
function withAdminBar(html, bar) {
|
|
121
|
+
const body = /<body\b[^>]*>/i.exec(html);
|
|
122
|
+
if (body === null)
|
|
123
|
+
return html;
|
|
124
|
+
const afterBody = body.index + body[0].length;
|
|
125
|
+
const head = /<\/head\s*>/i.exec(html.slice(0, body.index));
|
|
126
|
+
const withBar = head === null
|
|
127
|
+
? `${html.slice(0, afterBody)}${OFFSET_STYLE}${bar}${html.slice(afterBody)}`
|
|
128
|
+
: `${html.slice(0, head.index)}${OFFSET_STYLE}${html.slice(head.index, afterBody)}${bar}${html.slice(afterBody)}`;
|
|
129
|
+
return withRootClass(withBar);
|
|
130
|
+
}
|
|
131
|
+
/** `html` with ROOT_CLASS added to its `<html>` tag's classes. */
|
|
132
|
+
function withRootClass(html) {
|
|
133
|
+
const tag = /<html\b[^>]*>/i.exec(html);
|
|
134
|
+
if (tag === null)
|
|
135
|
+
return html;
|
|
136
|
+
const attribute = /(\sclass\s*=\s*)(?:"([^"]*)"|'([^']*)'|([^\s>]+))/i;
|
|
137
|
+
const classed = attribute.test(tag[0])
|
|
138
|
+
? tag[0].replace(attribute, (_match, lead, double, single, bare) => `${lead}"${ROOT_CLASS} ${(double ?? single ?? bare ?? '').replaceAll('"', '"')}"`)
|
|
139
|
+
: tag[0].replace(/^<html\b/i, `<html class="${ROOT_CLASS}"`);
|
|
140
|
+
return `${html.slice(0, tag.index)}${classed}${html.slice(tag.index + tag[0].length)}`;
|
|
141
|
+
}
|
|
142
|
+
function capitalized(word) {
|
|
143
|
+
return `${word.charAt(0).toUpperCase()}${word.slice(1)}`;
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=admin-bar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin-bar.js","sourceRoot":"","sources":["../../src/web/admin-bar.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAExF,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,8BAA8B,EAAE,MAAM,uBAAuB,CAAC;AACxF,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAIxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,8DAA8D;AAC9D,MAAM,KAAK,GAAiD,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;AAEjG,sFAAsF;AACtF,IAAI,WAAoC,CAAC;AAEzC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,cAAc,GAAkC,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE;IAC7E,MAAM,QAAQ,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;IAChC,IAAI,QAAQ,KAAK,YAAY,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,YAAY,GAAG,CAAC;QAAE,OAAO,MAAM,IAAI,EAAE,CAAC;IAE9F,MAAM,OAAO,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;IACnC,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,MAAM,IAAI,EAAE,CAAC;IAE/C,CAAC,CAAC,GAAG,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAC3B,MAAM,IAAI,EAAE,CAAC;IAEb,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC,UAAU,CAAC,WAAW,CAAC;QAAE,OAAO;IAE/E,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC3C,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,qBAAqB,CAAC,CAAC;IACpD,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACvB,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;IAChC,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;IAEjC,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC;IACzB,MAAM,IAAI,GAAG,YAAY,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;IAC9F,2EAA2E;IAC3E,0EAA0E;IAC1E,CAAC,CAAC,GAAG,GAAG,SAAS,CAAC;IAClB,CAAC,CAAC,GAAG,GAAG,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;AAClD,CAAC,CAAC;AAEF,sDAAsD;AACtD,SAAS,SAAS,CAAC,CAAsB,EAAE,OAAwB;IACjE,WAAW,KAAK,8BAA8B,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;IAChF,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC;IACzB,MAAM,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC;IAElC,OAAO,WAAW;SACf,MAAM,CAAC,eAAe,CAAC,cAAc,EAAE;QACtC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE;QAC3B,QAAQ,EAAE,YAAY;QACtB,QAAQ,EAAE;YACR,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,aAAa,CAAC,SAAS,CAAC,EAAE;YACjD,GAAG,CAAC,KAAK,KAAK,SAAS;gBACrB,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC;oBACE;wBACE,KAAK,EAAE,QAAQ,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,EAAE;wBACxD,GAAG,EAAE,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC;qBAC/C;iBACF,CAAC;SACP;QACD,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,WAAW,IAAI,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE;QACpF,SAAS,EAAE,WAAW;QACtB,SAAS,EAAE,OAAO,CAAC,SAAS;KAC7B,CAAC;SACD,IAAI,EAAE,CAAC;AACZ,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,uBAAuB,CAAC,IAAY;IAC3C,OAAO,IAAI,CAAC,OAAO,CACjB,mFAAmF,EACnF,EAAE,CACH,CAAC;AACJ,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,GAAG,mBAAmB,CAAC;AAEvC;;;;;;;;;;;;;;;GAeG;AACH,MAAM,YAAY,GAAG;;;;;SAKZ,CAAC;AAEV;;;;GAIG;AACH,SAAS,YAAY,CAAC,IAAY,EAAE,GAAW;IAC7C,MAAM,IAAI,GAAG,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzC,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC/B,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IAC9C,MAAM,IAAI,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAC5D,MAAM,OAAO,GACX,IAAI,KAAK,IAAI;QACX,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,GAAG,YAAY,GAAG,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE;QAC5E,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;IACtH,OAAO,aAAa,CAAC,OAAO,CAAC,CAAC;AAChC,CAAC;AAED,kEAAkE;AAClE,SAAS,aAAa,CAAC,IAAY;IACjC,MAAM,GAAG,GAAG,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxC,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC9B,MAAM,SAAS,GAAG,oDAAoD,CAAC;IACvE,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACpC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CACZ,SAAS,EACT,CAAC,MAAM,EAAE,IAAY,EAAE,MAAe,EAAE,MAAe,EAAE,IAAa,EAAE,EAAE,CACxE,GAAG,IAAI,IAAI,UAAU,IAAI,CAAC,MAAM,IAAI,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,GAAG,CACzF;QACH,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,gBAAgB,UAAU,GAAG,CAAC,CAAC;IAC/D,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,GAAG,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;AACzF,CAAC;AAED,SAAS,WAAW,CAAC,IAAY;IAC/B,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AAC3D,CAAC"}
|
package/dist/web/assets.d.ts
CHANGED
|
@@ -17,8 +17,15 @@ export declare const UPLOAD_ASSET_MAX_AGE = 86400;
|
|
|
17
17
|
export declare function findUpload(relative: string, contentDir: string): StaticAsset | undefined;
|
|
18
18
|
/** Directory inside a theme that holds the files served over HTTP. */
|
|
19
19
|
export declare const THEME_STATIC_DIR = "static";
|
|
20
|
-
/** How long a browser may keep a theme asset. One hour. */
|
|
20
|
+
/** How long a browser may keep a theme asset at its unhashed URL. One hour. */
|
|
21
21
|
export declare const THEME_ASSET_MAX_AGE = 3600;
|
|
22
|
+
/**
|
|
23
|
+
* How long a browser may keep a file whose URL names its bytes. A year, the
|
|
24
|
+
* longest lifetime HTTP caches are asked to honour.
|
|
25
|
+
*/
|
|
26
|
+
export declare const IMMUTABLE_ASSET_MAX_AGE = 31536000;
|
|
27
|
+
/** The query parameter a fingerprinted theme asset URL carries its hash in. */
|
|
28
|
+
export declare const ASSET_VERSION_PARAM = "v";
|
|
22
29
|
/** A file on disk, located and described, ready to be served. */
|
|
23
30
|
export interface StaticAsset {
|
|
24
31
|
/** Absolute path on disk. */
|
|
@@ -52,7 +59,28 @@ export declare function findThemeAsset(relative: string, themeDirs: readonly str
|
|
|
52
59
|
export interface AssetResponseOptions {
|
|
53
60
|
/** Seconds. Defaults to {@link THEME_ASSET_MAX_AGE}. */
|
|
54
61
|
maxAge?: number | undefined;
|
|
62
|
+
/** Whether the bytes at this URL can never change, so a browser need not revalidate. */
|
|
63
|
+
immutable?: boolean | undefined;
|
|
55
64
|
}
|
|
65
|
+
/** The lifetime of a response whose URL names its bytes. */
|
|
66
|
+
export declare const IMMUTABLE_ASSET: AssetResponseOptions;
|
|
67
|
+
/**
|
|
68
|
+
* A short hash of an asset's bytes, the part of a fingerprinted URL that
|
|
69
|
+
* changes when the file does.
|
|
70
|
+
*
|
|
71
|
+
* Memoised per file on the size-and-mtime validator, so a page pays a `stat`
|
|
72
|
+
* rather than a read, and an edit in place is seen on the next render with no
|
|
73
|
+
* restart and no watcher.
|
|
74
|
+
*/
|
|
75
|
+
export declare function assetVersion(asset: StaticAsset): string;
|
|
76
|
+
/**
|
|
77
|
+
* The URL a theme should link one of its files at: under
|
|
78
|
+
* {@link THEME_ASSET_PREFIX} with a hash of the bytes the search path resolves
|
|
79
|
+
* to, so it can be cached for a year and still change the moment the file
|
|
80
|
+
* does. A file no theme has gets its plain URL, which will 404 as it would
|
|
81
|
+
* have anyway.
|
|
82
|
+
*/
|
|
83
|
+
export declare function themeAssetUrl(relative: string, themeDirs: readonly string[]): string;
|
|
56
84
|
/** The response body and headers for an asset. */
|
|
57
85
|
export declare function assetResponse(asset: StaticAsset, options?: AssetResponseOptions): Response;
|
|
58
86
|
/** The 304 an unchanged asset gets, which carries the validators and no body. */
|
package/dist/web/assets.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../src/web/assets.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../src/web/assets.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAIrC,yDAAyD;AACzD,eAAO,MAAM,kBAAkB,YAAY,CAAC;AAE5C;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,cAAc,CAAC;AAE/C,2EAA2E;AAC3E,eAAO,MAAM,gBAAgB,YAAY,CAAC;AAE1C,qFAAqF;AACrF,eAAO,MAAM,oBAAoB,QAAQ,CAAC;AAE1C,yDAAyD;AACzD,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAExF;AAED,sEAAsE;AACtE,eAAO,MAAM,gBAAgB,WAAW,CAAC;AAEzC,+EAA+E;AAC/E,eAAO,MAAM,mBAAmB,OAAO,CAAC;AAExC;;;GAGG;AACH,eAAO,MAAM,uBAAuB,WAAW,CAAC;AAEhD,+EAA+E;AAC/E,eAAO,MAAM,mBAAmB,MAAM,CAAC;AAEvC,iEAAiE;AACjE,MAAM,WAAW,WAAW;IAC1B,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,sDAAsD;IACtD,KAAK,EAAE,KAAK,CAAC;IACb,sCAAsC;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,0EAA0E;AAC1E,MAAM,MAAM,UAAU,GAAG,WAAW,CAAC;AAErC;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,WAAW,GAAG,SAAS,CA6BpF;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,SAAS,MAAM,EAAE,GAC3B,UAAU,GAAG,SAAS,CAKxB;AAED,0EAA0E;AAC1E,MAAM,WAAW,oBAAoB;IACnC,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,wFAAwF;IACxF,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACjC;AAED,4DAA4D;AAC5D,eAAO,MAAM,eAAe,EAAE,oBAG7B,CAAC;AAIF;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAOvD;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAKpF;AAED,kDAAkD;AAClD,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,GAAE,oBAAyB,GAAG,QAAQ,CAG9F;AAED,iFAAiF;AACjF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,GAAE,oBAAyB,GAAG,QAAQ,CAKjG;AAED,2DAA2D;AAC3D,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,UAAU,GAAG,QAAQ,CAE9D;AAED,8DAA8D;AAC9D,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,UAAU,GAAG,QAAQ,CAEjE;AAED,6DAA6D;AAC7D,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAOlF"}
|
package/dist/web/assets.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { createReadStream, readFileSync, statSync } from 'node:fs';
|
|
2
3
|
import path from 'node:path';
|
|
3
4
|
import { Readable } from 'node:stream';
|
|
4
5
|
/** URL prefix the theme's own files are served under. */
|
|
@@ -21,8 +22,15 @@ export function findUpload(relative, contentDir) {
|
|
|
21
22
|
}
|
|
22
23
|
/** Directory inside a theme that holds the files served over HTTP. */
|
|
23
24
|
export const THEME_STATIC_DIR = 'static';
|
|
24
|
-
/** How long a browser may keep a theme asset. One hour. */
|
|
25
|
+
/** How long a browser may keep a theme asset at its unhashed URL. One hour. */
|
|
25
26
|
export const THEME_ASSET_MAX_AGE = 3600;
|
|
27
|
+
/**
|
|
28
|
+
* How long a browser may keep a file whose URL names its bytes. A year, the
|
|
29
|
+
* longest lifetime HTTP caches are asked to honour.
|
|
30
|
+
*/
|
|
31
|
+
export const IMMUTABLE_ASSET_MAX_AGE = 31536000;
|
|
32
|
+
/** The query parameter a fingerprinted theme asset URL carries its hash in. */
|
|
33
|
+
export const ASSET_VERSION_PARAM = 'v';
|
|
26
34
|
/**
|
|
27
35
|
* Find one file under a list of roots, first root that has it winning.
|
|
28
36
|
*
|
|
@@ -69,6 +77,42 @@ export function findAsset(relative, roots) {
|
|
|
69
77
|
export function findThemeAsset(relative, themeDirs) {
|
|
70
78
|
return findAsset(relative, themeDirs.map((themeDir) => path.join(themeDir, THEME_STATIC_DIR)));
|
|
71
79
|
}
|
|
80
|
+
/** The lifetime of a response whose URL names its bytes. */
|
|
81
|
+
export const IMMUTABLE_ASSET = {
|
|
82
|
+
maxAge: IMMUTABLE_ASSET_MAX_AGE,
|
|
83
|
+
immutable: true,
|
|
84
|
+
};
|
|
85
|
+
const versions = new Map();
|
|
86
|
+
/**
|
|
87
|
+
* A short hash of an asset's bytes, the part of a fingerprinted URL that
|
|
88
|
+
* changes when the file does.
|
|
89
|
+
*
|
|
90
|
+
* Memoised per file on the size-and-mtime validator, so a page pays a `stat`
|
|
91
|
+
* rather than a read, and an edit in place is seen on the next render with no
|
|
92
|
+
* restart and no watcher.
|
|
93
|
+
*/
|
|
94
|
+
export function assetVersion(asset) {
|
|
95
|
+
const known = versions.get(asset.file);
|
|
96
|
+
if (known?.etag === asset.etag)
|
|
97
|
+
return known.version;
|
|
98
|
+
const version = createHash('sha256').update(readFileSync(asset.file)).digest('hex').slice(0, 12);
|
|
99
|
+
versions.set(asset.file, { etag: asset.etag, version });
|
|
100
|
+
return version;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* The URL a theme should link one of its files at: under
|
|
104
|
+
* {@link THEME_ASSET_PREFIX} with a hash of the bytes the search path resolves
|
|
105
|
+
* to, so it can be cached for a year and still change the moment the file
|
|
106
|
+
* does. A file no theme has gets its plain URL, which will 404 as it would
|
|
107
|
+
* have anyway.
|
|
108
|
+
*/
|
|
109
|
+
export function themeAssetUrl(relative, themeDirs) {
|
|
110
|
+
const pathname = `${THEME_ASSET_PREFIX}${relative.replace(/^\/+/, '')}`;
|
|
111
|
+
const asset = findThemeAsset(relative, themeDirs);
|
|
112
|
+
if (asset === undefined)
|
|
113
|
+
return pathname;
|
|
114
|
+
return `${pathname}?${ASSET_VERSION_PARAM}=${assetVersion(asset)}`;
|
|
115
|
+
}
|
|
72
116
|
/** The response body and headers for an asset. */
|
|
73
117
|
export function assetResponse(asset, options = {}) {
|
|
74
118
|
const body = Readable.toWeb(createReadStream(asset.file));
|
|
@@ -102,10 +146,11 @@ export function matchesEtag(ifNoneMatch, etag) {
|
|
|
102
146
|
}
|
|
103
147
|
function assetHeaders(asset, options) {
|
|
104
148
|
const maxAge = options.maxAge ?? THEME_ASSET_MAX_AGE;
|
|
149
|
+
const immutable = options.immutable === true ? ', immutable' : '';
|
|
105
150
|
return new Headers({
|
|
106
151
|
'content-type': asset.contentType,
|
|
107
152
|
'content-length': String(asset.stats.size),
|
|
108
|
-
'cache-control': `public, max-age=${String(maxAge)}`,
|
|
153
|
+
'cache-control': `public, max-age=${String(maxAge)}${immutable}`,
|
|
109
154
|
'last-modified': new Date(asset.stats.mtimeMs).toUTCString(),
|
|
110
155
|
etag: asset.etag,
|
|
111
156
|
});
|
package/dist/web/assets.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assets.js","sourceRoot":"","sources":["../../src/web/assets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"assets.js","sourceRoot":"","sources":["../../src/web/assets.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { MiddlewareHandler } from 'hono';
|
|
2
|
+
/**
|
|
3
|
+
* Below this many bytes a response goes out as it is: the saving is smaller
|
|
4
|
+
* than the encoding's own framing and the CPU it costs.
|
|
5
|
+
*/
|
|
6
|
+
export declare const COMPRESSION_THRESHOLD = 1024;
|
|
7
|
+
/**
|
|
8
|
+
* Compress text responses on the way out (TASK-139).
|
|
9
|
+
*
|
|
10
|
+
* Mounted outside every other middleware, so it sees the body the client is
|
|
11
|
+
* about to get. It adds `Vary: Accept-Encoding` to every text response,
|
|
12
|
+
* compressed or not, so a cache never hands brotli to a client that asked for
|
|
13
|
+
* none. A compressed response's ETag is weakened: the encoded octets differ
|
|
14
|
+
* from the plain ones, but the representation is the same, and every
|
|
15
|
+
* `If-None-Match` check in the CMS already compares weakly, so the one
|
|
16
|
+
* validator revalidates in every encoding.
|
|
17
|
+
*/
|
|
18
|
+
export declare function compression(): MiddlewareHandler;
|
|
19
|
+
//# sourceMappingURL=compression.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compression.d.ts","sourceRoot":"","sources":["../../src/web/compression.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAK9C;;;GAGG;AACH,eAAO,MAAM,qBAAqB,OAAO,CAAC;AAsB1C;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,IAAI,iBAAiB,CAoD/C"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { promisify } from 'node:util';
|
|
2
|
+
import { brotliCompress, constants, gzip } from 'node:zlib';
|
|
3
|
+
import { ADMIN_ASSET_PREFIX } from '../admin/assets.js';
|
|
4
|
+
import { ADMIN_PREFIX } from '../admin/session.js';
|
|
5
|
+
/**
|
|
6
|
+
* Below this many bytes a response goes out as it is: the saving is smaller
|
|
7
|
+
* than the encoding's own framing and the CPU it costs.
|
|
8
|
+
*/
|
|
9
|
+
export const COMPRESSION_THRESHOLD = 1024;
|
|
10
|
+
const ENCODINGS = ['br', 'gzip'];
|
|
11
|
+
/**
|
|
12
|
+
* Media types that are text under another name. Everything `text/*`, `+json`
|
|
13
|
+
* and `+xml` (feeds, ActivityStreams, SVG, the manifest) is text already; the
|
|
14
|
+
* fonts are the two formats that carry no compression of their own.
|
|
15
|
+
*/
|
|
16
|
+
const COMPRESSIBLE_TYPES = new Set([
|
|
17
|
+
'application/json',
|
|
18
|
+
'application/javascript',
|
|
19
|
+
'application/xml',
|
|
20
|
+
'font/otf',
|
|
21
|
+
'font/ttf',
|
|
22
|
+
]);
|
|
23
|
+
const brotli = promisify(brotliCompress);
|
|
24
|
+
const gzipAsync = promisify(gzip);
|
|
25
|
+
/**
|
|
26
|
+
* Compress text responses on the way out (TASK-139).
|
|
27
|
+
*
|
|
28
|
+
* Mounted outside every other middleware, so it sees the body the client is
|
|
29
|
+
* about to get. It adds `Vary: Accept-Encoding` to every text response,
|
|
30
|
+
* compressed or not, so a cache never hands brotli to a client that asked for
|
|
31
|
+
* none. A compressed response's ETag is weakened: the encoded octets differ
|
|
32
|
+
* from the plain ones, but the representation is the same, and every
|
|
33
|
+
* `If-None-Match` check in the CMS already compares weakly, so the one
|
|
34
|
+
* validator revalidates in every encoding.
|
|
35
|
+
*/
|
|
36
|
+
export function compression() {
|
|
37
|
+
return async (c, next) => {
|
|
38
|
+
await next();
|
|
39
|
+
const response = c.res;
|
|
40
|
+
if (response.status === 304) {
|
|
41
|
+
// A 304 carries no media type to judge by, and a cache copies its
|
|
42
|
+
// headers over the stored response's, so a 304 saying only `Vary:
|
|
43
|
+
// Accept` would strip Accept-Encoding from a stored page. Every 304
|
|
44
|
+
// says it varies: over-stating Vary costs a cache a spare entry, while
|
|
45
|
+
// under-stating it could hand brotli to a client that cannot read it.
|
|
46
|
+
c.res = new Response(null, response);
|
|
47
|
+
addVary(c.res.headers);
|
|
48
|
+
// A client revalidating a compressed copy sends the weak form it was
|
|
49
|
+
// given; hand that back, so the validator it stores stays the one it has.
|
|
50
|
+
const etag = c.res.headers.get('etag');
|
|
51
|
+
if (etag !== null &&
|
|
52
|
+
!etag.startsWith('W/') &&
|
|
53
|
+
presents(c.req.header('if-none-match'), `W/${etag}`)) {
|
|
54
|
+
c.res.headers.set('etag', `W/${etag}`);
|
|
55
|
+
}
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (holdsSecrets(c.req.path, response) || !worthCompressing(response))
|
|
59
|
+
return;
|
|
60
|
+
const encoding = chooseEncoding(c.req.header('accept-encoding'));
|
|
61
|
+
const declared = Number(response.headers.get('content-length') ?? Number.NaN);
|
|
62
|
+
if (encoding === undefined || declared < COMPRESSION_THRESHOLD) {
|
|
63
|
+
c.res = new Response(response.body, response);
|
|
64
|
+
addVary(c.res.headers);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const plain = new Uint8Array(await response.arrayBuffer());
|
|
68
|
+
if (plain.byteLength < COMPRESSION_THRESHOLD) {
|
|
69
|
+
c.res = new Response(plain, response);
|
|
70
|
+
addVary(c.res.headers);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const encoded = await encode(plain, encoding);
|
|
74
|
+
c.res = new Response(encoded, response);
|
|
75
|
+
const headers = c.res.headers;
|
|
76
|
+
addVary(headers);
|
|
77
|
+
headers.set('content-encoding', encoding);
|
|
78
|
+
headers.set('content-length', String(encoded.byteLength));
|
|
79
|
+
const etag = headers.get('etag');
|
|
80
|
+
if (etag !== null && !etag.startsWith('W/'))
|
|
81
|
+
headers.set('etag', `W/${etag}`);
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Whether a response may carry a secret beside text a visitor controls: a
|
|
86
|
+
* CSRF token, a session's own data. Compressing such a page lets an attacker
|
|
87
|
+
* who can inject text and watch its size recover the secret a byte at a time
|
|
88
|
+
* (BREACH), so it goes out plain. Every page drawn for somebody signed in says
|
|
89
|
+
* `private` or `no-store`; the admin's screens, the setup and login forms
|
|
90
|
+
* among them, say neither, so the path covers those. The admin's static files
|
|
91
|
+
* hold no secret and are compressed like any other.
|
|
92
|
+
*/
|
|
93
|
+
function holdsSecrets(requestPath, response) {
|
|
94
|
+
if (/\b(private|no-store)\b/i.test(response.headers.get('cache-control') ?? ''))
|
|
95
|
+
return true;
|
|
96
|
+
if (requestPath.startsWith(ADMIN_ASSET_PREFIX))
|
|
97
|
+
return false;
|
|
98
|
+
return requestPath === ADMIN_PREFIX || requestPath.startsWith(`${ADMIN_PREFIX}/`);
|
|
99
|
+
}
|
|
100
|
+
/** Whether this response is text with a body that nothing has encoded yet. */
|
|
101
|
+
function worthCompressing(response) {
|
|
102
|
+
if (response.body === null || response.status === 204 || response.status === 206)
|
|
103
|
+
return false;
|
|
104
|
+
if (response.headers.has('content-encoding'))
|
|
105
|
+
return false;
|
|
106
|
+
if (/\bno-transform\b/i.test(response.headers.get('cache-control') ?? ''))
|
|
107
|
+
return false;
|
|
108
|
+
return isCompressible(response.headers.get('content-type'));
|
|
109
|
+
}
|
|
110
|
+
function isCompressible(contentType) {
|
|
111
|
+
const type = (contentType ?? '').split(';')[0]?.trim().toLowerCase() ?? '';
|
|
112
|
+
return (type.startsWith('text/') ||
|
|
113
|
+
type.endsWith('+json') ||
|
|
114
|
+
type.endsWith('+xml') ||
|
|
115
|
+
COMPRESSIBLE_TYPES.has(type));
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* The encoding to send for an `Accept-Encoding`, brotli first. A coding the
|
|
119
|
+
* header names with `q=0` is refused; one it leaves out is taken only when
|
|
120
|
+
* `*` is offered.
|
|
121
|
+
*/
|
|
122
|
+
function chooseEncoding(accept) {
|
|
123
|
+
if (accept === undefined)
|
|
124
|
+
return undefined;
|
|
125
|
+
const weights = new Map();
|
|
126
|
+
for (const part of accept.split(',')) {
|
|
127
|
+
const [name = '', ...params] = part.split(';').map((piece) => piece.trim().toLowerCase());
|
|
128
|
+
if (name === '')
|
|
129
|
+
continue;
|
|
130
|
+
const q = params.find((param) => param.startsWith('q='));
|
|
131
|
+
weights.set(name, q === undefined ? 1 : Number(q.slice(2)) || 0);
|
|
132
|
+
}
|
|
133
|
+
return ENCODINGS.find((encoding) => (weights.get(encoding) ?? weights.get('*') ?? 0) > 0);
|
|
134
|
+
}
|
|
135
|
+
function encode(body, encoding) {
|
|
136
|
+
if (encoding === 'gzip')
|
|
137
|
+
return gzipAsync(body, { level: 6 });
|
|
138
|
+
// Quality 5 rather than the maximum 11: these bodies are built per request,
|
|
139
|
+
// and at 11 the time spent encoding outweighs the bytes it saves.
|
|
140
|
+
return brotli(body, {
|
|
141
|
+
params: {
|
|
142
|
+
[constants.BROTLI_PARAM_MODE]: constants.BROTLI_MODE_TEXT,
|
|
143
|
+
[constants.BROTLI_PARAM_QUALITY]: 5,
|
|
144
|
+
[constants.BROTLI_PARAM_SIZE_HINT]: body.byteLength,
|
|
145
|
+
},
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
function addVary(headers) {
|
|
149
|
+
const names = (headers.get('vary') ?? '')
|
|
150
|
+
.split(',')
|
|
151
|
+
.map((name) => name.trim())
|
|
152
|
+
.filter((name) => name !== '');
|
|
153
|
+
if (names.some((name) => name === '*' || name.toLowerCase() === 'accept-encoding'))
|
|
154
|
+
return;
|
|
155
|
+
headers.set('vary', [...names, 'Accept-Encoding'].join(', '));
|
|
156
|
+
}
|
|
157
|
+
function presents(ifNoneMatch, etag) {
|
|
158
|
+
return (ifNoneMatch ?? '').split(',').some((candidate) => candidate.trim() === etag);
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=compression.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compression.js","sourceRoot":"","sources":["../../src/web/compression.ts"],"names":[],"mappings":"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"}
|
package/dist/web/context.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ResolvedConfig } from '../config.ts';
|
|
2
2
|
import type { Document } from '../content/document.ts';
|
|
3
3
|
import type { PostType } from '../content/post-type.ts';
|
|
4
|
+
import type { ImageLoading } from '../images/markup.ts';
|
|
4
5
|
import type { ImageConfig } from '../images/variants.ts';
|
|
5
6
|
import type { AuthorContext } from './authors.ts';
|
|
6
7
|
import type { TaxonomyBases, TaxonomyRedirect } from './taxonomy.ts';
|
|
@@ -189,8 +190,11 @@ export interface NeighbourContext {
|
|
|
189
190
|
* login, a display name from before decision-14, or somebody who has no
|
|
190
191
|
* account here at all. Without one the file's own string is left where it was,
|
|
191
192
|
* which is what a test over a single template renders.
|
|
193
|
+
*
|
|
194
|
+
* `loading` says whether this document opens the page it is printed on, and
|
|
195
|
+
* so whether its first image is fetched at once rather than lazily.
|
|
192
196
|
*/
|
|
193
|
-
export declare function documentContext(document: Document, images?: ImageConfig, author?: AuthorContext): DocumentContext;
|
|
197
|
+
export declare function documentContext(document: Document, images?: ImageConfig, author?: AuthorContext, loading?: ImageLoading): DocumentContext;
|
|
194
198
|
/** Reads `content/_data/site.json`, and re-reads it when the file changes. */
|
|
195
199
|
export interface SiteDataSource {
|
|
196
200
|
/** The current site data, defaults filled in. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/web/context.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/web/context.ts"],"names":[],"mappings":"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"}
|
package/dist/web/context.js
CHANGED
|
@@ -31,8 +31,11 @@ export const DEFAULT_POSTS_PER_PAGE = 10;
|
|
|
31
31
|
* login, a display name from before decision-14, or somebody who has no
|
|
32
32
|
* account here at all. Without one the file's own string is left where it was,
|
|
33
33
|
* which is what a test over a single template renders.
|
|
34
|
+
*
|
|
35
|
+
* `loading` says whether this document opens the page it is printed on, and
|
|
36
|
+
* so whether its first image is fetched at once rather than lazily.
|
|
34
37
|
*/
|
|
35
|
-
export function documentContext(document, images, author) {
|
|
38
|
+
export function documentContext(document, images, author, loading) {
|
|
36
39
|
const date = toDate(document.date);
|
|
37
40
|
return {
|
|
38
41
|
...document.extra,
|
|
@@ -51,7 +54,7 @@ export function documentContext(document, images, author) {
|
|
|
51
54
|
...optional('date', date),
|
|
52
55
|
tags: document.tags,
|
|
53
56
|
categories: document.categories,
|
|
54
|
-
content: images === undefined ? document.html : siteImageMarkup(images, document.html),
|
|
57
|
+
content: images === undefined ? document.html : siteImageMarkup(images, document.html, loading),
|
|
55
58
|
// The plain-text summary, taken off the document rather than off the
|
|
56
59
|
// markup above: an excerpt is text, and the `<picture>` a site's image
|
|
57
60
|
// config puts in the HTML is not something to cut words out of.
|
package/dist/web/context.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/web/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,IAAI,MAAM,WAAW,CAAC;AAI7B,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAEtF,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/web/context.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../../src/web/conversation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"conversation.d.ts","sourceRoot":"","sources":["../../src/web/conversation.ts"],"names":[],"mappings":"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"}
|