@tenphi/starlight 0.4.0 → 0.6.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/dist/index.js CHANGED
@@ -4,11 +4,12 @@ import { createRequire } from "node:module";
4
4
  import { existsSync } from "node:fs";
5
5
  import { cp, mkdir, readFile } from "node:fs/promises";
6
6
  import { dirname, extname, join } from "node:path";
7
- import { fileURLToPath } from "node:url";
8
- import { assertValidDocs, createDocsGraph } from "@tenphi/docs";
7
+ import { fileURLToPath, pathToFileURL } from "node:url";
8
+ import { COOKBOOK_COMPONENT_NAMES, assertValidDocs, createDocsGraph } from "@tenphi/docs";
9
9
  import { configure } from "@tenphi/tasty/core";
10
10
  import { tastyIntegration } from "@tenphi/tasty/ssr/astro";
11
11
  import { apcaContrast, glaze, okhslToLinearSrgb, relativeLuminanceFromLinearRgb, variantToOkhsl } from "@tenphi/glaze";
12
+ import "@tenphi/tasty";
12
13
  //#region src/theme/defaults.ts
13
14
  const DEFAULT_THEME_TOKENS = {
14
15
  $gap: "0.5rem",
@@ -27,40 +28,48 @@ const DEFAULT_TYPOGRAPHY_PRESETS = {
27
28
  body: {
28
29
  fontFamily: BODY_FONT,
29
30
  fontSize: "1rem",
30
- lineHeight: 1.75,
31
- letterSpacing: "0",
32
- fontWeight: 400,
33
- boldFontWeight: 650
31
+ lineHeight: 1.65,
32
+ letterSpacing: "-0.006em",
33
+ fontWeight: 420,
34
+ boldFontWeight: 640
34
35
  },
35
36
  heading: {
36
37
  fontFamily: BODY_FONT,
37
38
  fontSize: "1rem",
38
- lineHeight: 1.2,
39
- letterSpacing: "-0.018em",
40
- fontWeight: 650,
41
- boldFontWeight: 750
39
+ lineHeight: 1.15,
40
+ letterSpacing: "-0.025em",
41
+ fontWeight: 640,
42
+ boldFontWeight: 720
43
+ },
44
+ h1: heading("clamp(2.5rem, 5vw, 3.25rem)", 1.05, "-0.045em"),
45
+ h2: heading("clamp(1.75rem, 3vw, 2.125rem)", 1.1, "-0.035em"),
46
+ h3: heading("1.5rem", 1.15, "-0.025em"),
47
+ h4: heading("1.25rem", 1.2, "-0.018em"),
48
+ h5: heading("1.125rem", 1.25, "-0.012em"),
49
+ h6: heading("1rem", 1.3, "-0.006em"),
50
+ navigation: {
51
+ fontFamily: "var(--body-font-family)",
52
+ fontSize: "0.9375rem",
53
+ lineHeight: 1.4,
54
+ letterSpacing: "-0.006em",
55
+ fontWeight: 540,
56
+ boldFontWeight: 650
42
57
  },
43
- h1: heading("3rem", 1.08, "-0.035em"),
44
- h2: heading("2rem", 1.15, "-0.025em"),
45
- h3: heading("1.5rem", 1.2, "-0.015em"),
46
- h4: heading("1.25rem", 1.25, "-0.01em"),
47
- h5: heading("1.125rem", 1.3, "0"),
48
- h6: heading("1rem", 1.35, "0"),
49
58
  small: {
50
59
  fontFamily: "var(--body-font-family)",
51
60
  fontSize: "0.875rem",
52
- lineHeight: 1.5,
53
- letterSpacing: "0",
54
- fontWeight: 400,
55
- boldFontWeight: 700
61
+ lineHeight: 1.45,
62
+ letterSpacing: "-0.002em",
63
+ fontWeight: 420,
64
+ boldFontWeight: 650
56
65
  },
57
66
  code: {
58
67
  fontFamily: "'JetBrains Mono Variable', 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace",
59
68
  fontSize: "0.875rem",
60
- lineHeight: 1.6,
69
+ lineHeight: 1.65,
61
70
  letterSpacing: "0",
62
71
  fontWeight: 400,
63
- boldFontWeight: 700
72
+ boldFontWeight: 650
64
73
  }
65
74
  };
66
75
  function resolveThemeTokens(tokens = {}) {
@@ -108,16 +117,18 @@ function resolveDocsTheme(theme = {}) {
108
117
  const surface2 = glaze.color({
109
118
  from: surfaceFrom,
110
119
  base: surface,
111
- tone: ["-2", "-4"],
120
+ tone: "-2",
112
121
  mode: "auto",
113
- darkSaturation: .35
122
+ saturationFactor: .9,
123
+ darkSaturation: .325
114
124
  }, glazeOptions);
115
125
  const surface3 = glaze.color({
116
126
  from: surfaceFrom,
117
- base: surface,
118
- tone: ["-4", "-8"],
127
+ base: surface2,
128
+ tone: "-2",
119
129
  mode: "auto",
120
- darkSaturation: .35
130
+ saturationFactor: .8,
131
+ darkSaturation: .3
121
132
  }, glazeOptions);
122
133
  const text = glaze.color({
123
134
  from: theme.palette?.text ?? "#20232a",
@@ -160,6 +171,33 @@ function resolveDocsTheme(theme = {}) {
160
171
  });
161
172
  const resolvedSurface = surface.resolve();
162
173
  const resolvedAccent = accentText.resolve();
174
+ const shadowTheme = glaze({
175
+ hue: variantToOkhsl(resolvedSurface.light).h,
176
+ saturation: variantToOkhsl(resolvedSurface.light).s * 100,
177
+ darkHue: variantToOkhsl(resolvedSurface.dark).h,
178
+ darkSaturation: variantToOkhsl(resolvedSurface.dark).s * 100
179
+ }, void 0, glazeOptions);
180
+ shadowTheme.colors({
181
+ surface: {
182
+ from: surfaceFrom,
183
+ mode: "auto",
184
+ darkSaturation: .35
185
+ },
186
+ text: {
187
+ from: theme.palette?.text ?? "#20232a",
188
+ base: "surface",
189
+ role: "text",
190
+ contrast: { apca: [75, 90] },
191
+ mode: "auto"
192
+ },
193
+ shadow: {
194
+ type: "shadow",
195
+ bg: "surface",
196
+ fg: "text",
197
+ intensity: [12, 20],
198
+ tuning: { alphaMax: .28 }
199
+ }
200
+ });
163
201
  const scores = {
164
202
  light: score(resolvedAccent.light, resolvedSurface.light),
165
203
  dark: score(resolvedAccent.dark, resolvedSurface.dark),
@@ -177,20 +215,21 @@ function resolveDocsTheme(theme = {}) {
177
215
  });
178
216
  }
179
217
  const outputOptions = { modes: { highContrast: true } };
180
- const colors = {
181
- surface: surface.json(outputOptions),
182
- surface2: surface2.json(outputOptions),
183
- surface3: surface3.json(outputOptions),
184
- text: text.json(outputOptions),
185
- textSoft: textSoft.json(outputOptions),
186
- accentText: accentText.json(outputOptions),
187
- accentSurface: accentSurface.json(outputOptions),
188
- accentSurfaceText: accentSurfaceText.json(outputOptions),
189
- focus: focus.json(outputOptions)
190
- };
218
+ const shadow = shadowTheme.json(outputOptions).shadow;
219
+ if (!shadow) throw new Error("The Glaze shadow token failed to resolve.");
191
220
  return {
192
- css: themeCss(colors, theme),
193
- colors,
221
+ colors: {
222
+ surface: surface.json(outputOptions),
223
+ surface2: surface2.json(outputOptions),
224
+ surface3: surface3.json(outputOptions),
225
+ text: text.json(outputOptions),
226
+ textSoft: textSoft.json(outputOptions),
227
+ accentText: accentText.json(outputOptions),
228
+ accentSurface: accentSurface.json(outputOptions),
229
+ accentSurfaceText: accentSurfaceText.json(outputOptions),
230
+ focus: focus.json(outputOptions),
231
+ shadow
232
+ },
194
233
  tokens: resolveThemeTokens(theme.tokens),
195
234
  presets: resolveTypographyPresets(theme.presets),
196
235
  contrast: scores,
@@ -208,71 +247,115 @@ function luminance(variant) {
208
247
  const { h, s, l } = variantToOkhsl(variant);
209
248
  return relativeLuminanceFromLinearRgb(okhslToLinearSrgb(h, s, l, variant.pastel));
210
249
  }
211
- function themeCss(colors, theme) {
212
- const tokens = resolveThemeTokens(theme.tokens);
213
- const presets = resolveTypographyPresets(theme.presets);
214
- const designDeclarations = [...Object.entries(tokens).map(([name, value]) => `${tokenProperty(name)}:${String(value)}`), ...Object.entries(presets).flatMap(([name, preset]) => Object.entries(preset).map(([property, value]) => `--${kebab(name)}-${kebab(property)}:${String(value)}`))].join(";");
215
- const declarations = (mode) => [
216
- `--td-surface:${colors.surface[mode]}`,
217
- `--td-surface-2:${colors.surface2[mode]}`,
218
- `--td-surface-3:${colors.surface3[mode]}`,
219
- `--td-text:${colors.text[mode]}`,
220
- `--td-text-soft:${colors.textSoft[mode]}`,
221
- `--td-accent-text:${colors.accentText[mode]}`,
222
- `--td-accent-surface:${colors.accentSurface[mode]}`,
223
- `--td-accent-surface-text:${colors.accentSurfaceText[mode]}`,
224
- `--td-focus:${colors.focus[mode]}`,
225
- "--td-surface-2-hover:color-mix(in oklab,var(--td-text) 3%,var(--td-surface-2))",
226
- "--td-surface-2-pressed:color-mix(in oklab,var(--td-text) 9%,var(--td-surface-2))",
227
- "--td-surface-3-hover:color-mix(in oklab,var(--td-text) 3%,var(--td-surface-3))",
228
- "--td-surface-3-pressed:color-mix(in oklab,var(--td-text) 9%,var(--td-surface-3))",
229
- "--td-border:color-mix(in oklab,var(--td-text) 18%,var(--td-surface))",
230
- "--td-border-strong:color-mix(in oklab,var(--td-text) 34%,var(--td-surface))",
231
- "--td-shadow:color-mix(in oklab,var(--td-text) 16%,transparent)",
232
- "--td-overlay:color-mix(in oklab,var(--td-text) 58%,transparent)"
233
- ].join(";");
234
- return [
235
- `:root{${designDeclarations};${declarations("dark")}}`,
236
- `:root[data-theme=light]{${declarations("light")}}`,
237
- `@media(prefers-color-scheme:light){:root:not([data-theme]){${declarations("light")}}}`,
238
- `@media(prefers-contrast:more){:root{${declarations("darkContrast")}}:root[data-theme=light]{${declarations("lightContrast")}}@media(prefers-color-scheme:light){:root:not([data-theme]){${declarations("lightContrast")}}}}`,
239
- `:root[data-contrast=more]{${declarations("darkContrast")}}`,
240
- `:root[data-theme=light][data-contrast=more]{${declarations("lightContrast")}}`
241
- ].join("\n");
250
+ //#endregion
251
+ //#region src/theme/tasty-config.ts
252
+ const TASTY_UNITS = {
253
+ x: "var(--gap)",
254
+ r: "var(--radius)",
255
+ cr: "var(--card-radius)",
256
+ bw: "var(--border-width)"
257
+ };
258
+ const LIGHT = "theme=light | (@media(prefers-color-scheme: light) & :not([data-theme]))";
259
+ const HIGH_CONTRAST = "contrast=more | (@media(prefers-contrast: more) & :not([data-contrast]))";
260
+ function tastyTokens(theme) {
261
+ const tokens = Object.fromEntries(Object.entries(theme.tokens).filter(([name]) => name.startsWith("$")));
262
+ Object.assign(tokens, {
263
+ "#surface": colorStates(theme.colors.surface),
264
+ "#surface-2": colorStates(theme.colors.surface2),
265
+ "#surface-3": colorStates(theme.colors.surface3),
266
+ "#surface-2-hover": mix("#text", 3, "#surface-2"),
267
+ "#surface-2-pressed": mix("#text", 9, "#surface-2"),
268
+ "#surface-3-hover": mix("#text", 3, "#surface-3"),
269
+ "#surface-3-pressed": mix("#text", 9, "#surface-3"),
270
+ "#text": colorStates(theme.colors.text),
271
+ "#text-soft": colorStates(theme.colors.textSoft),
272
+ "#border": mix("#text", 18, "#surface"),
273
+ "#border-strong": mix("#text", 34, "#surface"),
274
+ "#accent-text": colorStates(theme.colors.accentText),
275
+ "#accent-surface": colorStates(theme.colors.accentSurface),
276
+ "#accent-surface-text": colorStates(theme.colors.accentSurfaceText),
277
+ "#focus": colorStates(theme.colors.focus),
278
+ "#shadow": colorStates(theme.colors.shadow),
279
+ "#overlay": mix("#text", 58, "transparent")
280
+ });
281
+ return tokens;
282
+ }
283
+ function colorStates(colors) {
284
+ return {
285
+ "": colors.dark,
286
+ [LIGHT]: colors.light,
287
+ [HIGH_CONTRAST]: colors.darkContrast,
288
+ [`(${LIGHT}) & (${HIGH_CONTRAST})`]: colors.lightContrast
289
+ };
242
290
  }
243
- function tokenProperty(name) {
244
- if (name.startsWith("--")) return name;
245
- return `--${name.replace(/^\$/, "")}`;
291
+ function mix(foreground, percentage, background) {
292
+ return `color-mix(in oklab, ${foreground} ${percentage}%, ${background})`;
246
293
  }
247
- function kebab(value) {
248
- return value.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/[^a-zA-Z0-9_-]/g, "-").toLowerCase();
294
+ //#endregion
295
+ //#region src/components/component-styles.ts
296
+ const sharedConfiguration = globalThis;
297
+ const cookbookComponentNames = new Set(COOKBOOK_COMPONENT_NAMES);
298
+ function configureComponentStyles(styles) {
299
+ sharedConfiguration.__tenphiCookbookComponentStyles = styles ?? {};
249
300
  }
301
+ /** Preserve custom anatomy names from the pre-component style API. */
302
+ function resolveLegacyAnatomyStyles(styles) {
303
+ if (!styles) return void 0;
304
+ const entries = Object.entries(styles).filter((entry) => !cookbookComponentNames.has(entry[0]) && entry[1] !== void 0).map(([name, value]) => [`[data-tasty-anatomy="${name}"]`, isModeConfig(value) ? value.styles : value]);
305
+ return entries.length ? Object.fromEntries(entries) : void 0;
306
+ }
307
+ function isModeConfig(value) {
308
+ return "mode" in value && (value.mode === "extend" || value.mode === "replace") && "styles" in value;
309
+ }
310
+ //#endregion
311
+ //#region src/components/tasty-states.js
312
+ const cookbookStates = {
313
+ "@mobile": "@media(w < 50rem)",
314
+ "@desktop": "@media(w >= 50rem)",
315
+ "@small": "@media(w <= 40rem)",
316
+ "@shell-mobile": "@media(w <= 48rem)",
317
+ "@shell-desktop": "@media(w > 48rem)",
318
+ "@narrow-layout": "@media(w < 72rem)",
319
+ "@medium-layout": "@media(w >= 50rem) & @media(w < 72rem)",
320
+ "@reduced-motion": "@media(prefers-reduced-motion: reduce)"
321
+ };
250
322
  //#endregion
251
323
  //#region src/integration.ts
252
324
  const packageRequire = createRequire(import.meta.url);
253
325
  const starlightRoot = dirname(packageRequire.resolve("@astrojs/starlight"));
254
326
  const tastyStaticMiddleware = packageRequire.resolve("@tenphi/tasty/ssr/astro-middleware-static");
327
+ const tastyExtractStaticMiddleware = packageRequire.resolve("@tenphi/tasty/ssr/astro-middleware-extract-static");
328
+ const astroReactServer = packageRequire.resolve("@astrojs/react/server.js");
329
+ const astroReactClient = packageRequire.resolve("@astrojs/react/client.js");
330
+ const astroReactIntegration = packageRequire.resolve("@astrojs/react");
331
+ const importNative = new Function("specifier", "return import(specifier)");
255
332
  function cookbook(options = {}) {
256
333
  const docsTheme = resolveDocsTheme(options.config?.theme);
257
334
  if (docsTheme.diagnostics.some((diagnostic) => diagnostic.severity === "error")) throw new Error(docsTheme.diagnostics.map((diagnostic) => diagnostic.message).join("\n"));
258
335
  configureTastyTheme(options.config?.theme, docsTheme);
259
- const cssPath = fileURLToPath(new URL("./styles.css", import.meta.url));
336
+ configureComponentStyles(options.config?.theme?.styles);
260
337
  const searchClientPath = fileURLToPath(new URL("./client/search.js", import.meta.url));
261
338
  const appearanceClientPath = fileURLToPath(new URL("./client/appearance.js", import.meta.url));
262
339
  const components = {
263
340
  Header: fileURLToPath(new URL("./overrides/Header.astro", import.meta.url)),
264
341
  Sidebar: fileURLToPath(new URL("./overrides/Sidebar.astro", import.meta.url)),
342
+ MobileMenuFooter: fileURLToPath(new URL("./overrides/MobileMenuFooter.astro", import.meta.url)),
343
+ ThemeSelect: fileURLToPath(new URL("./overrides/ThemeSelect.astro", import.meta.url)),
265
344
  ...options.config?.components?.overrides
266
345
  };
267
346
  const navigation = resolveNavigationLayout(options.config?.navigation);
268
- const inner = [tastyIntegration({ islands: false }), starlight({
347
+ const tasty = tastyIntegration({
348
+ islands: false,
349
+ css: { mode: "extract" }
350
+ });
351
+ const starlightIntegration = starlight({
269
352
  title: options.config?.site?.title ?? "Documentation",
270
353
  ...options.config?.site?.description ? { description: options.config.site.description } : {},
271
- customCss: ["virtual:cookbook/theme.css", cssPath],
272
354
  ...options.config?.search?.enabled === false ? { pagefind: false } : {},
273
355
  components,
274
356
  sidebar: starlightSidebar(navigation)
275
- })];
357
+ });
358
+ let inner = [tasty, starlightIntegration];
276
359
  let projectRoot = options.root;
277
360
  let graphConfig = options.config;
278
361
  let graph;
@@ -291,6 +374,11 @@ function cookbook(options = {}) {
291
374
  name: "cookbook",
292
375
  hooks: {
293
376
  "astro:config:setup": async (context) => {
377
+ inner = [
378
+ (await importNative(pathToFileURL(astroReactIntegration).href)).default(),
379
+ tasty,
380
+ starlightIntegration
381
+ ];
294
382
  if (context.config.integrations.some((integration) => integration.name === "@astrojs/starlight")) throw new Error("Cookbook already includes Starlight. Remove the direct @astrojs/starlight integration before continuing.");
295
383
  projectRoot ??= fileURLToPath(context.config.root);
296
384
  const base = options.config?.build?.base ?? context.config.base;
@@ -306,24 +394,47 @@ function cookbook(options = {}) {
306
394
  base,
307
395
  output: "static",
308
396
  vite: {
309
- ssr: { external: ["@tenphi/docs"] },
310
- plugins: [virtualDocsPlugin(docsTheme.css, () => ({
311
- entries: graph?.entries ?? [],
312
- routes: graph?.routes ?? [],
313
- site: graph?.config.site ?? options.config?.site ?? {},
314
- base: graph?.config.build.base ?? base,
315
- search: graph?.config.search.enabled ?? options.config?.search?.enabled ?? true
316
- }), navigation)],
317
- resolve: { alias: [{
318
- find: "@astrojs/starlight",
319
- replacement: starlightRoot
320
- }, {
321
- find: "@tenphi/tasty/ssr/astro-middleware-static",
322
- replacement: tastyStaticMiddleware
323
- }] }
397
+ ssr: { external: [
398
+ "@tenphi/docs",
399
+ "react",
400
+ "react-dom",
401
+ "react-dom/server"
402
+ ] },
403
+ plugins: [virtualDocsPlugin(async () => {
404
+ const loaded = await loadGraph();
405
+ return {
406
+ entries: loaded.entries,
407
+ routes: loaded.routes,
408
+ site: documentedSite(loaded),
409
+ base: loaded.config.build.base,
410
+ search: loaded.config.search.enabled
411
+ };
412
+ }, navigation)],
413
+ resolve: { alias: [
414
+ {
415
+ find: "@astrojs/starlight",
416
+ replacement: starlightRoot
417
+ },
418
+ {
419
+ find: "@tenphi/tasty/ssr/astro-middleware-static",
420
+ replacement: tastyStaticMiddleware
421
+ },
422
+ {
423
+ find: "@tenphi/tasty/ssr/astro-middleware-extract-static",
424
+ replacement: tastyExtractStaticMiddleware
425
+ },
426
+ {
427
+ find: "@astrojs/react/server.js",
428
+ replacement: astroReactServer
429
+ },
430
+ {
431
+ find: "@astrojs/react/client.js",
432
+ replacement: astroReactClient
433
+ }
434
+ ] }
324
435
  }
325
436
  });
326
- await callInner(inner.slice(0, 1), "astro:config:setup", context);
437
+ await callInner(inner.slice(0, 2), "astro:config:setup", context);
327
438
  if (!usingStarlight) {
328
439
  graph = await createDocsGraph({
329
440
  root: projectRoot,
@@ -339,20 +450,20 @@ function cookbook(options = {}) {
339
450
  });
340
451
  return;
341
452
  }
342
- const starlightIntegration = inner[1];
343
- if (starlightIntegration) {
453
+ const starlightWithPlugins = inner[2];
454
+ if (starlightWithPlugins) {
344
455
  const selfIndex = context.config.integrations.findIndex((integration) => integration.name === "cookbook");
345
- context.config.integrations.splice(selfIndex + 1, 0, starlightIntegration);
456
+ context.config.integrations.splice(selfIndex + 1, 0, starlightWithPlugins);
346
457
  try {
347
- await callInner([starlightIntegration], "astro:config:setup", context);
458
+ await callInner([starlightWithPlugins], "astro:config:setup", context);
348
459
  } finally {
349
- const placeholderIndex = context.config.integrations.indexOf(starlightIntegration);
460
+ const placeholderIndex = context.config.integrations.indexOf(starlightWithPlugins);
350
461
  if (placeholderIndex >= 0) context.config.integrations.splice(placeholderIndex, 1);
351
462
  }
352
463
  }
353
464
  },
354
465
  "astro:config:done": async (context) => {
355
- await callInner(usingStarlight ? inner : inner.slice(0, 1), "astro:config:done", context);
466
+ await callInner(usingStarlight ? inner : inner.slice(0, 2), "astro:config:done", context);
356
467
  },
357
468
  "astro:server:setup": async ({ server }) => {
358
469
  let assets = docsAssetMap(await loadGraph());
@@ -394,10 +505,10 @@ function cookbook(options = {}) {
394
505
  },
395
506
  "astro:build:start": async (context) => {
396
507
  await loadGraph();
397
- await callInner(usingStarlight ? inner : inner.slice(0, 1), "astro:build:start", context);
508
+ await callInner(usingStarlight ? inner : inner.slice(0, 2), "astro:build:start", context);
398
509
  },
399
510
  "astro:build:done": async (context) => {
400
- await callInner(usingStarlight ? inner : inner.slice(0, 1), "astro:build:done", context);
511
+ await callInner(usingStarlight ? inner : inner.slice(0, 2), "astro:build:done", context);
401
512
  if (!graph) return;
402
513
  const output = fileURLToPath(context.dir);
403
514
  for (const asset of graph.assets) {
@@ -423,6 +534,19 @@ function cookbook(options = {}) {
423
534
  function docsAssetMap(graph) {
424
535
  return new Map(graph.assets.flatMap((asset) => asset.publicPath && asset.sourcePath ? [[asset.publicPath, asset]] : []));
425
536
  }
537
+ function documentedSite(graph) {
538
+ if (graph.config.site.version) return graph.config.site;
539
+ const packages = new Set(graph.entries.flatMap((entry) => entry.package?.resolved ? [entry.package.resolved] : []));
540
+ if (packages.size !== 1) return graph.config.site;
541
+ const resolved = packages.values().next().value;
542
+ if (!resolved) return graph.config.site;
543
+ const separator = resolved.lastIndexOf("@");
544
+ if (separator <= 0 || separator === resolved.length - 1) return graph.config.site;
545
+ return {
546
+ ...graph.config.site,
547
+ version: resolved.slice(separator + 1)
548
+ };
549
+ }
426
550
  function requestPath(url) {
427
551
  try {
428
552
  return decodeURIComponent(new URL(url ?? "/", "http://localhost").pathname);
@@ -443,41 +567,19 @@ function assetContentType(pathname) {
443
567
  }
444
568
  }
445
569
  function configureTastyTheme(theme, resolved) {
446
- const tokens = Object.fromEntries(Object.entries(resolved.tokens).filter(([name]) => name.startsWith("$")));
447
- Object.assign(tokens, {
448
- "#surface": "var(--td-surface)",
449
- "#surface-2": "var(--td-surface-2)",
450
- "#surface-3": "var(--td-surface-3)",
451
- "#text": "var(--td-text)",
452
- "#text-soft": "var(--td-text-soft)",
453
- "#border": "var(--td-border)",
454
- "#border-strong": "var(--td-border-strong)",
455
- "#accent-text": "var(--td-accent-text)",
456
- "#accent-surface": "var(--td-accent-surface)",
457
- "#accent-surface-text": "var(--td-accent-surface-text)",
458
- "#focus": "var(--td-focus)"
459
- });
460
- const globalStyles = anatomyStyles(theme?.styles);
570
+ const tokens = tastyTokens(resolved);
571
+ const globalStyles = resolveLegacyAnatomyStyles(theme?.styles);
461
572
  configure({
462
- ...theme?.states ? { states: theme.states } : {},
463
- units: {
464
- x: "var(--gap)",
465
- r: "var(--radius)",
466
- cr: "var(--card-radius)",
467
- bw: "var(--border-width)"
573
+ states: {
574
+ ...cookbookStates,
575
+ ...theme?.states
468
576
  },
577
+ units: TASTY_UNITS,
469
578
  tokens,
470
579
  presets: resolved.presets,
471
580
  ...globalStyles ? { globalStyles } : {}
472
581
  });
473
582
  }
474
- function anatomyStyles(styles) {
475
- if (!styles) return void 0;
476
- return Object.fromEntries(Object.entries(styles).filter((entry) => isRecord(entry[1])).map(([name, value]) => [`[data-tasty-anatomy="${name}"]`, value]));
477
- }
478
- function isRecord(value) {
479
- return typeof value === "object" && value !== null && !Array.isArray(value);
480
- }
481
583
  function starlightSidebar(layout) {
482
584
  const fallback = layout.items?.length ? layout.items.map(starlightSidebarItem) : [{ autogenerate: { directory: "" } }];
483
585
  if (!layout.sectioned) return fallback;
@@ -516,20 +618,17 @@ async function callInner(integrations, hook, context) {
516
618
  if (typeof handler === "function") await handler(context);
517
619
  }
518
620
  }
519
- function virtualDocsPlugin(css, getContent, layout) {
520
- const themeId = "\0virtual:cookbook/theme.css";
621
+ function virtualDocsPlugin(getContent, layout) {
521
622
  const configId = "\0virtual:cookbook/config";
522
623
  const layoutId = "\0virtual:cookbook/layout";
523
624
  return {
524
- name: "cookbook-theme",
625
+ name: "cookbook-data",
525
626
  resolveId(id) {
526
- if (id === "virtual:cookbook/theme.css") return themeId;
527
627
  if (id === "virtual:cookbook/config") return configId;
528
628
  if (id === "virtual:cookbook/layout") return layoutId;
529
629
  },
530
- load(id) {
531
- if (id === themeId) return css;
532
- if (id === configId) return `export const content = ${JSON.stringify(getContent())};`;
630
+ async load(id) {
631
+ if (id === configId) return `export const content = ${JSON.stringify(await getContent())};`;
533
632
  if (id === layoutId) return `export const layout = ${JSON.stringify(layout)};`;
534
633
  }
535
634
  };