@brandon_m_behring/book-scaffold-astro 4.4.0 → 4.5.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.d.ts +19 -3
- package/dist/index.mjs +58 -8
- package/dist/schemas.d.ts +1 -1
- package/dist/schemas.mjs +15 -5
- package/package.json +1 -1
- package/pages/index.astro +111 -0
- package/src/profile-kit.ts +10 -0
- package/src/profiles/academic.ts +1 -0
- package/src/profiles/course-notes.ts +1 -0
- package/src/profiles/minimal.ts +1 -0
- package/src/profiles/research-portfolio.ts +1 -0
- package/src/profiles/tools.ts +1 -0
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,24 @@
|
|
|
1
1
|
import { AstroUserConfig, AstroIntegration } from 'astro';
|
|
2
|
-
import { c as BookConfigOptions, f as BookScaffoldIntegrationOptions, Q as volatilityLevels, h as ChaptersRenderer, n as Style } from './types-
|
|
3
|
-
export { A as AcademicChapter, B as BOOK_PRESETS, a as BOOK_PROFILES, b as BookConfigError, d as BookPreset, e as BookProfile, g as BookSchemasOptions, C as ChapterFor, i as CourseNotesChapter, F as FreshnessAffordance, j as FrontmatterRouteConfig, M as MinimalChapter, P as PartKey, k as PartialRouteToggles, l as ProfileDefinition, R as ResearchPortfolioChapter, m as RouteToggles, S as StatusBadge, o as StyleInput, T as ToolsChapter, V as VolatilityBadge, p as academicChapterSchema, q as academicParts, r as changeKinds, s as changelogSchema, t as chapterStatus, u as composeStyles, v as courseNotesChapterSchema, w as defineProfile, x as defineStyle, y as minimalChapterSchema, z as normalizeFrontmatterConfig, D as patternCategories, E as patternsSchema, G as researchPortfolioChapterSchema, H as resolvePreset, I as resolveProfile, J as sourceTiers, K as sourceTiersResearch, L as sourcesSchema, N as toolSlugs, O as toolsChapterSchema } from './types-
|
|
2
|
+
import { c as BookConfigOptions, f as BookScaffoldIntegrationOptions, Q as volatilityLevels, h as ChaptersRenderer, n as Style } from './types-DLIpEgTm.js';
|
|
3
|
+
export { A as AcademicChapter, B as BOOK_PRESETS, a as BOOK_PROFILES, b as BookConfigError, d as BookPreset, e as BookProfile, g as BookSchemasOptions, C as ChapterFor, i as CourseNotesChapter, F as FreshnessAffordance, j as FrontmatterRouteConfig, M as MinimalChapter, P as PartKey, k as PartialRouteToggles, l as ProfileDefinition, R as ResearchPortfolioChapter, m as RouteToggles, S as StatusBadge, o as StyleInput, T as ToolsChapter, V as VolatilityBadge, p as academicChapterSchema, q as academicParts, r as changeKinds, s as changelogSchema, t as chapterStatus, u as composeStyles, v as courseNotesChapterSchema, w as defineProfile, x as defineStyle, y as minimalChapterSchema, z as normalizeFrontmatterConfig, D as patternCategories, E as patternsSchema, G as researchPortfolioChapterSchema, H as resolvePreset, I as resolveProfile, J as sourceTiers, K as sourceTiersResearch, L as sourcesSchema, N as toolSlugs, O as toolsChapterSchema } from './types-DLIpEgTm.js';
|
|
4
4
|
import 'astro/zod';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* v4.5.0: Default portfolio backlink baked into the scaffold. Rendered in
|
|
8
|
+
* the auto-injected `/` landing footer for every consumer that doesn't
|
|
9
|
+
* explicitly override `portfolio` in defineBookConfig.
|
|
10
|
+
*
|
|
11
|
+
* Single source of truth for the brandon-behring.dev URL across all
|
|
12
|
+
* consumers — update here, bump scaffold version, every consumer inherits
|
|
13
|
+
* on next build. This is the intentional Brandon-specific default
|
|
14
|
+
* discussed in plan §Phase 6-pre. Consumers outside the brandon-behring.dev
|
|
15
|
+
* ecosystem set `portfolio: false` (no link) or pass `{ url, label }` to
|
|
16
|
+
* override.
|
|
17
|
+
*/
|
|
18
|
+
declare const BRANDON_PORTFOLIO_DEFAULT: {
|
|
19
|
+
readonly url: "https://brandon-behring.dev";
|
|
20
|
+
readonly label: "brandon-behring.dev";
|
|
21
|
+
};
|
|
6
22
|
declare function defineBookConfig(opts: BookConfigOptions): Promise<AstroUserConfig>;
|
|
7
23
|
|
|
8
24
|
declare function bookScaffoldIntegration(opts: BookScaffoldIntegrationOptions): AstroIntegration;
|
|
@@ -244,4 +260,4 @@ type TipsConfigInput = Omit<TipsConfig, typeof TipsConfigBrand | '__tipsConfigVe
|
|
|
244
260
|
*/
|
|
245
261
|
declare function defineTips(opts: TipsConfigInput): TipsConfig;
|
|
246
262
|
|
|
247
|
-
export { BUILTIN_STYLES, BookConfigOptions, BookScaffoldIntegrationOptions, ChaptersRenderer, type Freshness, type FreshnessStatus, Style, type TipsConfig, type TipsConfigInput, type VolatilityLevel, academicChaptersRenderer, academicStyle, bookScaffoldIntegration, chapterSortKey, courseNotesStyle, defineBookConfig, defineMdxComponents, defineTips, fallbackChaptersRenderer, freshnessLabel, getFreshness, minimalStyle, researchPortfolioStyle, toolsChaptersRenderer, toolsStyle, volatilityLevels };
|
|
263
|
+
export { BRANDON_PORTFOLIO_DEFAULT, BUILTIN_STYLES, BookConfigOptions, BookScaffoldIntegrationOptions, ChaptersRenderer, type Freshness, type FreshnessStatus, Style, type TipsConfig, type TipsConfigInput, type VolatilityLevel, academicChaptersRenderer, academicStyle, bookScaffoldIntegration, chapterSortKey, courseNotesStyle, defineBookConfig, defineMdxComponents, defineTips, fallbackChaptersRenderer, freshnessLabel, getFreshness, minimalStyle, researchPortfolioStyle, toolsChaptersRenderer, toolsStyle, volatilityLevels };
|
package/dist/index.mjs
CHANGED
|
@@ -380,8 +380,10 @@ var academicProfile = defineProfile({
|
|
|
380
380
|
// opt-in per book; see #7
|
|
381
381
|
tips: false,
|
|
382
382
|
// v4.3.0 #70: opt-in per book; requires build-tips
|
|
383
|
-
exercises: false
|
|
383
|
+
exercises: false,
|
|
384
384
|
// v4.4.0: opt-in per book; requires build-exercises
|
|
385
|
+
landing: true
|
|
386
|
+
// v4.5.0: auto-inject minimal root landing; consumers override via src/pages/index.astro
|
|
385
387
|
},
|
|
386
388
|
styles: ["tokens.css", "layout.css", "callouts.css", "chapter.css", "typography.css", "print.css"],
|
|
387
389
|
katex: true,
|
|
@@ -498,8 +500,10 @@ var toolsProfile = defineProfile({
|
|
|
498
500
|
// opt-in per book; see #7
|
|
499
501
|
tips: false,
|
|
500
502
|
// v4.3.0 #70: opt-in per book
|
|
501
|
-
exercises: false
|
|
503
|
+
exercises: false,
|
|
502
504
|
// v4.4.0: opt-in per book
|
|
505
|
+
landing: true
|
|
506
|
+
// v4.5.0: auto-inject minimal root landing
|
|
503
507
|
},
|
|
504
508
|
styles: [
|
|
505
509
|
"tokens.css",
|
|
@@ -580,8 +584,10 @@ var minimalProfile = defineProfile({
|
|
|
580
584
|
// opt-in per book; see #7
|
|
581
585
|
tips: false,
|
|
582
586
|
// v4.3.0 #70: opt-in per book
|
|
583
|
-
exercises: false
|
|
587
|
+
exercises: false,
|
|
584
588
|
// v4.4.0: opt-in per book
|
|
589
|
+
landing: true
|
|
590
|
+
// v4.5.0: auto-inject minimal root landing
|
|
585
591
|
},
|
|
586
592
|
styles: ["tokens.css", "layout.css", "callouts.css", "chapter.css", "typography.css", "print.css"],
|
|
587
593
|
// v3.7.0 (#35): minimal aliases tools schema; fallback renderer field-dispatches if a consumer opts into routes.chapters
|
|
@@ -603,8 +609,10 @@ var courseNotesProfile = defineProfile({
|
|
|
603
609
|
// opt-in per book; see #7
|
|
604
610
|
tips: false,
|
|
605
611
|
// v4.3.0 #70: opt-in per book
|
|
606
|
-
exercises: false
|
|
612
|
+
exercises: false,
|
|
607
613
|
// v4.4.0: opt-in per book
|
|
614
|
+
landing: true
|
|
615
|
+
// v4.5.0: auto-inject minimal root landing
|
|
608
616
|
},
|
|
609
617
|
styles: ["tokens.css", "layout.css", "callouts.css", "chapter.css", "typography.css", "print.css"],
|
|
610
618
|
// v3.7.0 (#35): course-notes schema has tools-style fields (chapter, volatility, sources) — fallback renderer dispatches via tools renderer
|
|
@@ -627,8 +635,10 @@ var researchPortfolioProfile = defineProfile({
|
|
|
627
635
|
// portfolios universally need title/disclosure/banner pages
|
|
628
636
|
tips: false,
|
|
629
637
|
// v4.3.0 #70: opt-in per book
|
|
630
|
-
exercises: false
|
|
638
|
+
exercises: false,
|
|
631
639
|
// v4.4.0: opt-in per book
|
|
640
|
+
landing: true
|
|
641
|
+
// v4.5.0: auto-inject minimal root landing
|
|
632
642
|
},
|
|
633
643
|
styles: ["tokens.css", "layout.css", "callouts.css", "chapter.css", "typography.css", "print.css"],
|
|
634
644
|
katex: true,
|
|
@@ -833,6 +843,11 @@ var ROUTE_REGISTRY = {
|
|
|
833
843
|
// v4.4.0: exercises index by chapter. Opt-in via routes.exercises: true;
|
|
834
844
|
// pairs with build-exercises script + <ExerciseSolutions auto /> mode.
|
|
835
845
|
exercises: { pattern: "/exercises", file: "exercises.astro" },
|
|
846
|
+
// v4.5.0: minimal root landing page. Reads title/description/portfolio/routes
|
|
847
|
+
// from vite.define-injected import.meta.env vars. Default-on per profile;
|
|
848
|
+
// consumers with their own src/pages/index.astro override (file-system route
|
|
849
|
+
// wins over injectRoute).
|
|
850
|
+
landing: { pattern: "/", file: "index.astro" },
|
|
836
851
|
// v3.4.0 (#7): consumer-collection-backed frontmatter route. Opt-in via
|
|
837
852
|
// routes: { frontmatter: true } AND content.config.ts defining the
|
|
838
853
|
// collection (use frontmatterCollection() helper from /schemas subpath).
|
|
@@ -850,7 +865,16 @@ function resolvePage(file) {
|
|
|
850
865
|
return fileURLToPath(new URL(`../pages/${file}`, import.meta.url));
|
|
851
866
|
}
|
|
852
867
|
function bookScaffoldIntegration(opts) {
|
|
853
|
-
const {
|
|
868
|
+
const {
|
|
869
|
+
profile,
|
|
870
|
+
routes: userOverrides = {},
|
|
871
|
+
extraStyles = [],
|
|
872
|
+
mdxComponentsModule,
|
|
873
|
+
// v4.5.0: landing-page data, propagated via vite.define to /index.astro.
|
|
874
|
+
title,
|
|
875
|
+
description,
|
|
876
|
+
portfolio
|
|
877
|
+
} = opts;
|
|
854
878
|
const def = PROFILES[profile];
|
|
855
879
|
const fmNormalized = normalizeFrontmatterConfig(userOverrides.frontmatter);
|
|
856
880
|
const fmEnabled = fmNormalized?.enabled ?? def.routes.frontmatter;
|
|
@@ -891,12 +915,20 @@ function bookScaffoldIntegration(opts) {
|
|
|
891
915
|
const consumerRoot = fileURLToPath(config.root);
|
|
892
916
|
const resolvedMdxPath = resolveMdxComponentsPath(consumerRoot, mdxComponentsModule);
|
|
893
917
|
const presetLiteral = JSON.stringify(profile);
|
|
918
|
+
const enabledRouteNames = Object.entries(enabledRoutes).filter(([, on]) => on).map(([name]) => name);
|
|
894
919
|
updateConfig({
|
|
895
920
|
vite: {
|
|
896
921
|
plugins: [makeMdxComponentsVitePlugin(resolvedMdxPath)],
|
|
897
922
|
define: {
|
|
898
923
|
"import.meta.env.BOOK_PRESET": presetLiteral,
|
|
899
|
-
"import.meta.env.BOOK_PROFILE": presetLiteral
|
|
924
|
+
"import.meta.env.BOOK_PROFILE": presetLiteral,
|
|
925
|
+
// v4.5.0: landing-page data. JSON.stringify on undefined → 'undefined'
|
|
926
|
+
// (which evaluates to JavaScript undefined at use site); on object →
|
|
927
|
+
// the JSON literal; on false → 'false'.
|
|
928
|
+
"import.meta.env.BOOK_TITLE": JSON.stringify(title ?? null),
|
|
929
|
+
"import.meta.env.BOOK_DESCRIPTION": JSON.stringify(description ?? null),
|
|
930
|
+
"import.meta.env.BOOK_PORTFOLIO": JSON.stringify(portfolio ?? null),
|
|
931
|
+
"import.meta.env.BOOK_ROUTES_ENABLED": JSON.stringify(enabledRouteNames)
|
|
900
932
|
}
|
|
901
933
|
}
|
|
902
934
|
});
|
|
@@ -906,6 +938,10 @@ function bookScaffoldIntegration(opts) {
|
|
|
906
938
|
}
|
|
907
939
|
|
|
908
940
|
// src/config.ts
|
|
941
|
+
var BRANDON_PORTFOLIO_DEFAULT = {
|
|
942
|
+
url: "https://brandon-behring.dev",
|
|
943
|
+
label: "brandon-behring.dev"
|
|
944
|
+
};
|
|
909
945
|
function v3MigrationError(opts) {
|
|
910
946
|
const v3Value = opts.preset ?? opts.profile;
|
|
911
947
|
const v3FieldUsed = "preset" in opts ? "preset" : "profile";
|
|
@@ -986,6 +1022,7 @@ async function defineBookConfig(opts) {
|
|
|
986
1022
|
}
|
|
987
1023
|
]);
|
|
988
1024
|
}
|
|
1025
|
+
const resolvedPortfolio = opts.portfolio === false ? false : opts.portfolio ?? BRANDON_PORTFOLIO_DEFAULT;
|
|
989
1026
|
const integrations = [
|
|
990
1027
|
mdx(),
|
|
991
1028
|
preact(),
|
|
@@ -993,7 +1030,12 @@ async function defineBookConfig(opts) {
|
|
|
993
1030
|
profile,
|
|
994
1031
|
routes: mergedRoutes,
|
|
995
1032
|
mdxComponentsModule,
|
|
996
|
-
extraStyles: mergedExtraStyles
|
|
1033
|
+
extraStyles: mergedExtraStyles,
|
|
1034
|
+
// v4.5.0: pass landing-page data through to the integration so it can
|
|
1035
|
+
// be exposed to the auto-injected /index.astro via vite.define.
|
|
1036
|
+
title: opts.title,
|
|
1037
|
+
description: opts.description,
|
|
1038
|
+
portfolio: resolvedPortfolio
|
|
997
1039
|
}),
|
|
998
1040
|
...mergedExtraIntegrations
|
|
999
1041
|
];
|
|
@@ -1028,6 +1070,10 @@ async function defineBookConfig(opts) {
|
|
|
1028
1070
|
extraStyles: _extraStyles,
|
|
1029
1071
|
markdown: _markdown,
|
|
1030
1072
|
katexMacros: _katexMacros,
|
|
1073
|
+
// v4.5.0: strip new landing-related opts so they don't leak into AstroUserConfig.
|
|
1074
|
+
title: _title,
|
|
1075
|
+
description: _description,
|
|
1076
|
+
portfolio: _portfolio,
|
|
1031
1077
|
...rest
|
|
1032
1078
|
} = opts;
|
|
1033
1079
|
void _styles;
|
|
@@ -1039,6 +1085,9 @@ async function defineBookConfig(opts) {
|
|
|
1039
1085
|
void _extraStyles;
|
|
1040
1086
|
void _markdown;
|
|
1041
1087
|
void _katexMacros;
|
|
1088
|
+
void _title;
|
|
1089
|
+
void _description;
|
|
1090
|
+
void _portfolio;
|
|
1042
1091
|
const katexExternals = wantsKatex ? [] : ["remark-math", "rehype-katex", "katex"];
|
|
1043
1092
|
const config = {
|
|
1044
1093
|
site,
|
|
@@ -1115,6 +1164,7 @@ function defineTips(opts) {
|
|
|
1115
1164
|
export {
|
|
1116
1165
|
BOOK_PRESETS,
|
|
1117
1166
|
BOOK_PROFILES,
|
|
1167
|
+
BRANDON_PORTFOLIO_DEFAULT,
|
|
1118
1168
|
BUILTIN_STYLES,
|
|
1119
1169
|
BookConfigError,
|
|
1120
1170
|
academicChapterSchema,
|
package/dist/schemas.d.ts
CHANGED
package/dist/schemas.mjs
CHANGED
|
@@ -265,8 +265,10 @@ var academicProfile = defineProfile({
|
|
|
265
265
|
// opt-in per book; see #7
|
|
266
266
|
tips: false,
|
|
267
267
|
// v4.3.0 #70: opt-in per book; requires build-tips
|
|
268
|
-
exercises: false
|
|
268
|
+
exercises: false,
|
|
269
269
|
// v4.4.0: opt-in per book; requires build-exercises
|
|
270
|
+
landing: true
|
|
271
|
+
// v4.5.0: auto-inject minimal root landing; consumers override via src/pages/index.astro
|
|
270
272
|
},
|
|
271
273
|
styles: ["tokens.css", "layout.css", "callouts.css", "chapter.css", "typography.css", "print.css"],
|
|
272
274
|
katex: true,
|
|
@@ -383,8 +385,10 @@ var toolsProfile = defineProfile({
|
|
|
383
385
|
// opt-in per book; see #7
|
|
384
386
|
tips: false,
|
|
385
387
|
// v4.3.0 #70: opt-in per book
|
|
386
|
-
exercises: false
|
|
388
|
+
exercises: false,
|
|
387
389
|
// v4.4.0: opt-in per book
|
|
390
|
+
landing: true
|
|
391
|
+
// v4.5.0: auto-inject minimal root landing
|
|
388
392
|
},
|
|
389
393
|
styles: [
|
|
390
394
|
"tokens.css",
|
|
@@ -465,8 +469,10 @@ var minimalProfile = defineProfile({
|
|
|
465
469
|
// opt-in per book; see #7
|
|
466
470
|
tips: false,
|
|
467
471
|
// v4.3.0 #70: opt-in per book
|
|
468
|
-
exercises: false
|
|
472
|
+
exercises: false,
|
|
469
473
|
// v4.4.0: opt-in per book
|
|
474
|
+
landing: true
|
|
475
|
+
// v4.5.0: auto-inject minimal root landing
|
|
470
476
|
},
|
|
471
477
|
styles: ["tokens.css", "layout.css", "callouts.css", "chapter.css", "typography.css", "print.css"],
|
|
472
478
|
// v3.7.0 (#35): minimal aliases tools schema; fallback renderer field-dispatches if a consumer opts into routes.chapters
|
|
@@ -488,8 +494,10 @@ var courseNotesProfile = defineProfile({
|
|
|
488
494
|
// opt-in per book; see #7
|
|
489
495
|
tips: false,
|
|
490
496
|
// v4.3.0 #70: opt-in per book
|
|
491
|
-
exercises: false
|
|
497
|
+
exercises: false,
|
|
492
498
|
// v4.4.0: opt-in per book
|
|
499
|
+
landing: true
|
|
500
|
+
// v4.5.0: auto-inject minimal root landing
|
|
493
501
|
},
|
|
494
502
|
styles: ["tokens.css", "layout.css", "callouts.css", "chapter.css", "typography.css", "print.css"],
|
|
495
503
|
// v3.7.0 (#35): course-notes schema has tools-style fields (chapter, volatility, sources) — fallback renderer dispatches via tools renderer
|
|
@@ -512,8 +520,10 @@ var researchPortfolioProfile = defineProfile({
|
|
|
512
520
|
// portfolios universally need title/disclosure/banner pages
|
|
513
521
|
tips: false,
|
|
514
522
|
// v4.3.0 #70: opt-in per book
|
|
515
|
-
exercises: false
|
|
523
|
+
exercises: false,
|
|
516
524
|
// v4.4.0: opt-in per book
|
|
525
|
+
landing: true
|
|
526
|
+
// v4.5.0: auto-inject minimal root landing
|
|
517
527
|
},
|
|
518
528
|
styles: ["tokens.css", "layout.css", "callouts.css", "chapter.css", "typography.css", "print.css"],
|
|
519
529
|
katex: true,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brandon_m_behring/book-scaffold-astro",
|
|
3
3
|
"description": "Astro 6 + MDX toolkit for long-form technical books. Profile-aware (academic / tools / minimal); ships Tufte typography, KaTeX, BibTeX citations, Pagefind, Cloudflare Workers deploy. See PACKAGE_DESIGN.md for the API contract.",
|
|
4
|
-
"version": "4.
|
|
4
|
+
"version": "4.5.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "Brandon Behring",
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* /index — minimal default landing page (v4.5.0).
|
|
4
|
+
*
|
|
5
|
+
* Auto-injected by bookScaffoldIntegration when routes.landing === true
|
|
6
|
+
* (default for every profile). Consumers with their own src/pages/index.astro
|
|
7
|
+
* override automatically — file-system routes win over injectRoute, no extra
|
|
8
|
+
* config needed.
|
|
9
|
+
*
|
|
10
|
+
* Reads book identity + portfolio + enabled-routes from vite.define-injected
|
|
11
|
+
* env vars (see integration.ts §4.5.0). Renders:
|
|
12
|
+
* - h1 with book title (fallback: 'book-scaffold-astro')
|
|
13
|
+
* - lead paragraph with description (omitted if not set)
|
|
14
|
+
* - "Read" list of links to enabled scaffold routes (filtered to only
|
|
15
|
+
* routes the integration actually injected; respects routes.<x>: false)
|
|
16
|
+
* - portfolio backlink in the footer (omitted if portfolio: false)
|
|
17
|
+
*
|
|
18
|
+
* Override paths:
|
|
19
|
+
* - Disable entirely: defineBookConfig({ routes: { landing: false } })
|
|
20
|
+
* - Compose differently: create src/pages/index.astro in your consumer
|
|
21
|
+
* repo (file wins; this page never renders)
|
|
22
|
+
* - Change portfolio target: defineBookConfig({ portfolio: { url, label } })
|
|
23
|
+
* or defineBookConfig({ portfolio: false })
|
|
24
|
+
*/
|
|
25
|
+
import Base from '../layouts/Base.astro';
|
|
26
|
+
|
|
27
|
+
// Vite-injected at build time. JSON.stringify(value ?? null) is the
|
|
28
|
+
// integration's convention; null means "not set", an object/string means real value.
|
|
29
|
+
const title = (import.meta.env.BOOK_TITLE as string | null) ?? 'book-scaffold-astro';
|
|
30
|
+
const description = import.meta.env.BOOK_DESCRIPTION as string | null;
|
|
31
|
+
const portfolio = import.meta.env.BOOK_PORTFOLIO as { url: string; label: string } | false | null;
|
|
32
|
+
const enabledRoutes = (import.meta.env.BOOK_ROUTES_ENABLED as string[] | undefined) ?? [];
|
|
33
|
+
|
|
34
|
+
// Map from internal route name → display label + URL. Only routes that
|
|
35
|
+
// produce a single landing-list entry are listed here (frontmatter is a
|
|
36
|
+
// slug pattern; chaptersSlug is dynamic; landing IS this page).
|
|
37
|
+
const ROUTE_LABELS: Record<string, { label: string; href: string }> = {
|
|
38
|
+
chapters: { label: 'Chapters', href: '/chapters/' },
|
|
39
|
+
search: { label: 'Search', href: '/search/' },
|
|
40
|
+
references: { label: 'References', href: '/references/' },
|
|
41
|
+
print: { label: 'Print view', href: '/print/' },
|
|
42
|
+
convergence: { label: 'Convergence', href: '/convergence/' },
|
|
43
|
+
tips: { label: 'Tips', href: '/tips/' },
|
|
44
|
+
exercises: { label: 'Exercises', href: '/exercises/' },
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const visibleRoutes = enabledRoutes
|
|
48
|
+
.filter((name) => name in ROUTE_LABELS)
|
|
49
|
+
.map((name) => ROUTE_LABELS[name]!);
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
<Base title={title} description={description ?? undefined}>
|
|
53
|
+
<article class="prose landing">
|
|
54
|
+
<h1>{title}</h1>
|
|
55
|
+
{description && <p class="lead">{description}</p>}
|
|
56
|
+
|
|
57
|
+
{visibleRoutes.length > 0 && (
|
|
58
|
+
<>
|
|
59
|
+
<h2 class="read-heading">Read</h2>
|
|
60
|
+
<ul class="route-list">
|
|
61
|
+
{visibleRoutes.map((r) => (
|
|
62
|
+
<li><a href={r.href}>{r.label}</a></li>
|
|
63
|
+
))}
|
|
64
|
+
</ul>
|
|
65
|
+
</>
|
|
66
|
+
)}
|
|
67
|
+
|
|
68
|
+
{portfolio && portfolio !== false && (
|
|
69
|
+
<p class="portfolio-footer">
|
|
70
|
+
<small>
|
|
71
|
+
Part of <a href={portfolio.url}>{portfolio.label}</a>
|
|
72
|
+
</small>
|
|
73
|
+
</p>
|
|
74
|
+
)}
|
|
75
|
+
</article>
|
|
76
|
+
</Base>
|
|
77
|
+
|
|
78
|
+
<style>
|
|
79
|
+
.landing {
|
|
80
|
+
max-width: 60ch;
|
|
81
|
+
margin: 2rem auto;
|
|
82
|
+
}
|
|
83
|
+
.lead {
|
|
84
|
+
font-size: 1.1rem;
|
|
85
|
+
line-height: 1.5;
|
|
86
|
+
margin: 1.25rem 0 2.5rem 0;
|
|
87
|
+
}
|
|
88
|
+
.read-heading {
|
|
89
|
+
font-size: 0.85rem;
|
|
90
|
+
text-transform: uppercase;
|
|
91
|
+
letter-spacing: 0.08em;
|
|
92
|
+
color: var(--color-text-muted, #555);
|
|
93
|
+
margin-top: 2.5rem;
|
|
94
|
+
margin-bottom: 0.75rem;
|
|
95
|
+
}
|
|
96
|
+
.route-list {
|
|
97
|
+
list-style: none;
|
|
98
|
+
padding: 0;
|
|
99
|
+
margin: 0;
|
|
100
|
+
}
|
|
101
|
+
.route-list li {
|
|
102
|
+
padding: 0.4rem 0;
|
|
103
|
+
font-family: var(--font-sans, sans-serif);
|
|
104
|
+
font-size: 1rem;
|
|
105
|
+
}
|
|
106
|
+
.portfolio-footer {
|
|
107
|
+
margin-top: 3rem;
|
|
108
|
+
color: var(--color-text-muted, #555);
|
|
109
|
+
font-family: var(--font-sans, sans-serif);
|
|
110
|
+
}
|
|
111
|
+
</style>
|
package/src/profile-kit.ts
CHANGED
|
@@ -41,6 +41,16 @@ export interface RouteToggles {
|
|
|
41
41
|
print: boolean;
|
|
42
42
|
chapters: boolean;
|
|
43
43
|
convergence: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* v4.5.0: auto-inject a minimal `/` landing page that reads the book's
|
|
46
|
+
* `title`, `description`, and `portfolio` from defineBookConfig and
|
|
47
|
+
* renders a route list (filtered to enabled routes). Defaults to `true`
|
|
48
|
+
* on every profile. Consumers with their own `src/pages/index.astro` keep
|
|
49
|
+
* their custom landing (file-system routes win over `injectRoute`). Set
|
|
50
|
+
* to `false` to suppress the auto-injection entirely without writing
|
|
51
|
+
* a custom landing.
|
|
52
|
+
*/
|
|
53
|
+
landing: boolean;
|
|
44
54
|
/**
|
|
45
55
|
* v3.4.0 (closes #7): auto-inject `/frontmatter/[slug]/` rendering a
|
|
46
56
|
* consumer-defined `frontmatter` content collection. Default `false` per
|
package/src/profiles/academic.ts
CHANGED
|
@@ -25,6 +25,7 @@ export const academicProfile = defineProfile({
|
|
|
25
25
|
frontmatter: false, // opt-in per book; see #7
|
|
26
26
|
tips: false, // v4.3.0 #70: opt-in per book; requires build-tips
|
|
27
27
|
exercises: false, // v4.4.0: opt-in per book; requires build-exercises
|
|
28
|
+
landing: true, // v4.5.0: auto-inject minimal root landing; consumers override via src/pages/index.astro
|
|
28
29
|
},
|
|
29
30
|
styles: ['tokens.css', 'layout.css', 'callouts.css', 'chapter.css', 'typography.css', 'print.css'],
|
|
30
31
|
katex: true,
|
|
@@ -27,6 +27,7 @@ export const courseNotesProfile = defineProfile({
|
|
|
27
27
|
frontmatter: false, // opt-in per book; see #7
|
|
28
28
|
tips: false, // v4.3.0 #70: opt-in per book
|
|
29
29
|
exercises: false, // v4.4.0: opt-in per book
|
|
30
|
+
landing: true, // v4.5.0: auto-inject minimal root landing
|
|
30
31
|
},
|
|
31
32
|
styles: ['tokens.css', 'layout.css', 'callouts.css', 'chapter.css', 'typography.css', 'print.css'],
|
|
32
33
|
// v3.7.0 (#35): course-notes schema has tools-style fields (chapter, volatility, sources) — fallback renderer dispatches via tools renderer
|
package/src/profiles/minimal.ts
CHANGED
|
@@ -22,6 +22,7 @@ export const minimalProfile = defineProfile({
|
|
|
22
22
|
frontmatter: false, // opt-in per book; see #7
|
|
23
23
|
tips: false, // v4.3.0 #70: opt-in per book
|
|
24
24
|
exercises: false, // v4.4.0: opt-in per book
|
|
25
|
+
landing: true, // v4.5.0: auto-inject minimal root landing
|
|
25
26
|
},
|
|
26
27
|
styles: ['tokens.css', 'layout.css', 'callouts.css', 'chapter.css', 'typography.css', 'print.css'],
|
|
27
28
|
// v3.7.0 (#35): minimal aliases tools schema; fallback renderer field-dispatches if a consumer opts into routes.chapters
|
|
@@ -38,6 +38,7 @@ export const researchPortfolioProfile = defineProfile({
|
|
|
38
38
|
frontmatter: true, // portfolios universally need title/disclosure/banner pages
|
|
39
39
|
tips: false, // v4.3.0 #70: opt-in per book
|
|
40
40
|
exercises: false, // v4.4.0: opt-in per book
|
|
41
|
+
landing: true, // v4.5.0: auto-inject minimal root landing
|
|
41
42
|
},
|
|
42
43
|
styles: ['tokens.css', 'layout.css', 'callouts.css', 'chapter.css', 'typography.css', 'print.css'],
|
|
43
44
|
katex: true, // math is common in research content
|
package/src/profiles/tools.ts
CHANGED
|
@@ -22,6 +22,7 @@ export const toolsProfile = defineProfile({
|
|
|
22
22
|
frontmatter: false, // opt-in per book; see #7
|
|
23
23
|
tips: false, // v4.3.0 #70: opt-in per book
|
|
24
24
|
exercises: false, // v4.4.0: opt-in per book
|
|
25
|
+
landing: true, // v4.5.0: auto-inject minimal root landing
|
|
25
26
|
},
|
|
26
27
|
styles: [
|
|
27
28
|
'tokens.css', 'layout.css', 'callouts.css', 'chapter.css',
|