@nu-appdev/northwestern-starlight-theme 1.4.0 → 1.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/CHANGELOG.md +35 -1
- package/README.md +8 -12
- package/config.ts +343 -0
- package/dist/config.d.ts +99 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/expressive-code.d.ts +21 -0
- package/dist/expressive-code.d.ts.map +1 -0
- package/dist/index.d.ts +123 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/legacy-html-redirects.d.ts +72 -0
- package/dist/legacy-html-redirects.d.ts.map +1 -0
- package/dist/mermaid.d.ts +97 -0
- package/dist/mermaid.d.ts.map +1 -0
- package/dist/src/config-schema.d.ts +161 -0
- package/dist/src/config-schema.d.ts.map +1 -0
- package/dist/src/rehype-table-scroll.d.ts +10 -0
- package/dist/src/rehype-table-scroll.d.ts.map +1 -0
- package/expressive-code.ts +35 -0
- package/index.ts +55 -44
- package/legacy-html-redirects.ts +168 -0
- package/mermaid.ts +22 -12
- package/package.json +26 -8
- package/src/config-schema.ts +285 -0
- package/src/og/endpoint.ts +49 -39
- package/src/og/render.ts +260 -0
- package/src/rehype-table-scroll.ts +7 -0
- package/src/styles/content.css +18 -17
- package/src/styles/typography.css +2 -2
- package/src/virtual.d.ts +1 -0
- package/expressive-code.mjs +0 -18
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { AstroIntegration } from "astro";
|
|
2
|
+
/**
|
|
3
|
+
* Options for {@link generateLegacyHtmlRedirects} and the wrapped integration
|
|
4
|
+
* in {@link legacyHtmlRedirectsIntegration}.
|
|
5
|
+
*/
|
|
6
|
+
export interface LegacyHtmlRedirectsOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Project-relative path to the Markdown/MDX content root.
|
|
9
|
+
*
|
|
10
|
+
* @default "src/content/docs"
|
|
11
|
+
*/
|
|
12
|
+
contentDir?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Build a `{ "/<slug>.html": "/<slug>/" }` map for every Markdown/MDX page
|
|
16
|
+
* under the content directory. Intended for sites migrated from VuePress, where
|
|
17
|
+
* pages were served at `<slug>.html` instead of `<slug>/`. Pass the result into
|
|
18
|
+
* Astro's `redirects` config — old external links then resolve to the new
|
|
19
|
+
* canonical URL.
|
|
20
|
+
*
|
|
21
|
+
* Pair with {@link legacyHtmlRedirectsIntegration} so the generated redirect
|
|
22
|
+
* pages preserve the URL hash fragment. Prefer
|
|
23
|
+
* {@link defineNorthwesternConfig}'s `legacyHtmlRedirects` option, which wires
|
|
24
|
+
* both together.
|
|
25
|
+
*
|
|
26
|
+
* Index files are mapped to their parent slug (e.g. `dev/fc/index.md` becomes
|
|
27
|
+
* `/dev/fc.html → /dev/fc/`); the root `index.{md,mdx}` is skipped.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* export default defineConfig({
|
|
32
|
+
* redirects: generateLegacyHtmlRedirects(),
|
|
33
|
+
* });
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare function generateLegacyHtmlRedirects(options?: LegacyHtmlRedirectsOptions): Record<string, string>;
|
|
37
|
+
/**
|
|
38
|
+
* Astro integration that post-processes the static redirect pages produced for
|
|
39
|
+
* `.html` sources so legacy deep links keep their URL hash.
|
|
40
|
+
*
|
|
41
|
+
* Two things happen after the build:
|
|
42
|
+
* 1. **Flatten the directory layout.** Astro's default `directory` build format
|
|
43
|
+
* writes each redirect to `<path>.html/index.html`. GitHub Pages serves
|
|
44
|
+
* those via a 301 that appends a trailing slash — an unnecessary hop.
|
|
45
|
+
* Rewriting them as flat `<path>.html` files cuts the round-trip.
|
|
46
|
+
* 2. **Preserve the URL hash.** Astro's redirect page uses a `<meta refresh>`
|
|
47
|
+
* tag, which drops the fragment because the target URL has none of its own.
|
|
48
|
+
* A small inline `<script>` calls `location.replace(target + location.hash)`
|
|
49
|
+
* first; the meta-refresh is wrapped in `<noscript>` as the no-JS fallback.
|
|
50
|
+
* Running both unconditionally races and loses the hash.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```ts
|
|
54
|
+
* export default defineConfig({
|
|
55
|
+
* integrations: [legacyHtmlRedirectsIntegration()],
|
|
56
|
+
* redirects: generateLegacyHtmlRedirects(),
|
|
57
|
+
* });
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export declare function legacyHtmlRedirectsIntegration(): AstroIntegration;
|
|
61
|
+
/** @internal — exposed for unit tests. */
|
|
62
|
+
export declare function flattenHtmlRedirectDirs(distDir: string): void;
|
|
63
|
+
/**
|
|
64
|
+
* Rewrite a static redirect page so forwarding preserves the URL hash.
|
|
65
|
+
*
|
|
66
|
+
* Returns the page unchanged if no `<meta http-equiv="refresh">` is present,
|
|
67
|
+
* the tag is missing a `url=` target, or the page has already been rewritten.
|
|
68
|
+
*
|
|
69
|
+
* @internal — exposed for unit tests.
|
|
70
|
+
*/
|
|
71
|
+
export declare function rewriteRedirectPage(html: string): string;
|
|
72
|
+
//# sourceMappingURL=legacy-html-redirects.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"legacy-html-redirects.d.ts","sourceRoot":"","sources":["../legacy-html-redirects.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,OAAO,CAAC;AAG9C;;;GAGG;AACH,MAAM,WAAW,0BAA0B;IACvC;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAUD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,GAAE,0BAA+B,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAqB5G;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,8BAA8B,IAAI,gBAAgB,CASjE;AAED,0CAA0C;AAC1C,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE7D;AAuCD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAWxD"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { AstroIntegration } from "astro";
|
|
2
|
+
import type { AstroMermaidOptions } from "astro-mermaid";
|
|
3
|
+
/**
|
|
4
|
+
* Configuration options for the Northwestern Mermaid integration.
|
|
5
|
+
*
|
|
6
|
+
* Extends `astro-mermaid` options with a `toolbar` toggle that controls
|
|
7
|
+
* the hover toolbar (fullscreen, download, copy) on rendered diagrams.
|
|
8
|
+
*
|
|
9
|
+
* @see {@link northwesternMermaid} for the integration factory
|
|
10
|
+
*/
|
|
11
|
+
export interface NorthwesternMermaidOptions extends AstroMermaidOptions {
|
|
12
|
+
/**
|
|
13
|
+
* Show the hover toolbar (fullscreen, download SVG, copy source) on diagrams.
|
|
14
|
+
*
|
|
15
|
+
* @default true
|
|
16
|
+
*/
|
|
17
|
+
toolbar?: boolean;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Theme mode for Mermaid color palette generation.
|
|
21
|
+
*
|
|
22
|
+
* Maps to the `data-theme` attribute on `<html>`: `"light"` for the default
|
|
23
|
+
* palette, `"dark"` for the inverted palette with lighter primary colors
|
|
24
|
+
* and darker canvas backgrounds.
|
|
25
|
+
*/
|
|
26
|
+
export type NorthwesternMermaidMode = "light" | "dark";
|
|
27
|
+
/**
|
|
28
|
+
* Generate a complete `astro-mermaid` config with Northwestern-branded colors
|
|
29
|
+
* for the given theme mode.
|
|
30
|
+
*
|
|
31
|
+
* Builds a Mermaid `themeVariables` object from the Northwestern brand palette,
|
|
32
|
+
* deriving all node, edge, label, chart, and diagram-specific colors from a
|
|
33
|
+
* small set of brand primaries via `khroma` color manipulation.
|
|
34
|
+
*
|
|
35
|
+
* @param mode - `"light"` or `"dark"`. Controls canvas, text, and primary color values.
|
|
36
|
+
* @returns A complete `AstroMermaidOptions` object ready to pass to `astro-mermaid`.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* import { createNorthwesternMermaidConfig } from "@nu-appdev/northwestern-starlight-theme/mermaid";
|
|
41
|
+
*
|
|
42
|
+
* const darkConfig = createNorthwesternMermaidConfig("dark");
|
|
43
|
+
* // darkConfig.mermaidConfig.themeVariables contains all colors
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export declare function createNorthwesternMermaidConfig(mode: NorthwesternMermaidMode): AstroMermaidOptions;
|
|
47
|
+
/**
|
|
48
|
+
* Pre-built light-mode Mermaid config with Northwestern brand colors.
|
|
49
|
+
*
|
|
50
|
+
* Used as the default when Mermaid is auto-detected. Override individual
|
|
51
|
+
* `themeVariables` by passing a `mermaid` object to {@link northwesternTheme}
|
|
52
|
+
* in `index.ts`, or use {@link createNorthwesternMermaidConfig} for full control.
|
|
53
|
+
*/
|
|
54
|
+
export declare const defaultMermaidConfig: AstroMermaidOptions;
|
|
55
|
+
/**
|
|
56
|
+
* Pre-built dark-mode Mermaid config with Northwestern brand colors.
|
|
57
|
+
*
|
|
58
|
+
* Applied at runtime when the user switches to dark mode. The toolbar script
|
|
59
|
+
* re-renders diagrams with this config via `window.__NU_MERMAID_CONFIGS__.dark`.
|
|
60
|
+
*/
|
|
61
|
+
export declare const darkMermaidConfig: AstroMermaidOptions;
|
|
62
|
+
/**
|
|
63
|
+
* Create an Astro integration that registers Northwestern-branded Mermaid diagrams.
|
|
64
|
+
*
|
|
65
|
+
* Wraps `astro-mermaid` with Northwestern color palettes for both light and dark
|
|
66
|
+
* modes, and injects the toolbar script (fullscreen viewer, download, copy).
|
|
67
|
+
*
|
|
68
|
+
* **Note:** `defineNorthwesternConfig` handles Mermaid integration ordering.
|
|
69
|
+
* This function is only needed for manual setups.
|
|
70
|
+
*
|
|
71
|
+
* **Must be added before `starlight()` in the `integrations` array.** The
|
|
72
|
+
* `astro-mermaid` remark plugin needs to register before Starlight's rehype
|
|
73
|
+
* processing, and Astro processes integrations in order. Placing it after
|
|
74
|
+
* `starlight()` causes Mermaid code blocks to be treated as plain code.
|
|
75
|
+
*
|
|
76
|
+
* @param options - Merged with Northwestern defaults. Set `toolbar: false` to
|
|
77
|
+
* disable the hover toolbar.
|
|
78
|
+
* @returns An Astro integration to add to `integrations` in your Astro config.
|
|
79
|
+
*
|
|
80
|
+
* @example Manual setup
|
|
81
|
+
* ```ts
|
|
82
|
+
* import { northwesternMermaid } from "@nu-appdev/northwestern-starlight-theme/mermaid";
|
|
83
|
+
* import northwesternTheme from "@nu-appdev/northwestern-starlight-theme";
|
|
84
|
+
*
|
|
85
|
+
* export default defineConfig({
|
|
86
|
+
* integrations: [
|
|
87
|
+
* northwesternMermaid(), // Must come before starlight()
|
|
88
|
+
* starlight({
|
|
89
|
+
* plugins: [northwesternTheme()],
|
|
90
|
+
* title: "My Docs",
|
|
91
|
+
* }),
|
|
92
|
+
* ],
|
|
93
|
+
* });
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
export declare function northwesternMermaid(options?: NorthwesternMermaidOptions): AstroIntegration;
|
|
97
|
+
//# sourceMappingURL=mermaid.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mermaid.d.ts","sourceRoot":"","sources":["../mermaid.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,OAAO,CAAC;AAC9C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAIzD;;;;;;;GAOG;AACH,MAAM,WAAW,0BAA2B,SAAQ,mBAAmB;IACnE;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,uBAAuB,GAAG,OAAO,GAAG,MAAM,CAAC;AAwUvD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,+BAA+B,CAAC,IAAI,EAAE,uBAAuB,GAAG,mBAAmB,CAmBlG;AAED;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,EAAE,mBAA8D,CAAC;AAElG;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,EAAE,mBAA6D,CAAC;AAE9F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,0BAA+B,GAAG,gBAAgB,CAqD9F"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* Non-empty string helper used when reading titles from mixed Starlight config shapes.
|
|
4
|
+
*
|
|
5
|
+
* Trims surrounding whitespace and rejects empty strings after trimming.
|
|
6
|
+
*/
|
|
7
|
+
export declare const nonEmptyStringSchema: z.ZodString;
|
|
8
|
+
/**
|
|
9
|
+
* Top-level configuration for the Northwestern Starlight theme plugin.
|
|
10
|
+
*
|
|
11
|
+
* With `defineNorthwesternConfig`, pass this object as the `theme` key.
|
|
12
|
+
* With `northwesternTheme()` directly, pass it as the function argument.
|
|
13
|
+
*/
|
|
14
|
+
export declare const northwesternThemeConfigSchema: z.ZodObject<{
|
|
15
|
+
/**
|
|
16
|
+
* Homepage hero layout configuration.
|
|
17
|
+
*/
|
|
18
|
+
homepage: z.ZodOptional<z.ZodObject<{
|
|
19
|
+
layout: z.ZodOptional<z.ZodEnum<{
|
|
20
|
+
centered: "centered";
|
|
21
|
+
split: "split";
|
|
22
|
+
}>>;
|
|
23
|
+
showTitle: z.ZodOptional<z.ZodBoolean>;
|
|
24
|
+
imageWidth: z.ZodOptional<z.ZodString>;
|
|
25
|
+
}, z.core.$strict>>;
|
|
26
|
+
/**
|
|
27
|
+
* Mermaid diagram support.
|
|
28
|
+
*
|
|
29
|
+
* - `true`: auto-detect Mermaid packages and enable support when available
|
|
30
|
+
* - `false`: disable Mermaid integration entirely
|
|
31
|
+
* - `object`: merge custom Mermaid options with Northwestern defaults
|
|
32
|
+
*/
|
|
33
|
+
mermaid: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodRecord<z.ZodString, z.ZodUnknown>]>>;
|
|
34
|
+
/**
|
|
35
|
+
* Open Graph image generation.
|
|
36
|
+
*
|
|
37
|
+
* Generates a branded 1200x630 image for each docs page when `site`
|
|
38
|
+
* is configured in `astro.config.ts`.
|
|
39
|
+
*/
|
|
40
|
+
ogImage: z.ZodOptional<z.ZodBoolean>;
|
|
41
|
+
}, z.core.$strict>;
|
|
42
|
+
/**
|
|
43
|
+
* Configuration options for the standalone Northwestern Mermaid integration.
|
|
44
|
+
*
|
|
45
|
+
* This intentionally validates only the Northwestern-owned wrapper surface and
|
|
46
|
+
* allows additional upstream `astro-mermaid` options to pass through unchanged.
|
|
47
|
+
*/
|
|
48
|
+
export declare const northwesternMermaidOptionsSchema: z.ZodObject<{
|
|
49
|
+
/**
|
|
50
|
+
* Show the hover toolbar on rendered diagrams.
|
|
51
|
+
*
|
|
52
|
+
* The toolbar provides fullscreen, download, and copy-source actions.
|
|
53
|
+
*/
|
|
54
|
+
toolbar: z.ZodOptional<z.ZodBoolean>;
|
|
55
|
+
}, z.core.$loose>;
|
|
56
|
+
/**
|
|
57
|
+
* Options for the legacy `.html` redirect helper.
|
|
58
|
+
*
|
|
59
|
+
* Accepts the content directory override. The schema is strict so typos in
|
|
60
|
+
* the option bag surface as validation errors instead of being ignored.
|
|
61
|
+
*/
|
|
62
|
+
export declare const legacyHtmlRedirectsOptionsSchema: z.ZodObject<{
|
|
63
|
+
contentDir: z.ZodOptional<z.ZodString>;
|
|
64
|
+
}, z.core.$strict>;
|
|
65
|
+
/**
|
|
66
|
+
* Configuration options for `defineNorthwesternConfig()`.
|
|
67
|
+
*
|
|
68
|
+
* This schema validates the Northwestern-owned wrapper surface while allowing
|
|
69
|
+
* the rest of Astro's top-level config to pass through untouched.
|
|
70
|
+
*/
|
|
71
|
+
export declare const northwesternConfigOptionsSchema: z.ZodObject<{
|
|
72
|
+
/**
|
|
73
|
+
* Full Starlight configuration object.
|
|
74
|
+
*
|
|
75
|
+
* This is forwarded to `starlight()` after Northwestern defaults and
|
|
76
|
+
* helper-managed integration ordering are applied.
|
|
77
|
+
*/
|
|
78
|
+
starlight: z.ZodObject<{}, z.core.$loose>;
|
|
79
|
+
/**
|
|
80
|
+
* Northwestern theme plugin options.
|
|
81
|
+
*/
|
|
82
|
+
theme: z.ZodOptional<z.ZodObject<{
|
|
83
|
+
/**
|
|
84
|
+
* Homepage hero layout configuration.
|
|
85
|
+
*/
|
|
86
|
+
homepage: z.ZodOptional<z.ZodObject<{
|
|
87
|
+
layout: z.ZodOptional<z.ZodEnum<{
|
|
88
|
+
centered: "centered";
|
|
89
|
+
split: "split";
|
|
90
|
+
}>>;
|
|
91
|
+
showTitle: z.ZodOptional<z.ZodBoolean>;
|
|
92
|
+
imageWidth: z.ZodOptional<z.ZodString>;
|
|
93
|
+
}, z.core.$strict>>;
|
|
94
|
+
/**
|
|
95
|
+
* Mermaid diagram support.
|
|
96
|
+
*
|
|
97
|
+
* - `true`: auto-detect Mermaid packages and enable support when available
|
|
98
|
+
* - `false`: disable Mermaid integration entirely
|
|
99
|
+
* - `object`: merge custom Mermaid options with Northwestern defaults
|
|
100
|
+
*/
|
|
101
|
+
mermaid: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodRecord<z.ZodString, z.ZodUnknown>]>>;
|
|
102
|
+
/**
|
|
103
|
+
* Open Graph image generation.
|
|
104
|
+
*
|
|
105
|
+
* Generates a branded 1200x630 image for each docs page when `site`
|
|
106
|
+
* is configured in `astro.config.ts`.
|
|
107
|
+
*/
|
|
108
|
+
ogImage: z.ZodOptional<z.ZodBoolean>;
|
|
109
|
+
}, z.core.$strict>>;
|
|
110
|
+
/**
|
|
111
|
+
* Mermaid diagram support.
|
|
112
|
+
*
|
|
113
|
+
* - `true`: add Northwestern Mermaid with defaults
|
|
114
|
+
* - `false`: disable Mermaid
|
|
115
|
+
* - `object`: add Northwestern Mermaid with custom options
|
|
116
|
+
*/
|
|
117
|
+
mermaid: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
|
|
118
|
+
/**
|
|
119
|
+
* Show the hover toolbar on rendered diagrams.
|
|
120
|
+
*
|
|
121
|
+
* The toolbar provides fullscreen, download, and copy-source actions.
|
|
122
|
+
*/
|
|
123
|
+
toolbar: z.ZodOptional<z.ZodBoolean>;
|
|
124
|
+
}, z.core.$loose>]>>;
|
|
125
|
+
/**
|
|
126
|
+
* Additional Starlight plugins to register after the Northwestern theme.
|
|
127
|
+
*/
|
|
128
|
+
plugins: z.ZodOptional<z.ZodArray<z.ZodUnknown>>;
|
|
129
|
+
/**
|
|
130
|
+
* Generate `.html` redirects for every content page and rewrite the
|
|
131
|
+
* emitted redirect pages so the URL hash is preserved on forward.
|
|
132
|
+
*
|
|
133
|
+
* - `true`: scan `src/content/docs` with the defaults
|
|
134
|
+
* - `false` (default): do nothing
|
|
135
|
+
* - `object`: scan a custom content directory
|
|
136
|
+
*/
|
|
137
|
+
legacyHtmlRedirects: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
|
|
138
|
+
contentDir: z.ZodOptional<z.ZodString>;
|
|
139
|
+
}, z.core.$strict>]>>;
|
|
140
|
+
/**
|
|
141
|
+
* Escape hatch for advanced integration ordering.
|
|
142
|
+
*
|
|
143
|
+
* Use `before` for integrations that must run before Mermaid/Starlight,
|
|
144
|
+
* and `after` for integrations that should be appended after Starlight.
|
|
145
|
+
*/
|
|
146
|
+
integrations: z.ZodOptional<z.ZodObject<{
|
|
147
|
+
/**
|
|
148
|
+
* Integrations added before Mermaid and Starlight.
|
|
149
|
+
*/
|
|
150
|
+
before: z.ZodOptional<z.ZodArray<z.ZodUnknown>>;
|
|
151
|
+
/**
|
|
152
|
+
* Integrations added after Starlight.
|
|
153
|
+
*/
|
|
154
|
+
after: z.ZodOptional<z.ZodArray<z.ZodUnknown>>;
|
|
155
|
+
}, z.core.$strict>>;
|
|
156
|
+
}, z.core.$loose>;
|
|
157
|
+
/**
|
|
158
|
+
* Validate a public config object and throw a friendly package-scoped error on failure.
|
|
159
|
+
*/
|
|
160
|
+
export declare function validateSchema<T>(schema: z.ZodType<T>, value: unknown, scope: string): T;
|
|
161
|
+
//# sourceMappingURL=config-schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-schema.d.ts","sourceRoot":"","sources":["../../src/config-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,aAIoD,CAAC;AA6DtF;;;;;GAKG;AACH,eAAO,MAAM,6BAA6B;IAElC;;OAEG;;;;;;;;;IAKH;;;;;;OAMG;;IASH;;;;;OAKG;;kBAOL,CAAC;AAEP;;;;;GAKG;AACH,eAAO,MAAM,gCAAgC;IAErC;;;;OAIG;;iBAQL,CAAC;AAEP;;;;;GAKG;AACH,eAAO,MAAM,gCAAgC;;kBAcvC,CAAC;AAEP;;;;;GAKG;AACH,eAAO,MAAM,+BAA+B;IAEpC;;;;;OAKG;;IAKH;;OAEG;;QApGH;;WAEG;;;;;;;;;QAKH;;;;;;WAMG;;QASH;;;;;WAKG;;;IA8EH;;;;;;OAMG;;QAnEH;;;;WAIG;;;IAqEH;;OAEG;;IAKH;;;;;;;OAOG;;;;IAMH;;;;;OAKG;;QAGK;;WAEG;;QAKH;;WAEG;;;iBAYb,CAAC;AA2BP;;GAEG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,CAAC,CAQxF"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rehype plugin that wraps `<table>` elements in a scrollable container at build time.
|
|
3
|
+
*
|
|
4
|
+
* Inserts a `<div class="nu-table-scroll">` around each table with `tabindex="0"`,
|
|
5
|
+
* `role="region"`, and `aria-label` for keyboard scrollability. Runs during the
|
|
6
|
+
* Astro build so the HTML arrives with the wrapper already in place.
|
|
7
|
+
*/
|
|
8
|
+
import type { Root } from "hast";
|
|
9
|
+
export default function rehypeTableScroll(): (tree: Root) => void;
|
|
10
|
+
//# sourceMappingURL=rehype-table-scroll.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rehype-table-scroll.d.ts","sourceRoot":"","sources":["../../src/rehype-table-scroll.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAkB,IAAI,EAAE,MAAM,MAAM,CAAC;AAgCjD,MAAM,CAAC,OAAO,UAAU,iBAAiB,KAC7B,MAAM,IAAI,UACrB"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { StarlightExpressiveCodeOptions } from "@astrojs/starlight/expressive-code";
|
|
2
|
+
import { pluginLineNumbers } from "@expressive-code/plugin-line-numbers";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Pre-configured Expressive Code options for the Northwestern Starlight theme.
|
|
6
|
+
*
|
|
7
|
+
* Adds the line-numbers plugin and sets sensible defaults. Pass your own
|
|
8
|
+
* options to merge with the Northwestern defaults.
|
|
9
|
+
*
|
|
10
|
+
* **Note:** `defineNorthwesternConfig` includes these options.
|
|
11
|
+
* This helper is only needed for manual setups using `northwesternTheme()` directly.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```ts
|
|
15
|
+
* // ec.config.mjs (manual setup only)
|
|
16
|
+
* import { defineEcConfig } from "@astrojs/starlight/expressive-code";
|
|
17
|
+
* import { northwesternExpressiveCode } from "@nu-appdev/northwestern-starlight-theme/expressive-code";
|
|
18
|
+
*
|
|
19
|
+
* export default defineEcConfig(northwesternExpressiveCode());
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export function northwesternExpressiveCode(
|
|
23
|
+
config: StarlightExpressiveCodeOptions = {},
|
|
24
|
+
): StarlightExpressiveCodeOptions {
|
|
25
|
+
const { defaultProps, plugins, ...rest } = config;
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
...rest,
|
|
29
|
+
plugins: [pluginLineNumbers(), ...(plugins ?? [])],
|
|
30
|
+
defaultProps: {
|
|
31
|
+
showLineNumbers: false,
|
|
32
|
+
...(defaultProps ?? {}),
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
}
|
package/index.ts
CHANGED
|
@@ -4,7 +4,8 @@ import { createRequire } from "node:module";
|
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import type { StarlightPlugin } from "@astrojs/starlight/types";
|
|
7
|
-
import
|
|
7
|
+
import { nonEmptyStringSchema, northwesternThemeConfigSchema, validateSchema } from "./src/config-schema";
|
|
8
|
+
import rehypeTableScroll from "./src/rehype-table-scroll";
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Configuration for the homepage hero section.
|
|
@@ -54,21 +55,16 @@ export interface NorthwesternHomepageConfig {
|
|
|
54
55
|
/**
|
|
55
56
|
* Top-level configuration for the Northwestern Starlight theme plugin.
|
|
56
57
|
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
58
|
+
* With `defineNorthwesternConfig`, pass these as the `theme` key.
|
|
59
|
+
* With `northwesternTheme()` directly, pass them as the function argument.
|
|
60
|
+
* All properties are optional.
|
|
59
61
|
*
|
|
60
62
|
* @example
|
|
61
63
|
* ```ts
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
* integrations: [
|
|
67
|
-
* starlight({
|
|
68
|
-
* plugins: [northwesternTheme({ homepage: { layout: "split" } })],
|
|
69
|
-
* }),
|
|
70
|
-
* ],
|
|
71
|
-
* });
|
|
64
|
+
* defineNorthwesternConfig({
|
|
65
|
+
* starlight: { title: "My Docs" },
|
|
66
|
+
* theme: { homepage: { layout: "split" } },
|
|
67
|
+
* })
|
|
72
68
|
* ```
|
|
73
69
|
*
|
|
74
70
|
* @see {@link NorthwesternHomepageConfig} for homepage hero options
|
|
@@ -87,8 +83,7 @@ export interface NorthwesternThemeConfig {
|
|
|
87
83
|
* - `true` (default) — auto-detect: enables Mermaid if `astro-mermaid` and `mermaid`
|
|
88
84
|
* are installed, skips silently if they are not
|
|
89
85
|
* - `false` — disables Mermaid entirely
|
|
90
|
-
* - `object` — enables Mermaid with custom
|
|
91
|
-
* merged with Northwestern defaults
|
|
86
|
+
* - `object` — enables Mermaid with custom Mermaid config merged with Northwestern defaults
|
|
92
87
|
*
|
|
93
88
|
* @default true
|
|
94
89
|
*/
|
|
@@ -107,6 +102,18 @@ export interface NorthwesternThemeConfig {
|
|
|
107
102
|
ogImage?: boolean;
|
|
108
103
|
}
|
|
109
104
|
|
|
105
|
+
function getSiteTitle(title: unknown): string {
|
|
106
|
+
const parsedTitle = nonEmptyStringSchema.safeParse(title);
|
|
107
|
+
if (parsedTitle.success) return parsedTitle.data;
|
|
108
|
+
if (title && typeof title === "object") {
|
|
109
|
+
for (const value of Object.values(title as Record<string, unknown>)) {
|
|
110
|
+
const parsedValue = nonEmptyStringSchema.safeParse(value);
|
|
111
|
+
if (parsedValue.success) return parsedValue.data;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return "";
|
|
115
|
+
}
|
|
116
|
+
|
|
110
117
|
/**
|
|
111
118
|
* Try to resolve a module. Returns true if it can be imported.
|
|
112
119
|
*/
|
|
@@ -129,10 +136,14 @@ const RESOLVED_VIRTUAL_MODULE_ID = `\0${VIRTUAL_MODULE_ID}`;
|
|
|
129
136
|
* component overrides (Hero, ThemeToggle, EditLink), and optional Mermaid diagram
|
|
130
137
|
* support with branded color schemes.
|
|
131
138
|
*
|
|
139
|
+
* **Recommended:** Use {@link https://github.com/NUAppDev/northwestern-starlight-theme | defineNorthwesternConfig}
|
|
140
|
+
* from `@nu-appdev/northwestern-starlight-theme/config` instead. It handles
|
|
141
|
+
* integration ordering, Mermaid, and Expressive Code (line numbers, GitHub themes).
|
|
142
|
+
*
|
|
132
143
|
* @param config - Theme configuration. All properties optional.
|
|
133
144
|
* @returns A Starlight plugin to pass to `plugins` in your Starlight config.
|
|
134
145
|
*
|
|
135
|
-
* @example
|
|
146
|
+
* @example Manual setup
|
|
136
147
|
* ```ts
|
|
137
148
|
* starlight({ plugins: [northwesternTheme()] })
|
|
138
149
|
* ```
|
|
@@ -150,7 +161,11 @@ const RESOLVED_VIRTUAL_MODULE_ID = `\0${VIRTUAL_MODULE_ID}`;
|
|
|
150
161
|
* ```
|
|
151
162
|
*/
|
|
152
163
|
export default function northwesternTheme(config: NorthwesternThemeConfig = {}): StarlightPlugin {
|
|
153
|
-
const {
|
|
164
|
+
const {
|
|
165
|
+
homepage = {},
|
|
166
|
+
mermaid = true,
|
|
167
|
+
ogImage = true,
|
|
168
|
+
} = validateSchema(northwesternThemeConfigSchema, config, "theme config");
|
|
154
169
|
const themeConfig = {
|
|
155
170
|
homepage: {
|
|
156
171
|
layout: homepage.layout ?? "centered",
|
|
@@ -161,6 +176,7 @@ export default function northwesternTheme(config: NorthwesternThemeConfig = {}):
|
|
|
161
176
|
enabled: false, // set to true in config:setup when ogImage is enabled
|
|
162
177
|
siteTitle: "",
|
|
163
178
|
logoPath: "",
|
|
179
|
+
resvgWasmPath: "",
|
|
164
180
|
},
|
|
165
181
|
};
|
|
166
182
|
|
|
@@ -268,36 +284,18 @@ export default function northwesternTheme(config: NorthwesternThemeConfig = {}):
|
|
|
268
284
|
}
|
|
269
285
|
}
|
|
270
286
|
|
|
271
|
-
// OG image generation (bundled via
|
|
287
|
+
// OG image generation (bundled via satori + @resvg/resvg-wasm)
|
|
272
288
|
if (ogImage) {
|
|
273
|
-
|
|
274
|
-
// doesn't exist in ESM. Under pnpm's strict symlinks the binary
|
|
275
|
-
// can't be found unless the consumer installs canvaskit-wasm
|
|
276
|
-
// directly. Probe resolution from the consumer's project root
|
|
277
|
-
// (not the theme package) so a missing install skips OG
|
|
278
|
-
// gracefully instead of crashing the build.
|
|
279
|
-
let canvaskitUsable = true;
|
|
280
|
-
try {
|
|
281
|
-
const require = createRequire(join(process.cwd(), "package.json"));
|
|
282
|
-
require.resolve("canvaskit-wasm");
|
|
283
|
-
} catch {
|
|
284
|
-
canvaskitUsable = false;
|
|
285
|
-
}
|
|
289
|
+
const siteTitle = getSiteTitle(starlightConfig.title);
|
|
286
290
|
|
|
287
|
-
if (!
|
|
291
|
+
if (!siteTitle) {
|
|
288
292
|
logger.warn(
|
|
289
|
-
"
|
|
290
|
-
"
|
|
291
|
-
" The build will continue without OG images.",
|
|
293
|
+
"Open Graph image generation was disabled because Starlight `title` is empty.\n" +
|
|
294
|
+
" Set `title` in starlight({...}) so OG images and structured data have a site name.",
|
|
292
295
|
);
|
|
293
296
|
} else {
|
|
294
|
-
themeConfig.ogImage.enabled = true;
|
|
295
297
|
themeConfig.ogImage.logoPath = faviconPath;
|
|
296
|
-
|
|
297
|
-
themeConfig.ogImage.siteTitle =
|
|
298
|
-
typeof rawTitle === "string"
|
|
299
|
-
? rawTitle
|
|
300
|
-
: (Object.values(rawTitle as Record<string, string>)[0] ?? "");
|
|
298
|
+
themeConfig.ogImage.siteTitle = siteTitle;
|
|
301
299
|
|
|
302
300
|
addRouteMiddleware({
|
|
303
301
|
entrypoint: "@nu-appdev/northwestern-starlight-theme/src/og/route-middleware",
|
|
@@ -307,16 +305,29 @@ export default function northwesternTheme(config: NorthwesternThemeConfig = {}):
|
|
|
307
305
|
addIntegration({
|
|
308
306
|
name: "northwestern-theme-og-image",
|
|
309
307
|
hooks: {
|
|
310
|
-
"astro:config:setup": ({ injectRoute }) => {
|
|
308
|
+
"astro:config:setup": ({ config: astroConfig, injectRoute }) => {
|
|
309
|
+
if (!astroConfig.site) {
|
|
310
|
+
logger.warn(
|
|
311
|
+
"Open Graph image generation was disabled because `site` is not set.\n" +
|
|
312
|
+
" Set `site` in astro.config.ts to enable absolute OG image URLs.",
|
|
313
|
+
);
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
themeConfig.ogImage.enabled = true;
|
|
318
|
+
const require = createRequire(import.meta.url);
|
|
319
|
+
themeConfig.ogImage.resvgWasmPath = require.resolve(
|
|
320
|
+
"@resvg/resvg-wasm/index_bg.wasm",
|
|
321
|
+
);
|
|
322
|
+
|
|
311
323
|
injectRoute({
|
|
312
324
|
pattern: "/og/[...slug]",
|
|
313
325
|
entrypoint: "@nu-appdev/northwestern-starlight-theme/src/og/endpoint.ts",
|
|
314
326
|
});
|
|
327
|
+
logger.info("OG image generation enabled");
|
|
315
328
|
},
|
|
316
329
|
},
|
|
317
330
|
});
|
|
318
|
-
|
|
319
|
-
logger.info("OG image generation enabled");
|
|
320
331
|
}
|
|
321
332
|
}
|
|
322
333
|
|