@jant/core 0.6.8 → 0.6.10
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/bin/commands/uploads/cleanup.js +1 -0
- package/dist/{app-9P4rVCe2.js → app-CGHkOdme.js} +3450 -3121
- package/dist/app-D24n0DoH.js +6 -0
- package/dist/client/.vite/manifest.json +3 -3
- package/dist/client/_assets/{client-CXnEhyyv.js → client-DYrWuaIk.js} +1 -1
- package/dist/client/_assets/{client-auth-CSItbyU8.js → client-auth-B5Re0uCd.js} +187 -167
- package/dist/client/_assets/client-xWDl78yi.css +2 -0
- package/dist/{export-Be082J0n.js → export-DY1v5Iqu.js} +2 -2
- package/dist/{github-sync-D1Cw8mOY.js → github-sync-2_T7nbOv.js} +1 -1
- package/dist/{github-sync-_kPWM4m9.js → github-sync-LefaslGJ.js} +2 -2
- package/dist/index.js +3 -3
- package/dist/node.js +4 -4
- package/package.json +1 -1
- package/src/client/components/__tests__/jant-settings-avatar.test.ts +8 -2
- package/src/client/components/__tests__/jant-settings-general.test.ts +64 -12
- package/src/client/components/jant-compose-dialog.ts +12 -0
- package/src/client/components/jant-settings-general.ts +74 -21
- package/src/client/components/settings-types.ts +13 -0
- package/src/client/settings-bridge.ts +3 -0
- package/src/client/tiptap/__tests__/link-toolbar.test.ts +41 -0
- package/src/client/tiptap/__tests__/mark-exit.test.ts +99 -0
- package/src/client/tiptap/bubble-menu.ts +37 -4
- package/src/client/tiptap/link-toolbar.ts +63 -1
- package/src/db/migrations/0026_absent_rhodey.sql +14 -0
- package/src/db/migrations/meta/0026_snapshot.json +2511 -0
- package/src/db/migrations/meta/_journal.json +7 -0
- package/src/db/migrations/pg/0024_high_violations.sql +14 -0
- package/src/db/migrations/pg/meta/0024_snapshot.json +3204 -0
- package/src/db/migrations/pg/meta/_journal.json +7 -0
- package/src/db/pg/schema.ts +36 -0
- package/src/db/schema.ts +36 -0
- package/src/i18n/__tests__/middleware.test.ts +46 -0
- package/src/i18n/locales/settings/en.po +282 -27
- package/src/i18n/locales/settings/en.ts +1 -1
- package/src/i18n/locales/settings/zh-Hans.po +282 -27
- package/src/i18n/locales/settings/zh-Hans.ts +1 -1
- package/src/i18n/locales/settings/zh-Hant.po +282 -27
- package/src/i18n/locales/settings/zh-Hant.ts +1 -1
- package/src/i18n/middleware.ts +17 -8
- package/src/i18n/supported-locales.ts +5 -4
- package/src/lib/__tests__/feed.test.ts +5 -1
- package/src/lib/feed.ts +6 -3
- package/src/lib/ids.ts +1 -0
- package/src/lib/resolve-config.ts +1 -0
- package/src/lib/upload.ts +14 -0
- package/src/routes/api/__tests__/settings.test.ts +1 -4
- package/src/routes/api/__tests__/upload.test.ts +2 -0
- package/src/routes/api/internal/__tests__/uploads.test.ts +19 -1
- package/src/routes/api/settings.ts +2 -1
- package/src/routes/auth/__tests__/setup.test.ts +14 -0
- package/src/routes/dash/__tests__/settings-avatar.test.ts +35 -17
- package/src/routes/dash/settings.tsx +22 -4
- package/src/routes/feed/__tests__/feed.test.ts +58 -19
- package/src/routes/feed/feed.ts +37 -28
- package/src/routes/pages/featured.tsx +17 -0
- package/src/routes/pages/latest.tsx +25 -0
- package/src/services/__tests__/media.test.ts +191 -30
- package/src/services/__tests__/settings.test.ts +55 -0
- package/src/services/bootstrap.ts +7 -0
- package/src/services/export-theme/layouts/_default/baseof.html +2 -1
- package/src/services/media.ts +169 -42
- package/src/services/post.ts +1 -1
- package/src/services/settings.ts +49 -15
- package/src/services/upload-session.ts +13 -3
- package/src/styles/tokens.css +21 -4
- package/src/styles/ui.css +44 -1
- package/src/types/bindings.ts +1 -0
- package/src/types/config.ts +13 -0
- package/src/ui/__tests__/color-themes.test.ts +2 -2
- package/src/ui/color-themes.ts +32 -0
- package/src/ui/dash/appearance/ColorThemeContent.tsx +264 -29
- package/src/ui/dash/settings/GeneralContent.tsx +54 -4
- package/src/ui/dash/settings/__tests__/GeneralContent.test.tsx +3 -2
- package/src/ui/layouts/BaseLayout.tsx +3 -2
- package/src/ui/layouts/__tests__/BaseLayout.test.tsx +17 -4
- package/dist/app-DaxS_Cz-.js +0 -6
- package/dist/client/_assets/client-C6peCkkD.css +0 -2
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Color theme picker
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import type { MessageDescriptor } from "@lingui/core";
|
|
5
6
|
import { msg } from "@lingui/core/macro";
|
|
6
7
|
import { useLingui } from "../../../i18n/context.js";
|
|
7
8
|
import { toPublicPath } from "../../../lib/url.js";
|
|
@@ -119,8 +120,260 @@ function ThemeModeCard({
|
|
|
119
120
|
);
|
|
120
121
|
}
|
|
121
122
|
|
|
123
|
+
interface ThemeCopy {
|
|
124
|
+
title: MessageDescriptor;
|
|
125
|
+
body: MessageDescriptor;
|
|
126
|
+
help: MessageDescriptor;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Per-theme preview copy: a plain description of each palette — what the
|
|
131
|
+
* background and accent look like, and when it fits. Keyed by theme id;
|
|
132
|
+
* unknown ids fall back to FALLBACK_COPY.
|
|
133
|
+
*/
|
|
134
|
+
const THEME_COPY: Record<string, ThemeCopy> = {
|
|
135
|
+
tufte: {
|
|
136
|
+
title: msg({
|
|
137
|
+
message: "Warm ivory",
|
|
138
|
+
comment: "@context: Tufte color theme preview title",
|
|
139
|
+
}),
|
|
140
|
+
body: msg({
|
|
141
|
+
message: "Off-white paper with a deep forest-green accent.",
|
|
142
|
+
comment: "@context: Tufte color theme preview body",
|
|
143
|
+
}),
|
|
144
|
+
help: msg({
|
|
145
|
+
message: "The default. Calm and easy for long reading.",
|
|
146
|
+
comment: "@context: Tufte color theme preview help line",
|
|
147
|
+
}),
|
|
148
|
+
},
|
|
149
|
+
linen: {
|
|
150
|
+
title: msg({
|
|
151
|
+
message: "Warm cream",
|
|
152
|
+
comment: "@context: Linen color theme preview title",
|
|
153
|
+
}),
|
|
154
|
+
body: msg({
|
|
155
|
+
message: "Soft cream background with a muted green accent.",
|
|
156
|
+
comment: "@context: Linen color theme preview body",
|
|
157
|
+
}),
|
|
158
|
+
help: msg({
|
|
159
|
+
message: "The original Jant palette, and a solid everyday pick.",
|
|
160
|
+
comment: "@context: Linen color theme preview help line",
|
|
161
|
+
}),
|
|
162
|
+
},
|
|
163
|
+
frost: {
|
|
164
|
+
title: msg({
|
|
165
|
+
message: "Cool white",
|
|
166
|
+
comment: "@context: Frost color theme preview title",
|
|
167
|
+
}),
|
|
168
|
+
body: msg({
|
|
169
|
+
message: "Pale cool-white with deep indigo text. High contrast.",
|
|
170
|
+
comment: "@context: Frost color theme preview body",
|
|
171
|
+
}),
|
|
172
|
+
help: msg({
|
|
173
|
+
message: "When you want a cooler, sharper look.",
|
|
174
|
+
comment: "@context: Frost color theme preview help line",
|
|
175
|
+
}),
|
|
176
|
+
},
|
|
177
|
+
cotton: {
|
|
178
|
+
title: msg({
|
|
179
|
+
message: "Soft ivory",
|
|
180
|
+
comment: "@context: Cotton color theme preview title",
|
|
181
|
+
}),
|
|
182
|
+
body: msg({
|
|
183
|
+
message: "Very light ivory with a faint tea-green accent.",
|
|
184
|
+
comment: "@context: Cotton color theme preview body",
|
|
185
|
+
}),
|
|
186
|
+
help: msg({
|
|
187
|
+
message: "Nearly white, with a touch of warmth.",
|
|
188
|
+
comment: "@context: Cotton color theme preview help line",
|
|
189
|
+
}),
|
|
190
|
+
},
|
|
191
|
+
bone: {
|
|
192
|
+
title: msg({
|
|
193
|
+
message: "Warm off-white",
|
|
194
|
+
comment: "@context: Bone color theme preview title",
|
|
195
|
+
}),
|
|
196
|
+
body: msg({
|
|
197
|
+
message: "Pale bone-white with a muted green accent.",
|
|
198
|
+
comment: "@context: Bone color theme preview body",
|
|
199
|
+
}),
|
|
200
|
+
help: msg({
|
|
201
|
+
message: "Warm-neutral and easy for long reading.",
|
|
202
|
+
comment: "@context: Bone color theme preview help line",
|
|
203
|
+
}),
|
|
204
|
+
},
|
|
205
|
+
parchment: {
|
|
206
|
+
title: msg({
|
|
207
|
+
message: "Warm parchment",
|
|
208
|
+
comment: "@context: Parchment color theme preview title",
|
|
209
|
+
}),
|
|
210
|
+
body: msg({
|
|
211
|
+
message: "Yellow-tinted paper with an olive-green accent.",
|
|
212
|
+
comment: "@context: Parchment color theme preview body",
|
|
213
|
+
}),
|
|
214
|
+
help: msg({
|
|
215
|
+
message: "A warmer look, like slightly aged paper.",
|
|
216
|
+
comment: "@context: Parchment color theme preview help line",
|
|
217
|
+
}),
|
|
218
|
+
},
|
|
219
|
+
dune: {
|
|
220
|
+
title: msg({
|
|
221
|
+
message: "Warm sand",
|
|
222
|
+
comment: "@context: Dune color theme preview title",
|
|
223
|
+
}),
|
|
224
|
+
body: msg({
|
|
225
|
+
message: "Sandy background with a green accent.",
|
|
226
|
+
comment: "@context: Dune color theme preview body",
|
|
227
|
+
}),
|
|
228
|
+
help: msg({
|
|
229
|
+
message: "Warm and earthy, but still light.",
|
|
230
|
+
comment: "@context: Dune color theme preview help line",
|
|
231
|
+
}),
|
|
232
|
+
},
|
|
233
|
+
ink: {
|
|
234
|
+
title: msg({
|
|
235
|
+
message: "Neutral gray",
|
|
236
|
+
comment: "@context: Ink color theme preview title",
|
|
237
|
+
}),
|
|
238
|
+
body: msg({
|
|
239
|
+
message: "Near-neutral light gray with a steel-blue accent.",
|
|
240
|
+
comment: "@context: Ink color theme preview body",
|
|
241
|
+
}),
|
|
242
|
+
help: msg({
|
|
243
|
+
message: "Minimal color, low distraction.",
|
|
244
|
+
comment: "@context: Ink color theme preview help line",
|
|
245
|
+
}),
|
|
246
|
+
},
|
|
247
|
+
slate: {
|
|
248
|
+
title: msg({
|
|
249
|
+
message: "Cool blue-gray",
|
|
250
|
+
comment: "@context: Slate color theme preview title",
|
|
251
|
+
}),
|
|
252
|
+
body: msg({
|
|
253
|
+
message: "Light blue-gray background, cool and even.",
|
|
254
|
+
comment: "@context: Slate color theme preview body",
|
|
255
|
+
}),
|
|
256
|
+
help: msg({
|
|
257
|
+
message: "A calm, cool backdrop.",
|
|
258
|
+
comment: "@context: Slate color theme preview help line",
|
|
259
|
+
}),
|
|
260
|
+
},
|
|
261
|
+
sage: {
|
|
262
|
+
title: msg({
|
|
263
|
+
message: "Soft green",
|
|
264
|
+
comment: "@context: Sage color theme preview title",
|
|
265
|
+
}),
|
|
266
|
+
body: msg({
|
|
267
|
+
message: "Light sage-green with a matching green accent.",
|
|
268
|
+
comment: "@context: Sage color theme preview body",
|
|
269
|
+
}),
|
|
270
|
+
help: msg({
|
|
271
|
+
message: "Calm and natural, easy on the eyes.",
|
|
272
|
+
comment: "@context: Sage color theme preview help line",
|
|
273
|
+
}),
|
|
274
|
+
},
|
|
275
|
+
clay: {
|
|
276
|
+
title: msg({
|
|
277
|
+
message: "Warm terracotta",
|
|
278
|
+
comment: "@context: Clay color theme preview title",
|
|
279
|
+
}),
|
|
280
|
+
body: msg({
|
|
281
|
+
message: "Muted red-brown background, earthy and warm.",
|
|
282
|
+
comment: "@context: Clay color theme preview body",
|
|
283
|
+
}),
|
|
284
|
+
help: msg({
|
|
285
|
+
message: "An earthier, warmer tone.",
|
|
286
|
+
comment: "@context: Clay color theme preview help line",
|
|
287
|
+
}),
|
|
288
|
+
},
|
|
289
|
+
ember: {
|
|
290
|
+
title: msg({
|
|
291
|
+
message: "Warm orange",
|
|
292
|
+
comment: "@context: Ember color theme preview title",
|
|
293
|
+
}),
|
|
294
|
+
body: msg({
|
|
295
|
+
message: "Orange-tinted background. The warmest palette.",
|
|
296
|
+
comment: "@context: Ember color theme preview body",
|
|
297
|
+
}),
|
|
298
|
+
help: msg({
|
|
299
|
+
message: "Cozy and bold among the warm tones.",
|
|
300
|
+
comment: "@context: Ember color theme preview help line",
|
|
301
|
+
}),
|
|
302
|
+
},
|
|
303
|
+
paper: {
|
|
304
|
+
title: msg({
|
|
305
|
+
message: "Bright paper white",
|
|
306
|
+
comment: "@context: Paper color theme preview title",
|
|
307
|
+
}),
|
|
308
|
+
body: msg({
|
|
309
|
+
message: "Bright warm-white with a moss-green accent.",
|
|
310
|
+
comment: "@context: Paper color theme preview body",
|
|
311
|
+
}),
|
|
312
|
+
help: msg({
|
|
313
|
+
message: "Clean and high-contrast, close to white.",
|
|
314
|
+
comment: "@context: Paper color theme preview help line",
|
|
315
|
+
}),
|
|
316
|
+
},
|
|
317
|
+
snow: {
|
|
318
|
+
title: msg({
|
|
319
|
+
message: "Pure white",
|
|
320
|
+
comment: "@context: Snow color theme preview title",
|
|
321
|
+
}),
|
|
322
|
+
body: msg({
|
|
323
|
+
message: "Pure white with neutral grays. No color tint.",
|
|
324
|
+
comment: "@context: Snow color theme preview body",
|
|
325
|
+
}),
|
|
326
|
+
help: msg({
|
|
327
|
+
message: "The cleanest, most neutral option.",
|
|
328
|
+
comment: "@context: Snow color theme preview help line",
|
|
329
|
+
}),
|
|
330
|
+
},
|
|
331
|
+
espresso: {
|
|
332
|
+
title: msg({
|
|
333
|
+
message: "Cream and coffee brown",
|
|
334
|
+
comment: "@context: Espresso color theme preview title",
|
|
335
|
+
}),
|
|
336
|
+
body: msg({
|
|
337
|
+
message: "Warm cream background with deep coffee-brown accents.",
|
|
338
|
+
comment: "@context: Espresso color theme preview body",
|
|
339
|
+
}),
|
|
340
|
+
help: msg({
|
|
341
|
+
message: "Warm and rich, with strong brown tones.",
|
|
342
|
+
comment: "@context: Espresso color theme preview help line",
|
|
343
|
+
}),
|
|
344
|
+
},
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
const EXAMPLE_LINK = msg({
|
|
348
|
+
message: "Example link",
|
|
349
|
+
comment:
|
|
350
|
+
"@context: Placeholder link label shown in color theme preview cards",
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
const ACCENT_LABEL = msg({
|
|
354
|
+
message: "Accent",
|
|
355
|
+
comment:
|
|
356
|
+
"@context: Label next to the theme accent-color swatch in a color theme preview card",
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
const FALLBACK_COPY: ThemeCopy = {
|
|
360
|
+
title: msg({
|
|
361
|
+
message: "This palette",
|
|
362
|
+
comment: "@context: Fallback color theme preview title",
|
|
363
|
+
}),
|
|
364
|
+
body: msg({
|
|
365
|
+
message: "Headings, body text, and links in this theme.",
|
|
366
|
+
comment: "@context: Fallback color theme preview body",
|
|
367
|
+
}),
|
|
368
|
+
help: msg({
|
|
369
|
+
message: "Pick the one that fits your writing.",
|
|
370
|
+
comment: "@context: Fallback color theme preview help line",
|
|
371
|
+
}),
|
|
372
|
+
};
|
|
373
|
+
|
|
122
374
|
function ThemePreview({ theme }: { theme: ColorTheme }) {
|
|
123
375
|
const { i18n } = useLingui();
|
|
376
|
+
const copy = THEME_COPY[theme.id] ?? FALLBACK_COPY;
|
|
124
377
|
|
|
125
378
|
return (
|
|
126
379
|
<div class="min-w-0">
|
|
@@ -129,39 +382,21 @@ function ThemePreview({ theme }: { theme: ColorTheme }) {
|
|
|
129
382
|
</div>
|
|
130
383
|
|
|
131
384
|
<div class="theme-preview-divider mt-2 border-t pt-2">
|
|
132
|
-
<h3 class="theme-preview-title text-[0.98rem]">
|
|
133
|
-
{i18n._(
|
|
134
|
-
msg({
|
|
135
|
-
message: "Field notes on quiet design",
|
|
136
|
-
comment: "@context: Color theme preview card title",
|
|
137
|
-
}),
|
|
138
|
-
)}
|
|
139
|
-
</h3>
|
|
385
|
+
<h3 class="theme-preview-title text-[0.98rem]">{i18n._(copy.title)}</h3>
|
|
140
386
|
|
|
141
387
|
<p class="theme-preview-body mt-2 text-[0.84rem]">
|
|
142
|
-
{i18n._(
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
388
|
+
{i18n._(copy.body)}{" "}
|
|
389
|
+
<a class="theme-preview-link" tabIndex={-1}>
|
|
390
|
+
{i18n._(EXAMPLE_LINK)}
|
|
391
|
+
</a>{" "}
|
|
392
|
+
<span aria-hidden="true">·</span>{" "}
|
|
393
|
+
<span class="theme-preview-accent">
|
|
394
|
+
<span class="theme-preview-swatch" aria-hidden="true"></span>
|
|
395
|
+
{i18n._(ACCENT_LABEL)}
|
|
396
|
+
</span>
|
|
148
397
|
</p>
|
|
149
398
|
<p class="theme-preview-meta mt-1.5 text-[0.8rem]">
|
|
150
|
-
{i18n._(
|
|
151
|
-
msg({
|
|
152
|
-
message: "Quiet surfaces let writing lead.",
|
|
153
|
-
comment: "@context: Color theme preview card secondary sentence",
|
|
154
|
-
}),
|
|
155
|
-
)}{" "}
|
|
156
|
-
<a class="theme-preview-link" tabIndex={-1}>
|
|
157
|
-
{i18n._(
|
|
158
|
-
msg({
|
|
159
|
-
message: "Read why",
|
|
160
|
-
comment: "@context: Color theme preview inline link label",
|
|
161
|
-
}),
|
|
162
|
-
)}
|
|
163
|
-
</a>
|
|
164
|
-
.
|
|
399
|
+
{i18n._(copy.help)}
|
|
165
400
|
</p>
|
|
166
401
|
|
|
167
402
|
<div class="theme-preview-divider mt-3 border-t pt-2">
|
|
@@ -15,6 +15,7 @@ export function GeneralContent({
|
|
|
15
15
|
siteName,
|
|
16
16
|
siteDescription,
|
|
17
17
|
siteLanguage,
|
|
18
|
+
dashboardLanguage,
|
|
18
19
|
cjkSerifFont,
|
|
19
20
|
siteNameFallback,
|
|
20
21
|
siteDescriptionFallback,
|
|
@@ -22,6 +23,7 @@ export function GeneralContent({
|
|
|
22
23
|
mainFeedUrl,
|
|
23
24
|
latestFeedUrl,
|
|
24
25
|
featuredFeedUrl,
|
|
26
|
+
archiveFeedUrl,
|
|
25
27
|
timeZone,
|
|
26
28
|
siteFooter,
|
|
27
29
|
showJantBrandingOnHome,
|
|
@@ -32,6 +34,7 @@ export function GeneralContent({
|
|
|
32
34
|
siteName: string;
|
|
33
35
|
siteDescription: string;
|
|
34
36
|
siteLanguage: string;
|
|
37
|
+
dashboardLanguage: string;
|
|
35
38
|
cjkSerifFont: string;
|
|
36
39
|
siteNameFallback: string;
|
|
37
40
|
siteDescriptionFallback: string;
|
|
@@ -39,6 +42,7 @@ export function GeneralContent({
|
|
|
39
42
|
mainFeedUrl: string;
|
|
40
43
|
latestFeedUrl: string;
|
|
41
44
|
featuredFeedUrl: string;
|
|
45
|
+
archiveFeedUrl: string;
|
|
42
46
|
timeZone: string;
|
|
43
47
|
siteFooter: string;
|
|
44
48
|
showJantBrandingOnHome: boolean;
|
|
@@ -101,15 +105,37 @@ export function GeneralContent({
|
|
|
101
105
|
),
|
|
102
106
|
siteLanguage: i18n._(
|
|
103
107
|
msg({
|
|
104
|
-
message: "
|
|
105
|
-
comment:
|
|
108
|
+
message: "Content language",
|
|
109
|
+
comment:
|
|
110
|
+
"@context: Settings form field for the public content language",
|
|
106
111
|
}),
|
|
107
112
|
),
|
|
108
113
|
siteLanguageHelp: i18n._(
|
|
109
114
|
msg({
|
|
110
115
|
message:
|
|
111
|
-
"
|
|
112
|
-
comment: "@context: Help text under the
|
|
116
|
+
"The language your posts are written in. Announced to readers and search engines through HTML lang and your RSS feed. Any BCP 47 tag works.",
|
|
117
|
+
comment: "@context: Help text under the content language picker",
|
|
118
|
+
}),
|
|
119
|
+
),
|
|
120
|
+
contentLanguagePreview: i18n._(
|
|
121
|
+
msg({
|
|
122
|
+
message: "Readers and search engines see",
|
|
123
|
+
comment:
|
|
124
|
+
"@context: Lead text before a live <html lang> preview of the content language",
|
|
125
|
+
}),
|
|
126
|
+
),
|
|
127
|
+
dashboardLanguage: i18n._(
|
|
128
|
+
msg({
|
|
129
|
+
message: "Dashboard language",
|
|
130
|
+
comment:
|
|
131
|
+
"@context: Settings form field for the admin interface language",
|
|
132
|
+
}),
|
|
133
|
+
),
|
|
134
|
+
dashboardLanguageHelp: i18n._(
|
|
135
|
+
msg({
|
|
136
|
+
message:
|
|
137
|
+
"The language this admin dashboard shows in. Available in English, 简体中文, and 繁體中文.",
|
|
138
|
+
comment: "@context: Help text under the dashboard language picker",
|
|
113
139
|
}),
|
|
114
140
|
),
|
|
115
141
|
siteLanguageSearchPlaceholder: i18n._(
|
|
@@ -210,6 +236,19 @@ export function GeneralContent({
|
|
|
210
236
|
comment: "@context: Label for the explicit featured RSS feed URL",
|
|
211
237
|
}),
|
|
212
238
|
),
|
|
239
|
+
archiveFeedUrl: i18n._(
|
|
240
|
+
msg({
|
|
241
|
+
message: "Archive feed",
|
|
242
|
+
comment: "@context: Label for the full-archive RSS feed URL",
|
|
243
|
+
}),
|
|
244
|
+
),
|
|
245
|
+
archiveFeedUrlHelp: i18n._(
|
|
246
|
+
msg({
|
|
247
|
+
message: "Every published post, including ones hidden from Latest.",
|
|
248
|
+
comment:
|
|
249
|
+
"@context: Help text under the archive feed URL, explaining it is the complete feed",
|
|
250
|
+
}),
|
|
251
|
+
),
|
|
213
252
|
latestFeedOption: i18n._(
|
|
214
253
|
msg({
|
|
215
254
|
message: "Latest",
|
|
@@ -308,6 +347,14 @@ export function GeneralContent({
|
|
|
308
347
|
timezones.map((tz) => ({ value: tz.value, label: tz.label })),
|
|
309
348
|
).replace(/</g, "\\u003c");
|
|
310
349
|
|
|
350
|
+
// The 3 catalog locales Jant's dashboard is translated into. Native-script
|
|
351
|
+
// labels so each reads in its own language, like the CJK font options.
|
|
352
|
+
const dashboardLanguagesJson = JSON.stringify([
|
|
353
|
+
{ value: "en", label: "English" },
|
|
354
|
+
{ value: "zh-Hans", label: "简体中文" },
|
|
355
|
+
{ value: "zh-Hant", label: "繁體中文" },
|
|
356
|
+
]).replace(/</g, "\\u003c");
|
|
357
|
+
|
|
311
358
|
const cjkFontsJson = JSON.stringify([
|
|
312
359
|
{ value: "off", label: "None" },
|
|
313
360
|
{
|
|
@@ -326,6 +373,7 @@ export function GeneralContent({
|
|
|
326
373
|
siteName,
|
|
327
374
|
siteDescription,
|
|
328
375
|
siteLanguage,
|
|
376
|
+
dashboardLanguage,
|
|
329
377
|
cjkSerifFont,
|
|
330
378
|
mainRssFeed,
|
|
331
379
|
timeZone,
|
|
@@ -341,11 +389,13 @@ export function GeneralContent({
|
|
|
341
389
|
labels={labels}
|
|
342
390
|
timezones={timezonesJson}
|
|
343
391
|
cjk-fonts={cjkFontsJson}
|
|
392
|
+
dashboard-languages={dashboardLanguagesJson}
|
|
344
393
|
sitename-fallback={siteNameFallback}
|
|
345
394
|
sitedescription-fallback={siteDescriptionFallback}
|
|
346
395
|
main-feed-url={mainFeedUrl}
|
|
347
396
|
latest-feed-url={latestFeedUrl}
|
|
348
397
|
featured-feed-url={featuredFeedUrl}
|
|
398
|
+
archive-feed-url={archiveFeedUrl}
|
|
349
399
|
demo-mode={demoMode || undefined}
|
|
350
400
|
>
|
|
351
401
|
{/* SSR fallback skeleton */}
|
|
@@ -41,8 +41,9 @@ function createProps(
|
|
|
41
41
|
siteDescriptionFallback: "Fallback Description",
|
|
42
42
|
mainRssFeed: "featured" as const,
|
|
43
43
|
mainFeedUrl: "/feed",
|
|
44
|
-
latestFeedUrl: "/feed
|
|
45
|
-
featuredFeedUrl: "/feed
|
|
44
|
+
latestFeedUrl: "/latest/feed",
|
|
45
|
+
featuredFeedUrl: "/featured/feed",
|
|
46
|
+
archiveFeedUrl: "/archive/feed",
|
|
46
47
|
timeZone: "UTC",
|
|
47
48
|
siteFooter: "Footer text",
|
|
48
49
|
showJantBrandingOnHome: false,
|
|
@@ -239,10 +239,10 @@ export const BaseLayout: FC<PropsWithChildren<BaseLayoutProps>> = ({
|
|
|
239
239
|
socialImageWidthValue >= 300;
|
|
240
240
|
const mainFeedHref = appConfig ? toPublicPath("/feed", sitePathPrefix) : null;
|
|
241
241
|
const latestFeedHref = appConfig
|
|
242
|
-
? toPublicPath("/feed
|
|
242
|
+
? toPublicPath("/latest/feed", sitePathPrefix)
|
|
243
243
|
: null;
|
|
244
244
|
const featuredFeedHref = appConfig
|
|
245
|
-
? toPublicPath("/feed
|
|
245
|
+
? toPublicPath("/featured/feed", sitePathPrefix)
|
|
246
246
|
: null;
|
|
247
247
|
const mainFeedTitle =
|
|
248
248
|
i18n?._(
|
|
@@ -277,6 +277,7 @@ export const BaseLayout: FC<PropsWithChildren<BaseLayoutProps>> = ({
|
|
|
277
277
|
{raw("<!DOCTYPE html>")}
|
|
278
278
|
<html
|
|
279
279
|
lang={resolvedLang}
|
|
280
|
+
data-theme={appConfig?.themeId}
|
|
280
281
|
data-theme-mode={themeMode}
|
|
281
282
|
data-site-path-prefix={sitePathPrefix}
|
|
282
283
|
data-asset-base-path={assetBasePath}
|
|
@@ -279,8 +279,8 @@ describe("BaseLayout", () => {
|
|
|
279
279
|
html.match(/rel="alternate" type="application\/atom\+xml"/g) ?? [],
|
|
280
280
|
).toHaveLength(2);
|
|
281
281
|
expect(html).toContain('href="/feed"');
|
|
282
|
-
expect(html).toContain('href="/feed
|
|
283
|
-
expect(html).not.toContain('href="/feed
|
|
282
|
+
expect(html).toContain('href="/latest/feed"');
|
|
283
|
+
expect(html).not.toContain('href="/featured/feed"');
|
|
284
284
|
});
|
|
285
285
|
|
|
286
286
|
it("switches the alternate feed link when latest is the main feed", async () => {
|
|
@@ -297,8 +297,8 @@ describe("BaseLayout", () => {
|
|
|
297
297
|
html.match(/rel="alternate" type="application\/atom\+xml"/g) ?? [],
|
|
298
298
|
).toHaveLength(2);
|
|
299
299
|
expect(html).toContain('href="/feed"');
|
|
300
|
-
expect(html).toContain('href="/feed
|
|
301
|
-
expect(html).not.toContain('href="/feed
|
|
300
|
+
expect(html).toContain('href="/featured/feed"');
|
|
301
|
+
expect(html).not.toContain('href="/latest/feed"');
|
|
302
302
|
});
|
|
303
303
|
|
|
304
304
|
it("uses the public asset base path from appConfig in production", async () => {
|
|
@@ -320,6 +320,19 @@ describe("BaseLayout", () => {
|
|
|
320
320
|
expect(html).toContain('data-asset-base-path="/blog/_assets"');
|
|
321
321
|
});
|
|
322
322
|
|
|
323
|
+
it("exposes the active theme id on the root html element", async () => {
|
|
324
|
+
const { BaseLayout } = await loadBaseLayout();
|
|
325
|
+
const html = renderToString(
|
|
326
|
+
BaseLayout({
|
|
327
|
+
title: "Jant",
|
|
328
|
+
c: createContext("featured", { themeId: "frost" }),
|
|
329
|
+
children: "Test",
|
|
330
|
+
}),
|
|
331
|
+
);
|
|
332
|
+
|
|
333
|
+
expect(html).toContain('data-theme="frost"');
|
|
334
|
+
});
|
|
335
|
+
|
|
323
336
|
it("renders theme-color tags that follow the active theme in auto mode", async () => {
|
|
324
337
|
const { BaseLayout } = await loadBaseLayout();
|
|
325
338
|
const html = renderToString(
|