@brandon_m_behring/book-scaffold-astro 4.26.0 → 4.26.3
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 -6
- package/dist/index.mjs +26 -2
- package/dist/schemas.d.ts +1 -1
- package/dist/schemas.mjs +14 -2
- package/dist/{types-BO5qyDqT.d.ts → types-CWXP1S4b.d.ts} +30 -2
- package/layouts/Base.astro +13 -0
- package/package.json +1 -1
- package/recipes/15-defining-styles.md +2 -1
- package/src/lib/define-style.ts +12 -2
- package/src/profiles/renderers/fallback-chapters.ts +3 -3
- package/src/profiles/renderers/research-portfolio-chapters.ts +26 -0
- package/src/profiles/research-portfolio.ts +4 -3
- package/styles/chapter.css +11 -0
- package/styles/tokens.css +1 -0
- package/styles/typography.css +37 -0
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AstroUserConfig, AstroIntegration, MarkdownHeading } from 'astro';
|
|
2
|
-
import { c as BookConfigOptions, f as BookScaffoldIntegrationOptions, h as ChaptersRenderer,
|
|
3
|
-
export { B as BOOK_PRESETS, a as BOOK_PROFILES, b as BookConfigError, d as BookPreset, e as BookProfile, g as BookSchemasOptions, C as ChapterFor, F as FreshnessAffordance, i as FrontmatterRouteConfig, P as PartKey, j as PartialRouteToggles, k as ProfileDefinition, R as RouteToggles, S as StatusBadge,
|
|
2
|
+
import { c as BookConfigOptions, f as BookScaffoldIntegrationOptions, h as ChaptersRenderer, m as Style } from './types-CWXP1S4b.js';
|
|
3
|
+
export { B as BOOK_PRESETS, a as BOOK_PROFILES, b as BookConfigError, d as BookPreset, e as BookProfile, g as BookSchemasOptions, C as ChapterFor, F as FreshnessAffordance, i as FrontmatterRouteConfig, P as PartKey, j as PartialRouteToggles, k as ProfileDefinition, R as ReleaseStatusConfig, l as RouteToggles, S as StatusBadge, n as StyleInput, V as VolatilityBadge, o as composeStyles, p as defineProfile, q as defineStyle, r as normalizeFrontmatterConfig, s as resolvePreset, t as resolveProfile } from './types-CWXP1S4b.js';
|
|
4
4
|
import { E as volatilityLevels, c as academicParts, Q as Question } from './schemas-CKipJ5Ie.js';
|
|
5
5
|
export { A as AcademicChapter, B as BloomLevel, C as CourseNotesChapter, G as GlossaryTerm, M as MinimalChapter, P as Provenance, a as QuestionType, R as ResearchPortfolioChapter, T as ToolsChapter, b as academicChapterSchema, d as bloomLevels, e as changeKinds, f as changelogSchema, g as chapterStatus, h as citationBackstops, i as courseNotesChapterSchema, j as glossarySchema, l as layoutModes, m as minimalChapterSchema, p as patternCategories, k as patternsSchema, n as provenanceObject, o as provenanceSchema, q as questionDifficulties, r as questionSchema, s as questionTypes, t as refineQuestion, u as refinedQuestionSchema, v as researchPortfolioChapterSchema, w as sourceTiers, x as sourceTiersResearch, y as sourcesSchema, z as toolSlugs, D as toolsChapterSchema } from './schemas-CKipJ5Ie.js';
|
|
6
6
|
export { KIND_LABEL, ResolvedTheoremLabel, THEOREM_KINDS, TheoremKind, TheoremLabelProps, resolveTheoremNumber, theoremLabel } from './lib/theorem-label.js';
|
|
@@ -144,18 +144,31 @@ declare const academicChaptersRenderer: ChaptersRenderer;
|
|
|
144
144
|
|
|
145
145
|
/**
|
|
146
146
|
* src/profiles/renderers/fallback-chapters.ts — ChaptersRenderer used by
|
|
147
|
-
* profiles that don't ship a dedicated renderer (minimal, course-notes
|
|
148
|
-
*
|
|
147
|
+
* profiles that don't ship a dedicated renderer (minimal, course-notes).
|
|
148
|
+
* Dispatches by field presence — exactly the v3.5.2
|
|
149
149
|
* logic that lived inline in pages/chapters.astro before #35.
|
|
150
150
|
*
|
|
151
151
|
* Safety net for shapes we haven't designed for explicitly. If a consumer
|
|
152
|
-
* opts a course-notes
|
|
152
|
+
* opts a course-notes book into `routes.chapters: true`,
|
|
153
153
|
* the fallback renders reasonably without crashing. Custom output for those
|
|
154
154
|
* profiles is a v4+ extension point (consumer-overridable renderer).
|
|
155
155
|
*/
|
|
156
156
|
|
|
157
157
|
declare const fallbackChaptersRenderer: ChaptersRenderer;
|
|
158
158
|
|
|
159
|
+
/**
|
|
160
|
+
* Research-portfolio /chapters renderer.
|
|
161
|
+
*
|
|
162
|
+
* The portfolio schema intentionally permits numeric Parts through 20. The
|
|
163
|
+
* generic fallback renderer inherits the tools profile's historical
|
|
164
|
+
* `part >= 6` appendix convention, which mislabels a portfolio's sixth Part
|
|
165
|
+
* as "Appendices" and its chapters as Appendix a/b/.... Keep the fallback's
|
|
166
|
+
* field-shape dispatch for every other affordance, but make numeric Parts
|
|
167
|
+
* ordinary numbered Parts throughout the portfolio schema's full range.
|
|
168
|
+
*/
|
|
169
|
+
|
|
170
|
+
declare const researchPortfolioChaptersRenderer: ChaptersRenderer;
|
|
171
|
+
|
|
159
172
|
/**
|
|
160
173
|
* src/lib/academic-parts.ts — single source of truth for academic-profile
|
|
161
174
|
* part labels (#95).
|
|
@@ -598,4 +611,4 @@ type TipsConfigInput = Omit<TipsConfig, typeof TipsConfigBrand | '__tipsConfigVe
|
|
|
598
611
|
*/
|
|
599
612
|
declare function defineTips(opts: TipsConfigInput): TipsConfig;
|
|
600
613
|
|
|
601
|
-
export { ACADEMIC_PART_NAMES, BRANDON_PORTFOLIO_DEFAULT, BUILTIN_STYLES, BookConfigOptions, BookScaffoldIntegrationOptions, type ChapterLike, ChaptersRenderer, DEFAULT_GITHUB_BRANCH, type Freshness, type FreshnessStatus, type PartReviewGroup, type PartReviewSelection, Question, type ReviewChapter, type ReviewExercise, Style, type TipsConfig, type TipsConfigInput, UNKNOWN_PART_ORDINAL, type VisibleHeading, type VolatilityLevel, academicChaptersRenderer, academicPartHeading, academicPartName, academicPartOrdinal, academicParts, academicStyle, apparatusHref, assertEnumProp, assertKnownDomain, bookOf, bookScaffoldIntegration, buildGithubUrl, chapterHref, chapterLabel, chapterSortKey, courseNotesStyle, defineBookConfig, defineMdxComponents, defineTips, deriveObjectiveMap, distinctChaptersSorted, fallbackChaptersRenderer, freshnessLabel, getFreshness, groupByChapter, groupByDomain, isCurrentChapter, minimalStyle, originUrlFromGitConfig, parseRepoSlug, pickActive, researchPortfolioStyle, resolveBookHref, resolveGithubRepo, selectPartExercises, slugOf, sortQuestions, tocHeadings, toolsChaptersRenderer, toolsStyle, volatilityLevels };
|
|
614
|
+
export { ACADEMIC_PART_NAMES, BRANDON_PORTFOLIO_DEFAULT, BUILTIN_STYLES, BookConfigOptions, BookScaffoldIntegrationOptions, type ChapterLike, ChaptersRenderer, DEFAULT_GITHUB_BRANCH, type Freshness, type FreshnessStatus, type PartReviewGroup, type PartReviewSelection, Question, type ReviewChapter, type ReviewExercise, Style, type TipsConfig, type TipsConfigInput, UNKNOWN_PART_ORDINAL, type VisibleHeading, type VolatilityLevel, academicChaptersRenderer, academicPartHeading, academicPartName, academicPartOrdinal, academicParts, academicStyle, apparatusHref, assertEnumProp, assertKnownDomain, bookOf, bookScaffoldIntegration, buildGithubUrl, chapterHref, chapterLabel, chapterSortKey, courseNotesStyle, defineBookConfig, defineMdxComponents, defineTips, deriveObjectiveMap, distinctChaptersSorted, fallbackChaptersRenderer, freshnessLabel, getFreshness, groupByChapter, groupByDomain, isCurrentChapter, minimalStyle, originUrlFromGitConfig, parseRepoSlug, pickActive, researchPortfolioChaptersRenderer, researchPortfolioStyle, resolveBookHref, resolveGithubRepo, selectPartExercises, slugOf, sortQuestions, tocHeadings, toolsChaptersRenderer, toolsStyle, volatilityLevels };
|
package/dist/index.mjs
CHANGED
|
@@ -851,6 +851,17 @@ var courseNotesProfile = defineProfile({
|
|
|
851
851
|
sitemapFilter: (page) => !page.includes("/print/")
|
|
852
852
|
});
|
|
853
853
|
|
|
854
|
+
// src/profiles/renderers/research-portfolio-chapters.ts
|
|
855
|
+
var researchPortfolioChaptersRenderer = {
|
|
856
|
+
...fallbackChaptersRenderer,
|
|
857
|
+
formatPartLabel(part) {
|
|
858
|
+
return typeof part === "number" ? `Part ${part}` : fallbackChaptersRenderer.formatPartLabel(part);
|
|
859
|
+
},
|
|
860
|
+
isAppendix(_part) {
|
|
861
|
+
return false;
|
|
862
|
+
}
|
|
863
|
+
};
|
|
864
|
+
|
|
854
865
|
// src/profiles/research-portfolio.ts
|
|
855
866
|
var researchPortfolioProfile = defineProfile({
|
|
856
867
|
name: "research-portfolio",
|
|
@@ -883,8 +894,9 @@ var researchPortfolioProfile = defineProfile({
|
|
|
883
894
|
styles: ["tokens.css", "layout.css", "callouts.css", "chapter.css", "typography.css", "print.css", "section-map.css"],
|
|
884
895
|
katex: true,
|
|
885
896
|
// math is common in research content
|
|
886
|
-
//
|
|
887
|
-
|
|
897
|
+
// Portfolio schema is a union of academic + tools shapes, but unlike the
|
|
898
|
+
// tools profile its numeric Parts remain numbered through the schema max 20.
|
|
899
|
+
chaptersRenderer: researchPortfolioChaptersRenderer
|
|
888
900
|
});
|
|
889
901
|
|
|
890
902
|
// src/profiles/index.ts
|
|
@@ -971,6 +983,9 @@ function composeStyles(styles) {
|
|
|
971
983
|
if (style.preset !== void 0) merged.preset = style.preset;
|
|
972
984
|
if (style.site !== void 0) merged.site = style.site;
|
|
973
985
|
if (style.deploy !== void 0) merged.deploy = style.deploy;
|
|
986
|
+
if (style.releaseStatus !== void 0) {
|
|
987
|
+
merged.releaseStatus = style.releaseStatus;
|
|
988
|
+
}
|
|
974
989
|
if (style.mdxComponentsModule !== void 0) {
|
|
975
990
|
merged.mdxComponentsModule = style.mdxComponentsModule;
|
|
976
991
|
}
|
|
@@ -1199,6 +1214,7 @@ function bookScaffoldIntegration(opts) {
|
|
|
1199
1214
|
// v4.5.0: landing-page data, propagated via virtual module to /index.astro.
|
|
1200
1215
|
title,
|
|
1201
1216
|
subtitle,
|
|
1217
|
+
releaseStatus,
|
|
1202
1218
|
description,
|
|
1203
1219
|
portfolio,
|
|
1204
1220
|
// v4.6.0: book-level author + SEO config, propagated through the
|
|
@@ -1268,6 +1284,7 @@ function bookScaffoldIntegration(opts) {
|
|
|
1268
1284
|
makeBookConfigVitePlugin({
|
|
1269
1285
|
title: title ?? null,
|
|
1270
1286
|
subtitle: subtitle ?? null,
|
|
1287
|
+
releaseStatus: releaseStatus ?? null,
|
|
1271
1288
|
description: description ?? null,
|
|
1272
1289
|
portfolio: portfolio ?? false,
|
|
1273
1290
|
enabledRoutes: enabledRouteNames,
|
|
@@ -1364,6 +1381,7 @@ async function defineBookConfig(opts) {
|
|
|
1364
1381
|
const mdxComponentsModule = opts.mdxComponentsModule ?? composed.mdxComponentsModule;
|
|
1365
1382
|
const composedMarkdown = composed.markdown ?? {};
|
|
1366
1383
|
const userMarkdown = opts.markdown ?? {};
|
|
1384
|
+
const resolvedReleaseStatus = opts.releaseStatus !== void 0 ? opts.releaseStatus : composed.releaseStatus;
|
|
1367
1385
|
const wantsKatex = PROFILES[profile]?.katex === true;
|
|
1368
1386
|
const remarkPlugins = [];
|
|
1369
1387
|
const rehypePlugins = [];
|
|
@@ -1413,6 +1431,8 @@ async function defineBookConfig(opts) {
|
|
|
1413
1431
|
title: opts.title,
|
|
1414
1432
|
// v4.23.0 (#135): sidebar brand subtitle.
|
|
1415
1433
|
subtitle: opts.subtitle,
|
|
1434
|
+
// v4.26.2 (#149; style inheritance + opt-out fixed in v4.26.3).
|
|
1435
|
+
releaseStatus: resolvedReleaseStatus === false ? void 0 : resolvedReleaseStatus,
|
|
1416
1436
|
description: opts.description,
|
|
1417
1437
|
portfolio: resolvedPortfolio,
|
|
1418
1438
|
// v4.6.0: book-level author + SEO config (ogImage, twitterHandle),
|
|
@@ -1470,6 +1490,8 @@ async function defineBookConfig(opts) {
|
|
|
1470
1490
|
// v4.5.0: strip new landing-related opts so they don't leak into AstroUserConfig.
|
|
1471
1491
|
title: _title,
|
|
1472
1492
|
subtitle: _subtitle,
|
|
1493
|
+
// v4.26.2 (#149): strip the release-state banner config.
|
|
1494
|
+
releaseStatus: _releaseStatus,
|
|
1473
1495
|
description: _description,
|
|
1474
1496
|
portfolio: _portfolio,
|
|
1475
1497
|
// v4.6.0: strip new book-level SEO opts (author + seo block).
|
|
@@ -1500,6 +1522,7 @@ async function defineBookConfig(opts) {
|
|
|
1500
1522
|
void _katexMacros;
|
|
1501
1523
|
void _title;
|
|
1502
1524
|
void _subtitle;
|
|
1525
|
+
void _releaseStatus;
|
|
1503
1526
|
void _description;
|
|
1504
1527
|
void _portfolio;
|
|
1505
1528
|
void _author;
|
|
@@ -1953,6 +1976,7 @@ export {
|
|
|
1953
1976
|
refineQuestion,
|
|
1954
1977
|
refinedQuestionSchema,
|
|
1955
1978
|
researchPortfolioChapterSchema,
|
|
1979
|
+
researchPortfolioChaptersRenderer,
|
|
1956
1980
|
researchPortfolioStyle,
|
|
1957
1981
|
resolveBookHref,
|
|
1958
1982
|
resolveGithubRepo,
|
package/dist/schemas.d.ts
CHANGED
package/dist/schemas.mjs
CHANGED
|
@@ -729,6 +729,17 @@ var courseNotesProfile = defineProfile({
|
|
|
729
729
|
sitemapFilter: (page) => !page.includes("/print/")
|
|
730
730
|
});
|
|
731
731
|
|
|
732
|
+
// src/profiles/renderers/research-portfolio-chapters.ts
|
|
733
|
+
var researchPortfolioChaptersRenderer = {
|
|
734
|
+
...fallbackChaptersRenderer,
|
|
735
|
+
formatPartLabel(part) {
|
|
736
|
+
return typeof part === "number" ? `Part ${part}` : fallbackChaptersRenderer.formatPartLabel(part);
|
|
737
|
+
},
|
|
738
|
+
isAppendix(_part) {
|
|
739
|
+
return false;
|
|
740
|
+
}
|
|
741
|
+
};
|
|
742
|
+
|
|
732
743
|
// src/profiles/research-portfolio.ts
|
|
733
744
|
var researchPortfolioProfile = defineProfile({
|
|
734
745
|
name: "research-portfolio",
|
|
@@ -761,8 +772,9 @@ var researchPortfolioProfile = defineProfile({
|
|
|
761
772
|
styles: ["tokens.css", "layout.css", "callouts.css", "chapter.css", "typography.css", "print.css", "section-map.css"],
|
|
762
773
|
katex: true,
|
|
763
774
|
// math is common in research content
|
|
764
|
-
//
|
|
765
|
-
|
|
775
|
+
// Portfolio schema is a union of academic + tools shapes, but unlike the
|
|
776
|
+
// tools profile its numeric Parts remain numbered through the schema max 20.
|
|
777
|
+
chaptersRenderer: researchPortfolioChaptersRenderer
|
|
766
778
|
});
|
|
767
779
|
|
|
768
780
|
// src/profiles/index.ts
|
|
@@ -379,6 +379,12 @@ interface Style {
|
|
|
379
379
|
* - `'pages'`: Cloudflare Pages (default for research-portfolio/course-notes)
|
|
380
380
|
* Closes #50. */
|
|
381
381
|
readonly deploy?: 'pages' | 'workers';
|
|
382
|
+
/**
|
|
383
|
+
* v4.26.2 (#149; style inheritance fixed in v4.26.3): release-state
|
|
384
|
+
* banner. Shallow override (last defined wins); `false` suppresses a
|
|
385
|
+
* banner inherited from an earlier style.
|
|
386
|
+
*/
|
|
387
|
+
readonly releaseStatus?: ReleaseStatusConfig | false;
|
|
382
388
|
/**
|
|
383
389
|
* Scoped consumer-side metadata. Ignored by the toolkit; survives composition
|
|
384
390
|
* as per-key spread (last wins per key). Use this for workflow data that
|
|
@@ -439,7 +445,8 @@ declare function defineStyle(opts: StyleInput): Style;
|
|
|
439
445
|
* - Top-level `defineBookConfig` fields beat any style (handled in config.ts)
|
|
440
446
|
*
|
|
441
447
|
* Per-key merge strategy:
|
|
442
|
-
* - `preset`, `site`, `deploy`, `mdxComponentsModule`, `name`
|
|
448
|
+
* - `preset`, `site`, `deploy`, `mdxComponentsModule`, `name`, `releaseStatus`
|
|
449
|
+
* → shallow override (last defined wins; `releaseStatus: false` suppresses)
|
|
443
450
|
* - `routes` → per-route spread (each route key independently overridable)
|
|
444
451
|
* - `katexMacros` → per-macro spread (each macro key independently overridable)
|
|
445
452
|
* - `extra` → per-key spread (consumer metadata accumulates across the chain)
|
|
@@ -475,6 +482,17 @@ declare function normalizeFrontmatterConfig(v: FrontmatterRouteConfig | undefine
|
|
|
475
482
|
|
|
476
483
|
type BookPreset = BookProfile;
|
|
477
484
|
declare const BOOK_PRESETS: readonly ("academic" | "tools" | "minimal" | "course-notes" | "research-portfolio")[];
|
|
485
|
+
/**
|
|
486
|
+
* v4.26.2 (#149): book-level release state rendered by
|
|
487
|
+
* `<PreReleaseBanner>` across every page.
|
|
488
|
+
*
|
|
489
|
+
* Style inheritance and explicit suppression were fixed in v4.26.3.
|
|
490
|
+
*/
|
|
491
|
+
interface ReleaseStatusConfig {
|
|
492
|
+
state: 'alpha' | 'beta' | 'rc' | 'locked';
|
|
493
|
+
dismissAt?: string;
|
|
494
|
+
message?: string;
|
|
495
|
+
}
|
|
478
496
|
/**
|
|
479
497
|
* Options for `defineBookConfig`. See PACKAGE_DESIGN.md §4.
|
|
480
498
|
*
|
|
@@ -600,6 +618,13 @@ interface BookConfigOptions {
|
|
|
600
618
|
* hardcoded both strings, so every consumer shipped the placeholder).
|
|
601
619
|
*/
|
|
602
620
|
subtitle?: string;
|
|
621
|
+
/**
|
|
622
|
+
* v4.26.2 (#149; style inheritance fixed in v4.26.3): book-level release
|
|
623
|
+
* state. When set, Base.astro renders the existing <PreReleaseBanner>
|
|
624
|
+
* site-wide (top of <body>) with these props. Omit to inherit from the
|
|
625
|
+
* composed style chain; set `false` to suppress an inherited banner.
|
|
626
|
+
*/
|
|
627
|
+
releaseStatus?: ReleaseStatusConfig | false;
|
|
603
628
|
/**
|
|
604
629
|
* v4.5.0: Book description. Read by the auto-injected `/` landing page (lead paragraph + <meta description>).
|
|
605
630
|
* Optional; landing renders no description paragraph if unset.
|
|
@@ -752,6 +777,9 @@ interface BookScaffoldIntegrationOptions {
|
|
|
752
777
|
/** v4.23.0 (#135): sidebar brand subtitle, propagated via the book-config
|
|
753
778
|
* virtual module to Sidebar.astro. */
|
|
754
779
|
subtitle?: string;
|
|
780
|
+
/** v4.26.2 (#149; style inheritance fixed in v4.26.3): resolved
|
|
781
|
+
* release-state banner propagated via the book-config virtual module. */
|
|
782
|
+
releaseStatus?: ReleaseStatusConfig;
|
|
755
783
|
/** v4.5.0: book description, propagated to `/` landing via vite.define. */
|
|
756
784
|
description?: string;
|
|
757
785
|
/**
|
|
@@ -827,4 +855,4 @@ declare function resolvePreset(explicitPreset?: BookPreset, explicitProfile?: Bo
|
|
|
827
855
|
*/
|
|
828
856
|
declare function resolveProfile(explicit?: BookProfile): BookProfile;
|
|
829
857
|
|
|
830
|
-
export { BOOK_PRESETS as B, type ChapterFor as C, type FreshnessAffordance as F, type PartKey as P, type
|
|
858
|
+
export { BOOK_PRESETS as B, type ChapterFor as C, type FreshnessAffordance as F, type PartKey as P, type ReleaseStatusConfig as R, type StatusBadge as S, type VolatilityBadge as V, BOOK_PROFILES as a, BookConfigError as b, type BookConfigOptions as c, type BookPreset as d, type BookProfile as e, type BookScaffoldIntegrationOptions as f, type BookSchemasOptions as g, type ChaptersRenderer as h, type FrontmatterRouteConfig as i, type PartialRouteToggles as j, type ProfileDefinition as k, type RouteToggles as l, type Style as m, type StyleInput as n, composeStyles as o, defineProfile as p, defineStyle as q, normalizeFrontmatterConfig as r, resolvePreset as s, resolveProfile as t };
|
package/layouts/Base.astro
CHANGED
|
@@ -59,6 +59,9 @@ import '../styles/print.css';
|
|
|
59
59
|
import VersionSelector from '@brandon_m_behring/book-scaffold-astro/components/VersionSelector';
|
|
60
60
|
import ToolFilter from '@brandon_m_behring/book-scaffold-astro/components/ToolFilter';
|
|
61
61
|
import Sidebar from '../components/Sidebar.astro';
|
|
62
|
+
// v4.26.2 (#149; style inheritance fixed in v4.26.3): site-wide
|
|
63
|
+
// release-state banner, driven by defineBookConfig.
|
|
64
|
+
import PreReleaseBanner from '../components/PreReleaseBanner.astro';
|
|
62
65
|
// v4.26.0 (#80): the mobile/tablet drawer reuses the same book-scoped nav source.
|
|
63
66
|
import NavContent from '../components/NavContent.astro';
|
|
64
67
|
// v4.6.0: SEO meta tags read book-level identity (title fallback,
|
|
@@ -165,6 +168,16 @@ const baseUrl = (import.meta.env.BASE_URL ?? '/').replace(/\/*$/, '/');
|
|
|
165
168
|
<slot name="head" />
|
|
166
169
|
</head>
|
|
167
170
|
<body>
|
|
171
|
+
{/* v4.26.2 (#149; style inheritance fixed in v4.26.3): book-level release banner — first element in <body> so
|
|
172
|
+
every page (chapters, apparatus, landing) declares its state. Renders
|
|
173
|
+
only when defineBookConfig({ releaseStatus }) is set. */}
|
|
174
|
+
{bookConfig.releaseStatus && (
|
|
175
|
+
<PreReleaseBanner
|
|
176
|
+
state={bookConfig.releaseStatus.state}
|
|
177
|
+
dismissAt={bookConfig.releaseStatus.dismissAt}
|
|
178
|
+
message={bookConfig.releaseStatus.message}
|
|
179
|
+
/>
|
|
180
|
+
)}
|
|
168
181
|
<div class="chrome-buttons">
|
|
169
182
|
{/* v4.26.0 (#80): hamburger → mobile/tablet nav drawer. <a href="#nav-drawer">
|
|
170
183
|
so it opens via :target with no JS; the controller below enhances it. */}
|
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.26.
|
|
4
|
+
"version": "4.26.3",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "Brandon Behring",
|
|
@@ -122,7 +122,8 @@ Different fields have different merge semantics. Documented:
|
|
|
122
122
|
|
|
123
123
|
| Field | Strategy |
|
|
124
124
|
|---|---|
|
|
125
|
-
| `name`, `preset`, `site`, `deploy`, `mdxComponentsModule` | Shallow override (last wins) |
|
|
125
|
+
| `name`, `preset`, `site`, `deploy`, `mdxComponentsModule` | Shallow override (last defined wins) |
|
|
126
|
+
| `releaseStatus` | Shallow override (last defined object replaces the whole earlier object); `false` suppresses an inherited banner |
|
|
126
127
|
| `routes` | Per-route spread (each route key independently overridable) |
|
|
127
128
|
| `routes.frontmatter` | Per-route spread; later value (boolean OR object) wholly replaces earlier |
|
|
128
129
|
| `katexMacros` | Object spread (per-macro override) |
|
package/src/lib/define-style.ts
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
* for migration from the v3 `preset:` shorthand.
|
|
28
28
|
*/
|
|
29
29
|
import type { AstroIntegration, AstroUserConfig } from 'astro';
|
|
30
|
-
import type { BookPreset, RouteToggles } from '../types.js';
|
|
30
|
+
import type { BookPreset, ReleaseStatusConfig, RouteToggles } from '../types.js';
|
|
31
31
|
|
|
32
32
|
// ===== Branded nominal type =====
|
|
33
33
|
|
|
@@ -123,6 +123,12 @@ export interface Style {
|
|
|
123
123
|
* - `'pages'`: Cloudflare Pages (default for research-portfolio/course-notes)
|
|
124
124
|
* Closes #50. */
|
|
125
125
|
readonly deploy?: 'pages' | 'workers';
|
|
126
|
+
/**
|
|
127
|
+
* v4.26.2 (#149; style inheritance fixed in v4.26.3): release-state
|
|
128
|
+
* banner. Shallow override (last defined wins); `false` suppresses a
|
|
129
|
+
* banner inherited from an earlier style.
|
|
130
|
+
*/
|
|
131
|
+
readonly releaseStatus?: ReleaseStatusConfig | false;
|
|
126
132
|
|
|
127
133
|
/**
|
|
128
134
|
* Scoped consumer-side metadata. Ignored by the toolkit; survives composition
|
|
@@ -193,7 +199,8 @@ export function defineStyle(opts: StyleInput): Style {
|
|
|
193
199
|
* - Top-level `defineBookConfig` fields beat any style (handled in config.ts)
|
|
194
200
|
*
|
|
195
201
|
* Per-key merge strategy:
|
|
196
|
-
* - `preset`, `site`, `deploy`, `mdxComponentsModule`, `name`
|
|
202
|
+
* - `preset`, `site`, `deploy`, `mdxComponentsModule`, `name`, `releaseStatus`
|
|
203
|
+
* → shallow override (last defined wins; `releaseStatus: false` suppresses)
|
|
197
204
|
* - `routes` → per-route spread (each route key independently overridable)
|
|
198
205
|
* - `katexMacros` → per-macro spread (each macro key independently overridable)
|
|
199
206
|
* - `extra` → per-key spread (consumer metadata accumulates across the chain)
|
|
@@ -216,6 +223,9 @@ export function composeStyles(styles: readonly Style[]): Style {
|
|
|
216
223
|
if (style.preset !== undefined) merged.preset = style.preset;
|
|
217
224
|
if (style.site !== undefined) merged.site = style.site;
|
|
218
225
|
if (style.deploy !== undefined) merged.deploy = style.deploy;
|
|
226
|
+
if (style.releaseStatus !== undefined) {
|
|
227
|
+
merged.releaseStatus = style.releaseStatus;
|
|
228
|
+
}
|
|
219
229
|
if (style.mdxComponentsModule !== undefined) {
|
|
220
230
|
merged.mdxComponentsModule = style.mdxComponentsModule;
|
|
221
231
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* src/profiles/renderers/fallback-chapters.ts — ChaptersRenderer used by
|
|
3
|
-
* profiles that don't ship a dedicated renderer (minimal, course-notes
|
|
4
|
-
*
|
|
3
|
+
* profiles that don't ship a dedicated renderer (minimal, course-notes).
|
|
4
|
+
* Dispatches by field presence — exactly the v3.5.2
|
|
5
5
|
* logic that lived inline in pages/chapters.astro before #35.
|
|
6
6
|
*
|
|
7
7
|
* Safety net for shapes we haven't designed for explicitly. If a consumer
|
|
8
|
-
* opts a course-notes
|
|
8
|
+
* opts a course-notes book into `routes.chapters: true`,
|
|
9
9
|
* the fallback renders reasonably without crashing. Custom output for those
|
|
10
10
|
* profiles is a v4+ extension point (consumer-overridable renderer).
|
|
11
11
|
*/
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Research-portfolio /chapters renderer.
|
|
3
|
+
*
|
|
4
|
+
* The portfolio schema intentionally permits numeric Parts through 20. The
|
|
5
|
+
* generic fallback renderer inherits the tools profile's historical
|
|
6
|
+
* `part >= 6` appendix convention, which mislabels a portfolio's sixth Part
|
|
7
|
+
* as "Appendices" and its chapters as Appendix a/b/.... Keep the fallback's
|
|
8
|
+
* field-shape dispatch for every other affordance, but make numeric Parts
|
|
9
|
+
* ordinary numbered Parts throughout the portfolio schema's full range.
|
|
10
|
+
*/
|
|
11
|
+
import type { ChaptersRenderer } from '../../lib/chapters-renderer.js';
|
|
12
|
+
import { fallbackChaptersRenderer } from './fallback-chapters.js';
|
|
13
|
+
|
|
14
|
+
export const researchPortfolioChaptersRenderer: ChaptersRenderer = {
|
|
15
|
+
...fallbackChaptersRenderer,
|
|
16
|
+
|
|
17
|
+
formatPartLabel(part) {
|
|
18
|
+
return typeof part === 'number'
|
|
19
|
+
? `Part ${part}`
|
|
20
|
+
: fallbackChaptersRenderer.formatPartLabel(part);
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
isAppendix(_part) {
|
|
24
|
+
return false;
|
|
25
|
+
},
|
|
26
|
+
};
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
*/
|
|
23
23
|
import { defineProfile } from '../profile-kit.js';
|
|
24
24
|
import { researchPortfolioChapterSchema } from '../schemas.js';
|
|
25
|
-
import {
|
|
25
|
+
import { researchPortfolioChaptersRenderer } from './renderers/research-portfolio-chapters.js';
|
|
26
26
|
|
|
27
27
|
export type { ResearchPortfolioChapter } from '../schemas.js';
|
|
28
28
|
|
|
@@ -46,6 +46,7 @@ export const researchPortfolioProfile = defineProfile({
|
|
|
46
46
|
},
|
|
47
47
|
styles: ['tokens.css', 'layout.css', 'callouts.css', 'chapter.css', 'typography.css', 'print.css', 'section-map.css'],
|
|
48
48
|
katex: true, // math is common in research content
|
|
49
|
-
//
|
|
50
|
-
|
|
49
|
+
// Portfolio schema is a union of academic + tools shapes, but unlike the
|
|
50
|
+
// tools profile its numeric Parts remain numbered through the schema max 20.
|
|
51
|
+
chaptersRenderer: researchPortfolioChaptersRenderer,
|
|
51
52
|
});
|
package/styles/chapter.css
CHANGED
|
@@ -244,4 +244,15 @@
|
|
|
244
244
|
overflow-x: auto;
|
|
245
245
|
/* a little room so the horizontal scrollbar doesn't clip the equation's descenders */
|
|
246
246
|
padding-block-end: 0.25rem;
|
|
247
|
+
/* Edge scroll-shadow when a wide equation scrolls (v4.25.3; docs/responsive-reading.md).
|
|
248
|
+
* Same Lea Verou layered technique as code blocks, page-bg covers. */
|
|
249
|
+
background-image:
|
|
250
|
+
linear-gradient(to right, var(--color-bg) 30%, rgba(0, 0, 0, 0)),
|
|
251
|
+
linear-gradient(to right, rgba(0, 0, 0, 0), var(--color-bg) 70%),
|
|
252
|
+
radial-gradient(farthest-side at 0 50%, rgba(0, 0, 0, 0.12), rgba(0, 0, 0, 0)),
|
|
253
|
+
radial-gradient(farthest-side at 100% 50%, rgba(0, 0, 0, 0.12), rgba(0, 0, 0, 0));
|
|
254
|
+
background-position: 0 0, 100% 0, 0 0, 100% 0;
|
|
255
|
+
background-repeat: no-repeat;
|
|
256
|
+
background-size: 30px 100%, 30px 100%, 12px 100%, 12px 100%;
|
|
257
|
+
background-attachment: local, local, scroll, scroll;
|
|
247
258
|
}
|
package/styles/tokens.css
CHANGED
|
@@ -108,6 +108,7 @@
|
|
|
108
108
|
*/
|
|
109
109
|
--measure-main: 60ch; /* default: main+gutter fits beside the sidebar at ≥64rem (v4.26.0, #80) */
|
|
110
110
|
--measure-side: 20ch; /* right-margin sidenote / section-map column */
|
|
111
|
+
--measure-code: 48rem; /* code-block break-out width: fits 80-char lines comfortably (≈88 mono chars @14px before padding); docs/responsive-reading.md */
|
|
111
112
|
--breakpoint-narrow: 48rem; /* ~768px — mobile fold (sidenotes inline) */
|
|
112
113
|
--breakpoint-wide: 90rem; /* ~1440px — wide-desktop tier */
|
|
113
114
|
--breakpoint-ultrawide: 120rem; /* ~1920px — ultrawide tier */
|
package/styles/typography.css
CHANGED
|
@@ -89,6 +89,43 @@ pre code {
|
|
|
89
89
|
font-size: var(--text-sm);
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
+
/* ===== Responsive reading (v4.25.3) — docs/responsive-reading.md =====
|
|
93
|
+
* Code blocks break out past the prose text measure to fit ~80-char lines,
|
|
94
|
+
* capped at --measure-code and centered within .prose. CONTAINER-bounded, not
|
|
95
|
+
* viewport-bounded: the width comes from the .prose column itself, so a left
|
|
96
|
+
* sidebar offset + the scrollbar gutter can never push the block into horizontal
|
|
97
|
+
* PAGE scroll. (The earlier `width: min(100vw - …)` overflowed ~8px at the
|
|
98
|
+
* 1024px sidebar boundary — #171 review finding A1, guarded by
|
|
99
|
+
* gallery/tests/fixtures/layout-overflow.spec.ts.) `.wide`/`.column-page` keep
|
|
100
|
+
* their full-bleed behavior (excluded here). */
|
|
101
|
+
.prose > pre:not(.wide):not(.column-page) {
|
|
102
|
+
max-width: var(--measure-code);
|
|
103
|
+
margin-inline: auto;
|
|
104
|
+
/* Lea Verou layered scroll-shadow: bg-colored covers move with content
|
|
105
|
+
* (attachment:local); shadow layers are fixed → shown only when scrollable. */
|
|
106
|
+
background-image:
|
|
107
|
+
linear-gradient(to right, var(--color-code-bg) 30%, rgba(0, 0, 0, 0)),
|
|
108
|
+
linear-gradient(to right, rgba(0, 0, 0, 0), var(--color-code-bg) 70%),
|
|
109
|
+
radial-gradient(farthest-side at 0 50%, rgba(0, 0, 0, 0.18), rgba(0, 0, 0, 0)),
|
|
110
|
+
radial-gradient(farthest-side at 100% 50%, rgba(0, 0, 0, 0.18), rgba(0, 0, 0, 0));
|
|
111
|
+
background-position: 0 0, 100% 0, 0 0, 100% 0;
|
|
112
|
+
background-repeat: no-repeat;
|
|
113
|
+
background-size: 40px 100%, 40px 100%, 14px 100%, 14px 100%;
|
|
114
|
+
background-attachment: local, local, scroll, scroll;
|
|
115
|
+
}
|
|
116
|
+
/* Phone (≤40rem): shrink code a touch so more fits before scrolling. Tighter
|
|
117
|
+
* than the 48rem mobile/table breakpoint below — phones benefit from the smaller
|
|
118
|
+
* glyphs; tablets (40–48rem) keep the full size. */
|
|
119
|
+
@media (max-width: 40rem) {
|
|
120
|
+
pre code { font-size: 0.75rem; }
|
|
121
|
+
}
|
|
122
|
+
/* Mobile: scroll a wide table within its own block instead of overflowing the
|
|
123
|
+
* page. Sticky thead intentionally NOT used — it can't stick inside a
|
|
124
|
+
* horizontal-scroll wrapper (CSS limitation; see docs/responsive-reading.md). */
|
|
125
|
+
@media (max-width: 48rem) {
|
|
126
|
+
.prose table { display: block; max-width: 100%; overflow-x: auto; }
|
|
127
|
+
}
|
|
128
|
+
|
|
92
129
|
/* ===== Links ===== */
|
|
93
130
|
a {
|
|
94
131
|
color: var(--color-link);
|