@glw907/cairn-cms 0.29.0 → 0.34.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/CHANGELOG.md +111 -0
- package/dist/components/AdminLayout.svelte +372 -44
- package/dist/components/AdminLayout.svelte.d.ts +5 -4
- package/dist/components/CairnLogo.svelte +28 -0
- package/dist/components/CairnLogo.svelte.d.ts +15 -0
- package/dist/components/ComponentForm.svelte +1 -1
- package/dist/components/ConceptList.svelte +240 -45
- package/dist/components/ConceptList.svelte.d.ts +12 -2
- package/dist/components/ConfirmPage.svelte +20 -3
- package/dist/components/EditPage.svelte +12 -7
- package/dist/components/LoginPage.svelte +27 -5
- package/dist/components/ManageEditors.svelte +8 -5
- package/dist/components/NavTree.svelte +2 -2
- package/dist/components/admin-icons.d.ts +13 -0
- package/dist/components/admin-icons.js +15 -0
- package/dist/components/cairn-admin.css +5516 -37
- package/dist/components/cairn-favicon.d.ts +2 -0
- package/dist/components/cairn-favicon.js +7 -0
- package/dist/components/chrome-guard.d.ts +9 -0
- package/dist/components/chrome-guard.js +55 -0
- package/dist/components/fonts/BricolageGrotesque-OFL.txt +93 -0
- package/dist/components/fonts/Figtree-OFL.txt +93 -0
- package/dist/components/fonts/bricolage-grotesque.woff2 +0 -0
- package/dist/components/fonts/figtree.woff2 +0 -0
- package/dist/index.d.ts +0 -2
- package/dist/index.js +4 -1
- package/dist/render/authoring.d.ts +3 -0
- package/dist/render/authoring.js +5 -0
- package/dist/render/registry.d.ts +2 -0
- package/dist/render/registry.js +15 -0
- package/dist/render/rehype-dispatch.d.ts +9 -6
- package/dist/render/rehype-dispatch.js +12 -6
- package/dist/render/remark-directives.js +1 -1
- package/dist/sveltekit/content-routes.d.ts +12 -1
- package/dist/sveltekit/content-routes.js +37 -13
- package/dist/sveltekit/guard.js +32 -0
- package/dist/sveltekit/https-required-page.d.ts +5 -0
- package/dist/sveltekit/https-required-page.js +216 -0
- package/package.json +16 -2
- package/src/lib/components/AdminLayout.svelte +372 -44
- package/src/lib/components/CairnLogo.svelte +28 -0
- package/src/lib/components/ComponentForm.svelte +1 -1
- package/src/lib/components/ConceptList.svelte +240 -45
- package/src/lib/components/ConfirmPage.svelte +20 -3
- package/src/lib/components/EditPage.svelte +12 -7
- package/src/lib/components/LoginPage.svelte +27 -5
- package/src/lib/components/ManageEditors.svelte +8 -5
- package/src/lib/components/NavTree.svelte +2 -2
- package/src/lib/components/admin-icons.ts +15 -0
- package/src/lib/components/cairn-admin.css +162 -7
- package/src/lib/components/cairn-favicon.ts +9 -0
- package/src/lib/components/chrome-guard.ts +62 -0
- package/src/lib/components/fonts/BricolageGrotesque-OFL.txt +93 -0
- package/src/lib/components/fonts/Figtree-OFL.txt +93 -0
- package/src/lib/components/fonts/bricolage-grotesque.woff2 +0 -0
- package/src/lib/components/fonts/figtree.woff2 +0 -0
- package/src/lib/index.ts +4 -2
- package/src/lib/render/authoring.ts +7 -0
- package/src/lib/render/registry.ts +20 -0
- package/src/lib/render/rehype-dispatch.ts +13 -6
- package/src/lib/render/remark-directives.ts +1 -1
- package/src/lib/sveltekit/content-routes.ts +51 -14
- package/src/lib/sveltekit/guard.ts +36 -0
- package/src/lib/sveltekit/https-required-page.ts +220 -0
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
// The standalone "this admin needs HTTPS" page. The auth guard serves it when a request reaches a
|
|
2
|
+
// deployed Worker over http, which is the one case that makes the magic-link sign-in fail: the
|
|
3
|
+
// JS-free login form posts over http, and the framework's CSRF guard rejects a form POST whose
|
|
4
|
+
// origin scheme does not match, so the editor would otherwise hit an opaque 403. This page names
|
|
5
|
+
// the problem, says why https is needed, and gives the exact Cloudflare fix.
|
|
6
|
+
//
|
|
7
|
+
// It is served raw from the edge, before SvelteKit renders anything, so it carries no external
|
|
8
|
+
// request: the Warm Stone tokens are inlined for both colour schemes and the type falls back to the
|
|
9
|
+
// system stack (the shipped admin fonts are not reachable from here). The cairn glyph is the same
|
|
10
|
+
// public-domain Temaki mark the admin chrome uses. See docs/internal/admin-design-system.md.
|
|
11
|
+
/** Escape a string for safe interpolation into HTML text and double-quoted attributes. */
|
|
12
|
+
function escapeHtml(value) {
|
|
13
|
+
return value
|
|
14
|
+
.replace(/&/g, '&')
|
|
15
|
+
.replace(/</g, '<')
|
|
16
|
+
.replace(/>/g, '>')
|
|
17
|
+
.replace(/"/g, '"');
|
|
18
|
+
}
|
|
19
|
+
// The cairn stone-stack glyph (Temaki, CC0), drawn in currentColor like CairnLogo.svelte.
|
|
20
|
+
const CAIRN_GLYPH = '<path d="M6.28 14C5.56 14 1 13.89 1 12.91C1 11.46 2.16 11.07 3.2 10.81C4.36 10.51 13.18 9.77 ' +
|
|
21
|
+
'13.76 10.07C14.46 10.43 13.52 12.49 12.44 12.77C11.28 13.07 10.21 14 8.48 14C7.05 14 9.69 14 ' +
|
|
22
|
+
'6.28 14ZM6.92 4.5C6.67 4.5 5 4.43 5 3.88C5 3.07 5.75 2.51 5.96 2.35C6.36 2.03 6.32 1.62 6.54 ' +
|
|
23
|
+
'1.27C6.84 0.79 7.61 0.5 7.88 0.5C8.1 0.5 8.75 0.9 9.23 1.42C9.45 1.66 10 2.77 10 3.12C10 4.22 ' +
|
|
24
|
+
'9.36 4.5 8.85 4.5C8.33 4.5 8.15 4.5 6.92 4.5ZM3.68 8.22C3 7.73 3.67 6.86 4.57 6.21C5.38 5.63 ' +
|
|
25
|
+
'5.92 5.96 6.79 5.7C8.33 5.24 9.02 5.72 9.02 5.72L10.9 6.82C12.03 7.63 10.99 7.67 10.38 8.56C9.79 ' +
|
|
26
|
+
'9.42 8.18 9.11 7.42 9.33C6.78 9.53 5.75 9.71 4.62 8.9L3.68 8.22Z"/>';
|
|
27
|
+
/**
|
|
28
|
+
* Render the full HTML document for the HTTPS-required page.
|
|
29
|
+
* @param httpsUrl The same request rebuilt over https, offered as the one-click recovery link.
|
|
30
|
+
*/
|
|
31
|
+
export function httpsRequiredPage(httpsUrl) {
|
|
32
|
+
const href = escapeHtml(httpsUrl);
|
|
33
|
+
return `<!doctype html>
|
|
34
|
+
<html lang="en">
|
|
35
|
+
<head>
|
|
36
|
+
<meta charset="utf-8" />
|
|
37
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
38
|
+
<meta name="robots" content="noindex, nofollow" />
|
|
39
|
+
<title>HTTPS required · Cairn</title>
|
|
40
|
+
<style>
|
|
41
|
+
:root {
|
|
42
|
+
color-scheme: light;
|
|
43
|
+
--bg: oklch(96.5% 0.006 75);
|
|
44
|
+
--glow: oklch(52% 0.2 293 / 0.06);
|
|
45
|
+
--panel: oklch(99% 0.004 75);
|
|
46
|
+
--recessed: oklch(95% 0.008 75);
|
|
47
|
+
--ink: oklch(26% 0.014 75);
|
|
48
|
+
--muted: oklch(48% 0.01 75);
|
|
49
|
+
--subtle: oklch(42% 0.01 75);
|
|
50
|
+
--primary: oklch(52% 0.2 293);
|
|
51
|
+
--primary-content: oklch(98% 0.012 293);
|
|
52
|
+
--border: oklch(93% 0.008 75);
|
|
53
|
+
--shadow: 0 1px 2px oklch(28% 0.02 75 / 0.05), 0 18px 40px -12px oklch(28% 0.02 75 / 0.16);
|
|
54
|
+
--radius-box: 1rem;
|
|
55
|
+
--radius-field: 0.625rem;
|
|
56
|
+
--font: 'Figtree Variable', system-ui, -apple-system, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
|
57
|
+
}
|
|
58
|
+
@media (prefers-color-scheme: dark) {
|
|
59
|
+
:root {
|
|
60
|
+
color-scheme: dark;
|
|
61
|
+
--bg: oklch(15.5% 0.009 75);
|
|
62
|
+
--glow: oklch(68% 0.18 293 / 0.1);
|
|
63
|
+
--panel: oklch(24% 0.01 75);
|
|
64
|
+
--recessed: oklch(20% 0.01 75);
|
|
65
|
+
--ink: oklch(93% 0.006 75);
|
|
66
|
+
--muted: oklch(72% 0.01 75);
|
|
67
|
+
--subtle: oklch(80% 0.008 75);
|
|
68
|
+
--primary: oklch(68% 0.18 293);
|
|
69
|
+
--primary-content: oklch(20% 0.04 293);
|
|
70
|
+
--border: oklch(30% 0.014 75);
|
|
71
|
+
--shadow: 0 1px 2px oklch(0% 0 0 / 0.35), 0 18px 40px -12px oklch(0% 0 0 / 0.55);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
* { box-sizing: border-box; }
|
|
75
|
+
body {
|
|
76
|
+
margin: 0;
|
|
77
|
+
min-height: 100vh;
|
|
78
|
+
display: flex;
|
|
79
|
+
align-items: center;
|
|
80
|
+
justify-content: center;
|
|
81
|
+
padding: 1.5rem;
|
|
82
|
+
font-family: var(--font);
|
|
83
|
+
color: var(--ink);
|
|
84
|
+
background-color: var(--bg);
|
|
85
|
+
background-image: radial-gradient(80rem 50rem at 50% -20%, var(--glow), transparent 60%);
|
|
86
|
+
-webkit-font-smoothing: antialiased;
|
|
87
|
+
-moz-osx-font-smoothing: grayscale;
|
|
88
|
+
line-height: 1.55;
|
|
89
|
+
}
|
|
90
|
+
main {
|
|
91
|
+
width: 100%;
|
|
92
|
+
max-width: 30rem;
|
|
93
|
+
background: var(--panel);
|
|
94
|
+
border: 1px solid var(--border);
|
|
95
|
+
border-radius: var(--radius-box);
|
|
96
|
+
box-shadow: var(--shadow);
|
|
97
|
+
padding: 2.25rem;
|
|
98
|
+
}
|
|
99
|
+
.brand { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 1.75rem; }
|
|
100
|
+
.brand .tile {
|
|
101
|
+
display: grid;
|
|
102
|
+
place-items: center;
|
|
103
|
+
width: 2rem;
|
|
104
|
+
height: 2rem;
|
|
105
|
+
border-radius: 0.75rem;
|
|
106
|
+
background: var(--primary);
|
|
107
|
+
color: var(--primary-content);
|
|
108
|
+
box-shadow: 0 1px 2px oklch(0% 0 0 / 0.12);
|
|
109
|
+
}
|
|
110
|
+
.brand .tile svg { width: 1.25rem; height: 1.25rem; }
|
|
111
|
+
.brand .word {
|
|
112
|
+
font-weight: 700;
|
|
113
|
+
font-size: 1.25rem;
|
|
114
|
+
letter-spacing: -0.01em;
|
|
115
|
+
}
|
|
116
|
+
.eyebrow {
|
|
117
|
+
display: inline-flex;
|
|
118
|
+
align-items: center;
|
|
119
|
+
gap: 0.4rem;
|
|
120
|
+
font-size: 0.6875rem;
|
|
121
|
+
font-weight: 600;
|
|
122
|
+
text-transform: uppercase;
|
|
123
|
+
letter-spacing: 0.08em;
|
|
124
|
+
color: var(--muted);
|
|
125
|
+
margin-bottom: 0.6rem;
|
|
126
|
+
}
|
|
127
|
+
.eyebrow svg { width: 0.85rem; height: 0.85rem; }
|
|
128
|
+
h1 {
|
|
129
|
+
margin: 0 0 0.75rem;
|
|
130
|
+
font-size: 1.6rem;
|
|
131
|
+
font-weight: 800;
|
|
132
|
+
letter-spacing: -0.02em;
|
|
133
|
+
line-height: 1.15;
|
|
134
|
+
}
|
|
135
|
+
p { margin: 0 0 1rem; color: var(--subtle); }
|
|
136
|
+
.cta {
|
|
137
|
+
display: inline-flex;
|
|
138
|
+
align-items: center;
|
|
139
|
+
gap: 0.5rem;
|
|
140
|
+
margin: 0.25rem 0 0.5rem;
|
|
141
|
+
padding: 0.7rem 1.15rem;
|
|
142
|
+
border-radius: var(--radius-field);
|
|
143
|
+
background: var(--primary);
|
|
144
|
+
color: var(--primary-content);
|
|
145
|
+
font-weight: 600;
|
|
146
|
+
font-size: 0.95rem;
|
|
147
|
+
text-decoration: none;
|
|
148
|
+
box-shadow: 0 4px 14px -4px oklch(52% 0.2 293 / 0.5);
|
|
149
|
+
transition: transform 0.12s ease, box-shadow 0.12s ease;
|
|
150
|
+
}
|
|
151
|
+
.cta:hover { transform: translateY(-1px); box-shadow: 0 8px 20px -6px oklch(52% 0.2 293 / 0.55); }
|
|
152
|
+
.cta:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
|
|
153
|
+
.cta svg { width: 1rem; height: 1rem; }
|
|
154
|
+
.fix {
|
|
155
|
+
margin-top: 1.75rem;
|
|
156
|
+
padding: 1.1rem 1.2rem;
|
|
157
|
+
background: var(--recessed);
|
|
158
|
+
border: 1px solid var(--border);
|
|
159
|
+
border-radius: var(--radius-field);
|
|
160
|
+
}
|
|
161
|
+
.fix h2 {
|
|
162
|
+
margin: 0 0 0.5rem;
|
|
163
|
+
font-size: 0.8125rem;
|
|
164
|
+
font-weight: 700;
|
|
165
|
+
letter-spacing: 0.01em;
|
|
166
|
+
}
|
|
167
|
+
.fix p { margin: 0 0 0.65rem; font-size: 0.875rem; }
|
|
168
|
+
.fix p:last-child { margin-bottom: 0; }
|
|
169
|
+
.path {
|
|
170
|
+
display: block;
|
|
171
|
+
font-size: 0.8125rem;
|
|
172
|
+
font-weight: 600;
|
|
173
|
+
color: var(--ink);
|
|
174
|
+
letter-spacing: 0.01em;
|
|
175
|
+
margin: 0 0 0.65rem;
|
|
176
|
+
}
|
|
177
|
+
.path .arrow { color: var(--muted); padding: 0 0.35rem; font-weight: 400; }
|
|
178
|
+
.foot {
|
|
179
|
+
margin-top: 1.75rem;
|
|
180
|
+
text-align: center;
|
|
181
|
+
font-size: 0.75rem;
|
|
182
|
+
color: var(--muted);
|
|
183
|
+
}
|
|
184
|
+
</style>
|
|
185
|
+
</head>
|
|
186
|
+
<body>
|
|
187
|
+
<main>
|
|
188
|
+
<div class="brand">
|
|
189
|
+
<span class="tile"><svg viewBox="0 0 15 15" fill="currentColor" aria-hidden="true">${CAIRN_GLYPH}</svg></span>
|
|
190
|
+
<span class="word">Cairn</span>
|
|
191
|
+
</div>
|
|
192
|
+
|
|
193
|
+
<span class="eyebrow">
|
|
194
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
|
|
195
|
+
Secure connection required
|
|
196
|
+
</span>
|
|
197
|
+
<h1>This admin needs a secure connection</h1>
|
|
198
|
+
<p>You opened this page over http. Sign-in only works over https, so open the secure version to continue.</p>
|
|
199
|
+
|
|
200
|
+
<a class="cta" href="${href}">
|
|
201
|
+
Open over HTTPS
|
|
202
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
|
|
203
|
+
</a>
|
|
204
|
+
|
|
205
|
+
<div class="fix">
|
|
206
|
+
<h2>If you run this site</h2>
|
|
207
|
+
<p>Turn on Always Use HTTPS in Cloudflare. It upgrades every request to https before it reaches the site:</p>
|
|
208
|
+
<span class="path">SSL/TLS<span class="arrow">›</span>Edge Certificates<span class="arrow">›</span>Always Use HTTPS</span>
|
|
209
|
+
<p>Keep HSTS on too. The browser then stays on https and sign-in works.</p>
|
|
210
|
+
</div>
|
|
211
|
+
|
|
212
|
+
<p class="foot">Powered by Cairn</p>
|
|
213
|
+
</main>
|
|
214
|
+
</body>
|
|
215
|
+
</html>`;
|
|
216
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@glw907/cairn-cms",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.34.0",
|
|
4
4
|
"description": "Embedded, magic-link, GitHub-committing CMS for SvelteKit/Cloudflare sites.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": [
|
|
@@ -26,9 +26,11 @@
|
|
|
26
26
|
"markdown"
|
|
27
27
|
],
|
|
28
28
|
"scripts": {
|
|
29
|
-
"package": "svelte-package && chmod +x dist/vite/bin.js",
|
|
29
|
+
"package": "svelte-package && node scripts/build-admin-css.mjs && chmod +x dist/vite/bin.js",
|
|
30
30
|
"check:package": "npm run package && publint --strict && attw --pack . --ignore-rules no-resolution cjs-resolves-to-esm internal-resolution-error",
|
|
31
31
|
"check:reference": "npm run package && node scripts/reference-coverage.mjs",
|
|
32
|
+
"check:docs": "node scripts/docs-links.mjs",
|
|
33
|
+
"check:prose": "node scripts/check-admin-prose.mjs",
|
|
32
34
|
"prepare": "npm run package",
|
|
33
35
|
"check": "svelte-check --tsconfig ./tsconfig.json",
|
|
34
36
|
"test": "vitest run",
|
|
@@ -53,6 +55,11 @@
|
|
|
53
55
|
"svelte": "./dist/components/index.js",
|
|
54
56
|
"default": "./dist/components/index.js"
|
|
55
57
|
},
|
|
58
|
+
"./render": {
|
|
59
|
+
"types": "./dist/render/authoring.d.ts",
|
|
60
|
+
"svelte": "./dist/render/authoring.js",
|
|
61
|
+
"default": "./dist/render/authoring.js"
|
|
62
|
+
},
|
|
56
63
|
"./delivery": {
|
|
57
64
|
"types": "./dist/delivery/index.d.ts",
|
|
58
65
|
"svelte": "./dist/delivery/index.js",
|
|
@@ -93,6 +100,7 @@
|
|
|
93
100
|
"@codemirror/language": "^6.12.3",
|
|
94
101
|
"@codemirror/state": "^6.6.0",
|
|
95
102
|
"@codemirror/view": "^6.43.0",
|
|
103
|
+
"@lucide/svelte": "^1.17.0",
|
|
96
104
|
"@rodrigodagostino/svelte-sortable-list": "^2.1.17",
|
|
97
105
|
"@types/hast": "^3.0.4",
|
|
98
106
|
"@types/mdast": "^4.0.4",
|
|
@@ -121,13 +129,19 @@
|
|
|
121
129
|
"@sveltejs/kit": "^2.61",
|
|
122
130
|
"@sveltejs/package": "^2",
|
|
123
131
|
"@sveltejs/vite-plugin-svelte": "^7.1",
|
|
132
|
+
"@tailwindcss/postcss": "^4.3.0",
|
|
124
133
|
"@types/node": "^22.19.19",
|
|
125
134
|
"@vitest/browser": "^4.1.7",
|
|
126
135
|
"@vitest/browser-playwright": "^4.1.7",
|
|
136
|
+
"daisyui": "^5.5.23",
|
|
137
|
+
"lightningcss": "^1.32.0",
|
|
127
138
|
"playwright": "^1.60.0",
|
|
139
|
+
"postcss": "^8.5.15",
|
|
140
|
+
"postcss-prefix-selector": "^2.1.1",
|
|
128
141
|
"publint": "^0.3.21",
|
|
129
142
|
"svelte": "^5.55",
|
|
130
143
|
"svelte-check": "^4",
|
|
144
|
+
"tailwindcss": "^4.3.0",
|
|
131
145
|
"typescript": "^6.0.3",
|
|
132
146
|
"vite": "^8.0",
|
|
133
147
|
"vitest": "^4.1",
|