@nu-appdev/northwestern-starlight-theme 1.1.1 → 1.3.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/CHANGELOG.md +73 -2
- package/index.ts +84 -5
- package/mermaid.ts +196 -80
- package/package.json +19 -4
- package/src/components/Expandable.astro +19 -0
- package/src/components/Glossary.astro +11 -0
- package/src/components/Hero.astro +0 -2
- package/src/components/Kbd.astro +147 -0
- package/src/components/Property.astro +64 -0
- package/src/components/PropertyGroup.astro +13 -0
- package/src/components/PropertyTable.astro +54 -0
- package/src/components/Term.astro +29 -0
- package/src/components/Tooltip.astro +138 -0
- package/src/components/glossary-store.ts +12 -0
- package/src/components/index.ts +8 -0
- package/src/rehype-table-scroll.ts +35 -0
- package/src/scripts/mermaid/focus.ts +100 -0
- package/src/scripts/mermaid/fullscreen.ts +120 -0
- package/src/scripts/mermaid/index.ts +2 -0
- package/src/scripts/mermaid/overlay.ts +132 -0
- package/src/scripts/mermaid/pan-zoom.ts +285 -0
- package/src/scripts/mermaid/render.ts +143 -0
- package/src/scripts/mermaid/toolbar.ts +137 -0
- package/src/scripts/mermaid/ui.ts +265 -0
- package/src/styles/a11y.css +69 -0
- package/src/styles/components/blockquotes.css +37 -0
- package/src/styles/components/code.css +8 -5
- package/src/styles/components/footnotes.css +76 -0
- package/src/styles/components/kbd.css +69 -0
- package/src/styles/components/mermaid.css +4 -4
- package/src/styles/components/property-table.css +569 -0
- package/src/styles/components/steps.css +0 -3
- package/src/styles/components/tables.css +60 -0
- package/src/styles/components/tabs.css +0 -3
- package/src/styles/components/tooltip.css +145 -0
- package/src/styles/content.css +9 -94
- package/src/styles/layers.css +0 -7
- package/src/styles/mermaid-toolbar.css +91 -14
- package/src/styles/navigation.css +72 -16
- package/src/styles/openapi.css +0 -3
- package/src/styles/theme.css +0 -4
- package/src/styles/typography.css +4 -0
- package/src/styles/variables.css +0 -3
- package/src/virtual.d.ts +11 -0
- package/src/scripts/mermaid-toolbar.ts +0 -589
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,75 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [1.3.0] - 2026-03-26
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **Property Table component suite**: `<PropertyTable>`, `<Property>`, `<PropertyGroup>`, `<Expandable>`.
|
|
15
|
+
- See the [documentation](https://starlight-theme.entapp.northwestern.edu/components/property-table) for more information.
|
|
16
|
+
- **Tooltip component suite**: `<Tooltip>`, `<Glossary>`, `<Term>`.
|
|
17
|
+
- See the [documentation](https://starlight-theme.entapp.northwestern.edu/components/tooltip) for more information.
|
|
18
|
+
- **Keyboard component**: `<Kbd>`.
|
|
19
|
+
- See the [documentation](https://starlight-theme.entapp.northwestern.edu/components/kbd) for more information.
|
|
20
|
+
- Fullscreen Mermaid overlay: scale animation, dot grid background, pan momentum on drag release, toast notifications on copy.
|
|
21
|
+
- `@media (prefers-contrast: more)`: heavier borders, system colors for focus rings.
|
|
22
|
+
- `@media (prefers-reduced-transparency: reduce)`: solid surfaces replace translucent backgrounds.
|
|
23
|
+
- `CONTRIBUTING.md` with development setup, conventions, and PR process.
|
|
24
|
+
- JSDoc comments on public TypeScript interfaces.
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
|
|
28
|
+
- Code block line numbers in dark mode had 2.85:1 contrast. Bumped from `#6e6e6e` to `#999` (4.6:1).
|
|
29
|
+
- Code block copy button icon in dark mode used `--nu-purple-100` on hover. Switched to `--nu-purple-40`.
|
|
30
|
+
- Wide tables overflowed into the sidebar. A [rehype](https://github.com/rehypejs/rehype) plugin now wraps each `<table>` in a scrollable `<div>` at build time.
|
|
31
|
+
- Reopening the fullscreen viewer after Escape showed a blue focus ring around the entire viewport.
|
|
32
|
+
- Mermaid hover toolbar sat unevenly relative to the diagram container border.
|
|
33
|
+
- Fullscreen close button used `rgb(255 255 255 / 20%)` while the theme toggle used `15%`. Both use `15%` now.
|
|
34
|
+
- Mobile sidebar: theme toggle and GitHub icon were white-on-white in light mode.
|
|
35
|
+
- Mobile sidebar: theme toggle was taller than wide; GitHub icon sat below it.
|
|
36
|
+
- Copy buttons did nothing on HTTP (insecure contexts). Added `document.execCommand("copy")` fallback.
|
|
37
|
+
- Clicking copy twice during the success animation duplicated the check icon. Debounced per button.
|
|
38
|
+
- iOS Safari toggled the URL bar when copying in the fullscreen viewer. The fallback textarea now appends inside the overlay.
|
|
39
|
+
- Mouse-opening the fullscreen viewer put a focus ring on the first control. Keyboard opens focus the first button; mouse opens focus the overlay container (no visible ring, Tab still works).
|
|
40
|
+
- Zoom in/out/reset buttons hidden on mobile (pinch-to-zoom covers it).
|
|
41
|
+
- Mermaid user overrides dropped on client-side theme toggle. Runtime configs now include merged user config.
|
|
42
|
+
- Mermaid lazy-rendered diagrams used stale theme after toggle. Observer callback now reads live theme mode.
|
|
43
|
+
- Mermaid pinch-to-zoom anchored to viewport center instead of pinch midpoint.
|
|
44
|
+
- Mermaid `MutationObservers` accumulated on view transitions. Previous observer now disconnected before creating a new one.
|
|
45
|
+
- Mermaid render race on rapid theme toggles. Per-container version tracking discards stale async completions.
|
|
46
|
+
- Mermaid fullscreen close could fire twice during animation. Added guard against double-close.
|
|
47
|
+
- Mermaid `diagramSources` `Map` leaked detached DOM nodes across view transitions. Switched to `WeakMap`.
|
|
48
|
+
- Tooltip event listeners duplicated on Astro view transitions. Added `WeakSet` idempotency guard.
|
|
49
|
+
- Tooltip Popover API called without feature detection. Added fallback for unsupported browsers.
|
|
50
|
+
- Tooltip positioning drifted on scroll. Now repositions via scroll listener while visible.
|
|
51
|
+
- Sidebar active item border shifted text. All sidebar links now reserve space with a transparent left border.
|
|
52
|
+
- Search modal focus ring used browser default blue. Now uses `--nu-focus-ring`.
|
|
53
|
+
- Site title clipped on mobile. Added fluid font sizing with `clamp()` and ellipsis overflow.
|
|
54
|
+
|
|
55
|
+
### Changed
|
|
56
|
+
|
|
57
|
+
- Fullscreen controls bar uses Starlight's `--sl-nav-pad-x` and `--sl-menu-button-size` so the close button aligns with the hamburger menu on mobile.
|
|
58
|
+
- Removed right padding on active sidebar headings that broke nested heading alignment.
|
|
59
|
+
|
|
60
|
+
## [1.2.0] - 2026-03-25
|
|
61
|
+
|
|
62
|
+
### Added
|
|
63
|
+
|
|
64
|
+
- Fullscreen Mermaid viewer: wheel zoom and double-click zoom anchor to the pointer position.
|
|
65
|
+
- Zoom level badge (e.g. `84%`) in the fullscreen viewer.
|
|
66
|
+
- GFM footnote styles: superscript `[n]` reference markers, footnotes section with separator, styled `↩︎` back-references.
|
|
67
|
+
|
|
68
|
+
### Fixed
|
|
69
|
+
|
|
70
|
+
- Mermaid diagrams sometimes breaking on Firefox and Safari. The toolbar script read `textContent` after `astro-mermaid` had already rendered SVG into the element. Reads `data-diagram` first now.
|
|
71
|
+
- Horizontal rules in dark mode used `--nu-purple-140`, which was invisible against the background. Switched to `--nu-border-color`.
|
|
72
|
+
|
|
73
|
+
### Accessibility
|
|
74
|
+
|
|
75
|
+
- Fullscreen Mermaid overlay: `role="dialog"`, `aria-modal`, focus trap, focus restore on close.
|
|
76
|
+
- White focus rings on overlay controls, theme toggle, and menu button (all sit on dark backgrounds where the purple ring was invisible).
|
|
77
|
+
- Inline Mermaid toolbar buttons use a solid accent outline on focus instead of the near-invisible shadow ring.
|
|
78
|
+
|
|
10
79
|
## [1.1.1] - 2026-03-25
|
|
11
80
|
|
|
12
81
|
### Fixed
|
|
@@ -21,7 +90,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
21
90
|
|
|
22
91
|
### Added
|
|
23
92
|
|
|
24
|
-
- Fullscreen
|
|
93
|
+
- Fullscreen Mermaid viewer supports touch: one-finger pan, pinch-to-zoom, two-finger pan.
|
|
25
94
|
- Mermaid toolbar stays visible on touch devices (`hover: none`) since hover is unavailable.
|
|
26
95
|
- SVG downloads use descriptive filenames derived from the site title, page slug, and diagram type (e.g., `northwestern-starlight-theme_examples-mermaid-flowchart.svg`).
|
|
27
96
|
|
|
@@ -52,7 +121,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
52
121
|
- OpenAPI plugin compatibility with method badge preservation
|
|
53
122
|
- Reduced motion support for transitions
|
|
54
123
|
|
|
55
|
-
[Unreleased]: https://github.com/NIT-Administrative-Systems/northwestern-starlight-theme/compare/v1.
|
|
124
|
+
[Unreleased]: https://github.com/NIT-Administrative-Systems/northwestern-starlight-theme/compare/v1.3.0...HEAD
|
|
125
|
+
[1.3.0]: https://github.com/NIT-Administrative-Systems/northwestern-starlight-theme/compare/v1.2.0...v1.3.0
|
|
126
|
+
[1.2.0]: https://github.com/NIT-Administrative-Systems/northwestern-starlight-theme/compare/v1.1.1...v1.2.0
|
|
56
127
|
[1.1.1]: https://github.com/NIT-Administrative-Systems/northwestern-starlight-theme/compare/v1.1.0...v1.1.1
|
|
57
128
|
[1.1.0]: https://github.com/NIT-Administrative-Systems/northwestern-starlight-theme/compare/v1.0.0...v1.1.0
|
|
58
129
|
[1.0.0]: https://github.com/NIT-Administrative-Systems/northwestern-starlight-theme/releases/tag/v1.0.0
|
package/index.ts
CHANGED
|
@@ -3,7 +3,25 @@ import type { IncomingMessage, ServerResponse } from "node:http";
|
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import type { StarlightPlugin } from "@astrojs/starlight/types";
|
|
6
|
+
import rehypeTableScroll from "./src/rehype-table-scroll.ts";
|
|
6
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Configuration for the homepage hero section.
|
|
10
|
+
*
|
|
11
|
+
* Controls hero layout, title visibility, and image sizing. Passed as the
|
|
12
|
+
* `homepage` property of {@link NorthwesternThemeConfig}.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* northwesternTheme({
|
|
17
|
+
* homepage: {
|
|
18
|
+
* layout: "split",
|
|
19
|
+
* showTitle: false,
|
|
20
|
+
* imageWidth: "750px",
|
|
21
|
+
* },
|
|
22
|
+
* })
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
7
25
|
export interface NorthwesternHomepageConfig {
|
|
8
26
|
/**
|
|
9
27
|
* Hero layout style.
|
|
@@ -32,19 +50,46 @@ export interface NorthwesternHomepageConfig {
|
|
|
32
50
|
imageWidth?: string;
|
|
33
51
|
}
|
|
34
52
|
|
|
53
|
+
/**
|
|
54
|
+
* Top-level configuration for the Northwestern Starlight theme plugin.
|
|
55
|
+
*
|
|
56
|
+
* Pass to {@link northwesternTheme} when registering the plugin in your
|
|
57
|
+
* Starlight config. All properties are optional and have sensible defaults.
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```ts
|
|
61
|
+
* // astro.config.ts
|
|
62
|
+
* import northwesternTheme from "@nu-appdev/northwestern-starlight-theme";
|
|
63
|
+
*
|
|
64
|
+
* export default defineConfig({
|
|
65
|
+
* integrations: [
|
|
66
|
+
* starlight({
|
|
67
|
+
* plugins: [northwesternTheme({ homepage: { layout: "split" } })],
|
|
68
|
+
* }),
|
|
69
|
+
* ],
|
|
70
|
+
* });
|
|
71
|
+
* ```
|
|
72
|
+
*
|
|
73
|
+
* @see {@link NorthwesternHomepageConfig} for homepage hero options
|
|
74
|
+
*/
|
|
35
75
|
export interface NorthwesternThemeConfig {
|
|
36
76
|
/**
|
|
37
77
|
* Homepage hero layout configuration.
|
|
78
|
+
*
|
|
79
|
+
* @see {@link NorthwesternHomepageConfig}
|
|
38
80
|
*/
|
|
39
81
|
homepage?: NorthwesternHomepageConfig;
|
|
40
82
|
|
|
41
83
|
/**
|
|
42
84
|
* Mermaid diagram support.
|
|
43
85
|
*
|
|
44
|
-
* - `true` (default) — auto-detect: enables
|
|
86
|
+
* - `true` (default) — auto-detect: enables Mermaid if `astro-mermaid` and `mermaid`
|
|
45
87
|
* are installed, skips silently if they are not
|
|
46
|
-
* - `false` — disables
|
|
47
|
-
* - `object` — enables
|
|
88
|
+
* - `false` — disables Mermaid entirely
|
|
89
|
+
* - `object` — enables Mermaid with custom {@link https://mermaid.js.org/config/schema-docs/config.html | MermaidConfig}
|
|
90
|
+
* merged with Northwestern defaults
|
|
91
|
+
*
|
|
92
|
+
* @default true
|
|
48
93
|
*/
|
|
49
94
|
mermaid?: boolean | Record<string, unknown>;
|
|
50
95
|
}
|
|
@@ -64,6 +109,33 @@ async function canResolve(id: string): Promise<boolean> {
|
|
|
64
109
|
const VIRTUAL_MODULE_ID = "virtual:northwestern-theme/config";
|
|
65
110
|
const RESOLVED_VIRTUAL_MODULE_ID = `\0${VIRTUAL_MODULE_ID}`;
|
|
66
111
|
|
|
112
|
+
/**
|
|
113
|
+
* Create a Northwestern-branded Starlight theme plugin.
|
|
114
|
+
*
|
|
115
|
+
* Registers Northwestern typography (Akkurat Pro, Poppins), purple color palette,
|
|
116
|
+
* component overrides (Hero, ThemeToggle, EditLink), and optional Mermaid diagram
|
|
117
|
+
* support with branded color schemes.
|
|
118
|
+
*
|
|
119
|
+
* @param config - Theme configuration. All properties optional.
|
|
120
|
+
* @returns A Starlight plugin to pass to `plugins` in your Starlight config.
|
|
121
|
+
*
|
|
122
|
+
* @example Basic usage (all defaults)
|
|
123
|
+
* ```ts
|
|
124
|
+
* starlight({ plugins: [northwesternTheme()] })
|
|
125
|
+
* ```
|
|
126
|
+
*
|
|
127
|
+
* @example Split hero with Mermaid disabled
|
|
128
|
+
* ```ts
|
|
129
|
+
* starlight({
|
|
130
|
+
* plugins: [
|
|
131
|
+
* northwesternTheme({
|
|
132
|
+
* homepage: { layout: "split", showTitle: false },
|
|
133
|
+
* mermaid: false,
|
|
134
|
+
* }),
|
|
135
|
+
* ],
|
|
136
|
+
* })
|
|
137
|
+
* ```
|
|
138
|
+
*/
|
|
67
139
|
export default function northwesternTheme(config: NorthwesternThemeConfig = {}): StarlightPlugin {
|
|
68
140
|
const { homepage = {}, mermaid = true } = config;
|
|
69
141
|
const themeConfig = {
|
|
@@ -92,6 +164,9 @@ export default function northwesternTheme(config: NorthwesternThemeConfig = {}):
|
|
|
92
164
|
hooks: {
|
|
93
165
|
"astro:config:setup": ({ updateConfig: updateAstroConfig }) => {
|
|
94
166
|
updateAstroConfig({
|
|
167
|
+
markdown: {
|
|
168
|
+
rehypePlugins: [rehypeTableScroll],
|
|
169
|
+
},
|
|
95
170
|
vite: {
|
|
96
171
|
plugins: [
|
|
97
172
|
{
|
|
@@ -151,7 +226,7 @@ export default function northwesternTheme(config: NorthwesternThemeConfig = {}):
|
|
|
151
226
|
},
|
|
152
227
|
},
|
|
153
228
|
});
|
|
154
|
-
// Detect
|
|
229
|
+
// Detect Mermaid availability
|
|
155
230
|
let mermaidEnabled = mermaid;
|
|
156
231
|
|
|
157
232
|
if (mermaidEnabled) {
|
|
@@ -159,7 +234,7 @@ export default function northwesternTheme(config: NorthwesternThemeConfig = {}):
|
|
|
159
234
|
|
|
160
235
|
if (!hasMermaid) {
|
|
161
236
|
if (typeof mermaid === "object") {
|
|
162
|
-
// User explicitly configured
|
|
237
|
+
// User explicitly configured Mermaid but it's not installed
|
|
163
238
|
logger.warn(
|
|
164
239
|
'Mermaid config was provided but "astro-mermaid" and "mermaid" are not installed.\n' +
|
|
165
240
|
" Run: pnpm add astro-mermaid mermaid",
|
|
@@ -190,6 +265,9 @@ export default function northwesternTheme(config: NorthwesternThemeConfig = {}):
|
|
|
190
265
|
"@nu-appdev/northwestern-starlight-theme/src/styles/theme.css",
|
|
191
266
|
"@nu-appdev/northwestern-starlight-theme/src/styles/navigation.css",
|
|
192
267
|
"@nu-appdev/northwestern-starlight-theme/src/styles/content.css",
|
|
268
|
+
"@nu-appdev/northwestern-starlight-theme/src/styles/components/blockquotes.css",
|
|
269
|
+
"@nu-appdev/northwestern-starlight-theme/src/styles/components/footnotes.css",
|
|
270
|
+
"@nu-appdev/northwestern-starlight-theme/src/styles/components/tables.css",
|
|
193
271
|
"@nu-appdev/northwestern-starlight-theme/src/styles/components/cards.css",
|
|
194
272
|
"@nu-appdev/northwestern-starlight-theme/src/styles/components/utility-surfaces.css",
|
|
195
273
|
"@nu-appdev/northwestern-starlight-theme/src/styles/components/steps.css",
|
|
@@ -198,6 +276,7 @@ export default function northwesternTheme(config: NorthwesternThemeConfig = {}):
|
|
|
198
276
|
"@nu-appdev/northwestern-starlight-theme/src/styles/components/mermaid.css",
|
|
199
277
|
"@nu-appdev/northwestern-starlight-theme/src/styles/mermaid-toolbar.css",
|
|
200
278
|
"@nu-appdev/northwestern-starlight-theme/src/styles/openapi.css",
|
|
279
|
+
"@nu-appdev/northwestern-starlight-theme/src/styles/a11y.css",
|
|
201
280
|
...(starlightConfig.customCss ?? []),
|
|
202
281
|
],
|
|
203
282
|
expressiveCode: {
|
package/mermaid.ts
CHANGED
|
@@ -2,14 +2,41 @@ import type { AstroIntegration } from "astro";
|
|
|
2
2
|
import mermaid, { type AstroMermaidOptions } from "astro-mermaid";
|
|
3
3
|
import { darken, isDark, lighten, mix, transparentize } from "khroma";
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Configuration options for the Northwestern Mermaid integration.
|
|
7
|
+
*
|
|
8
|
+
* Extends `astro-mermaid` options with a `toolbar` toggle that controls
|
|
9
|
+
* the hover toolbar (fullscreen, download, copy) on rendered diagrams.
|
|
10
|
+
*
|
|
11
|
+
* @see {@link northwesternMermaid} for the integration factory
|
|
12
|
+
*/
|
|
5
13
|
export interface NorthwesternMermaidOptions extends AstroMermaidOptions {
|
|
14
|
+
/**
|
|
15
|
+
* Show the hover toolbar (fullscreen, download SVG, copy source) on diagrams.
|
|
16
|
+
*
|
|
17
|
+
* @default true
|
|
18
|
+
*/
|
|
6
19
|
toolbar?: boolean;
|
|
7
20
|
}
|
|
8
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Theme mode for Mermaid color palette generation.
|
|
24
|
+
*
|
|
25
|
+
* Maps to the `data-theme` attribute on `<html>`: `"light"` for the default
|
|
26
|
+
* palette, `"dark"` for the inverted palette with lighter primary colors
|
|
27
|
+
* and darker canvas backgrounds.
|
|
28
|
+
*/
|
|
9
29
|
export type NorthwesternMermaidMode = "light" | "dark";
|
|
10
30
|
|
|
31
|
+
/** Flat key-value map passed to Mermaid's `themeVariables`. */
|
|
11
32
|
type ThemeVariables = Record<string, unknown>;
|
|
12
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Resolved brand palette for a single theme mode.
|
|
36
|
+
*
|
|
37
|
+
* All values are hex strings. Derived from Northwestern's brand primaries
|
|
38
|
+
* with light/dark adjustments via `khroma`.
|
|
39
|
+
*/
|
|
13
40
|
type BrandPalette = {
|
|
14
41
|
purple: string;
|
|
15
42
|
blue: string;
|
|
@@ -31,6 +58,15 @@ type BrandPalette = {
|
|
|
31
58
|
|
|
32
59
|
const chartPalette = ["#4e2a84", "#836eaa", "#5091cd", "#008656", "#ffc520", "#ef553f", "#7fcecd", "#d85820"];
|
|
33
60
|
|
|
61
|
+
/** Generate `{ prefix0: fn(0), prefix1: fn(1), ... }` from an array. */
|
|
62
|
+
function indexedVars(prefix: string, values: string[], startAt = 0): ThemeVariables {
|
|
63
|
+
const out: ThemeVariables = {};
|
|
64
|
+
for (let i = 0; i < values.length; i++) {
|
|
65
|
+
out[`${prefix}${i + startAt}`] = values[i];
|
|
66
|
+
}
|
|
67
|
+
return out;
|
|
68
|
+
}
|
|
69
|
+
|
|
34
70
|
function onColor(color: string, darkText = "#342f2e", lightText = "#fff") {
|
|
35
71
|
return isDark(color) ? lightText : darkText;
|
|
36
72
|
}
|
|
@@ -216,32 +252,16 @@ function createThemeVariables(mode: NorthwesternMermaidMode): ThemeVariables {
|
|
|
216
252
|
altSectionBkgColor: rowEven,
|
|
217
253
|
sectionBkgColor2: compositeAltBackground,
|
|
218
254
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
git6: chartPalette[6],
|
|
226
|
-
git7: chartPalette[7],
|
|
227
|
-
gitBranchLabel0: onColor(chartPalette[0]),
|
|
228
|
-
gitBranchLabel1: onColor(chartPalette[1]),
|
|
229
|
-
gitBranchLabel2: onColor(chartPalette[2]),
|
|
230
|
-
gitBranchLabel3: onColor(chartPalette[3]),
|
|
231
|
-
gitBranchLabel4: onColor(chartPalette[4]),
|
|
232
|
-
gitBranchLabel5: onColor(chartPalette[5]),
|
|
233
|
-
gitBranchLabel6: onColor(chartPalette[6]),
|
|
234
|
-
gitBranchLabel7: onColor(chartPalette[7]),
|
|
255
|
+
// Git graph — one color per branch from the chart palette
|
|
256
|
+
...indexedVars("git", chartPalette),
|
|
257
|
+
...indexedVars(
|
|
258
|
+
"gitBranchLabel",
|
|
259
|
+
chartPalette.map((c) => onColor(c)),
|
|
260
|
+
),
|
|
235
261
|
gitInv0: palette.white,
|
|
236
262
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
pie3: chartPalette[2],
|
|
240
|
-
pie4: chartPalette[3],
|
|
241
|
-
pie5: chartPalette[4],
|
|
242
|
-
pie6: chartPalette[5],
|
|
243
|
-
pie7: chartPalette[6],
|
|
244
|
-
pie8: chartPalette[7],
|
|
263
|
+
// Pie chart — 8 base slices + 4 extended with tint shift
|
|
264
|
+
...indexedVars("pie", chartPalette, 1),
|
|
245
265
|
pie9: dark ? lighten(chartPalette[0], 16) : darken(chartPalette[0], 10),
|
|
246
266
|
pie10: dark ? lighten(chartPalette[2], 16) : darken(chartPalette[2], 10),
|
|
247
267
|
pie11: dark ? lighten(chartPalette[3], 16) : darken(chartPalette[3], 10),
|
|
@@ -255,35 +275,64 @@ function createThemeVariables(mode: NorthwesternMermaidMode): ThemeVariables {
|
|
|
255
275
|
pieLegendTextSize: "14px",
|
|
256
276
|
pieStrokeWidth: "2px",
|
|
257
277
|
pieOuterStrokeWidth: "1px",
|
|
258
|
-
pieOuterStrokeColor:
|
|
278
|
+
pieOuterStrokeColor: palette.border,
|
|
259
279
|
pieOpacity: "0.85",
|
|
260
280
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
281
|
+
// C4/journey scale — each color mixed toward canvas in dark mode
|
|
282
|
+
...(() => {
|
|
283
|
+
const colors = [
|
|
284
|
+
primary,
|
|
285
|
+
palette.blue,
|
|
286
|
+
palette.green,
|
|
287
|
+
palette.orange,
|
|
288
|
+
palette.teal,
|
|
289
|
+
palette.yellow,
|
|
290
|
+
palette.red,
|
|
291
|
+
primary,
|
|
292
|
+
];
|
|
293
|
+
const darkMix = [40, 40, 40, 35, 35, 30, 35, 30];
|
|
294
|
+
const lightFallback = [
|
|
295
|
+
primary,
|
|
296
|
+
palette.blue,
|
|
297
|
+
palette.green,
|
|
298
|
+
palette.orange,
|
|
299
|
+
darken(palette.teal, 15),
|
|
300
|
+
darken(palette.yellow, 20),
|
|
301
|
+
palette.red,
|
|
302
|
+
lighten(primary, 10),
|
|
303
|
+
];
|
|
304
|
+
return indexedVars(
|
|
305
|
+
"cScale",
|
|
306
|
+
colors.map((c, i) => (dark ? mix(c, palette.canvas, darkMix[i]) : lightFallback[i])),
|
|
307
|
+
);
|
|
308
|
+
})(),
|
|
309
|
+
...indexedVars("cScaleLabel", [
|
|
310
|
+
palette.white,
|
|
311
|
+
palette.white,
|
|
312
|
+
palette.white,
|
|
313
|
+
palette.white,
|
|
314
|
+
dark ? palette.white : palette.black,
|
|
315
|
+
palette.black,
|
|
316
|
+
palette.white,
|
|
317
|
+
palette.white,
|
|
318
|
+
]),
|
|
319
|
+
|
|
320
|
+
// Quadrant chart — progressive primary tints
|
|
321
|
+
...(() => {
|
|
322
|
+
const darkRatios = [35, 28, 22, 15];
|
|
323
|
+
const lightRatios = [25, 18, 12, 8];
|
|
324
|
+
const fills = darkRatios.map((dr, i) =>
|
|
325
|
+
dark ? mix(primary, palette.canvas, dr) : mix(primary, palette.white, lightRatios[i]),
|
|
326
|
+
);
|
|
327
|
+
return {
|
|
328
|
+
...indexedVars("quadrantFill", fills, 1),
|
|
329
|
+
...indexedVars(
|
|
330
|
+
"quadrantTextFill",
|
|
331
|
+
fills.map((f) => onColor(f)),
|
|
332
|
+
1,
|
|
333
|
+
),
|
|
334
|
+
};
|
|
335
|
+
})(),
|
|
287
336
|
quadrantPointFill: primary,
|
|
288
337
|
quadrantPointTextFill: dark ? palette.white : palette.black,
|
|
289
338
|
quadrantXAxisTextFill: palette.text,
|
|
@@ -294,17 +343,36 @@ function createThemeVariables(mode: NorthwesternMermaidMode): ThemeVariables {
|
|
|
294
343
|
|
|
295
344
|
xyChart: {
|
|
296
345
|
plotColorPalette: chartPalette.join(","),
|
|
297
|
-
titleColor:
|
|
298
|
-
xAxisLabelColor:
|
|
299
|
-
yAxisLabelColor:
|
|
300
|
-
xAxisTitleColor:
|
|
301
|
-
yAxisTitleColor:
|
|
302
|
-
xAxisLineColor: "#ccc",
|
|
303
|
-
yAxisLineColor: "#ccc",
|
|
346
|
+
titleColor: palette.text,
|
|
347
|
+
xAxisLabelColor: palette.text,
|
|
348
|
+
yAxisLabelColor: palette.text,
|
|
349
|
+
xAxisTitleColor: palette.text,
|
|
350
|
+
yAxisTitleColor: palette.text,
|
|
351
|
+
xAxisLineColor: dark ? palette.border : "#ccc",
|
|
352
|
+
yAxisLineColor: dark ? palette.border : "#ccc",
|
|
304
353
|
},
|
|
305
354
|
};
|
|
306
355
|
}
|
|
307
356
|
|
|
357
|
+
/**
|
|
358
|
+
* Generate a complete `astro-mermaid` config with Northwestern-branded colors
|
|
359
|
+
* for the given theme mode.
|
|
360
|
+
*
|
|
361
|
+
* Builds a Mermaid `themeVariables` object from the Northwestern brand palette,
|
|
362
|
+
* deriving all node, edge, label, chart, and diagram-specific colors from a
|
|
363
|
+
* small set of brand primaries via `khroma` color manipulation.
|
|
364
|
+
*
|
|
365
|
+
* @param mode - `"light"` or `"dark"`. Controls canvas, text, and primary color values.
|
|
366
|
+
* @returns A complete `AstroMermaidOptions` object ready to pass to `astro-mermaid`.
|
|
367
|
+
*
|
|
368
|
+
* @example
|
|
369
|
+
* ```ts
|
|
370
|
+
* import { createNorthwesternMermaidConfig } from "@nu-appdev/northwestern-starlight-theme/mermaid";
|
|
371
|
+
*
|
|
372
|
+
* const darkConfig = createNorthwesternMermaidConfig("dark");
|
|
373
|
+
* // darkConfig.mermaidConfig.themeVariables contains all colors
|
|
374
|
+
* ```
|
|
375
|
+
*/
|
|
308
376
|
export function createNorthwesternMermaidConfig(mode: NorthwesternMermaidMode): AstroMermaidOptions {
|
|
309
377
|
const palette = createPalette(mode);
|
|
310
378
|
return {
|
|
@@ -314,45 +382,93 @@ export function createNorthwesternMermaidConfig(mode: NorthwesternMermaidMode):
|
|
|
314
382
|
themeVariables: createThemeVariables(mode),
|
|
315
383
|
xyChart: {
|
|
316
384
|
plotColorPalette: chartPalette.join(","),
|
|
317
|
-
titleColor:
|
|
318
|
-
xAxisLabelColor:
|
|
319
|
-
yAxisLabelColor:
|
|
320
|
-
xAxisTitleColor:
|
|
321
|
-
yAxisTitleColor:
|
|
322
|
-
xAxisLineColor: "#ccc",
|
|
323
|
-
yAxisLineColor: "#ccc",
|
|
385
|
+
titleColor: palette.text,
|
|
386
|
+
xAxisLabelColor: palette.text,
|
|
387
|
+
yAxisLabelColor: palette.text,
|
|
388
|
+
xAxisTitleColor: palette.text,
|
|
389
|
+
yAxisTitleColor: palette.text,
|
|
390
|
+
xAxisLineColor: mode === "dark" ? palette.border : "#ccc",
|
|
391
|
+
yAxisLineColor: mode === "dark" ? palette.border : "#ccc",
|
|
324
392
|
},
|
|
325
393
|
},
|
|
326
394
|
};
|
|
327
395
|
}
|
|
328
396
|
|
|
329
397
|
/**
|
|
330
|
-
*
|
|
398
|
+
* Pre-built light-mode Mermaid config with Northwestern brand colors.
|
|
331
399
|
*
|
|
332
|
-
*
|
|
333
|
-
*
|
|
334
|
-
*
|
|
400
|
+
* Used as the default when Mermaid is auto-detected. Override individual
|
|
401
|
+
* `themeVariables` by passing a `mermaid` object to {@link northwesternTheme}
|
|
402
|
+
* in `index.ts`, or use {@link createNorthwesternMermaidConfig} for full control.
|
|
335
403
|
*/
|
|
336
404
|
export const defaultMermaidConfig: AstroMermaidOptions = createNorthwesternMermaidConfig("light");
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Pre-built dark-mode Mermaid config with Northwestern brand colors.
|
|
408
|
+
*
|
|
409
|
+
* Applied at runtime when the user switches to dark mode. The toolbar script
|
|
410
|
+
* re-renders diagrams with this config via `window.__NU_MERMAID_CONFIGS__.dark`.
|
|
411
|
+
*/
|
|
337
412
|
export const darkMermaidConfig: AstroMermaidOptions = createNorthwesternMermaidConfig("dark");
|
|
338
413
|
|
|
414
|
+
/**
|
|
415
|
+
* Create an Astro integration that registers Northwestern-branded Mermaid diagrams.
|
|
416
|
+
*
|
|
417
|
+
* Wraps `astro-mermaid` with Northwestern color palettes for both light and dark
|
|
418
|
+
* modes, and injects the toolbar script (fullscreen viewer, download, copy).
|
|
419
|
+
*
|
|
420
|
+
* **Must be added before `starlight()` in the `integrations` array.** The
|
|
421
|
+
* `astro-mermaid` remark plugin needs to register before Starlight's rehype
|
|
422
|
+
* processing, and Astro processes integrations in order. Placing it after
|
|
423
|
+
* `starlight()` causes Mermaid code blocks to be treated as plain code.
|
|
424
|
+
*
|
|
425
|
+
* @param options - Merged with Northwestern defaults. Set `toolbar: false` to
|
|
426
|
+
* disable the hover toolbar.
|
|
427
|
+
* @returns An Astro integration to add to `integrations` in your Astro config.
|
|
428
|
+
*
|
|
429
|
+
* @example
|
|
430
|
+
* ```ts
|
|
431
|
+
* import { northwesternMermaid } from "@nu-appdev/northwestern-starlight-theme/mermaid";
|
|
432
|
+
* import northwesternTheme from "@nu-appdev/northwestern-starlight-theme";
|
|
433
|
+
*
|
|
434
|
+
* export default defineConfig({
|
|
435
|
+
* integrations: [
|
|
436
|
+
* northwesternMermaid(), // Must come before starlight()
|
|
437
|
+
* starlight({
|
|
438
|
+
* plugins: [northwesternTheme()],
|
|
439
|
+
* title: "My Docs",
|
|
440
|
+
* }),
|
|
441
|
+
* ],
|
|
442
|
+
* });
|
|
443
|
+
* ```
|
|
444
|
+
*/
|
|
339
445
|
export function northwesternMermaid(options: NorthwesternMermaidOptions = {}): AstroIntegration {
|
|
340
446
|
const { toolbar = true, ...overrides } = options;
|
|
341
447
|
const lightConfig = createNorthwesternMermaidConfig("light");
|
|
342
448
|
const darkConfig = createNorthwesternMermaidConfig("dark");
|
|
343
449
|
|
|
450
|
+
const userMermaidConfig = overrides.mermaidConfig ?? {};
|
|
451
|
+
const userThemeVars = (userMermaidConfig as Record<string, unknown>)?.themeVariables ?? {};
|
|
452
|
+
|
|
453
|
+
function mergeWithOverrides(base: Record<string, unknown>): Record<string, unknown> {
|
|
454
|
+
return {
|
|
455
|
+
...base,
|
|
456
|
+
...userMermaidConfig,
|
|
457
|
+
themeVariables: {
|
|
458
|
+
...(base.themeVariables ?? {}),
|
|
459
|
+
...userThemeVars,
|
|
460
|
+
},
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
const mergedLightMermaidConfig = mergeWithOverrides(lightConfig.mermaidConfig as Record<string, unknown>);
|
|
465
|
+
const mergedDarkMermaidConfig = mergeWithOverrides(darkConfig.mermaidConfig as Record<string, unknown>);
|
|
466
|
+
|
|
344
467
|
const mermaidIntegration = mermaid({
|
|
345
468
|
...lightConfig,
|
|
346
469
|
...overrides,
|
|
347
470
|
enableLog: false,
|
|
348
|
-
mermaidConfig:
|
|
349
|
-
...(lightConfig.mermaidConfig ?? {}),
|
|
350
|
-
...(overrides.mermaidConfig ?? {}),
|
|
351
|
-
themeVariables: {
|
|
352
|
-
...((lightConfig.mermaidConfig as Record<string, unknown>)?.themeVariables ?? {}),
|
|
353
|
-
...((overrides.mermaidConfig as Record<string, unknown>)?.themeVariables ?? {}),
|
|
354
|
-
},
|
|
355
|
-
},
|
|
471
|
+
mermaidConfig: mergedLightMermaidConfig,
|
|
356
472
|
});
|
|
357
473
|
|
|
358
474
|
return {
|
|
@@ -365,10 +481,10 @@ export function northwesternMermaid(options: NorthwesternMermaidOptions = {}): A
|
|
|
365
481
|
"page",
|
|
366
482
|
`window.__NU_MERMAID_TOOLBAR__ = ${toolbar ? "true" : "false"}; window.__NU_MERMAID_CONFIGS__ = ${JSON.stringify(
|
|
367
483
|
{
|
|
368
|
-
light:
|
|
369
|
-
dark:
|
|
484
|
+
light: mergedLightMermaidConfig,
|
|
485
|
+
dark: mergedDarkMermaidConfig,
|
|
370
486
|
},
|
|
371
|
-
)}; import "@nu-appdev/northwestern-starlight-theme/src/scripts/mermaid
|
|
487
|
+
)}; import "@nu-appdev/northwestern-starlight-theme/src/scripts/mermaid/toolbar.ts";`,
|
|
372
488
|
);
|
|
373
489
|
},
|
|
374
490
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nu-appdev/northwestern-starlight-theme",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "A Northwestern-branded theme for Astro Starlight",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Danny Foster <danny@northwestern.edu>",
|
|
@@ -27,9 +27,21 @@
|
|
|
27
27
|
"provenance": true
|
|
28
28
|
},
|
|
29
29
|
"exports": {
|
|
30
|
-
".":
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
".": {
|
|
31
|
+
"types": "./index.ts",
|
|
32
|
+
"import": "./index.ts"
|
|
33
|
+
},
|
|
34
|
+
"./expressive-code": {
|
|
35
|
+
"import": "./expressive-code.mjs"
|
|
36
|
+
},
|
|
37
|
+
"./mermaid": {
|
|
38
|
+
"types": "./mermaid.ts",
|
|
39
|
+
"import": "./mermaid.ts"
|
|
40
|
+
},
|
|
41
|
+
"./components": {
|
|
42
|
+
"types": "./src/components/index.ts",
|
|
43
|
+
"import": "./src/components/index.ts"
|
|
44
|
+
},
|
|
33
45
|
"./src/styles/components/*": "./src/styles/components/*",
|
|
34
46
|
"./src/components/*": "./src/components/*",
|
|
35
47
|
"./src/scripts/*": "./src/scripts/*",
|
|
@@ -59,5 +71,8 @@
|
|
|
59
71
|
"mermaid": {
|
|
60
72
|
"optional": true
|
|
61
73
|
}
|
|
74
|
+
},
|
|
75
|
+
"devDependencies": {
|
|
76
|
+
"@types/hast": "^3.0.4"
|
|
62
77
|
}
|
|
63
78
|
}
|