@glw907/cairn-cms 0.60.0 → 0.62.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/CHANGELOG.md +82 -0
- package/dist/components/AdminLayout.svelte +152 -229
- package/dist/components/CairnAdmin.svelte +13 -42
- package/dist/components/CairnLogo.svelte +1 -6
- package/dist/components/CairnMediaLibrary.svelte +821 -1210
- package/dist/components/CairnTidySettings.svelte +194 -261
- package/dist/components/CairnTidySettings.svelte.d.ts +1 -1
- package/dist/components/ComponentForm.svelte +110 -185
- package/dist/components/ComponentInsertDialog.svelte +163 -283
- package/dist/components/ConceptList.svelte +111 -191
- package/dist/components/ConfirmPage.svelte +5 -12
- package/dist/components/CsrfField.svelte +5 -11
- package/dist/components/DeleteDialog.svelte +15 -42
- package/dist/components/EditPage.svelte +781 -1205
- package/dist/components/EditorToolbar.svelte +108 -170
- package/dist/components/HelpHome.svelte +824 -0
- package/dist/components/HelpHome.svelte.d.ts +22 -0
- package/dist/components/IconPicker.svelte +23 -53
- package/dist/components/LinkPicker.svelte +34 -58
- package/dist/components/LoginPage.svelte +14 -27
- package/dist/components/ManageEditors.svelte +3 -15
- package/dist/components/MarkdownEditor.svelte +689 -957
- package/dist/components/MarkdownHelpDialog.svelte +12 -27
- package/dist/components/MediaCaptureCard.svelte +18 -57
- package/dist/components/MediaFigureControl.svelte +32 -71
- package/dist/components/MediaHeroField.svelte +210 -329
- package/dist/components/MediaInsertPopover.svelte +156 -283
- package/dist/components/MediaPicker.svelte +67 -131
- package/dist/components/NavTree.svelte +46 -78
- package/dist/components/RenameDialog.svelte +16 -43
- package/dist/components/ShortcutsDialog.svelte +9 -13
- package/dist/components/ShortcutsGrid.svelte +1 -2
- package/dist/components/TidyReview.svelte +140 -248
- package/dist/components/WebLinkDialog.svelte +19 -40
- package/dist/components/cairn-admin.css +4 -0
- package/dist/components/client-ingest.d.ts +16 -8
- package/dist/components/client-ingest.js +12 -6
- package/dist/components/editor-media.js +16 -8
- package/dist/components/editor-placeholder.d.ts +4 -2
- package/dist/components/editor-tidy.d.ts +24 -12
- package/dist/components/editor-tidy.js +8 -4
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +1 -0
- package/dist/components/link-completion.d.ts +12 -6
- package/dist/components/link-completion.js +12 -6
- package/dist/components/markdown-directives.d.ts +9 -6
- package/dist/components/markdown-directives.js +9 -6
- package/dist/components/markdown-format.d.ts +7 -2
- package/dist/components/markdown-format.js +59 -28
- package/dist/components/markdown-reference.d.ts +8 -0
- package/dist/components/markdown-reference.js +22 -0
- package/dist/components/media-upload-outcome.d.ts +12 -6
- package/dist/components/objective-errors.d.ts +8 -4
- package/dist/components/objective-errors.js +8 -4
- package/dist/components/preview-doc.d.ts +4 -2
- package/dist/components/preview-doc.js +4 -2
- package/dist/components/spellcheck.d.ts +57 -29
- package/dist/components/spellcheck.js +50 -20
- package/dist/components/tidy-categorize.d.ts +20 -10
- package/dist/components/tidy-categorize.js +16 -8
- package/dist/components/tidy-validate.d.ts +12 -6
- package/dist/components/tidy-validate.js +20 -10
- package/dist/components/topbar-context.d.ts +4 -2
- package/dist/content/advisories.d.ts +51 -0
- package/dist/content/advisories.js +79 -0
- package/dist/content/compose.d.ts +4 -2
- package/dist/content/compose.js +1 -0
- package/dist/content/excerpt.js +4 -2
- package/dist/content/getting-started.d.ts +18 -0
- package/dist/content/getting-started.js +12 -0
- package/dist/content/links.d.ts +16 -8
- package/dist/content/links.js +12 -6
- package/dist/content/manifest.d.ts +36 -18
- package/dist/content/manifest.js +32 -16
- package/dist/content/media-refs.d.ts +4 -2
- package/dist/content/media-refs.js +4 -2
- package/dist/content/media-rewrite.d.ts +8 -4
- package/dist/content/media-rewrite.js +76 -38
- package/dist/content/schema.d.ts +20 -10
- package/dist/content/site-dictionary.d.ts +4 -2
- package/dist/content/site-dictionary.js +8 -4
- package/dist/content/types.d.ts +97 -42
- package/dist/delivery/CairnHead.svelte +8 -11
- package/dist/delivery/content-index.d.ts +16 -8
- package/dist/delivery/feeds.js +4 -2
- package/dist/delivery/json-ld.d.ts +3 -0
- package/dist/delivery/json-ld.js +3 -0
- package/dist/delivery/manifest.d.ts +4 -2
- package/dist/delivery/manifest.js +4 -2
- package/dist/delivery/public-routes.d.ts +12 -6
- package/dist/delivery/public-routes.js +4 -2
- package/dist/delivery/seo-fields.d.ts +12 -6
- package/dist/delivery/seo-fields.js +8 -4
- package/dist/delivery/site-indexes.d.ts +4 -2
- package/dist/delivery/site-resolver.d.ts +4 -2
- package/dist/delivery/site-resolver.js +4 -2
- package/dist/doctor/cloudflare-api.d.ts +6 -0
- package/dist/doctor/cloudflare-api.js +6 -0
- package/dist/doctor/index.d.ts +12 -6
- package/dist/doctor/report.d.ts +3 -0
- package/dist/doctor/report.js +3 -0
- package/dist/doctor/run.d.ts +3 -0
- package/dist/doctor/run.js +3 -0
- package/dist/doctor/types.d.ts +10 -2
- package/dist/doctor/types.js +6 -0
- package/dist/doctor/wrangler-config.d.ts +7 -2
- package/dist/doctor/wrangler-config.js +3 -0
- package/dist/email.d.ts +4 -2
- package/dist/env.d.ts +0 -3
- package/dist/env.js +0 -3
- package/dist/github/branches.d.ts +4 -2
- package/dist/github/branches.js +4 -2
- package/dist/github/signing.d.ts +1 -1
- package/dist/github/signing.js +2 -2
- package/dist/log/events.d.ts +1 -1
- package/dist/media/bulk-delete-plan.d.ts +8 -4
- package/dist/media/config.d.ts +12 -6
- package/dist/media/config.js +16 -8
- package/dist/media/delivery-bucket.d.ts +4 -2
- package/dist/media/library-entry.d.ts +4 -2
- package/dist/media/library-entry.js +4 -2
- package/dist/media/manifest.d.ts +29 -15
- package/dist/media/manifest.js +29 -16
- package/dist/media/naming.d.ts +12 -6
- package/dist/media/naming.js +24 -12
- package/dist/media/orphan-scan.d.ts +4 -2
- package/dist/media/reconcile.d.ts +21 -11
- package/dist/media/reconcile.js +12 -6
- package/dist/media/reference.d.ts +8 -4
- package/dist/media/reference.js +12 -6
- package/dist/media/rewrite-plan.d.ts +12 -6
- package/dist/media/sniff.d.ts +4 -2
- package/dist/media/sniff.js +28 -14
- package/dist/media/store.d.ts +16 -8
- package/dist/media/store.js +4 -2
- package/dist/media/transform-url.d.ts +12 -6
- package/dist/media/transform-url.js +8 -4
- package/dist/media/usage.d.ts +8 -4
- package/dist/nav/site-config.d.ts +16 -8
- package/dist/render/component-grammar.d.ts +23 -10
- package/dist/render/component-grammar.js +19 -8
- package/dist/render/component-insert.d.ts +8 -4
- package/dist/render/component-insert.js +4 -2
- package/dist/render/component-reference.d.ts +4 -2
- package/dist/render/component-reference.js +4 -2
- package/dist/render/component-validate.d.ts +3 -0
- package/dist/render/component-validate.js +3 -0
- package/dist/render/glyph.d.ts +4 -2
- package/dist/render/glyph.js +4 -2
- package/dist/render/pipeline.d.ts +20 -10
- package/dist/render/pipeline.js +4 -2
- package/dist/render/registry.d.ts +40 -20
- package/dist/render/registry.js +16 -8
- package/dist/render/rehype-dispatch.d.ts +22 -8
- package/dist/render/rehype-dispatch.js +22 -8
- package/dist/render/remark-directives.d.ts +3 -0
- package/dist/render/remark-directives.js +3 -0
- package/dist/render/remark-figure.d.ts +4 -2
- package/dist/render/remark-figure.js +4 -2
- package/dist/render/resolve-links.d.ts +4 -2
- package/dist/render/resolve-links.js +4 -2
- package/dist/render/resolve-media.d.ts +16 -8
- package/dist/render/resolve-media.js +12 -6
- package/dist/sveltekit/admin-dispatch.d.ts +2 -0
- package/dist/sveltekit/admin-dispatch.js +9 -3
- package/dist/sveltekit/auth-routes.d.ts +3 -0
- package/dist/sveltekit/auth-routes.js +3 -0
- package/dist/sveltekit/cairn-admin.d.ts +16 -5
- package/dist/sveltekit/cairn-admin.js +26 -10
- package/dist/sveltekit/content-routes.d.ts +191 -86
- package/dist/sveltekit/content-routes.js +295 -107
- package/dist/sveltekit/editors-routes.d.ts +3 -0
- package/dist/sveltekit/editors-routes.js +3 -0
- package/dist/sveltekit/guard.d.ts +4 -2
- package/dist/sveltekit/guard.js +4 -2
- package/dist/sveltekit/https-required-page.d.ts +1 -1
- package/dist/sveltekit/https-required-page.js +1 -1
- package/dist/sveltekit/index.d.ts +1 -1
- package/dist/sveltekit/media-route.d.ts +1 -2
- package/dist/sveltekit/media-route.js +13 -8
- package/dist/sveltekit/nav-routes.d.ts +7 -2
- package/dist/sveltekit/nav-routes.js +3 -0
- package/dist/sveltekit/types.d.ts +4 -2
- package/dist/vite/index.d.ts +32 -16
- package/dist/vite/index.js +52 -26
- package/dist/vite/resolve-root.d.ts +8 -4
- package/dist/vite/resolve-root.js +4 -2
- package/package.json +8 -2
- package/src/lib/components/AdminLayout.svelte +22 -0
- package/src/lib/components/CairnAdmin.svelte +3 -0
- package/src/lib/components/CairnTidySettings.svelte +2 -2
- package/src/lib/components/ComponentForm.svelte +0 -1
- package/src/lib/components/EditPage.svelte +133 -41
- package/src/lib/components/HelpHome.svelte +850 -0
- package/src/lib/components/MarkdownHelpDialog.svelte +4 -15
- package/src/lib/components/client-ingest.ts +20 -10
- package/src/lib/components/editor-media.ts +20 -10
- package/src/lib/components/editor-placeholder.ts +12 -6
- package/src/lib/components/editor-tidy.ts +28 -14
- package/src/lib/components/index.ts +1 -0
- package/src/lib/components/link-completion.ts +12 -6
- package/src/lib/components/markdown-directives.ts +13 -8
- package/src/lib/components/markdown-format.ts +63 -30
- package/src/lib/components/markdown-reference.ts +30 -0
- package/src/lib/components/media-upload-outcome.ts +12 -6
- package/src/lib/components/objective-errors.ts +16 -8
- package/src/lib/components/preview-doc.ts +4 -2
- package/src/lib/components/spellcheck.ts +92 -40
- package/src/lib/components/tidy-categorize.ts +28 -14
- package/src/lib/components/tidy-validate.ts +28 -14
- package/src/lib/components/topbar-context.ts +4 -2
- package/src/lib/content/advisories.ts +141 -0
- package/src/lib/content/compose.ts +5 -2
- package/src/lib/content/excerpt.ts +4 -2
- package/src/lib/content/getting-started.ts +31 -0
- package/src/lib/content/links.ts +16 -8
- package/src/lib/content/manifest.ts +36 -18
- package/src/lib/content/media-refs.ts +4 -2
- package/src/lib/content/media-rewrite.ts +100 -50
- package/src/lib/content/schema.ts +20 -10
- package/src/lib/content/site-dictionary.ts +8 -4
- package/src/lib/content/types.ts +97 -42
- package/src/lib/delivery/content-index.ts +16 -8
- package/src/lib/delivery/feeds.ts +4 -2
- package/src/lib/delivery/json-ld.ts +3 -0
- package/src/lib/delivery/manifest.ts +4 -2
- package/src/lib/delivery/public-routes.ts +16 -8
- package/src/lib/delivery/seo-fields.ts +12 -6
- package/src/lib/delivery/site-indexes.ts +4 -2
- package/src/lib/delivery/site-resolver.ts +4 -2
- package/src/lib/doctor/cloudflare-api.ts +6 -0
- package/src/lib/doctor/index.ts +12 -6
- package/src/lib/doctor/report.ts +3 -0
- package/src/lib/doctor/run.ts +3 -0
- package/src/lib/doctor/types.ts +10 -2
- package/src/lib/doctor/wrangler-config.ts +7 -2
- package/src/lib/email.ts +4 -2
- package/src/lib/env.ts +0 -3
- package/src/lib/github/branches.ts +4 -2
- package/src/lib/github/signing.ts +2 -2
- package/src/lib/log/events.ts +1 -0
- package/src/lib/media/bulk-delete-plan.ts +8 -4
- package/src/lib/media/config.ts +24 -12
- package/src/lib/media/delivery-bucket.ts +4 -2
- package/src/lib/media/library-entry.ts +4 -2
- package/src/lib/media/manifest.ts +33 -18
- package/src/lib/media/naming.ts +24 -12
- package/src/lib/media/orphan-scan.ts +4 -2
- package/src/lib/media/reconcile.ts +21 -11
- package/src/lib/media/reference.ts +12 -6
- package/src/lib/media/rewrite-plan.ts +12 -6
- package/src/lib/media/sniff.ts +28 -14
- package/src/lib/media/store.ts +16 -8
- package/src/lib/media/transform-url.ts +12 -6
- package/src/lib/media/usage.ts +8 -4
- package/src/lib/nav/site-config.ts +16 -8
- package/src/lib/render/component-grammar.ts +23 -10
- package/src/lib/render/component-insert.ts +8 -4
- package/src/lib/render/component-reference.ts +4 -2
- package/src/lib/render/component-validate.ts +3 -0
- package/src/lib/render/glyph.ts +4 -2
- package/src/lib/render/pipeline.ts +20 -10
- package/src/lib/render/registry.ts +44 -22
- package/src/lib/render/rehype-dispatch.ts +22 -8
- package/src/lib/render/remark-directives.ts +3 -0
- package/src/lib/render/remark-figure.ts +4 -2
- package/src/lib/render/resolve-links.ts +4 -2
- package/src/lib/render/resolve-media.ts +16 -8
- package/src/lib/sveltekit/admin-dispatch.ts +10 -4
- package/src/lib/sveltekit/auth-routes.ts +3 -0
- package/src/lib/sveltekit/cairn-admin.ts +37 -15
- package/src/lib/sveltekit/content-routes.ts +492 -197
- package/src/lib/sveltekit/editors-routes.ts +3 -0
- package/src/lib/sveltekit/guard.ts +4 -2
- package/src/lib/sveltekit/https-required-page.ts +1 -1
- package/src/lib/sveltekit/index.ts +3 -0
- package/src/lib/sveltekit/media-route.ts +13 -8
- package/src/lib/sveltekit/nav-routes.ts +7 -2
- package/src/lib/sveltekit/types.ts +4 -2
- package/src/lib/vite/index.ts +60 -30
- package/src/lib/vite/resolve-root.ts +8 -4
|
@@ -10,6 +10,9 @@ import { createAuthRoutes } from './auth-routes.js';
|
|
|
10
10
|
import { createContentRoutes, } from './content-routes.js';
|
|
11
11
|
import { createEditorRoutes } from './editors-routes.js';
|
|
12
12
|
import { createNavRoutes } from './nav-routes.js';
|
|
13
|
+
/**
|
|
14
|
+
*
|
|
15
|
+
*/
|
|
13
16
|
export function createCairnAdmin(runtime, deps = {}) {
|
|
14
17
|
// The runtime already composes the site name and the sender identity, so the magic-link
|
|
15
18
|
// branding needs no second copy of either unless a site overrides it.
|
|
@@ -27,11 +30,13 @@ export function createCairnAdmin(runtime, deps = {}) {
|
|
|
27
30
|
const editors = createEditorRoutes();
|
|
28
31
|
// The nav surface exists only when the site configures a menu; without one its view is a 404.
|
|
29
32
|
const nav = runtime.navMenu ? createNavRoutes(runtime, { mintToken: deps.mintToken }) : null;
|
|
30
|
-
/**
|
|
33
|
+
/**
|
|
34
|
+
* Build the event a wrapped content load reads. The catch-all route carries only a rest
|
|
31
35
|
* param, so `concept` and `id` are synthesized from the parsed view. The override names
|
|
32
36
|
* each field explicitly rather than spreading: a real RequestEvent's fields can sit behind
|
|
33
37
|
* getters a bare spread copies poorly, and the structural ContentEvent contract needs only
|
|
34
|
-
* these.
|
|
38
|
+
* these.
|
|
39
|
+
*/
|
|
35
40
|
function contentEvent(event, params) {
|
|
36
41
|
return {
|
|
37
42
|
url: event.url,
|
|
@@ -42,9 +47,11 @@ export function createCairnAdmin(runtime, deps = {}) {
|
|
|
42
47
|
cookies: event.cookies,
|
|
43
48
|
};
|
|
44
49
|
}
|
|
45
|
-
/**
|
|
50
|
+
/**
|
|
51
|
+
* Serve the admin view the pathname names, or a 404 for any shape the parser refuses.
|
|
46
52
|
* The authed views run the layout load and the view load concurrently; both mint a GitHub
|
|
47
|
-
* token, and the installation-token cache coalesces the mints into one signing.
|
|
53
|
+
* token, and the installation-token cache coalesces the mints into one signing.
|
|
54
|
+
*/
|
|
48
55
|
async function load(event) {
|
|
49
56
|
const view = parseAdminPath(event.url.pathname, runtime.concepts);
|
|
50
57
|
if (!view)
|
|
@@ -91,11 +98,18 @@ export function createCairnAdmin(runtime, deps = {}) {
|
|
|
91
98
|
const [layout, page] = await Promise.all([content.layoutLoad(delegated), content.settingsLoad(delegated)]);
|
|
92
99
|
return { view: 'settings', layout, page };
|
|
93
100
|
}
|
|
101
|
+
case 'help': {
|
|
102
|
+
const delegated = contentEvent(event, {});
|
|
103
|
+
const [layout, page] = await Promise.all([content.layoutLoad(delegated), content.helpLoad(delegated)]);
|
|
104
|
+
return { view: 'help', layout, page };
|
|
105
|
+
}
|
|
94
106
|
}
|
|
95
107
|
}
|
|
96
|
-
/**
|
|
108
|
+
/**
|
|
109
|
+
* Wrap a delegate in the parse-and-check every action shares: parse the pathname exactly
|
|
97
110
|
* as load does, 404 on a null parse or a view outside the allowed set, then hand the
|
|
98
|
-
* narrowed view to the delegate.
|
|
111
|
+
* narrowed view to the delegate.
|
|
112
|
+
*/
|
|
99
113
|
function viewAction(allowed, delegate) {
|
|
100
114
|
return async (event) => {
|
|
101
115
|
const view = parseAdminPath(event.url.pathname, runtime.concepts);
|
|
@@ -106,13 +120,15 @@ export function createCairnAdmin(runtime, deps = {}) {
|
|
|
106
120
|
};
|
|
107
121
|
}
|
|
108
122
|
// The topbar posts publishAll from every authed admin page; login and confirm may not.
|
|
109
|
-
const authedViews = ['list', 'edit', 'editors', 'nav', 'media', 'settings'];
|
|
123
|
+
const authedViews = ['list', 'edit', 'editors', 'nav', 'media', 'settings', 'help'];
|
|
110
124
|
// An editor signs out from wherever they are, so logout accepts any parsed view.
|
|
111
|
-
const anyView = ['index', 'login', 'confirm', 'list', 'edit', 'editors', 'nav', 'media', 'settings'];
|
|
112
|
-
/**
|
|
125
|
+
const anyView = ['index', 'login', 'confirm', 'list', 'edit', 'editors', 'nav', 'media', 'settings', 'help'];
|
|
126
|
+
/**
|
|
127
|
+
* The full admin action vocabulary, one named async function per action, so a site's
|
|
113
128
|
* catch-all route exports `admin.actions` directly. Each wrapper stays thin: parse,
|
|
114
129
|
* validate the view, synthesize the params the wrapped action reads, delegate. The
|
|
115
|
-
* editor actions gate themselves with requireOwner, so no second gate is added here.
|
|
130
|
+
* editor actions gate themselves with requireOwner, so no second gate is added here.
|
|
131
|
+
*/
|
|
116
132
|
const actions = {
|
|
117
133
|
request: viewAction(['login'], (event) => auth.requestAction(event)),
|
|
118
134
|
confirm: viewAction(['confirm'], (event) => auth.confirmAction(event)),
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { fail } from '@sveltejs/kit';
|
|
2
|
+
import { type AdvisoryNotice } from '../content/advisories.js';
|
|
2
3
|
import { type GithubKeyEnv } from '../github/credentials.js';
|
|
3
4
|
import { type LinkTarget, type InboundLink } from '../content/manifest.js';
|
|
5
|
+
import { type GettingStarted } from '../content/getting-started.js';
|
|
6
|
+
import { type MarkdownReferenceRow } from '../components/markdown-reference.js';
|
|
4
7
|
import type { TidyConventions } from '../nav/site-config.js';
|
|
5
8
|
import type { MediaEntry } from '../media/manifest.js';
|
|
6
9
|
import type { MediaLibrary, MediaLibraryEntry } from '../media/library-entry.js';
|
|
@@ -12,6 +15,7 @@ import type { BulkDeleteSkip } from '../media/bulk-delete-plan.js';
|
|
|
12
15
|
import type { CookieJar, EventBase } from './types.js';
|
|
13
16
|
import type { CairnRuntime, FrontmatterField, ResolvedPreview } from '../content/types.js';
|
|
14
17
|
import type { Role } from '../auth/types.js';
|
|
18
|
+
export type { AdvisoryNotice, AdvisoryAction } from '../content/advisories.js';
|
|
15
19
|
/** A sidebar concept entry: just enough to render the nav without shipping validators to the client. */
|
|
16
20
|
export interface NavConcept {
|
|
17
21
|
id: string;
|
|
@@ -32,13 +36,17 @@ export interface LayoutData {
|
|
|
32
36
|
navLabel: string | null;
|
|
33
37
|
/** The admin theme resolved for SSR: the persisted cookie choice, or the light default. */
|
|
34
38
|
theme: 'cairn-admin' | 'cairn-admin-dark';
|
|
35
|
-
/**
|
|
36
|
-
*
|
|
39
|
+
/**
|
|
40
|
+
* The nav group labels the user has collapsed, from the persisted cookie. Read at SSR so a
|
|
41
|
+
* collapsed group renders collapsed with no flash. Empty when none are collapsed.
|
|
42
|
+
*/
|
|
37
43
|
collapsedNav: string[];
|
|
38
44
|
/** The session's CSRF double-submit token, rendered as a hidden field in every admin form. */
|
|
39
45
|
csrf: string;
|
|
40
|
-
/**
|
|
41
|
-
*
|
|
46
|
+
/**
|
|
47
|
+
* Every entry with unpublished edits (a `cairn/` ref), for the topbar's publish-all action.
|
|
48
|
+
* Null when GitHub is unreachable, so the topbar hides the action rather than lying.
|
|
49
|
+
*/
|
|
42
50
|
pendingEntries: {
|
|
43
51
|
concept: string;
|
|
44
52
|
id: string;
|
|
@@ -52,16 +60,20 @@ export interface EntrySummary {
|
|
|
52
60
|
draft: boolean;
|
|
53
61
|
/** Publish state derived from the ref set: live as-is, live with pending edits, or branch-only. */
|
|
54
62
|
status: 'published' | 'edited' | 'new';
|
|
55
|
-
/**
|
|
56
|
-
*
|
|
63
|
+
/**
|
|
64
|
+
* The row's one-line summary: the manifest's indexed excerpt for a published row, the branch
|
|
65
|
+
* frontmatter/body excerpt for a pending one, and null when neither yields text.
|
|
66
|
+
*/
|
|
57
67
|
summary: string | null;
|
|
58
68
|
}
|
|
59
69
|
/** The concept list view's data. */
|
|
60
70
|
export interface ListData {
|
|
61
71
|
conceptId: string;
|
|
62
72
|
label: string;
|
|
63
|
-
/**
|
|
64
|
-
*
|
|
73
|
+
/**
|
|
74
|
+
* The singular noun for the create affordances ("New post"); from the descriptor, which defaults
|
|
75
|
+
* it to `label`.
|
|
76
|
+
*/
|
|
65
77
|
singular: string;
|
|
66
78
|
/** Posts carry a date in the new-entry form; pages do not (concept routing, spec §7.2). */
|
|
67
79
|
dated: boolean;
|
|
@@ -91,17 +103,21 @@ export interface EditData {
|
|
|
91
103
|
slug: string;
|
|
92
104
|
/** The site's link targets, for the preview resolver and the link picker; from the committed manifest. */
|
|
93
105
|
linkTargets: LinkTarget[];
|
|
94
|
-
/**
|
|
95
|
-
*
|
|
106
|
+
/**
|
|
107
|
+
* The minimal media-resolver input the edit page builds its preview `resolveMedia` from, keyed by
|
|
108
|
+
* the 16-hex content hash and parallel to `linkTargets`. Empty when media is off or the read fails.
|
|
109
|
+
*/
|
|
96
110
|
mediaTargets: Record<string, {
|
|
97
111
|
slug: string;
|
|
98
112
|
ext: string;
|
|
99
113
|
contentType: string;
|
|
100
114
|
}>;
|
|
101
|
-
/**
|
|
115
|
+
/**
|
|
116
|
+
* The picker's human layer for each stored asset, keyed by the 16-hex content hash and projected
|
|
102
117
|
* from the same committed media manifest read that populates `mediaTargets`. The `hash` field
|
|
103
118
|
* duplicates the key, so the picker can iterate `Object.values`. Empty when media is off or the
|
|
104
|
-
* read fails (the same degradation path as `mediaTargets`).
|
|
119
|
+
* read fails (the same degradation path as `mediaTargets`).
|
|
120
|
+
*/
|
|
105
121
|
mediaLibrary: MediaLibrary;
|
|
106
122
|
/** The entries that link to this one, for the delete guard. Empty when nothing links here. */
|
|
107
123
|
inboundLinks: InboundLink[];
|
|
@@ -113,107 +129,152 @@ export interface EditData {
|
|
|
113
129
|
publishedFlash: boolean;
|
|
114
130
|
/** True after a discard redirect (`?discarded=1`), for the confirmation strip. */
|
|
115
131
|
discardedFlash: boolean;
|
|
116
|
-
/**
|
|
132
|
+
/**
|
|
133
|
+
* The adapter's preview knob resolved for this entry's concept (its `byConcept` override,
|
|
117
134
|
* when one exists, applied over the top-level values); null when the site sets none, which
|
|
118
|
-
* leaves the frame rendering unstyled markup behind a hint.
|
|
135
|
+
* leaves the frame rendering unstyled markup behind a hint.
|
|
136
|
+
*/
|
|
119
137
|
preview: ResolvedPreview | null;
|
|
120
|
-
/**
|
|
138
|
+
/**
|
|
139
|
+
* The spellcheck dictionary file for the site's configured dialect (default US English), resolved
|
|
121
140
|
* once at compose. The editor resolves it to a real asset URL on the main thread and hands that URL
|
|
122
141
|
* to the spellcheck Worker's `init`, the same way `mediaLibrary` is threaded in. Just the filename,
|
|
123
|
-
* e.g. "dictionary-en-us.txt".
|
|
142
|
+
* e.g. "dictionary-en-us.txt".
|
|
143
|
+
*/
|
|
124
144
|
spellcheckDictionary: string;
|
|
125
|
-
/**
|
|
145
|
+
/**
|
|
146
|
+
* The committed personal-dictionary words for the site (spec 1.6): the durable, shared, reviewable
|
|
126
147
|
* layer the editor seeds the spellcheck Worker's personal set from, the way `mediaLibrary` is handed
|
|
127
148
|
* in. Read from the git-committed `dictionary.txt` at editor load; empty when the file is absent or
|
|
128
149
|
* unreadable (the editor degrades to dialect-only). The dialect dictionary and the session ignore
|
|
129
|
-
* list are the other two layers; only this one is committed.
|
|
150
|
+
* list are the other two layers; only this one is committed.
|
|
151
|
+
*/
|
|
130
152
|
siteDictionary: string[];
|
|
131
|
-
/**
|
|
153
|
+
/**
|
|
154
|
+
* The editor-tier tidy facts the review surface needs (spec 2.5): whether tidy is enabled, the model
|
|
132
155
|
* that runs (for the head pill), and the RESOLVED conventions (the only data source for a
|
|
133
156
|
* normalization's because-line and the local category inference). The API key never appears here, it
|
|
134
|
-
* is a Worker secret. `enabled` false hides the Tidy control.
|
|
157
|
+
* is a Worker secret. `enabled` false hides the Tidy control.
|
|
158
|
+
*/
|
|
135
159
|
tidy: {
|
|
136
160
|
enabled: boolean;
|
|
137
161
|
model: string;
|
|
138
162
|
conventions: TidyConventions;
|
|
139
163
|
};
|
|
164
|
+
/** Non-blocking editor advisories built server-side; today the cross-branch address collision. */
|
|
165
|
+
advisories: AdvisoryNotice[];
|
|
140
166
|
}
|
|
141
|
-
/**
|
|
142
|
-
*
|
|
167
|
+
/**
|
|
168
|
+
* One asset's where-used overlay, kept separate from MediaLibraryEntry so the picker's shared
|
|
169
|
+
* projection stays decoupled from the Library-only usage facts.
|
|
170
|
+
*/
|
|
143
171
|
export interface MediaUsageInfo {
|
|
144
172
|
/** Distinct content entries that reference the asset (count by distinct concept+id). */
|
|
145
173
|
count: number;
|
|
146
174
|
/** Every where-used row (published and edit-branch origins), for the detail's grouped list. */
|
|
147
175
|
entries: UsageEntry[];
|
|
148
176
|
}
|
|
149
|
-
/**
|
|
177
|
+
/**
|
|
178
|
+
* The Media Library screen's data: the unioned assets, the per-hash usage overlay, and the
|
|
150
179
|
* degraded-load error. The usage overlay is keyed by content hash; an asset with no references
|
|
151
|
-
* simply has no key, which the screen renders as "no references found".
|
|
180
|
+
* simply has no key, which the screen renders as "no references found".
|
|
181
|
+
*/
|
|
152
182
|
export interface MediaLibraryData {
|
|
153
183
|
assets: MediaLibraryEntry[];
|
|
154
184
|
/** Per-hash usage overlay, kept separate from MediaLibraryEntry so the popover stays decoupled. */
|
|
155
185
|
usage: Record<string, MediaUsageInfo>;
|
|
156
|
-
/**
|
|
186
|
+
/**
|
|
187
|
+
* The degraded-load error: a failed token mint or media read. This slot is the failure of THIS
|
|
157
188
|
* load, distinct from a prior action's conflict error (see `flashError`), so a read failure and a
|
|
158
|
-
* redirected commit conflict never overwrite each other.
|
|
189
|
+
* redirected commit conflict never overwrite each other.
|
|
190
|
+
*/
|
|
159
191
|
error: string | null;
|
|
160
|
-
/**
|
|
192
|
+
/**
|
|
193
|
+
* The success flash a redirected action carries: `deleted` from `?deleted=1`, `updated` from
|
|
161
194
|
* `?updated=1`, `replaced` from `?replaced=1`, `altPropagated` from `?altPropagated=1`,
|
|
162
195
|
* `bulkDeleted` from `?bulkDeleted=1`, `orphansPurged` from `?orphansPurged=1`, null otherwise.
|
|
163
|
-
* The component renders a polite success strip for each.
|
|
196
|
+
* The component renders a polite success strip for each.
|
|
197
|
+
*/
|
|
164
198
|
flash: 'deleted' | 'updated' | 'replaced' | 'altPropagated' | 'bulkDeleted' | 'orphansPurged' | null;
|
|
165
|
-
/**
|
|
166
|
-
*
|
|
199
|
+
/**
|
|
200
|
+
* A redirected action's conflict error read from `?error=` (a commit-conflict bounce). Kept in
|
|
201
|
+
* its own slot rather than the degraded-load `error` above, so the two never collide.
|
|
202
|
+
*/
|
|
167
203
|
flashError: string | null;
|
|
168
204
|
}
|
|
169
|
-
/**
|
|
205
|
+
/**
|
|
206
|
+
* The two-tier tidy settings load (spec 2.8, Task 15). The developer tier is read-only: `enabled`,
|
|
170
207
|
* `keyConfigured`, and `model`/`modelLabel` are deploy-time facts the editor sees but cannot change.
|
|
171
208
|
* The editor tier is the resolved `conventions` block, written back through the save. The visibility
|
|
172
209
|
* gate is truthful: `enabled` is true only when `tidy.enabled` is set AND the API key is present, so
|
|
173
210
|
* the screen renders the convention list only then and the honest gate note otherwise. The key is a
|
|
174
211
|
* Worker secret, so `keyConfigured` is the presence of `ANTHROPIC_API_KEY` in the load's env, never
|
|
175
|
-
* the key itself; nothing here returns or logs the secret.
|
|
212
|
+
* the key itself; nothing here returns or logs the secret.
|
|
213
|
+
*/
|
|
176
214
|
export interface SettingsData {
|
|
177
|
-
/**
|
|
215
|
+
/**
|
|
216
|
+
* The truthful gate: tidy is enabled AND the API key is present. The screen renders the editor
|
|
178
217
|
* tier only when this is true, and the honest gate note (a labelled region, no disabled controls)
|
|
179
|
-
* otherwise.
|
|
218
|
+
* otherwise.
|
|
219
|
+
*/
|
|
180
220
|
enabled: boolean;
|
|
181
|
-
/**
|
|
182
|
-
*
|
|
221
|
+
/**
|
|
222
|
+
* Whether `tidy.enabled` is set in the site config, independent of the key. The gate note's
|
|
223
|
+
* checklist reads this to show which deploy-time step is still open.
|
|
224
|
+
*/
|
|
183
225
|
tidyEnabled: boolean;
|
|
184
226
|
/** Whether the API key secret is present in the Worker env. A presence flag, never the key. */
|
|
185
227
|
keyConfigured: boolean;
|
|
186
228
|
/** The model id (a developer-tier fact, read-only on the screen). */
|
|
187
229
|
model: string;
|
|
188
|
-
/**
|
|
189
|
-
*
|
|
230
|
+
/**
|
|
231
|
+
* A plain-language label for the model id ("Claude Sonnet"), so the read-only fact is not a bare
|
|
232
|
+
* jargon token. Falls back to the raw id for an unknown model.
|
|
233
|
+
*/
|
|
190
234
|
modelLabel: string;
|
|
191
|
-
/**
|
|
192
|
-
*
|
|
235
|
+
/**
|
|
236
|
+
* The resolved editor-tier conventions: every field concrete, the screen's initial control state.
|
|
237
|
+
* Present only when the gate is open; the gate state needs no conventions.
|
|
238
|
+
*/
|
|
193
239
|
conventions: TidyConventions;
|
|
194
240
|
/** The success flash a redirected save carries (`?saved=1`). */
|
|
195
241
|
saved: boolean;
|
|
196
242
|
/** A redirected save's validation or conflict error read from `?error=`. */
|
|
197
243
|
error: string | null;
|
|
198
244
|
}
|
|
199
|
-
/**
|
|
200
|
-
*
|
|
245
|
+
/**
|
|
246
|
+
* A refused settings save: a conflict bounce or a malformed conventions payload. Just the one-line
|
|
247
|
+
* summary; the save commits nothing on a refusal.
|
|
248
|
+
*/
|
|
201
249
|
export interface SettingsSaveFailure {
|
|
202
250
|
error: string;
|
|
203
251
|
}
|
|
252
|
+
/**
|
|
253
|
+
* The Help home's data: the derived getting-started progress, the full markdown reference (the
|
|
254
|
+
* component curates by group), and the optional support hand-off (rendered only when set).
|
|
255
|
+
*/
|
|
256
|
+
export interface HelpData {
|
|
257
|
+
gettingStarted: GettingStarted;
|
|
258
|
+
reference: MarkdownReferenceRow[];
|
|
259
|
+
supportContact?: string;
|
|
260
|
+
}
|
|
204
261
|
/** The structural event the content routes read; a real SvelteKit RequestEvent satisfies it. */
|
|
205
262
|
export interface ContentEvent extends EventBase<GithubKeyEnv> {
|
|
206
263
|
params: Record<string, string>;
|
|
207
|
-
/**
|
|
208
|
-
*
|
|
264
|
+
/**
|
|
265
|
+
* SvelteKit's cookie jar. The layout load reads the persisted admin theme and issues the CSRF
|
|
266
|
+
* token. Optional for non-route callers.
|
|
267
|
+
*/
|
|
209
268
|
cookies?: CookieJar;
|
|
210
269
|
}
|
|
211
270
|
/** Injectable dependencies; tests stub the token mint to avoid signing a real key. */
|
|
212
|
-
/**
|
|
271
|
+
/**
|
|
272
|
+
* The minimal Anthropic client surface the tidy action uses, typed structurally so the SDK's deep
|
|
213
273
|
* generics never reach a public signature and so the integration test can inject a fake whose
|
|
214
274
|
* `messages.create` it stubs. The real factory builds `new Anthropic({ apiKey })`, which satisfies
|
|
215
275
|
* this shape. The success path reads only the text blocks, the model, the stop reason, and the usage
|
|
216
|
-
* counts.
|
|
276
|
+
* counts.
|
|
277
|
+
*/
|
|
217
278
|
export interface TidyClient {
|
|
218
279
|
messages: {
|
|
219
280
|
create(body: {
|
|
@@ -241,25 +302,33 @@ export interface TidyClient {
|
|
|
241
302
|
};
|
|
242
303
|
}
|
|
243
304
|
export interface ContentRoutesDeps {
|
|
244
|
-
/**
|
|
245
|
-
*
|
|
305
|
+
/**
|
|
306
|
+
* Mint a GitHub App installation token from the Worker env. Defaults to the real signer.
|
|
307
|
+
* A bare string works too; the routes await whatever comes back.
|
|
308
|
+
*/
|
|
246
309
|
mintToken?: (env: GithubKeyEnv) => string | Promise<string>;
|
|
247
|
-
/**
|
|
310
|
+
/**
|
|
311
|
+
* Build the Anthropic client for the tidy action from the resolved API key. Defaults to the real
|
|
248
312
|
* SDK client. Injected in tests so `messages.create` is stubbed and no network call (or real key)
|
|
249
313
|
* is ever needed. The factory runs only after the key is read from the env, so a disabled or
|
|
250
|
-
* unconfigured site never constructs a client.
|
|
314
|
+
* unconfigured site never constructs a client.
|
|
315
|
+
*/
|
|
251
316
|
anthropic?: (opts: {
|
|
252
317
|
apiKey: string;
|
|
253
318
|
}) => TidyClient;
|
|
254
|
-
/**
|
|
319
|
+
/**
|
|
320
|
+
* The tidy action's own request deadline in milliseconds, set shorter than the platform limit so a
|
|
255
321
|
* slow model call becomes a clean retryable fail(502) rather than a platform timeout. Defaults to
|
|
256
|
-
* {@link DEFAULT_TIDY_TIMEOUT_MS}. Overridable in tests to assert the deadline path without waiting.
|
|
322
|
+
* {@link DEFAULT_TIDY_TIMEOUT_MS}. Overridable in tests to assert the deadline path without waiting.
|
|
323
|
+
*/
|
|
257
324
|
tidyTimeoutMs?: number;
|
|
258
325
|
}
|
|
259
|
-
/**
|
|
326
|
+
/**
|
|
327
|
+
* The successful tidy outcome (spec 2.1): the corrected markdown, the model that produced it, and the
|
|
260
328
|
* token usage. The diff is computed on the client (Task 12), so the server returns the plain text and
|
|
261
329
|
* commits nothing. Admin-internal: consumed by the editor's review surface, not on the package's
|
|
262
|
-
* sveltekit subpath, so it carries no reference page.
|
|
330
|
+
* sveltekit subpath, so it carries no reference page.
|
|
331
|
+
*/
|
|
263
332
|
export interface TidyResult {
|
|
264
333
|
corrected: string;
|
|
265
334
|
model: string;
|
|
@@ -268,10 +337,12 @@ export interface TidyResult {
|
|
|
268
337
|
output_tokens: number;
|
|
269
338
|
};
|
|
270
339
|
}
|
|
271
|
-
/**
|
|
340
|
+
/**
|
|
341
|
+
* A refused tidy: `fail(403)` on a failed CSRF check, `fail(503)` when tidy is disabled or the API
|
|
272
342
|
* key is missing, `fail(413)` for an over-long body, `fail(502)` for a deadline overrun, abort, or
|
|
273
343
|
* model error (all retryable), `fail(422)` for a model refusal, `fail(400)` for a malformed body. Just
|
|
274
|
-
* the one-line summary; the action commits nothing, so a refusal can never corrupt the entry.
|
|
344
|
+
* the one-line summary; the action commits nothing, so a refusal can never corrupt the entry.
|
|
345
|
+
*/
|
|
275
346
|
export interface TidyFailure {
|
|
276
347
|
error: string;
|
|
277
348
|
}
|
|
@@ -298,9 +369,11 @@ export interface RenameFailure {
|
|
|
298
369
|
/** The one-line human summary every content action failure carries. */
|
|
299
370
|
error: string;
|
|
300
371
|
}
|
|
301
|
-
/**
|
|
372
|
+
/**
|
|
373
|
+
* A refused media delete: `fail(404)` for an asset not committed on the default branch, or
|
|
302
374
|
* `fail(409)` when a fresh usage read finds the asset still in use and the typed-slug override
|
|
303
|
-
* was not given. `fail(503)` covers media-off or a missing bucket binding.
|
|
375
|
+
* was not given. `fail(503)` covers media-off or a missing bucket binding.
|
|
376
|
+
*/
|
|
304
377
|
export interface MediaDeleteRefusal {
|
|
305
378
|
/** The one-line human summary every action failure carries. */
|
|
306
379
|
error: string;
|
|
@@ -311,49 +384,63 @@ export interface MediaDeleteRefusal {
|
|
|
311
384
|
/** The distinct-entry count behind the refusal; zero when the asset is uncommitted. */
|
|
312
385
|
foundIn: number;
|
|
313
386
|
}
|
|
314
|
-
/**
|
|
315
|
-
*
|
|
387
|
+
/**
|
|
388
|
+
* A refused media metadata edit: `fail(404)` for an asset not committed on the default branch, or
|
|
389
|
+
* `fail(400)` for an invalid slug.
|
|
390
|
+
*/
|
|
316
391
|
export interface MediaUpdateFailure {
|
|
317
392
|
/** The one-line human summary every action failure carries. */
|
|
318
393
|
error: string;
|
|
319
394
|
}
|
|
320
|
-
/**
|
|
395
|
+
/**
|
|
396
|
+
* A refused media replace: `fail(409)` when a fresh usage read finds the asset still in use and the
|
|
321
397
|
* typed-slug override was not given, or `fail(503)` when usage cannot be verified (fail closed) or the
|
|
322
|
-
* bucket is unbound. Mirrors MediaDeleteRefusal: the asset hash, the where-used rows, and the count.
|
|
398
|
+
* bucket is unbound. Mirrors MediaDeleteRefusal: the asset hash, the where-used rows, and the count.
|
|
399
|
+
*/
|
|
323
400
|
export interface MediaReplaceFailure {
|
|
324
401
|
error: string;
|
|
325
402
|
hash: string;
|
|
326
403
|
usage: UsageEntry[];
|
|
327
404
|
foundIn: number;
|
|
328
405
|
}
|
|
329
|
-
/**
|
|
406
|
+
/**
|
|
407
|
+
* A refused media alt-propagation: `fail(503)` when usage cannot be verified across main and every
|
|
330
408
|
* open branch (fail closed), or the bucket is unbound. Just the one-line summary; alt fill has no
|
|
331
|
-
* typed-slug gate.
|
|
409
|
+
* typed-slug gate.
|
|
410
|
+
*/
|
|
332
411
|
export interface MediaAltPropagateFailure {
|
|
333
412
|
error: string;
|
|
334
413
|
}
|
|
335
|
-
/**
|
|
414
|
+
/**
|
|
415
|
+
* The personal-dictionary add outcome (spec 1.6): the merged, canonical sorted word list after the
|
|
336
416
|
* add landed. The client reconciles its pending-additions set against this (a word now in the list is
|
|
337
417
|
* committed and dropped from pending). Admin-internal: exported for the editor host's reconcile, not
|
|
338
|
-
* on the package's sveltekit subpath, so it carries no reference page.
|
|
418
|
+
* on the package's sveltekit subpath, so it carries no reference page.
|
|
419
|
+
*/
|
|
339
420
|
export interface DictionaryAddResult {
|
|
340
421
|
words: string[];
|
|
341
422
|
}
|
|
342
|
-
/**
|
|
423
|
+
/**
|
|
424
|
+
* A refused personal-dictionary add: `fail(403)` on a failed CSRF check, `fail(400)` on a body that
|
|
343
425
|
* carries no valid word. The client keeps its pending additions for the session and re-attempts on
|
|
344
|
-
* the next save, so the word is never silently dropped. Just the one-line summary.
|
|
426
|
+
* the next save, so the word is never silently dropped. Just the one-line summary.
|
|
427
|
+
*/
|
|
345
428
|
export interface DictionaryAddFailure {
|
|
346
429
|
error: string;
|
|
347
430
|
}
|
|
348
|
-
/**
|
|
431
|
+
/**
|
|
432
|
+
* A refused media bulk delete or orphan purge: `fail(503)` for the fail-closed strict-usage refusal
|
|
349
433
|
* (the whole batch refuses) or media-off / a missing bucket binding. The per-item outcomes ride the
|
|
350
|
-
* returned summary, not a fail.
|
|
434
|
+
* returned summary, not a fail.
|
|
435
|
+
*/
|
|
351
436
|
export interface MediaBulkFailure {
|
|
352
437
|
error: string;
|
|
353
438
|
}
|
|
354
|
-
/**
|
|
439
|
+
/**
|
|
440
|
+
* The bulk-delete outcome the component renders: the deleted hashes, the skipped rows from the
|
|
355
441
|
* partition (with their reason and where-used), and any per-object R2 delete failure. Admin-internal,
|
|
356
|
-
* not on the package subpath, so no reference page.
|
|
442
|
+
* not on the package subpath, so no reference page.
|
|
443
|
+
*/
|
|
357
444
|
export interface MediaBulkDeleteResult {
|
|
358
445
|
deleted: string[];
|
|
359
446
|
skipped: BulkDeleteSkip[];
|
|
@@ -362,8 +449,10 @@ export interface MediaBulkDeleteResult {
|
|
|
362
449
|
error: string;
|
|
363
450
|
}[];
|
|
364
451
|
}
|
|
365
|
-
/**
|
|
366
|
-
*
|
|
452
|
+
/**
|
|
453
|
+
* The orphan-purge outcome: the purged R2 keys, the keys skipped because their hash was claimed by a
|
|
454
|
+
* manifest row since the scan, and any per-object delete failure. Admin-internal, no reference page.
|
|
455
|
+
*/
|
|
367
456
|
export interface MediaOrphanPurgeResult {
|
|
368
457
|
purged: string[];
|
|
369
458
|
skippedClaimed: string[];
|
|
@@ -372,11 +461,13 @@ export interface MediaOrphanPurgeResult {
|
|
|
372
461
|
error: string;
|
|
373
462
|
}[];
|
|
374
463
|
}
|
|
375
|
-
/**
|
|
464
|
+
/**
|
|
465
|
+
* One entry the replace preview will rewrite, enriched with its display title and permalink from the
|
|
376
466
|
* content manifest (the planner's PlannedEntry carries neither). The screen lists these as the
|
|
377
467
|
* confirm dialog's where-touched preview, and the apply re-derives its own plan rather than trusting
|
|
378
468
|
* this. Admin-internal: exported from content-routes for the bundled Media Library component, not
|
|
379
|
-
* added to the package's sveltekit subpath, so it carries no reference page.
|
|
469
|
+
* added to the package's sveltekit subpath, so it carries no reference page.
|
|
470
|
+
*/
|
|
380
471
|
export interface MediaReplacePreviewEntry {
|
|
381
472
|
/** The concept id, e.g. "posts". */
|
|
382
473
|
concept: string;
|
|
@@ -389,20 +480,24 @@ export interface MediaReplacePreviewEntry {
|
|
|
389
480
|
/** The per-reference diff for this entry: one placement per repointed `media:` token. */
|
|
390
481
|
placements: RepointPlacement[];
|
|
391
482
|
}
|
|
392
|
-
/**
|
|
483
|
+
/**
|
|
484
|
+
* The replace preview plan: the affected main entries (enriched), the distinct affected count, and
|
|
393
485
|
* the report-only cross-branch delta (open cairn/* branches that reference the same bytes; an apply
|
|
394
|
-
* rewrites main only). Display-only: the apply re-derives a fresh plan and never trusts this.
|
|
486
|
+
* rewrites main only). Display-only: the apply re-derives a fresh plan and never trusts this.
|
|
487
|
+
*/
|
|
395
488
|
export interface MediaReplacePreviewPlan {
|
|
396
489
|
affectedCount: number;
|
|
397
490
|
entries: MediaReplacePreviewEntry[];
|
|
398
491
|
branchDelta: BranchRef[];
|
|
399
492
|
}
|
|
400
|
-
/**
|
|
493
|
+
/**
|
|
494
|
+
* One entry the alt-propagation preview reports, enriched with its display title and permalink from
|
|
401
495
|
* the content manifest. Its placements carry every reference of the asset on this entry, each tagged
|
|
402
496
|
* with the bucket it falls in (a will-fill, a customized alt left as-is, or a decorative hero), so
|
|
403
497
|
* the screen can show what would change. Admin-internal: exported from content-routes for the bundled
|
|
404
498
|
* Media Library component, not added to the package's sveltekit subpath, so it carries no reference
|
|
405
|
-
* page.
|
|
499
|
+
* page.
|
|
500
|
+
*/
|
|
406
501
|
export interface MediaAltPreviewEntry {
|
|
407
502
|
/** The concept id, e.g. "posts". */
|
|
408
503
|
concept: string;
|
|
@@ -415,11 +510,13 @@ export interface MediaAltPreviewEntry {
|
|
|
415
510
|
/** The per-reference diff for this entry: one placement per reference of the asset. */
|
|
416
511
|
placements: AltPlacement[];
|
|
417
512
|
}
|
|
418
|
-
/**
|
|
513
|
+
/**
|
|
514
|
+
* The alt-propagation preview plan: every entry that references the asset (enriched), the report-only
|
|
419
515
|
* cross-branch delta, and the bucket counts aggregated across every placement. Display-only: the
|
|
420
516
|
* apply re-derives a fresh plan and never trusts this. The preview reports an entry even when its
|
|
421
517
|
* only placements are reported-but-unchanged (a kept custom alt, a decorative hero), so the screen
|
|
422
|
-
* can show every bucket; the apply commits only the entries it actually changes.
|
|
518
|
+
* can show every bucket; the apply commits only the entries it actually changes.
|
|
519
|
+
*/
|
|
423
520
|
export interface MediaAltPreviewPlan {
|
|
424
521
|
entries: MediaAltPreviewEntry[];
|
|
425
522
|
branchDelta: BranchRef[];
|
|
@@ -430,24 +527,32 @@ export interface MediaAltPreviewPlan {
|
|
|
430
527
|
decorativeSkipped: number;
|
|
431
528
|
};
|
|
432
529
|
}
|
|
433
|
-
/**
|
|
530
|
+
/**
|
|
531
|
+
* What a route's single `form` export presents to a view component: whichever content action
|
|
434
532
|
* last failed, merged with every field optional. `error` is always set on a failure; the richer
|
|
435
533
|
* keys identify which guard refused. The media refusals ride here too, so the Media Library's one
|
|
436
534
|
* `form` prop carries a `?/mediaDelete`, `?/mediaUpdate`, `?/mediaReplace`, or `?/mediaAltPropagate`
|
|
437
|
-
* refusal without a second type.
|
|
535
|
+
* refusal without a second type.
|
|
536
|
+
*/
|
|
438
537
|
export type ContentFormFailure = Partial<SaveFailure & DeleteRefusal & RenameFailure & MediaDeleteRefusal & MediaUpdateFailure & MediaReplaceFailure & MediaAltPropagateFailure & MediaBulkFailure & TidyFailure>;
|
|
439
|
-
/**
|
|
538
|
+
/**
|
|
539
|
+
* The successful upload's response (`uploadAction`). The server-owned `record` rides the editor's
|
|
440
540
|
* optimistic client state and commits with the entry at Save (the upload itself commits nothing).
|
|
441
541
|
* `reused` is true when identical bytes were already stored, so the second upload did no second put;
|
|
442
|
-
* `mismatch` flags an existing object whose stored content type differs from this sniff.
|
|
542
|
+
* `mismatch` flags an existing object whose stored content type differs from this sniff.
|
|
543
|
+
*/
|
|
443
544
|
export interface UploadResult {
|
|
444
545
|
reference: string;
|
|
445
546
|
record: MediaEntry;
|
|
446
547
|
reused: boolean;
|
|
447
548
|
mismatch: boolean;
|
|
448
549
|
}
|
|
550
|
+
/**
|
|
551
|
+
*
|
|
552
|
+
*/
|
|
449
553
|
export declare function createContentRoutes(runtime: CairnRuntime, deps?: ContentRoutesDeps): {
|
|
450
554
|
layoutLoad: (event: ContentEvent) => Promise<LayoutData>;
|
|
555
|
+
helpLoad: (event: ContentEvent) => Promise<HelpData>;
|
|
451
556
|
indexRedirect: () => never;
|
|
452
557
|
listLoad: (event: ContentEvent) => Promise<ListData>;
|
|
453
558
|
mediaLibraryLoad: (event: ContentEvent) => Promise<MediaLibraryData>;
|