coherent-docs-theme 1.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/README.md +314 -0
- package/assets/gameface-ui-header-dark.svg +5 -0
- package/assets/gameface-ui-header-light.svg +5 -0
- package/components/Api.astro +29 -0
- package/components/BeforeAfter.astro +124 -0
- package/components/Details.astro +37 -0
- package/components/Enhancement.astro +29 -0
- package/components/Feature.astro +29 -0
- package/components/Figure.astro +107 -0
- package/components/Fix.astro +29 -0
- package/components/GallerySlider.astro +260 -0
- package/components/If.astro +6 -0
- package/components/IfEnv.astro +5 -0
- package/components/IfNot.astro +6 -0
- package/components/IncludeSnippets.astro +13 -0
- package/components/Internal.astro +3 -0
- package/components/ProductName.astro +13 -0
- package/components/Release.astro +68 -0
- package/components/SideBarWithDropdown.astro +8 -0
- package/components/Typeref.astro +35 -0
- package/index.ts +152 -0
- package/internal/overrideComponents.ts +29 -0
- package/internal/themeConfig.ts +21 -0
- package/internal-components/ChangelogRow.astro +39 -0
- package/internal-components/NavLinks.astro +253 -0
- package/internal-components/ProgressIndicator.astro +53 -0
- package/overrides/Footer.astro +103 -0
- package/overrides/Header.astro +91 -0
- package/overrides/Search.astro +234 -0
- package/overrides/ThemeSelect.astro +218 -0
- package/package.json +46 -0
- package/remark-directives/if.ts +51 -0
- package/remark-directives/includeSnippets.ts +120 -0
- package/remark-directives/index.ts +13 -0
- package/remark-directives/internal.ts +20 -0
- package/remark-directives/release.ts +29 -0
- package/styles.css +452 -0
- package/utils/changelogSideBar.ts +105 -0
- package/utils/changelogSideBarMultipleDocs.ts +119 -0
- package/utils/coherentReleases.ts +62 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { visit } from 'unist-util-visit';
|
|
2
|
+
import type { Root } from 'mdast';
|
|
3
|
+
|
|
4
|
+
export function remarkInternalDirective() {
|
|
5
|
+
return (tree: Root) => {
|
|
6
|
+
visit(tree, ['mdxJsxFlowElement', 'mdxJsxTextElement'], (node: any, index, parent) => {
|
|
7
|
+
const nodeName = node.name;
|
|
8
|
+
if (nodeName !== 'Internal' || index === undefined || !parent) return;
|
|
9
|
+
const isDev = process.env.MODE === 'development' || process.env.NODE_ENV === 'development';
|
|
10
|
+
|
|
11
|
+
if (isDev) {
|
|
12
|
+
parent.children.splice(index, 1, ...node.children);
|
|
13
|
+
return index;
|
|
14
|
+
} else {
|
|
15
|
+
parent.children.splice(index, 1);
|
|
16
|
+
return index;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { visit } from 'unist-util-visit';
|
|
2
|
+
import type { Root } from 'mdast';
|
|
3
|
+
|
|
4
|
+
export function remarkReleaseDirective() {
|
|
5
|
+
return (tree: Root) => {
|
|
6
|
+
visit(tree, ['mdxJsxFlowElement', 'mdxJsxTextElement'], (node: any, index, parent) => {
|
|
7
|
+
const nodeName = node.name;
|
|
8
|
+
if (nodeName !== 'Release' || index === undefined || !parent) return;
|
|
9
|
+
|
|
10
|
+
const attrs = Object.fromEntries(node.attributes?.map((a: any) => [a.name, a.value]) || []);
|
|
11
|
+
const { version } = attrs;
|
|
12
|
+
|
|
13
|
+
if (!version) return;
|
|
14
|
+
|
|
15
|
+
const headingNode = {
|
|
16
|
+
type: 'heading',
|
|
17
|
+
depth: 2,
|
|
18
|
+
children: [{ type: 'text', value: `Version ${version}` }],
|
|
19
|
+
data: {
|
|
20
|
+
hProperties: { id: version }
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
parent.children.splice(index, 0, headingNode);
|
|
25
|
+
|
|
26
|
+
return index + 2;
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
}
|
package/styles.css
ADDED
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
@import url('https://fonts.googleapis.com/css2?family=Barlow+Semi+Condensed:wght@400;600;700&family=Karla:wght@400;700&display=swap');
|
|
2
|
+
|
|
3
|
+
@layer starlight, coh-theme;
|
|
4
|
+
|
|
5
|
+
@layer coh-theme {
|
|
6
|
+
|
|
7
|
+
/* ========================================= */
|
|
8
|
+
/* 1. GLOBAL VARIABLES & DARK THEME (DEFAULT) */
|
|
9
|
+
/* ========================================= */
|
|
10
|
+
:root {
|
|
11
|
+
--pagefind-ui-scale: 0.9;
|
|
12
|
+
|
|
13
|
+
/* --- Shared Settings (Typography & Shapes) --- */
|
|
14
|
+
--sl-font: 'Karla', sans-serif;
|
|
15
|
+
--sl-font-system: 'Karla', sans-serif;
|
|
16
|
+
--sl-font-heading: 'Barlow Semi Condensed', sans-serif;
|
|
17
|
+
|
|
18
|
+
/* Layout */
|
|
19
|
+
--sl-content-width: 80%;
|
|
20
|
+
--sl-sidebar-width: 20rem;
|
|
21
|
+
|
|
22
|
+
/* Accents (Shared) */
|
|
23
|
+
--gameface-cyan: #00DCFF;
|
|
24
|
+
--gameface-blue: #3E42B8;
|
|
25
|
+
|
|
26
|
+
/* --- DARK MODE PALETTE (Default) --- */
|
|
27
|
+
--gameface-bg-main: #0A0A0A;
|
|
28
|
+
--gameface-bg-content: #141414;
|
|
29
|
+
/* Deep Teal */
|
|
30
|
+
--gameface-bg-panel: #141414;
|
|
31
|
+
--gameface-border: #262626;
|
|
32
|
+
--gameface-text-head: #FFFFFF;
|
|
33
|
+
--gameface-text-body: #F4F4F4;
|
|
34
|
+
--gameface-text-meta: #8fa3a3;
|
|
35
|
+
|
|
36
|
+
/* Starlight Mappings (Dark) */
|
|
37
|
+
--sl-color-bg: var(--gameface-bg-main);
|
|
38
|
+
--sl-color-bg-nav: var(--gameface-bg-panel);
|
|
39
|
+
--sl-color-bg-sidebar: var(--gameface-bg-main);
|
|
40
|
+
--sl-color-white: var(--gameface-text-head);
|
|
41
|
+
--sl-color-text: var(--gameface-text-body);
|
|
42
|
+
--sl-color-text-accent: var(--gameface-cyan);
|
|
43
|
+
|
|
44
|
+
--sl-color-accent: var(--gameface-cyan);
|
|
45
|
+
--sl-color-accent-high: #99f3ff;
|
|
46
|
+
--sl-color-accent-low: #003640;
|
|
47
|
+
|
|
48
|
+
--sl-color-gray-1: #F4F4F4;
|
|
49
|
+
--sl-color-gray-2: #c1d1d1;
|
|
50
|
+
--sl-color-gray-3: var(--gameface-text-meta);
|
|
51
|
+
--sl-color-gray-4: #5f7575;
|
|
52
|
+
--sl-color-gray-5: var(--gameface-border);
|
|
53
|
+
--sl-color-gray-6: var(--gameface-bg-panel);
|
|
54
|
+
|
|
55
|
+
--sl-color-hairline: var(--gameface-border);
|
|
56
|
+
--overlay-backdrop: rgba(10, 10, 10, 0.95);
|
|
57
|
+
--before-after-line: rgba(255, 255, 255, 0.43);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
main .sl-container {
|
|
61
|
+
max-width: none;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.content-panel {
|
|
65
|
+
padding: 1.5rem 1.5rem;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
@media (min-width: 72rem) {
|
|
69
|
+
.content-panel {
|
|
70
|
+
padding: 1.5rem 2.5rem;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
@media (min-width: 90rem) {
|
|
75
|
+
.content-panel {
|
|
76
|
+
padding: 1.5rem 3.5rem;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.right-sidebar {
|
|
81
|
+
width: fit-content;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* ========================================= */
|
|
85
|
+
/* 2. LIGHT THEME OVERRIDES */
|
|
86
|
+
/* ========================================= */
|
|
87
|
+
[data-theme='light'] {
|
|
88
|
+
/* --- Gameface Light Palette --- */
|
|
89
|
+
/* Backgrounds: White (Main) and Light Grey 1 (Sidebars) */
|
|
90
|
+
--gameface-bg-main: #FFFFFF;
|
|
91
|
+
--gameface-bg-content: #FFFFFF;
|
|
92
|
+
--gameface-bg-panel: #F4F4F4;
|
|
93
|
+
--gameface-border: #E0E0E0;
|
|
94
|
+
/* Subtle border for light mode */
|
|
95
|
+
|
|
96
|
+
/* Text Colors */
|
|
97
|
+
--gameface-text-head: #0A0A0A;
|
|
98
|
+
/* Coherent Black */
|
|
99
|
+
--gameface-text-body: #333333;
|
|
100
|
+
/* Dark Grey 2 */
|
|
101
|
+
--gameface-text-meta: #666666;
|
|
102
|
+
/* Grey */
|
|
103
|
+
|
|
104
|
+
/* Starlight Mappings (Light) */
|
|
105
|
+
--sl-color-bg: var(--gameface-bg-main);
|
|
106
|
+
--sl-color-bg-nav: var(--gameface-bg-main);
|
|
107
|
+
/* Header blends with main */
|
|
108
|
+
--sl-color-bg-sidebar: var(--gameface-bg-panel);
|
|
109
|
+
/* Light Grey Sidebar */
|
|
110
|
+
|
|
111
|
+
/* Re-mapping 'White' var to Black because Starlight uses it for Headings */
|
|
112
|
+
--sl-color-white: var(--gameface-text-head);
|
|
113
|
+
--sl-color-text: var(--gameface-text-body);
|
|
114
|
+
--sl-color-text-accent: #009bb3;
|
|
115
|
+
/* Darker Cyan for text readability on white */
|
|
116
|
+
|
|
117
|
+
--sl-color-accent: var(--gameface-cyan);
|
|
118
|
+
--sl-color-accent-high: #008fa6;
|
|
119
|
+
--sl-color-accent-low: #e0faff;
|
|
120
|
+
|
|
121
|
+
/* Grays (Inverted for Light Mode) */
|
|
122
|
+
--sl-color-gray-1: #1a1a1a;
|
|
123
|
+
--sl-color-gray-2: #333333;
|
|
124
|
+
--sl-color-gray-3: var(--gameface-text-meta);
|
|
125
|
+
--sl-color-gray-4: #999999;
|
|
126
|
+
--sl-color-gray-5: var(--gameface-border);
|
|
127
|
+
--sl-color-gray-6: #F9F9F9;
|
|
128
|
+
|
|
129
|
+
--sl-color-hairline: var(--gameface-border);
|
|
130
|
+
--overlay-backdrop: rgba(255, 255, 255, 0.95);
|
|
131
|
+
--before-after-line: rgba(10, 10, 10, 0.43);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/* ========================================= */
|
|
135
|
+
/* 3. DEEP TEAL LOGIC (DARK MODE ONLY) */
|
|
136
|
+
/* ========================================= */
|
|
137
|
+
/* Apply Deep Teal background ONLY in Dark Mode and NOT on Splash pages */
|
|
138
|
+
:root:not([data-theme='light']) body:not([data-template="splash"]) {
|
|
139
|
+
--sl-color-bg: var(--gameface-bg-content);
|
|
140
|
+
/* #0F2123 */
|
|
141
|
+
--sl-color-bg-sidebar: var(--gameface-bg-main);
|
|
142
|
+
/* Keep Sidebar Black */
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/* ========================================= */
|
|
146
|
+
/* 4. GLOBAL RESET & TYPOGRAPHY */
|
|
147
|
+
/* ========================================= */
|
|
148
|
+
/* Strictly sharp corners */
|
|
149
|
+
*,
|
|
150
|
+
*::before,
|
|
151
|
+
*::after {
|
|
152
|
+
border-radius: 0 !important;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
body {
|
|
156
|
+
font-family: var(--sl-font-system);
|
|
157
|
+
color: var(--sl-color-text);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
h1,
|
|
161
|
+
/* h2,
|
|
162
|
+
h3,
|
|
163
|
+
h4,
|
|
164
|
+
h5,
|
|
165
|
+
h6, */
|
|
166
|
+
.site-title {
|
|
167
|
+
font-family: var(--sl-font-heading);
|
|
168
|
+
text-transform: uppercase !important;
|
|
169
|
+
font-weight: 600 !important;
|
|
170
|
+
letter-spacing: 0.02em;
|
|
171
|
+
color: var(--sl-color-white);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/* Labels: Bold Caps, 0.2em spacing */
|
|
175
|
+
.sl-badge,
|
|
176
|
+
.kbd,
|
|
177
|
+
button,
|
|
178
|
+
.button {
|
|
179
|
+
font-family: 'Karla', sans-serif;
|
|
180
|
+
font-weight: 700;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.sl-link-button.primary {
|
|
184
|
+
font-weight: bold;
|
|
185
|
+
transition: filter 0.2s ease, border-color 0.2s ease;
|
|
186
|
+
border: 1px solid transparent;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
.sl-link-button.primary:hover {
|
|
190
|
+
filter: brightness(1.2);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.sl-link-button.secondary {
|
|
194
|
+
transition: border-color 0.2s ease, color 0.2s ease;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.sl-link-button.secondary:hover {
|
|
198
|
+
border-color: var(--gameface-cyan);
|
|
199
|
+
color: var(--gameface-cyan)
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.sl-link-button.minimal {
|
|
203
|
+
transition: color 0.2s ease;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.sl-link-button.minimal:hover {
|
|
207
|
+
color: var(--gameface-cyan)
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/* ========================================= */
|
|
211
|
+
/* 5. COMPONENT STYLING */
|
|
212
|
+
/* ========================================= */
|
|
213
|
+
|
|
214
|
+
/* --- Header --- */
|
|
215
|
+
header.header {
|
|
216
|
+
background-color: var(--overlay-backdrop) !important;
|
|
217
|
+
border-bottom: 1px solid var(--sl-color-hairline) !important;
|
|
218
|
+
backdrop-filter: blur(10px);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/* --- Left Sidebar --- */
|
|
222
|
+
nav.sidebar {
|
|
223
|
+
background-color: var(--sl-color-bg-sidebar) !important;
|
|
224
|
+
border-right: 1px solid var(--sl-color-hairline);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.sidebar-content details summary {
|
|
228
|
+
flex-direction: row-reverse;
|
|
229
|
+
justify-content: flex-end;
|
|
230
|
+
padding: 0.2em 0.2em;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
.sidebar-content details summary .group-label {
|
|
234
|
+
padding-left: 0.3em;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.sidebar-content details li {
|
|
238
|
+
border-inline-start: 1px solid var(--sl-color-gray-5);
|
|
239
|
+
padding-inline-start: var(--sl-sidebar-item-padding-inline);
|
|
240
|
+
position: relative;
|
|
241
|
+
margin-inline-start: calc(var(--sl-sidebar-item-padding-inline) + (0.5rem / 2));
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.sidebar-content details li:hover {
|
|
245
|
+
color: var(--sl-color-white);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.sidebar-content details li:hover:not(:has(li:hover)) {
|
|
249
|
+
border-color: var(--sl-color-gray-1);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
.sidebar-content details li:has(>a[aria-current=page]) {
|
|
253
|
+
background-color: var(--sl-color-gray-6) !important;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
.sidebar-content details li:has(>a[aria-current=page])::before {
|
|
257
|
+
content: '';
|
|
258
|
+
position: absolute;
|
|
259
|
+
left: -1px;
|
|
260
|
+
height: 100%;
|
|
261
|
+
color: var(--sl-color-white);
|
|
262
|
+
border-left: 4px solid var(--gameface-cyan) !important;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
.sidebar-content ul a {
|
|
266
|
+
color: var(--sl-color-gray-3);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/* Active Page Styling */
|
|
270
|
+
.sidebar-content ul a[aria-current="page"] {
|
|
271
|
+
color: var(--gameface-cyan) !important;
|
|
272
|
+
background-color: transparent !important;
|
|
273
|
+
font-weight: 700;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/* Fix for Light Mode Text on Active Sidebar */
|
|
277
|
+
[data-theme='light'] .sidebar-content ul a[aria-current="page"] {
|
|
278
|
+
color: #009bb3 !important;
|
|
279
|
+
/* Darker cyan for readability on light bg */
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
.sidebar-content ul a:hover:not([aria-current="page"]) {
|
|
283
|
+
color: var(--sl-color-white);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
.right-sidebar a {
|
|
287
|
+
padding-inline-start: calc(1rem - 4px) !important;
|
|
288
|
+
border-left: 4px solid transparent;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
.right-sidebar ul ul {
|
|
292
|
+
padding-inline-start: 1rem !important;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
.right-sidebar a[aria-current="true"] {
|
|
296
|
+
color: var(--gameface-cyan) !important;
|
|
297
|
+
font-weight: 700;
|
|
298
|
+
border-left-color: var(--gameface-cyan) !important;
|
|
299
|
+
padding-inline-start: calc(1rem - 4px) !important;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/* Light mode override for TOC active text */
|
|
303
|
+
[data-theme='light'] .right-sidebar a[aria-current="true"] {
|
|
304
|
+
color: #009bb3 !important;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
#starlight__on-this-page {
|
|
308
|
+
border-left: 4px solid var(--gameface-cyan) !important;
|
|
309
|
+
padding-left: calc(1rem - 4px);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
.right-sidebar h2 {
|
|
313
|
+
letter-spacing: 0.15em !important;
|
|
314
|
+
color: var(--sl-color-white) !important;
|
|
315
|
+
margin-bottom: 1rem;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/* --- Cards & UI --- */
|
|
319
|
+
.card,
|
|
320
|
+
.sl-link-card {
|
|
321
|
+
background-color: var(--sl-color-bg-nav) !important;
|
|
322
|
+
/* Context aware */
|
|
323
|
+
border: 1px solid var(--sl-color-gray-5);
|
|
324
|
+
transition: border-color 0.2s;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
.card:hover,
|
|
328
|
+
.card:focus,
|
|
329
|
+
.sl-link-card:hover,
|
|
330
|
+
.sl-link-card:focus {
|
|
331
|
+
border-color: var(--gameface-cyan);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/* Code Blocks */
|
|
335
|
+
.expressive-code .frame {
|
|
336
|
+
background-color: var(--gameface-bg-panel) !important;
|
|
337
|
+
/* Code is usually dark even in light mode for Gameface? */
|
|
338
|
+
border: 1px solid var(--sl-color-gray-5);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/* Override for Light mode if code blocks should be light (Optional, keeping dark per typical tech docs) */
|
|
342
|
+
[data-theme='light'] .expressive-code .frame {
|
|
343
|
+
background-color: #f0f0f0 !important;
|
|
344
|
+
border-color: #ccc;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/* Admonitions */
|
|
348
|
+
.starlight-aside--tip,
|
|
349
|
+
.starlight-aside--note {
|
|
350
|
+
border: 1px solid var(--sl-color-hairline) !important;
|
|
351
|
+
border-left: 4px solid var(--sl-color-asides-text-accent) !important;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
.starlight-aside__title {
|
|
355
|
+
font-family: var(--sl-font-heading);
|
|
356
|
+
text-transform: uppercase;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/* --- Pagination Buttons --- */
|
|
360
|
+
/* Next: Cyan Background, Black Text */
|
|
361
|
+
.pagination-links a[rel="next"] {
|
|
362
|
+
border: none;
|
|
363
|
+
font-weight: 800;
|
|
364
|
+
text-transform: uppercase;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/* Prev: Ghost Button */
|
|
368
|
+
.pagination-links a {
|
|
369
|
+
transition: all 0.2s ease;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
.pagination-links a[rel="prev"],
|
|
373
|
+
.pagination-links a[rel="next"] {
|
|
374
|
+
font-weight: 800;
|
|
375
|
+
background-color: transparent !important;
|
|
376
|
+
border: none;
|
|
377
|
+
color: var(--sl-color-gray-3) !important;
|
|
378
|
+
text-transform: uppercase;
|
|
379
|
+
box-shadow: none;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
.pagination-links .link-title {
|
|
383
|
+
color: inherit !important;
|
|
384
|
+
font-size: var(--sl-text-xl);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
.pagination-links a[rel="prev"]:hover,
|
|
388
|
+
.pagination-links a[rel="next"]:hover {
|
|
389
|
+
color: var(--sl-color-white) !important;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/* Light mode prev button needs dark border/text */
|
|
393
|
+
[data-theme='light'] .pagination-links a[rel="prev"],
|
|
394
|
+
[data-theme='light'] .pagination-links a[rel="next"] {
|
|
395
|
+
border-color: var(--gameface-text-head) !important;
|
|
396
|
+
color: var(--gameface-text-head) !important;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
[data-theme='light'] .pagination-links a[rel="prev"]:hover,
|
|
400
|
+
[data-theme='light'] .pagination-links a[rel="next"]:hover {
|
|
401
|
+
color: var(--sl-color-gray-3) !important;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/* --- Theme Toggle --- */
|
|
405
|
+
starlight-theme-select {
|
|
406
|
+
border: 1px solid var(--sl-color-gray-5);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
starlight-theme-select select {
|
|
410
|
+
opacity: 0;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
starlight-theme-select:hover {
|
|
414
|
+
border-color: var(--gameface-cyan);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
starlight-theme-select svg {
|
|
418
|
+
color: var(--gameface-cyan);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
[data-theme='light'] starlight-theme-select svg {
|
|
422
|
+
color: #009bb3;
|
|
423
|
+
/* Darker cyan for visibility */
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
.starlight-sidebar-topics-dropdown-button-label,
|
|
427
|
+
.starlight-sidebar-topics-dropdown-label {
|
|
428
|
+
white-space: pre-line !important;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
.starlight-sidebar-topics-dropdown-button-label {
|
|
432
|
+
margin-right: 0 !important;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
starlight-menu-button button {
|
|
436
|
+
background-color: transparent;
|
|
437
|
+
color: var(--sl-color-gray-1);
|
|
438
|
+
box-shadow: none;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
starlight-menu-button button:hover {
|
|
442
|
+
opacity: 0.66;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
site-search button {
|
|
446
|
+
font-size: var(--sl-icon-size);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
site-search button:hover {
|
|
450
|
+
opacity: 0.66;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import matter from 'gray-matter';
|
|
4
|
+
import { unified } from 'unified';
|
|
5
|
+
import remarkParse from 'remark-parse';
|
|
6
|
+
import remarkMdx from 'remark-mdx';
|
|
7
|
+
|
|
8
|
+
type Heading = { label: string; link: string, badge?: { text: string, variant: "note" | "danger" | "success" | "caution" | "tip" | "default" | undefined } };
|
|
9
|
+
const headings: Heading[] = [];
|
|
10
|
+
|
|
11
|
+
function parseHeadingWithBadge(node: any) {
|
|
12
|
+
const text = node.children
|
|
13
|
+
.filter((child: any) => child.type === 'text')
|
|
14
|
+
.map((child: any) => child.value)
|
|
15
|
+
.join('');
|
|
16
|
+
|
|
17
|
+
const badgeNode = node.children.find(
|
|
18
|
+
(child: any) =>
|
|
19
|
+
child.type === 'text' &&
|
|
20
|
+
child.value.includes(':badge[')
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
let badgeText = '';
|
|
24
|
+
if (badgeNode) {
|
|
25
|
+
const match = badgeNode.value.match(/:badge\[(.*?)\]/);
|
|
26
|
+
if (match) {
|
|
27
|
+
badgeText = match[1];
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const badgeVariantNode = node.children.find(
|
|
32
|
+
(child: any) =>
|
|
33
|
+
child.type === 'mdxTextExpression' &&
|
|
34
|
+
child.value.includes('variant="')
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
let badgeVariant: "note" | "danger" | "success" | "caution" | "tip" | "default" | undefined;
|
|
38
|
+
if (badgeVariantNode) {
|
|
39
|
+
const match = badgeVariantNode.value.match(/variant="(.*?)"/);
|
|
40
|
+
if (match) {
|
|
41
|
+
badgeVariant = match[1];
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
let badge = null;
|
|
46
|
+
if (badgeText) {
|
|
47
|
+
badge = { text: badgeText, variant: badgeVariant };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return { text, badge };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function slugify(text: string) {
|
|
54
|
+
return text
|
|
55
|
+
.replace(/:badge\[.*?\]/g, '')
|
|
56
|
+
.trim()
|
|
57
|
+
.toLowerCase()
|
|
58
|
+
.replace(/\s+/g, '-')
|
|
59
|
+
.replace(/[^\w\-]+/g, '')
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function walk(node: any) {
|
|
63
|
+
if (node.type === 'heading' && node.depth === 2) {
|
|
64
|
+
const { text, badge } = parseHeadingWithBadge(node);
|
|
65
|
+
const heading: Heading = {
|
|
66
|
+
label: text.replace(/:badge\[.*?\]/g, ''),
|
|
67
|
+
link: `/changelog/#${slugify(text)}`,
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
if (badge) {
|
|
71
|
+
heading.badge = {
|
|
72
|
+
text: badge.text,
|
|
73
|
+
variant: badge.variant
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
headings.push(heading);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (node.children) {
|
|
81
|
+
for (const child of node.children) {
|
|
82
|
+
walk(child);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export default function generateChangelog(changelogPath: string) {
|
|
88
|
+
const filePath = path.resolve(changelogPath);
|
|
89
|
+
const file = fs.readFileSync(filePath, 'utf-8');
|
|
90
|
+
|
|
91
|
+
const { content } = matter(file);
|
|
92
|
+
|
|
93
|
+
const tree = unified()
|
|
94
|
+
.use(remarkParse)
|
|
95
|
+
.use(remarkMdx)
|
|
96
|
+
.parse(content);
|
|
97
|
+
|
|
98
|
+
walk(tree);
|
|
99
|
+
return {
|
|
100
|
+
label: 'Changelog',
|
|
101
|
+
items: [
|
|
102
|
+
...headings
|
|
103
|
+
]
|
|
104
|
+
}
|
|
105
|
+
}
|