@nu-appdev/northwestern-starlight-theme 1.3.1 → 1.4.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 +26 -1
- package/index.ts +78 -2
- package/package.json +3 -1
- package/src/components/Hero.astro +1 -0
- package/src/og/endpoint.ts +53 -0
- package/src/og/route-middleware.ts +125 -0
- package/src/styles/components/blockquotes.css +2 -1
- package/src/styles/components/property-table.css +1 -0
- package/src/styles/components/tables.css +21 -15
- package/src/styles/content.css +9 -3
- package/src/styles/typography.css +78 -7
- package/src/styles/variables.css +6 -6
- package/src/virtual.d.ts +5 -0
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [1.4.0] - 2026-03-31
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **Open Graph image generation**: builds a branded 1200x630 PNG per docs page. Favicon logo, page title, and description on Northwestern purple with a light purple accent border. Slack, Teams, and social media link previews use these images.
|
|
15
|
+
- Enabled by default. Set `site` in your Astro config. pnpm users: run `pnpm add canvaskit-wasm` to enable (build skips OG gracefully without it).
|
|
16
|
+
- Disable with `ogImage: false`.
|
|
17
|
+
- Adds `og:image`, `og:image:type`, `og:image:width`, `og:image:height`, `og:image:alt`, `og:logo`, `twitter:image`, and `twitter:image:alt` meta tags to every page. Overrides `twitter:card` to `summary_large_image`.
|
|
18
|
+
- New dependency: `astro-og-canvas`.
|
|
19
|
+
|
|
20
|
+
## [1.3.2] - 2026-03-30
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
|
|
24
|
+
- H1/H2 now use Noto Serif (`--nu-font-display`), H3–H6 use Poppins (`--nu-font-heading`). Sizes, weights, and colors match the [Department 4.0 stylesheet](https://common.northwestern.edu/dept/4.0/css/styles.css).
|
|
25
|
+
- Poppins 400 loaded the Light file instead of Regular. Poppins 500 (Medium) added from v4 CDN.
|
|
26
|
+
- Table headers now use `--nu-purple-100` with white text.
|
|
27
|
+
- Table striping moved to odd rows (`#f9f6ff`); dark mode uses `rgb(78 42 132 / 10%)`.
|
|
28
|
+
- `--nu-purple-surface` corrected to `#f9f6ff`, `--nu-purple-surface-subtle` to `#f3f0f7`.
|
|
29
|
+
- Blockquote background uses `#f9f6ff` instead of translucent purple.
|
|
30
|
+
- Horizontal rules use 3px `--nu-purple-10` instead of 1px gray.
|
|
31
|
+
- List markers use `--nu-purple-100` instead of `--nu-purple-40`.
|
|
32
|
+
|
|
10
33
|
## [1.3.1] - 2026-03-27
|
|
11
34
|
|
|
12
35
|
### Fixed
|
|
@@ -130,7 +153,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
130
153
|
- OpenAPI plugin compatibility with method badge preservation
|
|
131
154
|
- Reduced motion support for transitions
|
|
132
155
|
|
|
133
|
-
[Unreleased]: https://github.com/NIT-Administrative-Systems/northwestern-starlight-theme/compare/v1.
|
|
156
|
+
[Unreleased]: https://github.com/NIT-Administrative-Systems/northwestern-starlight-theme/compare/v1.4.0...HEAD
|
|
157
|
+
[1.4.0]: https://github.com/NIT-Administrative-Systems/northwestern-starlight-theme/compare/v1.3.2...v1.4.0
|
|
158
|
+
[1.3.2]: https://github.com/NIT-Administrative-Systems/northwestern-starlight-theme/compare/v1.3.1...v1.3.2
|
|
134
159
|
[1.3.1]: https://github.com/NIT-Administrative-Systems/northwestern-starlight-theme/compare/v1.3.0...v1.3.1
|
|
135
160
|
[1.3.0]: https://github.com/NIT-Administrative-Systems/northwestern-starlight-theme/compare/v1.2.0...v1.3.0
|
|
136
161
|
[1.2.0]: https://github.com/NIT-Administrative-Systems/northwestern-starlight-theme/compare/v1.1.1...v1.2.0
|
package/index.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { copyFileSync, mkdirSync, readFileSync } from "node:fs";
|
|
2
2
|
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
3
|
+
import { createRequire } from "node:module";
|
|
3
4
|
import { dirname, join } from "node:path";
|
|
4
5
|
import { fileURLToPath } from "node:url";
|
|
5
6
|
import type { StarlightPlugin } from "@astrojs/starlight/types";
|
|
@@ -92,6 +93,18 @@ export interface NorthwesternThemeConfig {
|
|
|
92
93
|
* @default true
|
|
93
94
|
*/
|
|
94
95
|
mermaid?: boolean | Record<string, unknown>;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Open Graph image generation.
|
|
99
|
+
*
|
|
100
|
+
* Generates branded OG images (1200x630 PNG) for every docs page with the
|
|
101
|
+
* page title and description on a Northwestern purple background.
|
|
102
|
+
*
|
|
103
|
+
* Requires `site` to be set in `astro.config.ts` for absolute image URLs.
|
|
104
|
+
*
|
|
105
|
+
* @default true
|
|
106
|
+
*/
|
|
107
|
+
ogImage?: boolean;
|
|
95
108
|
}
|
|
96
109
|
|
|
97
110
|
/**
|
|
@@ -137,19 +150,30 @@ const RESOLVED_VIRTUAL_MODULE_ID = `\0${VIRTUAL_MODULE_ID}`;
|
|
|
137
150
|
* ```
|
|
138
151
|
*/
|
|
139
152
|
export default function northwesternTheme(config: NorthwesternThemeConfig = {}): StarlightPlugin {
|
|
140
|
-
const { homepage = {}, mermaid = true } = config;
|
|
153
|
+
const { homepage = {}, mermaid = true, ogImage = true } = config;
|
|
141
154
|
const themeConfig = {
|
|
142
155
|
homepage: {
|
|
143
156
|
layout: homepage.layout ?? "centered",
|
|
144
157
|
showTitle: homepage.showTitle ?? true,
|
|
145
158
|
imageWidth: homepage.imageWidth ?? "500px",
|
|
146
159
|
},
|
|
160
|
+
ogImage: {
|
|
161
|
+
enabled: false, // set to true in config:setup when ogImage is enabled
|
|
162
|
+
siteTitle: "",
|
|
163
|
+
logoPath: "",
|
|
164
|
+
},
|
|
147
165
|
};
|
|
148
166
|
|
|
149
167
|
return {
|
|
150
168
|
name: "northwestern-starlight-theme",
|
|
151
169
|
hooks: {
|
|
152
|
-
async "config:setup"({
|
|
170
|
+
async "config:setup"({
|
|
171
|
+
config: starlightConfig,
|
|
172
|
+
updateConfig,
|
|
173
|
+
addIntegration,
|
|
174
|
+
addRouteMiddleware,
|
|
175
|
+
logger,
|
|
176
|
+
}) {
|
|
153
177
|
// Apply default favicon if consumer hasn't set one
|
|
154
178
|
const consumerSetFavicon =
|
|
155
179
|
starlightConfig.favicon &&
|
|
@@ -244,6 +268,58 @@ export default function northwesternTheme(config: NorthwesternThemeConfig = {}):
|
|
|
244
268
|
}
|
|
245
269
|
}
|
|
246
270
|
|
|
271
|
+
// OG image generation (bundled via astro-og-canvas)
|
|
272
|
+
if (ogImage) {
|
|
273
|
+
// canvaskit-wasm uses __dirname to locate its WASM binary, which
|
|
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
|
+
}
|
|
286
|
+
|
|
287
|
+
if (!canvaskitUsable) {
|
|
288
|
+
logger.warn(
|
|
289
|
+
"OG image generation requires canvaskit-wasm, which could not be loaded.\n" +
|
|
290
|
+
" pnpm users: run `pnpm add canvaskit-wasm`\n" +
|
|
291
|
+
" The build will continue without OG images.",
|
|
292
|
+
);
|
|
293
|
+
} else {
|
|
294
|
+
themeConfig.ogImage.enabled = true;
|
|
295
|
+
themeConfig.ogImage.logoPath = faviconPath;
|
|
296
|
+
const rawTitle = starlightConfig.title;
|
|
297
|
+
themeConfig.ogImage.siteTitle =
|
|
298
|
+
typeof rawTitle === "string"
|
|
299
|
+
? rawTitle
|
|
300
|
+
: (Object.values(rawTitle as Record<string, string>)[0] ?? "");
|
|
301
|
+
|
|
302
|
+
addRouteMiddleware({
|
|
303
|
+
entrypoint: "@nu-appdev/northwestern-starlight-theme/src/og/route-middleware",
|
|
304
|
+
order: "post",
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
addIntegration({
|
|
308
|
+
name: "northwestern-theme-og-image",
|
|
309
|
+
hooks: {
|
|
310
|
+
"astro:config:setup": ({ injectRoute }) => {
|
|
311
|
+
injectRoute({
|
|
312
|
+
pattern: "/og/[...slug]",
|
|
313
|
+
entrypoint: "@nu-appdev/northwestern-starlight-theme/src/og/endpoint.ts",
|
|
314
|
+
});
|
|
315
|
+
},
|
|
316
|
+
},
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
logger.info("OG image generation enabled");
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
247
323
|
updateConfig({
|
|
248
324
|
...(consumerSetFavicon ? {} : { favicon: "/favicon.png" }),
|
|
249
325
|
components: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nu-appdev/northwestern-starlight-theme",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "A Northwestern-branded theme for Astro Starlight",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Danny Foster <danny@northwestern.edu>",
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
},
|
|
45
45
|
"./src/styles/components/*": "./src/styles/components/*",
|
|
46
46
|
"./src/components/*": "./src/components/*",
|
|
47
|
+
"./src/og/*": "./src/og/*",
|
|
47
48
|
"./src/scripts/*": "./src/scripts/*",
|
|
48
49
|
"./src/styles/*": "./src/styles/*"
|
|
49
50
|
},
|
|
@@ -56,6 +57,7 @@
|
|
|
56
57
|
],
|
|
57
58
|
"dependencies": {
|
|
58
59
|
"@expressive-code/plugin-line-numbers": "^0.41.7",
|
|
60
|
+
"astro-og-canvas": "^0.10.1",
|
|
59
61
|
"khroma": "^2.1.0"
|
|
60
62
|
},
|
|
61
63
|
"peerDependencies": {
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { getCollection } from "astro:content";
|
|
2
|
+
import config from "virtual:northwestern-theme/config";
|
|
3
|
+
import { OGImageRoute } from "astro-og-canvas";
|
|
4
|
+
|
|
5
|
+
const siteTitle = config.ogImage.siteTitle;
|
|
6
|
+
const logoPath = config.ogImage.logoPath;
|
|
7
|
+
const docs = await getCollection("docs");
|
|
8
|
+
let changelogs: typeof docs = [];
|
|
9
|
+
try {
|
|
10
|
+
changelogs = await getCollection("changelogs" as "docs");
|
|
11
|
+
} catch {}
|
|
12
|
+
const pages = Object.fromEntries([...docs, ...changelogs].map((entry) => [entry.id, entry]));
|
|
13
|
+
|
|
14
|
+
export const { getStaticPaths, GET } = await OGImageRoute({
|
|
15
|
+
param: "slug",
|
|
16
|
+
pages,
|
|
17
|
+
getImageOptions: (path, page) => {
|
|
18
|
+
const isIndex = path === "index";
|
|
19
|
+
const isChangelogVersion = path.startsWith("changelog/version/");
|
|
20
|
+
const title = isIndex ? siteTitle : isChangelogVersion ? `Changelog\n${page.data.title}` : page.data.title;
|
|
21
|
+
return {
|
|
22
|
+
title,
|
|
23
|
+
description: page.data.description,
|
|
24
|
+
logo: { path: logoPath, size: [60] },
|
|
25
|
+
bgGradient: [[64, 31, 104]],
|
|
26
|
+
padding: 120,
|
|
27
|
+
border: {
|
|
28
|
+
color: [164, 149, 195],
|
|
29
|
+
width: 12,
|
|
30
|
+
side: "inline-start",
|
|
31
|
+
},
|
|
32
|
+
font: {
|
|
33
|
+
title: {
|
|
34
|
+
families: ["Poppins"],
|
|
35
|
+
weight: "Bold",
|
|
36
|
+
size: isChangelogVersion ? 56 : 48,
|
|
37
|
+
lineHeight: 1.3,
|
|
38
|
+
color: [255, 255, 255],
|
|
39
|
+
},
|
|
40
|
+
description: {
|
|
41
|
+
families: ["Akkurat Pro"],
|
|
42
|
+
size: 28,
|
|
43
|
+
lineHeight: 1.5,
|
|
44
|
+
color: [182, 172, 209],
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
fonts: [
|
|
48
|
+
"https://common.northwestern.edu/v8/css/fonts/Poppins-Bold.woff",
|
|
49
|
+
"https://common.northwestern.edu/v8/css/fonts/AkkuratProRegular.woff",
|
|
50
|
+
],
|
|
51
|
+
};
|
|
52
|
+
},
|
|
53
|
+
});
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { defineRouteMiddleware } from "@astrojs/starlight/route-data";
|
|
2
|
+
import type { HeadConfig } from "@astrojs/starlight/schemas/head";
|
|
3
|
+
|
|
4
|
+
type HeadEntry = HeadConfig[number];
|
|
5
|
+
type JsonLd = Record<string, unknown>;
|
|
6
|
+
|
|
7
|
+
function getStructuredData({
|
|
8
|
+
imageUrl,
|
|
9
|
+
isHomepage,
|
|
10
|
+
isChangelogVersion,
|
|
11
|
+
logoUrl,
|
|
12
|
+
pageUrl,
|
|
13
|
+
siteName,
|
|
14
|
+
title,
|
|
15
|
+
description,
|
|
16
|
+
}: {
|
|
17
|
+
imageUrl: string;
|
|
18
|
+
isHomepage: boolean;
|
|
19
|
+
isChangelogVersion: boolean;
|
|
20
|
+
logoUrl: string;
|
|
21
|
+
pageUrl: string;
|
|
22
|
+
siteName: string;
|
|
23
|
+
title: string;
|
|
24
|
+
description?: string;
|
|
25
|
+
}): JsonLd {
|
|
26
|
+
const origin = new URL(pageUrl).origin;
|
|
27
|
+
const organization = {
|
|
28
|
+
"@id": `${origin}/#organization`,
|
|
29
|
+
"@type": "Organization",
|
|
30
|
+
name: "Northwestern University",
|
|
31
|
+
url: "https://www.northwestern.edu",
|
|
32
|
+
logo: logoUrl,
|
|
33
|
+
};
|
|
34
|
+
const website = {
|
|
35
|
+
"@id": `${origin}/#website`,
|
|
36
|
+
"@type": "WebSite",
|
|
37
|
+
name: siteName,
|
|
38
|
+
url: `${origin}/`,
|
|
39
|
+
description,
|
|
40
|
+
image: imageUrl,
|
|
41
|
+
publisher: { "@id": organization["@id"] },
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
if (isHomepage) {
|
|
45
|
+
return {
|
|
46
|
+
"@context": "https://schema.org",
|
|
47
|
+
"@graph": [organization, website],
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
"@context": "https://schema.org",
|
|
53
|
+
"@graph": [
|
|
54
|
+
organization,
|
|
55
|
+
website,
|
|
56
|
+
{
|
|
57
|
+
"@type": isChangelogVersion ? "Article" : "TechArticle",
|
|
58
|
+
headline: title,
|
|
59
|
+
name: title,
|
|
60
|
+
description,
|
|
61
|
+
image: imageUrl,
|
|
62
|
+
url: pageUrl,
|
|
63
|
+
mainEntityOfPage: pageUrl,
|
|
64
|
+
isPartOf: { "@id": website["@id"] },
|
|
65
|
+
publisher: { "@id": organization["@id"] },
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export const onRequest = defineRouteMiddleware((context) => {
|
|
72
|
+
const route = context.locals.starlightRoute;
|
|
73
|
+
const site = context.site;
|
|
74
|
+
if (!site) return;
|
|
75
|
+
|
|
76
|
+
const pageUrl = new URL(context.url.pathname, site).href;
|
|
77
|
+
const siteName = route.siteTitle ?? route.entry.data.title;
|
|
78
|
+
const isHomepage = route.id === "index" || context.url.pathname === "/";
|
|
79
|
+
const isChangelogVersion = route.id?.startsWith("changelog/version/") ?? false;
|
|
80
|
+
const ogPath = route.id ? `/og/${route.id}.png` : "/og/index.png";
|
|
81
|
+
const imageUrl = new URL(ogPath, site).href;
|
|
82
|
+
|
|
83
|
+
// Replace Starlight's twitter:card (defaults to "summary" on non-splash
|
|
84
|
+
// pages) with "summary_large_image" so the 1200x630 image isn't cropped.
|
|
85
|
+
const twitterCardIndex = route.head.findIndex(
|
|
86
|
+
(entry: HeadEntry) => entry.tag === "meta" && entry.attrs.name === "twitter:card",
|
|
87
|
+
);
|
|
88
|
+
if (twitterCardIndex !== -1) {
|
|
89
|
+
route.head[twitterCardIndex] = {
|
|
90
|
+
tag: "meta",
|
|
91
|
+
attrs: { name: "twitter:card", content: "summary_large_image" },
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Resolve the favicon path from Starlight's head tags for og:logo.
|
|
96
|
+
const faviconEntry = route.head.find(
|
|
97
|
+
(entry: HeadEntry) => entry.tag === "link" && entry.attrs.rel === "shortcut icon",
|
|
98
|
+
);
|
|
99
|
+
const faviconHref = faviconEntry?.attrs.href ?? "/favicon.png";
|
|
100
|
+
const logoUrl = new URL(faviconHref, site).href;
|
|
101
|
+
const structuredData = JSON.stringify(
|
|
102
|
+
getStructuredData({
|
|
103
|
+
imageUrl,
|
|
104
|
+
isHomepage,
|
|
105
|
+
isChangelogVersion,
|
|
106
|
+
logoUrl,
|
|
107
|
+
pageUrl,
|
|
108
|
+
siteName,
|
|
109
|
+
title: route.entry.data.title,
|
|
110
|
+
description: route.entry.data.description,
|
|
111
|
+
}),
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
route.head.push(
|
|
115
|
+
{ tag: "meta", attrs: { property: "og:image", content: imageUrl } },
|
|
116
|
+
{ tag: "meta", attrs: { property: "og:image:type", content: "image/png" } },
|
|
117
|
+
{ tag: "meta", attrs: { property: "og:image:width", content: "1200" } },
|
|
118
|
+
{ tag: "meta", attrs: { property: "og:image:height", content: "630" } },
|
|
119
|
+
{ tag: "meta", attrs: { property: "og:image:alt", content: route.entry.data.title } },
|
|
120
|
+
{ tag: "meta", attrs: { property: "og:logo", content: logoUrl } },
|
|
121
|
+
{ tag: "meta", attrs: { name: "twitter:image", content: imageUrl } },
|
|
122
|
+
{ tag: "meta", attrs: { name: "twitter:image:alt", content: route.entry.data.title } },
|
|
123
|
+
{ tag: "script", attrs: { type: "application/ld+json" }, content: structuredData },
|
|
124
|
+
);
|
|
125
|
+
});
|
|
@@ -7,8 +7,9 @@
|
|
|
7
7
|
padding: 1rem 1.5rem;
|
|
8
8
|
margin: 2rem 0;
|
|
9
9
|
color: var(--nu-color-text);
|
|
10
|
-
background:
|
|
10
|
+
background: #f9f6ff;
|
|
11
11
|
border-inline-start: 10px solid var(--nu-purple-100);
|
|
12
|
+
border-radius: 0 0.75rem 0.75rem 0 !important;
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
.sl-markdown-content blockquote:not(:where(.not-content *)) p:last-child {
|
|
@@ -16,18 +16,20 @@
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
.sl-markdown-content table:not(:where(.not-content *)) > thead > tr > th {
|
|
19
|
-
padding: 0.5rem
|
|
20
|
-
font-family: var(--nu-font-
|
|
21
|
-
font-
|
|
22
|
-
|
|
19
|
+
padding: 0.75rem 0.5rem;
|
|
20
|
+
font-family: var(--nu-font-body);
|
|
21
|
+
font-size: 1rem;
|
|
22
|
+
font-weight: 700;
|
|
23
|
+
color: #fff;
|
|
23
24
|
text-align: left;
|
|
24
|
-
background-color: var(--nu-purple-
|
|
25
|
+
background-color: var(--nu-purple-100);
|
|
25
26
|
border: 1px solid var(--nu-border-color);
|
|
27
|
+
border-right: 1px solid rgb(255 255 255 / 30%);
|
|
28
|
+
border-left: 1px solid rgb(255 255 255 / 30%);
|
|
26
29
|
}
|
|
27
30
|
|
|
28
31
|
:root:not([data-theme="light"]) .sl-markdown-content table:not(:where(.not-content *)) > thead > tr > th {
|
|
29
|
-
color:
|
|
30
|
-
background-color: rgb(78 42 132 / 14%);
|
|
32
|
+
background-color: rgb(78 42 132 / 40%);
|
|
31
33
|
}
|
|
32
34
|
|
|
33
35
|
.sl-markdown-content table:not(:where(.not-content *)) > tbody > tr > td {
|
|
@@ -46,15 +48,19 @@
|
|
|
46
48
|
text-align: center;
|
|
47
49
|
}
|
|
48
50
|
|
|
49
|
-
.sl-markdown-content table:not(:where(.not-content *)) > tbody > tr:nth-child(
|
|
50
|
-
background-color: #
|
|
51
|
+
.sl-markdown-content table:not(:where(.not-content *)) > tbody > tr:nth-child(odd) {
|
|
52
|
+
background-color: #f9f6ff;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.sl-markdown-content table:not(:where(.not-content *)) > tbody > tr:hover {
|
|
56
|
+
background-color: #f0f0f0;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
:root:not([data-theme="light"]) .sl-markdown-content table:not(:where(.not-content *)) > tbody > tr:nth-child(odd) {
|
|
60
|
+
background-color: rgb(78 42 132 / 10%);
|
|
51
61
|
}
|
|
52
62
|
|
|
53
|
-
:root:not([data-theme="light"])
|
|
54
|
-
|
|
55
|
-
table:not(:where(.not-content *))
|
|
56
|
-
> tbody
|
|
57
|
-
> tr:nth-child(even) {
|
|
58
|
-
background-color: #1e1e1e;
|
|
63
|
+
:root:not([data-theme="light"]) .sl-markdown-content table:not(:where(.not-content *)) > tbody > tr:hover {
|
|
64
|
+
background-color: rgb(255 255 255 / 5%);
|
|
59
65
|
}
|
|
60
66
|
}
|
package/src/styles/content.css
CHANGED
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
width: 6px;
|
|
40
40
|
height: 6px;
|
|
41
41
|
content: "";
|
|
42
|
-
background: var(--nu-purple-
|
|
42
|
+
background: var(--nu-purple-100);
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
:root:not([data-theme="light"]) .sl-markdown-content ul:not(:where(.not-content *)) > li::before {
|
|
@@ -56,10 +56,16 @@
|
|
|
56
56
|
border-color: var(--nu-purple-30);
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
.sl-markdown-content mark:not(:where(.not-content *)),
|
|
60
|
+
.sl-markdown-content .highlight:not(:where(.not-content *)) {
|
|
61
|
+
padding: 3px;
|
|
62
|
+
background: rgb(228 224 238 / 50%);
|
|
63
|
+
}
|
|
64
|
+
|
|
59
65
|
.sl-markdown-content hr:not(:where(.not-content *)) {
|
|
60
|
-
height:
|
|
66
|
+
height: 3px;
|
|
61
67
|
margin: 2.5rem 0;
|
|
62
|
-
background: var(--nu-
|
|
68
|
+
background: var(--nu-purple-10);
|
|
63
69
|
border: 0;
|
|
64
70
|
}
|
|
65
71
|
|
|
@@ -78,7 +78,15 @@
|
|
|
78
78
|
font-family: Poppins;
|
|
79
79
|
font-style: normal;
|
|
80
80
|
font-weight: 400;
|
|
81
|
-
src: url("https://common.northwestern.edu/v8/css/fonts/Poppins-
|
|
81
|
+
src: url("https://common.northwestern.edu/v8/css/fonts/Poppins-Regular.woff") format("woff");
|
|
82
|
+
font-display: swap;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
@font-face {
|
|
86
|
+
font-family: Poppins;
|
|
87
|
+
font-style: normal;
|
|
88
|
+
font-weight: 500;
|
|
89
|
+
src: url("https://common.northwestern.edu/dept/4.0/css/fonts/poppins/poppins-v21-latin-500.woff2") format("woff2");
|
|
82
90
|
font-display: swap;
|
|
83
91
|
}
|
|
84
92
|
|
|
@@ -150,18 +158,81 @@
|
|
|
150
158
|
|
|
151
159
|
h1,
|
|
152
160
|
h2 {
|
|
153
|
-
font-family: var(--nu-font-
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
h1 {
|
|
157
|
-
color: var(--sl-color-text-accent);
|
|
161
|
+
font-family: var(--nu-font-display);
|
|
158
162
|
}
|
|
159
163
|
|
|
160
164
|
h3,
|
|
161
165
|
h4,
|
|
162
166
|
h5,
|
|
163
167
|
h6 {
|
|
164
|
-
font-family: var(--nu-font-
|
|
168
|
+
font-family: var(--nu-font-heading);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.main-pane h1 {
|
|
172
|
+
display: inline;
|
|
173
|
+
font-size: clamp(2rem, 1rem + 3vw, 2.8125rem);
|
|
174
|
+
font-weight: 500;
|
|
175
|
+
line-height: 1.4;
|
|
176
|
+
color: #000;
|
|
177
|
+
box-shadow: inset 0 -0.55em 0 0 var(--nu-purple-10);
|
|
178
|
+
box-decoration-break: clone;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
:root:not([data-theme="light"]) .main-pane h1 {
|
|
182
|
+
color: #fff;
|
|
183
|
+
box-shadow: inset 0 -0.55em 0 0 var(--nu-purple-140);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.sl-markdown-content h2 {
|
|
187
|
+
font-size: 1.875rem;
|
|
188
|
+
font-weight: 700;
|
|
189
|
+
line-height: 1.4;
|
|
190
|
+
color: var(--nu-purple-120);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.sl-markdown-content h3 {
|
|
194
|
+
font-size: 1.625rem;
|
|
195
|
+
font-weight: 500;
|
|
196
|
+
line-height: 1.4;
|
|
197
|
+
color: var(--nu-black-80);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.sl-markdown-content h4 {
|
|
201
|
+
font-size: 1.4375rem;
|
|
202
|
+
font-weight: 500;
|
|
203
|
+
line-height: 1.4;
|
|
204
|
+
color: var(--nu-purple-120);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.sl-markdown-content h5 {
|
|
208
|
+
font-size: 1.25rem;
|
|
209
|
+
font-weight: 500;
|
|
210
|
+
line-height: 1.4;
|
|
211
|
+
color: var(--nu-black-80);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.sl-markdown-content h6 {
|
|
215
|
+
font-size: 1.125rem;
|
|
216
|
+
font-weight: 500;
|
|
217
|
+
line-height: 1.4;
|
|
218
|
+
color: var(--nu-black-80);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
:root:not([data-theme="light"]) .sl-markdown-content h2 {
|
|
222
|
+
color: var(--nu-purple-30);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
:root:not([data-theme="light"]) .sl-markdown-content h3 {
|
|
226
|
+
color: var(--nu-color-text);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
:root:not([data-theme="light"]) .sl-markdown-content h4 {
|
|
230
|
+
color: var(--nu-purple-30);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
:root:not([data-theme="light"]) .sl-markdown-content h5,
|
|
234
|
+
:root:not([data-theme="light"]) .sl-markdown-content h6 {
|
|
235
|
+
color: var(--nu-color-text);
|
|
165
236
|
}
|
|
166
237
|
|
|
167
238
|
.site-title {
|
package/src/styles/variables.css
CHANGED
|
@@ -55,12 +55,12 @@
|
|
|
55
55
|
--nu-transition-default: 200ms ease;
|
|
56
56
|
--nu-transition-slow: 300ms ease-in-out;
|
|
57
57
|
|
|
58
|
-
--nu-purple-surface: #
|
|
59
|
-
--nu-purple-surface-subtle: #
|
|
58
|
+
--nu-purple-surface: #f9f6ff;
|
|
59
|
+
--nu-purple-surface-subtle: #f3f0f7;
|
|
60
60
|
--nu-purple-tint: rgb(78 42 132 / 15%);
|
|
61
61
|
--nu-purple-tint-strong: rgb(78 42 132 / 20%);
|
|
62
62
|
--nu-surface-muted: #f9fafb;
|
|
63
|
-
--nu-hover-bg: #
|
|
63
|
+
--nu-hover-bg: #f0f0f0;
|
|
64
64
|
|
|
65
65
|
--nu-focus-ring: var(--nu-purple-100);
|
|
66
66
|
--nu-focus-border: #a795c2;
|
|
@@ -90,10 +90,10 @@
|
|
|
90
90
|
--nu-focus-ring: var(--nu-purple-100);
|
|
91
91
|
--nu-focus-shadow-color: rgb(78 42 132 / 25%);
|
|
92
92
|
|
|
93
|
-
--nu-purple-surface: #
|
|
94
|
-
--nu-purple-surface-subtle: #
|
|
93
|
+
--nu-purple-surface: #f9f6ff;
|
|
94
|
+
--nu-purple-surface-subtle: #f3f0f7;
|
|
95
95
|
--nu-surface-muted: #f9fafb;
|
|
96
|
-
--nu-hover-bg: #
|
|
96
|
+
--nu-hover-bg: #f0f0f0;
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
:root:not([data-theme="light"]),
|
package/src/virtual.d.ts
CHANGED