@brandon_m_behring/book-scaffold-astro 3.0.0-alpha.8 → 3.0.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/components/SourceArchive.astro +1 -1
- package/components/VersionSelector.tsx +3 -1
- package/dist/components/ToolFilter.d.ts +5 -0
- package/dist/components/ToolFilter.mjs +118 -0
- package/dist/components/VersionSelector.d.ts +5 -0
- package/dist/components/VersionSelector.mjs +58 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.mjs +50 -5
- package/dist/schemas.d.ts +1 -1
- package/dist/schemas.mjs +36 -6
- package/layouts/Base.astro +7 -2
- package/package.json +11 -4
- package/pages/convergence.astro +1 -1
- package/src/lib/patterns.ts +1 -1
- package/src/lib/sources.ts +1 -1
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* pedagogy of Appendix D — the archive is intentionally sparse in the
|
|
13
13
|
* early book, and the gap is visible by design.
|
|
14
14
|
*/
|
|
15
|
-
import { sourceTiers } from '
|
|
15
|
+
import { sourceTiers } from '@brandon_m_behring/book-scaffold-astro';
|
|
16
16
|
import {
|
|
17
17
|
getSourcesByTier,
|
|
18
18
|
TIER_LABELS,
|
|
@@ -50,7 +50,9 @@ export default function VersionSelector() {
|
|
|
50
50
|
};
|
|
51
51
|
}, [open]);
|
|
52
52
|
|
|
53
|
-
const
|
|
53
|
+
// STUB_VERSIONS is a const literal with >=1 entry so the fallback is
|
|
54
|
+
// always defined; the bang silences TS's noUncheckedIndexedAccess.
|
|
55
|
+
const current = STUB_VERSIONS.find((v) => v.current) ?? STUB_VERSIONS[0]!;
|
|
54
56
|
|
|
55
57
|
return (
|
|
56
58
|
<div class="version-selector" ref={ref}>
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// components/ToolFilter.tsx
|
|
2
|
+
import { useState, useRef, useEffect } from "preact/hooks";
|
|
3
|
+
import { jsx, jsxs } from "preact/jsx-runtime";
|
|
4
|
+
var STORAGE_KEY = "book:tool-filter";
|
|
5
|
+
var EVENT_NAME = "book:tool-filter:change";
|
|
6
|
+
var FILTERABLE_TOOLS = ["claude-code", "gemini-cli", "codex-cli"];
|
|
7
|
+
function readSaved() {
|
|
8
|
+
try {
|
|
9
|
+
const raw = localStorage.getItem(STORAGE_KEY);
|
|
10
|
+
if (!raw) return [];
|
|
11
|
+
const parsed = JSON.parse(raw);
|
|
12
|
+
if (!Array.isArray(parsed)) return [];
|
|
13
|
+
return parsed.filter((s) => typeof s === "string");
|
|
14
|
+
} catch {
|
|
15
|
+
return [];
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function writeSaved(selected) {
|
|
19
|
+
try {
|
|
20
|
+
localStorage.setItem(STORAGE_KEY, JSON.stringify(selected));
|
|
21
|
+
} catch {
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function announce(selected) {
|
|
25
|
+
window.dispatchEvent(
|
|
26
|
+
new CustomEvent(EVENT_NAME, { detail: { selected } })
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
function ToolFilter() {
|
|
30
|
+
const [open, setOpen] = useState(false);
|
|
31
|
+
const [selected, setSelected] = useState([]);
|
|
32
|
+
const ref = useRef(null);
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
const saved = readSaved();
|
|
35
|
+
setSelected(saved);
|
|
36
|
+
announce(saved);
|
|
37
|
+
}, []);
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
if (!open) return;
|
|
40
|
+
const onClick = (e) => {
|
|
41
|
+
if (ref.current && !ref.current.contains(e.target)) {
|
|
42
|
+
setOpen(false);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
const onKey = (e) => {
|
|
46
|
+
if (e.key === "Escape") setOpen(false);
|
|
47
|
+
};
|
|
48
|
+
window.addEventListener("click", onClick);
|
|
49
|
+
window.addEventListener("keydown", onKey);
|
|
50
|
+
return () => {
|
|
51
|
+
window.removeEventListener("click", onClick);
|
|
52
|
+
window.removeEventListener("keydown", onKey);
|
|
53
|
+
};
|
|
54
|
+
}, [open]);
|
|
55
|
+
function toggle(tool) {
|
|
56
|
+
const next = selected.includes(tool) ? selected.filter((s) => s !== tool) : [...selected, tool];
|
|
57
|
+
setSelected(next);
|
|
58
|
+
writeSaved(next);
|
|
59
|
+
announce(next);
|
|
60
|
+
}
|
|
61
|
+
function clearAll() {
|
|
62
|
+
setSelected([]);
|
|
63
|
+
writeSaved([]);
|
|
64
|
+
announce([]);
|
|
65
|
+
}
|
|
66
|
+
const activeCount = selected.length;
|
|
67
|
+
const buttonLabel = activeCount === 0 ? "Filter chapters by tool (showing all)" : `Filter chapters by tool (${activeCount} active)`;
|
|
68
|
+
return /* @__PURE__ */ jsxs("div", { class: "tool-filter", ref, children: [
|
|
69
|
+
/* @__PURE__ */ jsxs(
|
|
70
|
+
"button",
|
|
71
|
+
{
|
|
72
|
+
type: "button",
|
|
73
|
+
class: "chrome-button tool-filter-trigger",
|
|
74
|
+
"aria-label": buttonLabel,
|
|
75
|
+
title: buttonLabel,
|
|
76
|
+
"aria-expanded": open,
|
|
77
|
+
"aria-haspopup": "true",
|
|
78
|
+
onClick: () => setOpen((v) => !v),
|
|
79
|
+
children: [
|
|
80
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\u2690" }),
|
|
81
|
+
activeCount > 0 && /* @__PURE__ */ jsx("span", { class: "tool-filter-count", "aria-hidden": "true", children: activeCount })
|
|
82
|
+
]
|
|
83
|
+
}
|
|
84
|
+
),
|
|
85
|
+
open && /* @__PURE__ */ jsxs("div", { class: "tool-filter-panel", role: "group", "aria-label": "Tool filters", children: [
|
|
86
|
+
/* @__PURE__ */ jsx("p", { class: "tool-filter-heading", children: "Show chapters for" }),
|
|
87
|
+
/* @__PURE__ */ jsx("ul", { class: "tool-filter-chips", children: FILTERABLE_TOOLS.map((tool) => {
|
|
88
|
+
const on = selected.includes(tool);
|
|
89
|
+
return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
|
|
90
|
+
"button",
|
|
91
|
+
{
|
|
92
|
+
type: "button",
|
|
93
|
+
class: `tool-filter-chip${on ? " tool-filter-chip-on" : ""}`,
|
|
94
|
+
"aria-pressed": on,
|
|
95
|
+
onClick: () => toggle(tool),
|
|
96
|
+
children: tool
|
|
97
|
+
}
|
|
98
|
+
) });
|
|
99
|
+
}) }),
|
|
100
|
+
/* @__PURE__ */ jsxs("div", { class: "tool-filter-footer", children: [
|
|
101
|
+
/* @__PURE__ */ jsx(
|
|
102
|
+
"button",
|
|
103
|
+
{
|
|
104
|
+
type: "button",
|
|
105
|
+
class: "tool-filter-clear",
|
|
106
|
+
onClick: clearAll,
|
|
107
|
+
disabled: activeCount === 0,
|
|
108
|
+
children: "Clear"
|
|
109
|
+
}
|
|
110
|
+
),
|
|
111
|
+
/* @__PURE__ */ jsx("span", { class: "tool-filter-note", children: "Cross-tool chapters stay visible under any filter." })
|
|
112
|
+
] })
|
|
113
|
+
] })
|
|
114
|
+
] });
|
|
115
|
+
}
|
|
116
|
+
export {
|
|
117
|
+
ToolFilter as default
|
|
118
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// components/VersionSelector.tsx
|
|
2
|
+
import { useState, useRef, useEffect } from "preact/hooks";
|
|
3
|
+
import { jsx, jsxs } from "preact/jsx-runtime";
|
|
4
|
+
var STUB_VERSIONS = [
|
|
5
|
+
{ id: "", label: "Latest (main)", date: "2026-04-17", current: true },
|
|
6
|
+
{ id: "v1.0", label: "v1.0", date: "2026-05-01", current: false }
|
|
7
|
+
];
|
|
8
|
+
function VersionSelector() {
|
|
9
|
+
const [open, setOpen] = useState(false);
|
|
10
|
+
const ref = useRef(null);
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
if (!open) return;
|
|
13
|
+
const onClick = (e) => {
|
|
14
|
+
if (ref.current && !ref.current.contains(e.target)) {
|
|
15
|
+
setOpen(false);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
const onKey = (e) => {
|
|
19
|
+
if (e.key === "Escape") setOpen(false);
|
|
20
|
+
};
|
|
21
|
+
window.addEventListener("click", onClick);
|
|
22
|
+
window.addEventListener("keydown", onKey);
|
|
23
|
+
return () => {
|
|
24
|
+
window.removeEventListener("click", onClick);
|
|
25
|
+
window.removeEventListener("keydown", onKey);
|
|
26
|
+
};
|
|
27
|
+
}, [open]);
|
|
28
|
+
const current = STUB_VERSIONS.find((v) => v.current) ?? STUB_VERSIONS[0];
|
|
29
|
+
return /* @__PURE__ */ jsxs("div", { class: "version-selector", ref, children: [
|
|
30
|
+
/* @__PURE__ */ jsx(
|
|
31
|
+
"button",
|
|
32
|
+
{
|
|
33
|
+
type: "button",
|
|
34
|
+
class: "chrome-button version-selector-trigger",
|
|
35
|
+
"aria-label": "Select book version",
|
|
36
|
+
title: `Current: ${current.label} (${current.date})`,
|
|
37
|
+
"aria-expanded": open,
|
|
38
|
+
"aria-haspopup": "listbox",
|
|
39
|
+
onClick: () => setOpen((v) => !v),
|
|
40
|
+
children: /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "v" })
|
|
41
|
+
}
|
|
42
|
+
),
|
|
43
|
+
open && /* @__PURE__ */ jsx("ul", { class: "version-selector-menu", role: "listbox", children: STUB_VERSIONS.map((v) => /* @__PURE__ */ jsx("li", { role: "option", "aria-selected": v.current, children: /* @__PURE__ */ jsxs(
|
|
44
|
+
"a",
|
|
45
|
+
{
|
|
46
|
+
href: v.id ? `/${v.id}/` : "/",
|
|
47
|
+
class: v.current ? "version-current" : "",
|
|
48
|
+
children: [
|
|
49
|
+
/* @__PURE__ */ jsx("span", { class: "version-label", children: v.label }),
|
|
50
|
+
/* @__PURE__ */ jsx("span", { class: "version-date", children: v.date })
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
) })) })
|
|
54
|
+
] });
|
|
55
|
+
}
|
|
56
|
+
export {
|
|
57
|
+
VersionSelector as default
|
|
58
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AstroUserConfig, AstroIntegration } from 'astro';
|
|
2
|
-
import { b as BookConfigOptions, d as BookScaffoldIntegrationOptions } from './types-
|
|
3
|
-
export { B as BOOK_PROFILES, a as BookConfigError, c as BookProfile, e as BookSchemasOptions, r as resolveProfile } from './types-
|
|
2
|
+
import { b as BookConfigOptions, d as BookScaffoldIntegrationOptions } from './types-BoCXCvBy.js';
|
|
3
|
+
export { B as BOOK_PROFILES, a as BookConfigError, c as BookProfile, e as BookSchemasOptions, r as resolveProfile } from './types-BoCXCvBy.js';
|
|
4
4
|
import { z } from 'astro/zod';
|
|
5
5
|
|
|
6
6
|
declare function defineBookConfig(opts: BookConfigOptions): Promise<AstroUserConfig>;
|
package/dist/index.mjs
CHANGED
|
@@ -119,6 +119,7 @@ import mdx from "@astrojs/mdx";
|
|
|
119
119
|
import preact from "@astrojs/preact";
|
|
120
120
|
|
|
121
121
|
// src/types.ts
|
|
122
|
+
import { existsSync, readFileSync } from "fs";
|
|
122
123
|
var BOOK_PROFILES = ["academic", "tools", "minimal"];
|
|
123
124
|
var BookConfigError = class extends Error {
|
|
124
125
|
constructor(message) {
|
|
@@ -126,14 +127,43 @@ var BookConfigError = class extends Error {
|
|
|
126
127
|
this.name = "BookConfigError";
|
|
127
128
|
}
|
|
128
129
|
};
|
|
130
|
+
function readEnvFile(path = ".env") {
|
|
131
|
+
try {
|
|
132
|
+
if (!existsSync(path)) return {};
|
|
133
|
+
const out = {};
|
|
134
|
+
for (const line of readFileSync(path, "utf8").split(/\r?\n/)) {
|
|
135
|
+
const m = line.match(/^\s*([A-Z_][A-Z0-9_]*)\s*=\s*(.*?)\s*$/);
|
|
136
|
+
if (!m) continue;
|
|
137
|
+
let val = m[2] ?? "";
|
|
138
|
+
if (val.startsWith('"') && val.endsWith('"') || val.startsWith("'") && val.endsWith("'")) {
|
|
139
|
+
val = val.slice(1, -1);
|
|
140
|
+
}
|
|
141
|
+
out[m[1]] = val;
|
|
142
|
+
}
|
|
143
|
+
return out;
|
|
144
|
+
} catch {
|
|
145
|
+
return {};
|
|
146
|
+
}
|
|
147
|
+
}
|
|
129
148
|
function resolveProfile(explicit) {
|
|
130
|
-
|
|
149
|
+
let candidate = explicit ?? process.env.BOOK_PROFILE;
|
|
150
|
+
let source = "default";
|
|
151
|
+
if (explicit) source = "param";
|
|
152
|
+
else if (process.env.BOOK_PROFILE) source = "env";
|
|
153
|
+
if (!candidate) {
|
|
154
|
+
const fromFile = readEnvFile().BOOK_PROFILE;
|
|
155
|
+
if (fromFile) {
|
|
156
|
+
candidate = fromFile;
|
|
157
|
+
source = "dotenv";
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
candidate = candidate ?? "minimal";
|
|
131
161
|
if (!BOOK_PROFILES.includes(candidate)) {
|
|
132
162
|
throw new BookConfigError(
|
|
133
163
|
`profile must be one of ${BOOK_PROFILES.join(" | ")} (got ${JSON.stringify(candidate)})`
|
|
134
164
|
);
|
|
135
165
|
}
|
|
136
|
-
if (
|
|
166
|
+
if (source === "default") {
|
|
137
167
|
console.warn("book-scaffold-astro: BOOK_PROFILE not set; falling back to 'minimal'.");
|
|
138
168
|
}
|
|
139
169
|
return candidate;
|
|
@@ -194,8 +224,14 @@ async function defineBookConfig(opts) {
|
|
|
194
224
|
const remarkPlugins = [];
|
|
195
225
|
const rehypePlugins = [];
|
|
196
226
|
if (profile === "academic") {
|
|
197
|
-
const { default: remarkMath } = await import(
|
|
198
|
-
|
|
227
|
+
const { default: remarkMath } = await import(
|
|
228
|
+
/* @vite-ignore */
|
|
229
|
+
"remark-math"
|
|
230
|
+
);
|
|
231
|
+
const { default: rehypeKatex } = await import(
|
|
232
|
+
/* @vite-ignore */
|
|
233
|
+
"rehype-katex"
|
|
234
|
+
);
|
|
199
235
|
const { ssmMacros: ssmMacros2 } = await Promise.resolve().then(() => (init_katex_macros(), katex_macros_exports));
|
|
200
236
|
remarkPlugins.push(remarkMath);
|
|
201
237
|
rehypePlugins.push([
|
|
@@ -240,10 +276,19 @@ async function defineBookConfig(opts) {
|
|
|
240
276
|
void _extraIntegrations;
|
|
241
277
|
void _extraStyles;
|
|
242
278
|
void _markdown;
|
|
279
|
+
const katexExternals = profile === "academic" ? [] : ["remark-math", "rehype-katex", "katex"];
|
|
243
280
|
const config = {
|
|
244
281
|
...rest,
|
|
245
282
|
integrations,
|
|
246
|
-
markdown
|
|
283
|
+
markdown,
|
|
284
|
+
vite: {
|
|
285
|
+
build: {
|
|
286
|
+
rollupOptions: {
|
|
287
|
+
external: katexExternals
|
|
288
|
+
}
|
|
289
|
+
},
|
|
290
|
+
...rest.vite ?? {}
|
|
291
|
+
}
|
|
247
292
|
};
|
|
248
293
|
return config;
|
|
249
294
|
}
|
package/dist/schemas.d.ts
CHANGED
package/dist/schemas.mjs
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
// src/schemas-entry.ts
|
|
2
|
-
import { existsSync } from "fs";
|
|
2
|
+
import { existsSync as existsSync2 } from "fs";
|
|
3
3
|
import { defineCollection } from "astro:content";
|
|
4
4
|
import { glob, file } from "astro/loaders";
|
|
5
5
|
|
|
6
6
|
// src/types.ts
|
|
7
|
+
import { existsSync, readFileSync } from "fs";
|
|
7
8
|
var BOOK_PROFILES = ["academic", "tools", "minimal"];
|
|
8
9
|
var BookConfigError = class extends Error {
|
|
9
10
|
constructor(message) {
|
|
@@ -11,14 +12,43 @@ var BookConfigError = class extends Error {
|
|
|
11
12
|
this.name = "BookConfigError";
|
|
12
13
|
}
|
|
13
14
|
};
|
|
15
|
+
function readEnvFile(path = ".env") {
|
|
16
|
+
try {
|
|
17
|
+
if (!existsSync(path)) return {};
|
|
18
|
+
const out = {};
|
|
19
|
+
for (const line of readFileSync(path, "utf8").split(/\r?\n/)) {
|
|
20
|
+
const m = line.match(/^\s*([A-Z_][A-Z0-9_]*)\s*=\s*(.*?)\s*$/);
|
|
21
|
+
if (!m) continue;
|
|
22
|
+
let val = m[2] ?? "";
|
|
23
|
+
if (val.startsWith('"') && val.endsWith('"') || val.startsWith("'") && val.endsWith("'")) {
|
|
24
|
+
val = val.slice(1, -1);
|
|
25
|
+
}
|
|
26
|
+
out[m[1]] = val;
|
|
27
|
+
}
|
|
28
|
+
return out;
|
|
29
|
+
} catch {
|
|
30
|
+
return {};
|
|
31
|
+
}
|
|
32
|
+
}
|
|
14
33
|
function resolveProfile(explicit) {
|
|
15
|
-
|
|
34
|
+
let candidate = explicit ?? process.env.BOOK_PROFILE;
|
|
35
|
+
let source = "default";
|
|
36
|
+
if (explicit) source = "param";
|
|
37
|
+
else if (process.env.BOOK_PROFILE) source = "env";
|
|
38
|
+
if (!candidate) {
|
|
39
|
+
const fromFile = readEnvFile().BOOK_PROFILE;
|
|
40
|
+
if (fromFile) {
|
|
41
|
+
candidate = fromFile;
|
|
42
|
+
source = "dotenv";
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
candidate = candidate ?? "minimal";
|
|
16
46
|
if (!BOOK_PROFILES.includes(candidate)) {
|
|
17
47
|
throw new BookConfigError(
|
|
18
48
|
`profile must be one of ${BOOK_PROFILES.join(" | ")} (got ${JSON.stringify(candidate)})`
|
|
19
49
|
);
|
|
20
50
|
}
|
|
21
|
-
if (
|
|
51
|
+
if (source === "default") {
|
|
22
52
|
console.warn("book-scaffold-astro: BOOK_PROFILE not set; falling back to 'minimal'.");
|
|
23
53
|
}
|
|
24
54
|
return candidate;
|
|
@@ -143,19 +173,19 @@ function defineBookSchemas(opts = {}) {
|
|
|
143
173
|
const collections = {
|
|
144
174
|
chapters
|
|
145
175
|
};
|
|
146
|
-
if (
|
|
176
|
+
if (existsSync2("./sources/manifest.yaml")) {
|
|
147
177
|
collections.sources = defineCollection({
|
|
148
178
|
loader: file("sources/manifest.yaml"),
|
|
149
179
|
schema: sourcesSchema
|
|
150
180
|
});
|
|
151
181
|
}
|
|
152
|
-
if (
|
|
182
|
+
if (existsSync2("./changelog/tools")) {
|
|
153
183
|
collections.changelog = defineCollection({
|
|
154
184
|
loader: glob({ pattern: "*.yaml", base: "./changelog/tools" }),
|
|
155
185
|
schema: changelogSchema
|
|
156
186
|
});
|
|
157
187
|
}
|
|
158
|
-
if (
|
|
188
|
+
if (existsSync2("./changelog/patterns.yaml")) {
|
|
159
189
|
collections.patterns = defineCollection({
|
|
160
190
|
loader: file("changelog/patterns.yaml"),
|
|
161
191
|
schema: patternsSchema
|
package/layouts/Base.astro
CHANGED
|
@@ -42,8 +42,13 @@ import '../styles/chapter.css';
|
|
|
42
42
|
import '../styles/tool-filter.css';
|
|
43
43
|
import '../styles/convergence.css';
|
|
44
44
|
import '../styles/print.css';
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
// Use package-path imports for the .tsx islands so Vite resolves them
|
|
46
|
+
// via the exports map (→ pre-compiled dist/components/*.mjs with proper
|
|
47
|
+
// preact JSX). The raw .tsx files are also shipped so consumers can
|
|
48
|
+
// import them directly, but relative imports from inside the package
|
|
49
|
+
// must route through the exports map, not the raw source.
|
|
50
|
+
import VersionSelector from '@brandon_m_behring/book-scaffold-astro/components/VersionSelector';
|
|
51
|
+
import ToolFilter from '@brandon_m_behring/book-scaffold-astro/components/ToolFilter';
|
|
47
52
|
import Sidebar from '../components/Sidebar.astro';
|
|
48
53
|
|
|
49
54
|
const profile = import.meta.env.BOOK_PROFILE ?? 'minimal';
|
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": "3.0.0
|
|
4
|
+
"version": "3.0.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "Brandon Behring",
|
|
@@ -73,9 +73,15 @@
|
|
|
73
73
|
"./components/Tag.astro": "./components/Tag.astro",
|
|
74
74
|
"./components/Theorem.astro": "./components/Theorem.astro",
|
|
75
75
|
"./components/TipBox.astro": "./components/TipBox.astro",
|
|
76
|
-
"./components/ToolFilter":
|
|
76
|
+
"./components/ToolFilter": {
|
|
77
|
+
"types": "./dist/components/ToolFilter.d.ts",
|
|
78
|
+
"import": "./dist/components/ToolFilter.mjs"
|
|
79
|
+
},
|
|
77
80
|
"./components/TryThis.astro": "./components/TryThis.astro",
|
|
78
|
-
"./components/VersionSelector":
|
|
81
|
+
"./components/VersionSelector": {
|
|
82
|
+
"types": "./dist/components/VersionSelector.d.ts",
|
|
83
|
+
"import": "./dist/components/VersionSelector.mjs"
|
|
84
|
+
},
|
|
79
85
|
"./components/WarnBox.astro": "./components/WarnBox.astro",
|
|
80
86
|
"./components/WeekRef.astro": "./components/WeekRef.astro",
|
|
81
87
|
"./components/XRef.astro": "./components/XRef.astro",
|
|
@@ -111,7 +117,8 @@
|
|
|
111
117
|
],
|
|
112
118
|
"scripts": {
|
|
113
119
|
"build": "tsup && rm -f dist/types-*.d.ts",
|
|
114
|
-
"prepublishOnly": "npm run build"
|
|
120
|
+
"prepublishOnly": "npm run build",
|
|
121
|
+
"test": "node --test tests/*.test.mjs"
|
|
115
122
|
},
|
|
116
123
|
"peerDependencies": {
|
|
117
124
|
"astro": "^6.1.7",
|
package/pages/convergence.astro
CHANGED
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
getPatternsByCategory,
|
|
17
17
|
CATEGORY_LABELS,
|
|
18
18
|
} from '../src/lib/patterns';
|
|
19
|
-
import { patternCategories } from '
|
|
19
|
+
import { patternCategories } from '@brandon_m_behring/book-scaffold-astro';
|
|
20
20
|
|
|
21
21
|
const grouped = await getPatternsByCategory();
|
|
22
22
|
const totalPatterns = Object.values(grouped).reduce(
|
package/src/lib/patterns.ts
CHANGED
package/src/lib/sources.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* component and any future dashboards share a single source of truth.
|
|
7
7
|
*/
|
|
8
8
|
import { getCollection, type CollectionEntry } from 'astro:content';
|
|
9
|
-
import { sourceTiers } from '
|
|
9
|
+
import { sourceTiers } from '@brandon_m_behring/book-scaffold-astro';
|
|
10
10
|
|
|
11
11
|
export type SourceEntry = CollectionEntry<'sources'>;
|
|
12
12
|
export type SourceTier = (typeof sourceTiers)[number];
|