@brandon_m_behring/book-scaffold-astro 4.4.0 → 4.5.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/dist/index.d.ts +19 -3
- package/dist/index.mjs +80 -8
- package/dist/schemas.d.ts +1 -1
- package/dist/schemas.mjs +15 -5
- package/package.json +1 -1
- package/pages/index.astro +118 -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,
|
|
@@ -814,6 +824,23 @@ function defineMdxComponents(components) {
|
|
|
814
824
|
}
|
|
815
825
|
|
|
816
826
|
// src/integration.ts
|
|
827
|
+
var LANDING_VIRTUAL_ID = "virtual:book-scaffold/landing-config";
|
|
828
|
+
var LANDING_RESOLVED_ID = "\0" + LANDING_VIRTUAL_ID;
|
|
829
|
+
function makeLandingConfigVitePlugin(config) {
|
|
830
|
+
const serialized = `export default ${JSON.stringify(config)};`;
|
|
831
|
+
return {
|
|
832
|
+
name: "book-scaffold:landing-config",
|
|
833
|
+
enforce: "pre",
|
|
834
|
+
resolveId(id) {
|
|
835
|
+
if (id === LANDING_VIRTUAL_ID) return LANDING_RESOLVED_ID;
|
|
836
|
+
return null;
|
|
837
|
+
},
|
|
838
|
+
load(id) {
|
|
839
|
+
if (id !== LANDING_RESOLVED_ID) return null;
|
|
840
|
+
return serialized;
|
|
841
|
+
}
|
|
842
|
+
};
|
|
843
|
+
}
|
|
817
844
|
var PACKAGE_NAME = "@brandon_m_behring/book-scaffold-astro";
|
|
818
845
|
var ROUTE_REGISTRY = {
|
|
819
846
|
references: { pattern: "/references", file: "references.astro" },
|
|
@@ -833,6 +860,11 @@ var ROUTE_REGISTRY = {
|
|
|
833
860
|
// v4.4.0: exercises index by chapter. Opt-in via routes.exercises: true;
|
|
834
861
|
// pairs with build-exercises script + <ExerciseSolutions auto /> mode.
|
|
835
862
|
exercises: { pattern: "/exercises", file: "exercises.astro" },
|
|
863
|
+
// v4.5.0: minimal root landing page. Reads title/description/portfolio/routes
|
|
864
|
+
// from vite.define-injected import.meta.env vars. Default-on per profile;
|
|
865
|
+
// consumers with their own src/pages/index.astro override (file-system route
|
|
866
|
+
// wins over injectRoute).
|
|
867
|
+
landing: { pattern: "/", file: "index.astro" },
|
|
836
868
|
// v3.4.0 (#7): consumer-collection-backed frontmatter route. Opt-in via
|
|
837
869
|
// routes: { frontmatter: true } AND content.config.ts defining the
|
|
838
870
|
// collection (use frontmatterCollection() helper from /schemas subpath).
|
|
@@ -850,7 +882,16 @@ function resolvePage(file) {
|
|
|
850
882
|
return fileURLToPath(new URL(`../pages/${file}`, import.meta.url));
|
|
851
883
|
}
|
|
852
884
|
function bookScaffoldIntegration(opts) {
|
|
853
|
-
const {
|
|
885
|
+
const {
|
|
886
|
+
profile,
|
|
887
|
+
routes: userOverrides = {},
|
|
888
|
+
extraStyles = [],
|
|
889
|
+
mdxComponentsModule,
|
|
890
|
+
// v4.5.0: landing-page data, propagated via vite.define to /index.astro.
|
|
891
|
+
title,
|
|
892
|
+
description,
|
|
893
|
+
portfolio
|
|
894
|
+
} = opts;
|
|
854
895
|
const def = PROFILES[profile];
|
|
855
896
|
const fmNormalized = normalizeFrontmatterConfig(userOverrides.frontmatter);
|
|
856
897
|
const fmEnabled = fmNormalized?.enabled ?? def.routes.frontmatter;
|
|
@@ -891,10 +932,23 @@ function bookScaffoldIntegration(opts) {
|
|
|
891
932
|
const consumerRoot = fileURLToPath(config.root);
|
|
892
933
|
const resolvedMdxPath = resolveMdxComponentsPath(consumerRoot, mdxComponentsModule);
|
|
893
934
|
const presetLiteral = JSON.stringify(profile);
|
|
935
|
+
const enabledRouteNames = Object.entries(enabledRoutes).filter(([, on]) => on).map(([name]) => name);
|
|
894
936
|
updateConfig({
|
|
895
937
|
vite: {
|
|
896
|
-
plugins: [
|
|
938
|
+
plugins: [
|
|
939
|
+
makeMdxComponentsVitePlugin(resolvedMdxPath),
|
|
940
|
+
makeLandingConfigVitePlugin({
|
|
941
|
+
title: title ?? null,
|
|
942
|
+
description: description ?? null,
|
|
943
|
+
portfolio: portfolio ?? false,
|
|
944
|
+
enabledRoutes: enabledRouteNames
|
|
945
|
+
})
|
|
946
|
+
],
|
|
897
947
|
define: {
|
|
948
|
+
// Preset/profile stay as env vars — preference-flag pattern where
|
|
949
|
+
// env-based override IS the convention (resolvePreset reads from
|
|
950
|
+
// process.env / .env explicitly). Config values (title, etc.) now
|
|
951
|
+
// route through the virtual module above to avoid that override.
|
|
898
952
|
"import.meta.env.BOOK_PRESET": presetLiteral,
|
|
899
953
|
"import.meta.env.BOOK_PROFILE": presetLiteral
|
|
900
954
|
}
|
|
@@ -906,6 +960,10 @@ function bookScaffoldIntegration(opts) {
|
|
|
906
960
|
}
|
|
907
961
|
|
|
908
962
|
// src/config.ts
|
|
963
|
+
var BRANDON_PORTFOLIO_DEFAULT = {
|
|
964
|
+
url: "https://brandon-behring.dev",
|
|
965
|
+
label: "brandon-behring.dev"
|
|
966
|
+
};
|
|
909
967
|
function v3MigrationError(opts) {
|
|
910
968
|
const v3Value = opts.preset ?? opts.profile;
|
|
911
969
|
const v3FieldUsed = "preset" in opts ? "preset" : "profile";
|
|
@@ -986,6 +1044,7 @@ async function defineBookConfig(opts) {
|
|
|
986
1044
|
}
|
|
987
1045
|
]);
|
|
988
1046
|
}
|
|
1047
|
+
const resolvedPortfolio = opts.portfolio === false ? false : opts.portfolio ?? BRANDON_PORTFOLIO_DEFAULT;
|
|
989
1048
|
const integrations = [
|
|
990
1049
|
mdx(),
|
|
991
1050
|
preact(),
|
|
@@ -993,7 +1052,12 @@ async function defineBookConfig(opts) {
|
|
|
993
1052
|
profile,
|
|
994
1053
|
routes: mergedRoutes,
|
|
995
1054
|
mdxComponentsModule,
|
|
996
|
-
extraStyles: mergedExtraStyles
|
|
1055
|
+
extraStyles: mergedExtraStyles,
|
|
1056
|
+
// v4.5.0: pass landing-page data through to the integration so it can
|
|
1057
|
+
// be exposed to the auto-injected /index.astro via vite.define.
|
|
1058
|
+
title: opts.title,
|
|
1059
|
+
description: opts.description,
|
|
1060
|
+
portfolio: resolvedPortfolio
|
|
997
1061
|
}),
|
|
998
1062
|
...mergedExtraIntegrations
|
|
999
1063
|
];
|
|
@@ -1028,6 +1092,10 @@ async function defineBookConfig(opts) {
|
|
|
1028
1092
|
extraStyles: _extraStyles,
|
|
1029
1093
|
markdown: _markdown,
|
|
1030
1094
|
katexMacros: _katexMacros,
|
|
1095
|
+
// v4.5.0: strip new landing-related opts so they don't leak into AstroUserConfig.
|
|
1096
|
+
title: _title,
|
|
1097
|
+
description: _description,
|
|
1098
|
+
portfolio: _portfolio,
|
|
1031
1099
|
...rest
|
|
1032
1100
|
} = opts;
|
|
1033
1101
|
void _styles;
|
|
@@ -1039,6 +1107,9 @@ async function defineBookConfig(opts) {
|
|
|
1039
1107
|
void _extraStyles;
|
|
1040
1108
|
void _markdown;
|
|
1041
1109
|
void _katexMacros;
|
|
1110
|
+
void _title;
|
|
1111
|
+
void _description;
|
|
1112
|
+
void _portfolio;
|
|
1042
1113
|
const katexExternals = wantsKatex ? [] : ["remark-math", "rehype-katex", "katex"];
|
|
1043
1114
|
const config = {
|
|
1044
1115
|
site,
|
|
@@ -1115,6 +1186,7 @@ function defineTips(opts) {
|
|
|
1115
1186
|
export {
|
|
1116
1187
|
BOOK_PRESETS,
|
|
1117
1188
|
BOOK_PROFILES,
|
|
1189
|
+
BRANDON_PORTFOLIO_DEFAULT,
|
|
1118
1190
|
BUILTIN_STYLES,
|
|
1119
1191
|
BookConfigError,
|
|
1120
1192
|
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.1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "Brandon Behring",
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* /index — minimal default landing page (v4.5.0; landing-config source
|
|
4
|
+
* refactored in v4.5.1 from env vars to virtual module).
|
|
5
|
+
*
|
|
6
|
+
* Auto-injected by bookScaffoldIntegration when routes.landing === true
|
|
7
|
+
* (default for every profile). Consumers with their own src/pages/index.astro
|
|
8
|
+
* override automatically — file-system routes win over injectRoute, no extra
|
|
9
|
+
* config needed.
|
|
10
|
+
*
|
|
11
|
+
* Reads book identity + portfolio + enabled-routes from the
|
|
12
|
+
* `virtual:book-scaffold/landing-config` virtual module exposed by
|
|
13
|
+
* makeLandingConfigVitePlugin (see integration.ts §4.5.1). v4.5.0 used
|
|
14
|
+
* import.meta.env.BOOK_* env vars; that pattern was vulnerable to silent
|
|
15
|
+
* override by consumer .env files (caught during DML deploy when a stale
|
|
16
|
+
* `BOOK_TITLE=web` in web/.env overrode defineBookConfig({title})). The
|
|
17
|
+
* virtual module isolates landing config from any env-based override.
|
|
18
|
+
*
|
|
19
|
+
* Renders:
|
|
20
|
+
* - h1 with book title (fallback: 'book-scaffold-astro')
|
|
21
|
+
* - lead paragraph with description (omitted if not set)
|
|
22
|
+
* - "Read" list of links to enabled scaffold routes (filtered to only
|
|
23
|
+
* routes the integration actually injected; respects routes.<x>: false)
|
|
24
|
+
* - portfolio backlink in the footer (omitted if portfolio: false)
|
|
25
|
+
*
|
|
26
|
+
* Override paths:
|
|
27
|
+
* - Disable entirely: defineBookConfig({ routes: { landing: false } })
|
|
28
|
+
* - Compose differently: create src/pages/index.astro in your consumer
|
|
29
|
+
* repo (file wins; this page never renders)
|
|
30
|
+
* - Change portfolio target: defineBookConfig({ portfolio: { url, label } })
|
|
31
|
+
* or defineBookConfig({ portfolio: false })
|
|
32
|
+
*/
|
|
33
|
+
import Base from '../layouts/Base.astro';
|
|
34
|
+
import bookConfig from 'virtual:book-scaffold/landing-config';
|
|
35
|
+
|
|
36
|
+
const title = bookConfig.title ?? 'book-scaffold-astro';
|
|
37
|
+
const description = bookConfig.description;
|
|
38
|
+
const portfolio = bookConfig.portfolio;
|
|
39
|
+
const enabledRoutes = bookConfig.enabledRoutes;
|
|
40
|
+
|
|
41
|
+
// Map from internal route name → display label + URL. Only routes that
|
|
42
|
+
// produce a single landing-list entry are listed here (frontmatter is a
|
|
43
|
+
// slug pattern; chaptersSlug is dynamic; landing IS this page).
|
|
44
|
+
const ROUTE_LABELS: Record<string, { label: string; href: string }> = {
|
|
45
|
+
chapters: { label: 'Chapters', href: '/chapters/' },
|
|
46
|
+
search: { label: 'Search', href: '/search/' },
|
|
47
|
+
references: { label: 'References', href: '/references/' },
|
|
48
|
+
print: { label: 'Print view', href: '/print/' },
|
|
49
|
+
convergence: { label: 'Convergence', href: '/convergence/' },
|
|
50
|
+
tips: { label: 'Tips', href: '/tips/' },
|
|
51
|
+
exercises: { label: 'Exercises', href: '/exercises/' },
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const visibleRoutes = enabledRoutes
|
|
55
|
+
.filter((name) => name in ROUTE_LABELS)
|
|
56
|
+
.map((name) => ROUTE_LABELS[name]!);
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
<Base title={title} description={description ?? undefined}>
|
|
60
|
+
<article class="prose landing">
|
|
61
|
+
<h1>{title}</h1>
|
|
62
|
+
{description && <p class="lead">{description}</p>}
|
|
63
|
+
|
|
64
|
+
{visibleRoutes.length > 0 && (
|
|
65
|
+
<>
|
|
66
|
+
<h2 class="read-heading">Read</h2>
|
|
67
|
+
<ul class="route-list">
|
|
68
|
+
{visibleRoutes.map((r) => (
|
|
69
|
+
<li><a href={r.href}>{r.label}</a></li>
|
|
70
|
+
))}
|
|
71
|
+
</ul>
|
|
72
|
+
</>
|
|
73
|
+
)}
|
|
74
|
+
|
|
75
|
+
{portfolio && portfolio !== false && (
|
|
76
|
+
<p class="portfolio-footer">
|
|
77
|
+
<small>
|
|
78
|
+
Part of <a href={portfolio.url}>{portfolio.label}</a>
|
|
79
|
+
</small>
|
|
80
|
+
</p>
|
|
81
|
+
)}
|
|
82
|
+
</article>
|
|
83
|
+
</Base>
|
|
84
|
+
|
|
85
|
+
<style>
|
|
86
|
+
.landing {
|
|
87
|
+
max-width: 60ch;
|
|
88
|
+
margin: 2rem auto;
|
|
89
|
+
}
|
|
90
|
+
.lead {
|
|
91
|
+
font-size: 1.1rem;
|
|
92
|
+
line-height: 1.5;
|
|
93
|
+
margin: 1.25rem 0 2.5rem 0;
|
|
94
|
+
}
|
|
95
|
+
.read-heading {
|
|
96
|
+
font-size: 0.85rem;
|
|
97
|
+
text-transform: uppercase;
|
|
98
|
+
letter-spacing: 0.08em;
|
|
99
|
+
color: var(--color-text-muted, #555);
|
|
100
|
+
margin-top: 2.5rem;
|
|
101
|
+
margin-bottom: 0.75rem;
|
|
102
|
+
}
|
|
103
|
+
.route-list {
|
|
104
|
+
list-style: none;
|
|
105
|
+
padding: 0;
|
|
106
|
+
margin: 0;
|
|
107
|
+
}
|
|
108
|
+
.route-list li {
|
|
109
|
+
padding: 0.4rem 0;
|
|
110
|
+
font-family: var(--font-sans, sans-serif);
|
|
111
|
+
font-size: 1rem;
|
|
112
|
+
}
|
|
113
|
+
.portfolio-footer {
|
|
114
|
+
margin-top: 3rem;
|
|
115
|
+
color: var(--color-text-muted, #555);
|
|
116
|
+
font-family: var(--font-sans, sans-serif);
|
|
117
|
+
}
|
|
118
|
+
</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',
|