@astrojs/starlight 0.0.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/404.astro +51 -0
- package/CHANGELOG.md +7 -0
- package/LICENSE +21 -0
- package/README.md +28 -0
- package/components/ContentPanel.astro +25 -0
- package/components/EditLink.astro +23 -0
- package/components/FallbackContentNotice.astro +27 -0
- package/components/HeadSEO.astro +60 -0
- package/components/Header.astro +62 -0
- package/components/Icon.astro +36 -0
- package/components/Icons.ts +43 -0
- package/components/LanguageSelect.astro +51 -0
- package/components/LastUpdated.astro +41 -0
- package/components/MarkdownContent.astro +112 -0
- package/components/MobileMenuToggle.astro +89 -0
- package/components/PrevNextLinks.astro +77 -0
- package/components/RightSidebarPanel.astro +38 -0
- package/components/Search.astro +296 -0
- package/components/Select.astro +80 -0
- package/components/Sidebar.astro +34 -0
- package/components/SidebarSublist.astro +78 -0
- package/components/SkipLink.astro +18 -0
- package/components/TableOfContents/TableOfContentsList.astro +35 -0
- package/components/TableOfContents/generateToC.ts +66 -0
- package/components/TableOfContents.astro +17 -0
- package/components/ThemeProvider.astro +50 -0
- package/components/ThemeSelect.astro +88 -0
- package/index.astro +102 -0
- package/index.ts +104 -0
- package/integrations/asides.ts +164 -0
- package/layout/PageFrame.astro +88 -0
- package/layout/TwoColumnContent.astro +42 -0
- package/package.json +42 -0
- package/schema.ts +23 -0
- package/style/asides.css +49 -0
- package/style/props.css +197 -0
- package/style/reset.css +43 -0
- package/style/shiki.css +13 -0
- package/style/util.css +32 -0
- package/types.ts +1 -0
- package/utils/git.ts +96 -0
- package/utils/localizedUrl.ts +32 -0
- package/utils/navigation.ts +232 -0
- package/utils/routing.ts +109 -0
- package/utils/slugs.ts +91 -0
- package/utils/user-config.ts +250 -0
- package/virtual.d.ts +9 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
---
|
|
2
|
+
import MobileMenuToggle from '../components/MobileMenuToggle.astro';
|
|
3
|
+
|
|
4
|
+
const hasSidebar = Astro.slots.has('sidebar');
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<div class:list={['page', { hasSidebar }]}>
|
|
8
|
+
<header class="header"><slot name="header" /></header>
|
|
9
|
+
{
|
|
10
|
+
hasSidebar && (
|
|
11
|
+
<nav class="sidebar" aria-label="Main">
|
|
12
|
+
<MobileMenuToggle />
|
|
13
|
+
<div id="starlight__sidebar" class="sidebar-pane">
|
|
14
|
+
<div class="sidebar-content">
|
|
15
|
+
<slot name="sidebar" />
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
</nav>
|
|
19
|
+
)
|
|
20
|
+
}
|
|
21
|
+
<div class="main-frame"><slot /></div>
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
<style>
|
|
25
|
+
.page {
|
|
26
|
+
display: flex;
|
|
27
|
+
flex-direction: column;
|
|
28
|
+
min-height: 100vh;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.header {
|
|
32
|
+
z-index: var(--sl-z-index-navbar);
|
|
33
|
+
position: fixed;
|
|
34
|
+
inset-inline-start: 0;
|
|
35
|
+
inset-block-start: 0;
|
|
36
|
+
width: 100%;
|
|
37
|
+
height: var(--sl-nav-height);
|
|
38
|
+
border-bottom: 1px solid var(--sl-color-hairline-shade);
|
|
39
|
+
padding: var(--sl-nav-pad-y) var(--sl-nav-pad-x);
|
|
40
|
+
padding-inline-end: var(--sl-nav-pad-x);
|
|
41
|
+
background-color: var(--sl-color-bg-nav);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.hasSidebar .header {
|
|
45
|
+
padding-inline-end: calc(
|
|
46
|
+
var(--sl-nav-gap) + var(--sl-nav-pad-x) + var(--sl-menu-button-size)
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.sidebar-pane {
|
|
51
|
+
visibility: var(--sl-sidebar-visibility, hidden);
|
|
52
|
+
position: fixed;
|
|
53
|
+
inset-block: 0;
|
|
54
|
+
inset-inline-start: 0;
|
|
55
|
+
padding-top: var(--sl-nav-height);
|
|
56
|
+
width: 100%;
|
|
57
|
+
background-color: var(--sl-color-black);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
:global([aria-expanded='true']) ~ .sidebar-pane {
|
|
61
|
+
--sl-sidebar-visibility: visible;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.sidebar-content {
|
|
65
|
+
height: 100%;
|
|
66
|
+
overflow-y: auto;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.main-frame {
|
|
70
|
+
padding-top: var(--sl-nav-height);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
@media (min-width: 50rem) {
|
|
74
|
+
.hasSidebar .header {
|
|
75
|
+
padding-inline-end: var(--sl-nav-pad-x);
|
|
76
|
+
}
|
|
77
|
+
.sidebar-pane {
|
|
78
|
+
--sl-sidebar-visibility: visible;
|
|
79
|
+
width: var(--sl-sidebar-width);
|
|
80
|
+
background-color: var(--sl-color-bg-sidebar);
|
|
81
|
+
border-inline-end: 1px solid var(--sl-color-hairline-shade);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.hasSidebar .main-frame {
|
|
85
|
+
padding-inline-start: var(--sl-sidebar-width);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
</style>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<div class="container">
|
|
2
|
+
<aside class="right-sidebar-container">
|
|
3
|
+
<div class="right-sidebar"><slot name="right-sidebar" /></div>
|
|
4
|
+
</aside>
|
|
5
|
+
<div class="main-pane"><slot /></div>
|
|
6
|
+
</div>
|
|
7
|
+
|
|
8
|
+
<style>
|
|
9
|
+
@media (min-width: 72rem) {
|
|
10
|
+
.container {
|
|
11
|
+
display: flex;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.right-sidebar-container {
|
|
15
|
+
order: 2;
|
|
16
|
+
position: relative;
|
|
17
|
+
width: calc(
|
|
18
|
+
var(--sl-sidebar-width) +
|
|
19
|
+
(100% - var(--sl-content-width) - var(--sl-sidebar-width)) / 2
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.right-sidebar {
|
|
24
|
+
position: fixed;
|
|
25
|
+
top: 0;
|
|
26
|
+
border-inline-start: 1px solid var(--sl-color-gray-6);
|
|
27
|
+
padding-top: var(--sl-nav-height);
|
|
28
|
+
width: 100%;
|
|
29
|
+
height: 100vh;
|
|
30
|
+
overflow-y: auto;
|
|
31
|
+
scrollbar-width: none;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.main-pane {
|
|
35
|
+
order: 1;
|
|
36
|
+
width: calc(
|
|
37
|
+
var(--sl-content-width) +
|
|
38
|
+
(100% - var(--sl-content-width) - var(--sl-sidebar-width)) / 2
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
</style>
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@astrojs/starlight",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Build beautiful, high-performance documentation websites with Astro",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"docs",
|
|
7
|
+
"documentation",
|
|
8
|
+
"astro",
|
|
9
|
+
"withastro"
|
|
10
|
+
],
|
|
11
|
+
"author": "Chris Swithinbank <swithinbank@gmail.com>",
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"type": "module",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": "./index.ts",
|
|
16
|
+
"./schema": "./schema.ts",
|
|
17
|
+
"./types": "./types.ts",
|
|
18
|
+
"./index.astro": "./index.astro",
|
|
19
|
+
"./404.astro": "./404.astro"
|
|
20
|
+
},
|
|
21
|
+
"peerDependencies": {
|
|
22
|
+
"astro": "^2.4.3"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@types/node": "^18.15.11",
|
|
26
|
+
"astro": "^2.4.3"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@astrojs/mdx": "^0.19.1",
|
|
30
|
+
"@pagefind/default-ui": "^0.12.0",
|
|
31
|
+
"@types/mdast": "^3.0.11",
|
|
32
|
+
"bcp-47": "^2.1.0",
|
|
33
|
+
"execa": "^7.1.1",
|
|
34
|
+
"hastscript": "^7.2.0",
|
|
35
|
+
"pagefind": "^0.12.0",
|
|
36
|
+
"remark-directive": "^2.0.1",
|
|
37
|
+
"unified": "^10.1.2",
|
|
38
|
+
"unist-util-remove": "^3.1.1",
|
|
39
|
+
"unist-util-visit": "^4.1.2"
|
|
40
|
+
},
|
|
41
|
+
"scripts": {}
|
|
42
|
+
}
|
package/schema.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { z } from 'astro:content';
|
|
2
|
+
|
|
3
|
+
export function docsSchema() {
|
|
4
|
+
return z.object({
|
|
5
|
+
/** The title of the current page. Required. */
|
|
6
|
+
title: z.string(),
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* A short description of the current page’s content. Optional, but recommended.
|
|
10
|
+
* A good description is 150–160 characters long and outlines the key content
|
|
11
|
+
* of the page in a clear and engaging way.
|
|
12
|
+
*/
|
|
13
|
+
description: z.string().optional(),
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Custom URL where a reader can edit this page.
|
|
17
|
+
* Overrides the `editLink.baseUrl` global config if set.
|
|
18
|
+
*
|
|
19
|
+
* Can also be set to `false` to disable showing an edit link on this page.
|
|
20
|
+
*/
|
|
21
|
+
editUrl: z.union([z.string().url(), z.boolean()]).optional().default(true),
|
|
22
|
+
});
|
|
23
|
+
}
|
package/style/asides.css
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
.starlight-aside {
|
|
2
|
+
padding: 1rem;
|
|
3
|
+
border-inline-start: 0.25rem solid;
|
|
4
|
+
color: var(--sl-color-white);
|
|
5
|
+
}
|
|
6
|
+
.starlight-aside--note {
|
|
7
|
+
--sl-color-asides-text-accent: var(--sl-color-blue-high);
|
|
8
|
+
border-color: var(--sl-color-blue);
|
|
9
|
+
background-color: var(--sl-color-blue-low);
|
|
10
|
+
}
|
|
11
|
+
.starlight-aside--tip {
|
|
12
|
+
--sl-color-asides-text-accent: var(--sl-color-purple-high);
|
|
13
|
+
border-color: var(--sl-color-purple);
|
|
14
|
+
background-color: var(--sl-color-purple-low);
|
|
15
|
+
}
|
|
16
|
+
.starlight-aside--caution {
|
|
17
|
+
--sl-color-asides-text-accent: var(--sl-color-orange-high);
|
|
18
|
+
border-color: var(--sl-color-orange);
|
|
19
|
+
background-color: var(--sl-color-orange-low);
|
|
20
|
+
}
|
|
21
|
+
.starlight-aside--danger {
|
|
22
|
+
--sl-color-asides-text-accent: var(--sl-color-red-high);
|
|
23
|
+
border-color: var(--sl-color-red);
|
|
24
|
+
background-color: var(--sl-color-red-low);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.starlight-aside__title {
|
|
28
|
+
display: flex;
|
|
29
|
+
gap: 0.5rem;
|
|
30
|
+
align-items: center;
|
|
31
|
+
font-size: var(--sl-text-h5);
|
|
32
|
+
font-weight: 600;
|
|
33
|
+
line-height: var(--sl-line-height-headings);
|
|
34
|
+
color: var(--sl-color-asides-text-accent);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.starlight-aside__icon {
|
|
38
|
+
font-size: 1.333em;
|
|
39
|
+
width: 1em;
|
|
40
|
+
height: 1em;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.starlight-aside__title + .starlight-aside__content {
|
|
44
|
+
margin-top: 0.5rem;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.starlight-aside__content a {
|
|
48
|
+
color: var(--sl-color-asides-text-accent);
|
|
49
|
+
}
|
package/style/props.css
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
:root,
|
|
2
|
+
::backdrop {
|
|
3
|
+
/* Colors (dark mode) */
|
|
4
|
+
--sl-color-white: hsl(0, 0%, 100%); /* “white” */
|
|
5
|
+
--sl-color-gray-1: hsl(231, 23%, 94%);
|
|
6
|
+
--sl-color-gray-2: hsl(228, 8%, 77%);
|
|
7
|
+
--sl-color-gray-3: hsl(221, 8%, 56%);
|
|
8
|
+
--sl-color-gray-4: hsl(225, 9%, 36%);
|
|
9
|
+
--sl-color-gray-5: hsl(222, 11%, 23%);
|
|
10
|
+
--sl-color-gray-6: hsl(222, 13%, 16%);
|
|
11
|
+
--sl-color-black: hsl(223, 13%, 10%);
|
|
12
|
+
|
|
13
|
+
--sl-hue-orange: 41;
|
|
14
|
+
--sl-color-orange-low: hsl(var(--sl-hue-orange), 39%, 22%);
|
|
15
|
+
--sl-color-orange: hsl(var(--sl-hue-orange), 82%, 63%);
|
|
16
|
+
--sl-color-orange-high: hsl(var(--sl-hue-orange), 82%, 87%);
|
|
17
|
+
--sl-hue-green: 101;
|
|
18
|
+
--sl-color-green-low: hsl(var(--sl-hue-green), 39%, 22%);
|
|
19
|
+
--sl-color-green: hsl(var(--sl-hue-green), 82%, 63%);
|
|
20
|
+
--sl-color-green-high: hsl(var(--sl-hue-green), 82%, 87%);
|
|
21
|
+
--sl-hue-blue: 234;
|
|
22
|
+
--sl-color-blue-low: hsl(var(--sl-hue-blue), 54%, 20%);
|
|
23
|
+
--sl-color-blue: hsl(var(--sl-hue-blue), 100%, 60%);
|
|
24
|
+
--sl-color-blue-high: hsl(var(--sl-hue-blue), 100%, 87%);
|
|
25
|
+
--sl-hue-purple: 281;
|
|
26
|
+
--sl-color-purple-low: hsl(var(--sl-hue-purple), 39%, 22%);
|
|
27
|
+
--sl-color-purple: hsl(var(--sl-hue-purple), 82%, 63%);
|
|
28
|
+
--sl-color-purple-high: hsl(var(--sl-hue-purple), 82%, 89%);
|
|
29
|
+
--sl-hue-red: 339;
|
|
30
|
+
--sl-color-red-low: hsl(var(--sl-hue-red), 39%, 22%);
|
|
31
|
+
--sl-color-red: hsl(var(--sl-hue-red), 82%, 63%);
|
|
32
|
+
--sl-color-red-high: hsl(var(--sl-hue-red), 82%, 87%);
|
|
33
|
+
|
|
34
|
+
--sl-hue-accent: var(--sl-hue-blue);
|
|
35
|
+
--sl-color-accent-low: hsl(var(--sl-hue-accent), 54%, 20%);
|
|
36
|
+
--sl-color-accent: hsl(var(--sl-hue-accent), 100%, 60%);
|
|
37
|
+
--sl-color-accent-high: hsl(var(--sl-hue-accent), 100%, 87%);
|
|
38
|
+
|
|
39
|
+
--sl-color-text: var(--sl-color-gray-2);
|
|
40
|
+
--sl-color-text-accent: var(--sl-color-accent-high);
|
|
41
|
+
--sl-color-text-invert: var(--sl-color-accent-low);
|
|
42
|
+
--sl-color-bg: var(--sl-color-black);
|
|
43
|
+
--sl-color-bg-nav: var(--sl-color-gray-6);
|
|
44
|
+
--sl-color-bg-sidebar: var(--sl-color-gray-6);
|
|
45
|
+
--sl-color-bg-inline-code: var(--sl-color-gray-5);
|
|
46
|
+
--sl-color-hairline: var(--sl-color-gray-6);
|
|
47
|
+
--sl-color-hairline-shade: var(--sl-color-black);
|
|
48
|
+
|
|
49
|
+
--sl-color-backdrop-overlay: hsla(223, 13%, 10%, 0.66);
|
|
50
|
+
|
|
51
|
+
/* Shadows (dark mode) */
|
|
52
|
+
--sl-shadow-sm: 0px 1px 1px hsla(0, 0%, 0%, 0.12),
|
|
53
|
+
0px 2px 1px hsla(0, 0%, 0%, 0.24);
|
|
54
|
+
--sl-shadow-md: 0px 8px 4px hsla(0, 0%, 0%, 0.08),
|
|
55
|
+
0px 5px 2px hsla(0, 0%, 0%, 0.08), 0px 3px 2px hsla(0, 0%, 0%, 0.12),
|
|
56
|
+
0px 1px 1px hsla(0, 0%, 0%, 0.15);
|
|
57
|
+
--sl-shadow-lg: 0px 25px 7px hsla(0, 0%, 0%, 0.03),
|
|
58
|
+
0px 16px 6px hsla(0, 0%, 0%, 0.1), 0px 9px 5px hsla(223, 13%, 10%, 0.33),
|
|
59
|
+
0px 4px 4px hsla(0, 0%, 0%, 0.75), 0px 4px 2px hsla(0, 0%, 0%, 0.25);
|
|
60
|
+
|
|
61
|
+
/* Gradients (unchanged across dark & light modes) */
|
|
62
|
+
--sl-gradient-blue-purple: linear-gradient(
|
|
63
|
+
to bottom,
|
|
64
|
+
hsl(234, 100%, 59.8%) 0%,
|
|
65
|
+
hsl(281, 82.1%, 62.7%) 100%
|
|
66
|
+
);
|
|
67
|
+
--sl-gradient-red-pink: linear-gradient(
|
|
68
|
+
to bottom,
|
|
69
|
+
hsl(0, 67.9%, 52.4%) 0%,
|
|
70
|
+
hsl(295, 100%, 62.7%) 100%
|
|
71
|
+
);
|
|
72
|
+
--sl-gradient-orange-yellow: linear-gradient(
|
|
73
|
+
to bottom,
|
|
74
|
+
hsl(54, 93.5%, 57.6%) 0%,
|
|
75
|
+
hsl(14, 100%, 66.5%) 100%
|
|
76
|
+
);
|
|
77
|
+
--sl-gradient-blue-green: linear-gradient(
|
|
78
|
+
to bottom,
|
|
79
|
+
hsl(165, 86.6%, 62%) 0%,
|
|
80
|
+
hsl(227, 58.4%, 44.3%) 100%
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
/* Text size and line height */
|
|
84
|
+
--sl-text-xs: 0.8125rem; /* 13px */
|
|
85
|
+
--sl-text-sm: 0.875rem; /* 14px */
|
|
86
|
+
--sl-text-base: 1rem; /* 16px */
|
|
87
|
+
--sl-text-lg: 1.125rem; /* 18px */
|
|
88
|
+
--sl-text-xl: 1.25rem; /* 20px */
|
|
89
|
+
--sl-text-2xl: 1.5rem; /* 24px */
|
|
90
|
+
--sl-text-3xl: 1.8125rem; /* 29px */
|
|
91
|
+
--sl-text-4xl: 2.1875rem; /* 35px */
|
|
92
|
+
--sl-text-5xl: 2.625rem; /* 42px */
|
|
93
|
+
|
|
94
|
+
--sl-text-body: var(--sl-text-base);
|
|
95
|
+
--sl-text-body-sm: var(--sl-text-xs);
|
|
96
|
+
--sl-text-code: var(--sl-text-base);
|
|
97
|
+
--sl-text-code-sm: var(--sl-text-xs);
|
|
98
|
+
--sl-text-h1: var(--sl-text-4xl);
|
|
99
|
+
--sl-text-h2: var(--sl-text-3xl);
|
|
100
|
+
--sl-text-h3: var(--sl-text-2xl);
|
|
101
|
+
--sl-text-h4: var(--sl-text-xl);
|
|
102
|
+
--sl-text-h5: var(--sl-text-lg);
|
|
103
|
+
|
|
104
|
+
--sl-line-height: 1.8;
|
|
105
|
+
--sl-line-height-headings: 1.2;
|
|
106
|
+
|
|
107
|
+
--sl-font-system: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
|
|
108
|
+
'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif,
|
|
109
|
+
'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
|
110
|
+
--sl-font-system-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
|
|
111
|
+
'Liberation Mono', 'Courier New', monospace;
|
|
112
|
+
--__sb-font: var(--sl-font, ''), var(--sl-font-system);
|
|
113
|
+
--__sb-font-mono: var(--sl-font-mono, ''), var(--sl-font-system-mono);
|
|
114
|
+
|
|
115
|
+
/** Key layout values */
|
|
116
|
+
--sl-nav-height: 4rem;
|
|
117
|
+
--sl-nav-pad-x: 1.5rem;
|
|
118
|
+
--sl-nav-pad-y: 0.75rem;
|
|
119
|
+
--sl-sidebar-width: 18.75rem;
|
|
120
|
+
--sl-sidebar-pad-x: 1rem;
|
|
121
|
+
--sl-content-width: 45rem;
|
|
122
|
+
--sl-content-pad-x: 1rem;
|
|
123
|
+
--sl-menu-button-size: 2rem;
|
|
124
|
+
--sl-nav-gap: var(--sl-content-pad-x);
|
|
125
|
+
|
|
126
|
+
/* Global z-index values */
|
|
127
|
+
--sl-z-index-navbar: 10;
|
|
128
|
+
--sl-z-index-skiplink: 20;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
:root[data-theme='light'],
|
|
132
|
+
[data-theme='light'] ::backdrop {
|
|
133
|
+
/* Colours (light mode) */
|
|
134
|
+
--sl-color-white: hsl(223, 13%, 10%);
|
|
135
|
+
--sl-color-gray-1: hsl(222, 13%, 16%);
|
|
136
|
+
--sl-color-gray-2: hsl(222, 11%, 23%);
|
|
137
|
+
--sl-color-gray-3: hsl(225, 9%, 36%);
|
|
138
|
+
--sl-color-gray-4: hsl(221, 8%, 56%);
|
|
139
|
+
--sl-color-gray-5: hsl(228, 8%, 77%);
|
|
140
|
+
--sl-color-gray-6: hsl(231, 23%, 94%);
|
|
141
|
+
--sl-color-gray-7: hsl(240, 20%, 97%);
|
|
142
|
+
--sl-color-black: hsl(0, 0%, 100%);
|
|
143
|
+
|
|
144
|
+
--sl-color-orange-high: hsl(var(--sl-hue-orange), 80%, 25%);
|
|
145
|
+
--sl-color-orange: hsl(var(--sl-hue-orange), 90%, 60%);
|
|
146
|
+
--sl-color-orange-low: hsl(var(--sl-hue-orange), 90%, 88%);
|
|
147
|
+
--sl-color-green-high: hsl(var(--sl-hue-green), 80%, 22%);
|
|
148
|
+
--sl-color-green: hsl(var(--sl-hue-green), 90%, 60%);
|
|
149
|
+
--sl-color-green-low: hsl(var(--sl-hue-green), 85%, 90%);
|
|
150
|
+
--sl-color-blue-high: hsl(var(--sl-hue-blue), 80%, 30%);
|
|
151
|
+
--sl-color-blue: hsl(var(--sl-hue-blue), 90%, 60%);
|
|
152
|
+
--sl-color-blue-low: hsl(var(--sl-hue-blue), 88%, 90%);
|
|
153
|
+
--sl-color-purple-high: hsl(var(--sl-hue-purple), 39%, 30%);
|
|
154
|
+
--sl-color-purple: hsl(var(--sl-hue-purple), 90%, 60%);
|
|
155
|
+
--sl-color-purple-low: hsl(var(--sl-hue-purple), 80%, 90%);
|
|
156
|
+
--sl-color-red-high: hsl(var(--sl-hue-red), 80%, 30%);
|
|
157
|
+
--sl-color-red: hsl(var(--sl-hue-red), 90%, 60%);
|
|
158
|
+
--sl-color-red-low: hsl(var(--sl-hue-red), 80%, 90%);
|
|
159
|
+
|
|
160
|
+
--sl-color-accent-high: hsl(var(--sl-hue-accent), 80%, 30%);
|
|
161
|
+
--sl-color-accent: hsl(var(--sl-hue-accent), 90%, 60%);
|
|
162
|
+
--sl-color-accent-low: hsl(var(--sl-hue-accent), 88%, 90%);
|
|
163
|
+
|
|
164
|
+
--sl-color-text-accent: var(--sl-color-accent);
|
|
165
|
+
--sl-color-text-invert: var(--sl-color-black);
|
|
166
|
+
--sl-color-bg-nav: var(--sl-color-gray-7);
|
|
167
|
+
--sl-color-bg-sidebar: var(--sl-color-bg);
|
|
168
|
+
--sl-color-bg-inline-code: var(--sl-color-gray-6);
|
|
169
|
+
--sl-color-hairline-shade: var(--sl-color-gray-6);
|
|
170
|
+
|
|
171
|
+
--sl-color-backdrop-overlay: hsla(225, 9%, 36%, 0.66);
|
|
172
|
+
|
|
173
|
+
/* Shadows (light mode) */
|
|
174
|
+
--sl-shadow-sm: 0px 1px 1px hsla(0, 0%, 0%, 0.06),
|
|
175
|
+
0px 2px 1px hsla(0, 0%, 0%, 0.06);
|
|
176
|
+
--sl-shadow-md: 0px 8px 4px hsla(0, 0%, 0%, 0.03),
|
|
177
|
+
0px 5px 2px hsla(0, 0%, 0%, 0.03), 0px 3px 2px hsla(0, 0%, 0%, 0.06),
|
|
178
|
+
0px 1px 1px hsla(0, 0%, 0%, 0.06);
|
|
179
|
+
--sl-shadow-lg: 0px 25px 7px rgba(0, 0, 0, 0.01),
|
|
180
|
+
0px 16px 6px hsla(0, 0%, 0%, 0.03), 0px 9px 5px hsla(223, 13%, 10%, 0.08),
|
|
181
|
+
0px 4px 4px hsla(0, 0%, 0%, 0.16), 0px 4px 2px hsla(0, 0%, 0%, 0.04);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
@media (min-width: 50em) {
|
|
185
|
+
:root {
|
|
186
|
+
--sl-text-h1: var(--sl-text-5xl);
|
|
187
|
+
--sl-text-h2: var(--sl-text-4xl);
|
|
188
|
+
--sl-text-h3: var(--sl-text-3xl);
|
|
189
|
+
--sl-text-h4: var(--sl-text-2xl);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
@media (min-width: 72rem) {
|
|
194
|
+
:root {
|
|
195
|
+
--sl-content-pad-x: 1.5rem;
|
|
196
|
+
}
|
|
197
|
+
}
|
package/style/reset.css
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
*,
|
|
2
|
+
*::before,
|
|
3
|
+
*::after {
|
|
4
|
+
box-sizing: border-box;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
* {
|
|
8
|
+
margin: 0;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
html {
|
|
12
|
+
color-scheme: dark;
|
|
13
|
+
accent-color: var(--sl-color-accent);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
html[data-theme='light'] {
|
|
17
|
+
color-scheme: light;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
body {
|
|
21
|
+
font-family: var(--__sb-font);
|
|
22
|
+
line-height: var(--sl-line-height);
|
|
23
|
+
-webkit-font-smoothing: antialiased;
|
|
24
|
+
color: var(--sl-color-text);
|
|
25
|
+
background-color: var(--sl-color-bg);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
input,
|
|
29
|
+
button,
|
|
30
|
+
textarea,
|
|
31
|
+
select {
|
|
32
|
+
font: inherit;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
p,
|
|
36
|
+
h1,
|
|
37
|
+
h2,
|
|
38
|
+
h3,
|
|
39
|
+
h4,
|
|
40
|
+
h5,
|
|
41
|
+
h6 {
|
|
42
|
+
overflow-wrap: break-word;
|
|
43
|
+
}
|
package/style/shiki.css
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--astro-code-color-text: var(--sl-color-white);
|
|
3
|
+
--astro-code-color-background: var(--sl-color-gray-6);
|
|
4
|
+
--astro-code-token-constant: var(--sl-color-blue-high);
|
|
5
|
+
--astro-code-token-string: var(--sl-color-green-high);
|
|
6
|
+
--astro-code-token-comment: var(--sl-color-gray-2);
|
|
7
|
+
--astro-code-token-keyword: var(--sl-color-purple-high);
|
|
8
|
+
--astro-code-token-parameter: var(--sl-color-red-high);
|
|
9
|
+
--astro-code-token-function: var(--sl-color-red-high);
|
|
10
|
+
--astro-code-token-string-expression: var(--sl-color-green-high);
|
|
11
|
+
--astro-code-token-punctuation: var(--sl-color-gray-2);
|
|
12
|
+
--astro-code-token-link: var(--sl-color-blue-high);
|
|
13
|
+
}
|
package/style/util.css
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
.sr-only {
|
|
2
|
+
position: absolute;
|
|
3
|
+
width: 1px;
|
|
4
|
+
height: 1px;
|
|
5
|
+
padding: 0;
|
|
6
|
+
margin: -1px;
|
|
7
|
+
overflow: hidden;
|
|
8
|
+
clip: rect(0, 0, 0, 0);
|
|
9
|
+
white-space: nowrap;
|
|
10
|
+
border-width: 0;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.hidden {
|
|
14
|
+
display: none;
|
|
15
|
+
}
|
|
16
|
+
.flex {
|
|
17
|
+
display: flex;
|
|
18
|
+
}
|
|
19
|
+
.block {
|
|
20
|
+
display: block;
|
|
21
|
+
}
|
|
22
|
+
@media (min-width: 50rem) {
|
|
23
|
+
.md\:hidden {
|
|
24
|
+
display: none;
|
|
25
|
+
}
|
|
26
|
+
.md\:flex {
|
|
27
|
+
display: flex;
|
|
28
|
+
}
|
|
29
|
+
.md\:block {
|
|
30
|
+
display: block;
|
|
31
|
+
}
|
|
32
|
+
}
|
package/types.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { StarlightConfig } from './utils/user-config';
|
package/utils/git.ts
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Heavily inspired by
|
|
3
|
+
* https://github.com/facebook/docusaurus/blob/46d2aa231ddb18ed67311b6195260af46d7e8bdc/packages/docusaurus-utils/src/gitUtils.ts
|
|
4
|
+
*
|
|
5
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
6
|
+
*
|
|
7
|
+
* This source code is licensed under the MIT license found in the
|
|
8
|
+
* LICENSE file in the root directory of this source tree.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import path from 'node:path';
|
|
12
|
+
import { execaSync } from 'execa';
|
|
13
|
+
|
|
14
|
+
/** Custom error thrown when git is not found in `PATH`. */
|
|
15
|
+
class GitNotFoundError extends Error {}
|
|
16
|
+
|
|
17
|
+
/** Custom error thrown when the current file is not tracked by git. */
|
|
18
|
+
class FileNotTrackedError extends Error {}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Fetches the git history of a file and returns a relevant commit date.
|
|
22
|
+
* It gets the commit date instead of author date so that amended commits
|
|
23
|
+
* can have their dates updated.
|
|
24
|
+
*
|
|
25
|
+
* @throws {GitNotFoundError} If git is not found in `PATH`.
|
|
26
|
+
* @throws {FileNotTrackedError} If the current file is not tracked by git.
|
|
27
|
+
* @throws Also throws when `git log` exited with non-zero, or when it outputs
|
|
28
|
+
* unexpected text.
|
|
29
|
+
*/
|
|
30
|
+
export function getFileCommitDate(
|
|
31
|
+
file: string,
|
|
32
|
+
age: 'oldest' | 'newest' = 'oldest'
|
|
33
|
+
): {
|
|
34
|
+
date: Date;
|
|
35
|
+
timestamp: number;
|
|
36
|
+
} {
|
|
37
|
+
try {
|
|
38
|
+
const { stdout } = execaSync('which', ['git']);
|
|
39
|
+
if (!stdout) {
|
|
40
|
+
throw new GitNotFoundError(
|
|
41
|
+
`Failed to retrieve git history for "${file}" because git is not installed.`
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
} catch {}
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
const { stdout } = execaSync('test', ['-f', file]);
|
|
48
|
+
if (!stdout) {
|
|
49
|
+
throw new Error(
|
|
50
|
+
`Failed to retrieve git history for "${file}" because the file does not exist.`
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
} catch {}
|
|
54
|
+
|
|
55
|
+
const result = execaSync(
|
|
56
|
+
'git',
|
|
57
|
+
[
|
|
58
|
+
'log',
|
|
59
|
+
`--format=%ct`,
|
|
60
|
+
'--max-count=1',
|
|
61
|
+
...(age === 'oldest' ? ['--follow', '--diff-filter=A'] : []),
|
|
62
|
+
'--',
|
|
63
|
+
path.basename(file),
|
|
64
|
+
],
|
|
65
|
+
{
|
|
66
|
+
cwd: path.dirname(file),
|
|
67
|
+
}
|
|
68
|
+
);
|
|
69
|
+
if (result.exitCode !== 0) {
|
|
70
|
+
throw new Error(
|
|
71
|
+
`Failed to retrieve the git history for file "${file}" with exit code ${result.exitCode}: ${result.stderr}`
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
let regex = /^(?<timestamp>\d+)$/;
|
|
75
|
+
|
|
76
|
+
const output = result.stdout.trim();
|
|
77
|
+
|
|
78
|
+
if (!output) {
|
|
79
|
+
throw new FileNotTrackedError(
|
|
80
|
+
`Failed to retrieve the git history for file "${file}" because the file is not tracked by git.`
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const match = output.match(regex);
|
|
85
|
+
|
|
86
|
+
if (!match) {
|
|
87
|
+
throw new Error(
|
|
88
|
+
`Failed to retrieve the git history for file "${file}" with unexpected output: ${output}`
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const timestamp = Number(match.groups!.timestamp);
|
|
93
|
+
const date = new Date(timestamp * 1000);
|
|
94
|
+
|
|
95
|
+
return { date, timestamp };
|
|
96
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import config from 'virtual:starlight/user-config';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Get the equivalent of the passed URL for the passed locale.
|
|
5
|
+
*/
|
|
6
|
+
export function localizedUrl(url: URL, locale: string | undefined): URL {
|
|
7
|
+
// Create a new URL object to void mutating the global.
|
|
8
|
+
url = new URL(url);
|
|
9
|
+
if (!config.locales) {
|
|
10
|
+
// i18n is not configured on this site, no localization required.
|
|
11
|
+
return url;
|
|
12
|
+
}
|
|
13
|
+
if (locale === 'root') locale = '';
|
|
14
|
+
/** Base URL with trailing `/` stripped. */
|
|
15
|
+
const base = import.meta.env.BASE_URL.replace(/\/$/, '');
|
|
16
|
+
const hasBase = url.pathname.startsWith(base);
|
|
17
|
+
// Temporarily remove base to simplify
|
|
18
|
+
if (hasBase) url.pathname = url.pathname.replace(base, '');
|
|
19
|
+
const [_leadingSlash, baseSegment] = url.pathname.split('/');
|
|
20
|
+
if (baseSegment && baseSegment in config.locales) {
|
|
21
|
+
// We’re in a localized route, substitute the new locale (or strip for root lang).
|
|
22
|
+
url.pathname = locale
|
|
23
|
+
? url.pathname.replace(baseSegment, locale)
|
|
24
|
+
: url.pathname.replace('/' + baseSegment, '');
|
|
25
|
+
} else if (locale) {
|
|
26
|
+
// We’re in the root language. Inject the new locale if we have one.
|
|
27
|
+
url.pathname = '/' + locale + url.pathname;
|
|
28
|
+
}
|
|
29
|
+
// Restore base
|
|
30
|
+
if (hasBase) url.pathname = base + url.pathname;
|
|
31
|
+
return url;
|
|
32
|
+
}
|