@astrojs/starlight 0.10.3 → 0.11.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/404.astro +9 -4
- package/CHANGELOG.md +73 -0
- package/components/Badge.astro +1 -0
- package/components/Banner.astro +4 -4
- package/components/ContentPanel.astro +4 -0
- package/components/EditLink.astro +5 -24
- package/components/FallbackContentNotice.astro +2 -5
- package/components/Footer.astro +5 -32
- package/components/{HeadSEO.astro → Head.astro} +10 -14
- package/components/Header.astro +26 -16
- package/components/Hero.astro +6 -9
- package/components/Icons.ts +9 -0
- package/components/LanguageSelect.astro +1 -4
- package/components/LastUpdated.astro +5 -24
- package/components/MarkdownContent.astro +4 -0
- package/components/MobileMenuFooter.astro +17 -0
- package/components/MobileMenuToggle.astro +2 -4
- package/components/{TableOfContents/MobileTableOfContents.astro → MobileTableOfContents.astro} +26 -29
- package/components/Page.astro +120 -0
- package/{layout → components}/PageFrame.astro +16 -8
- package/components/{RightSidebarPanel.astro → PageSidebar.astro} +21 -9
- package/components/PageTitle.astro +16 -0
- package/components/{PrevNextLinks.astro → Pagination.astro} +3 -9
- package/components/Search.astro +5 -5
- package/components/Sidebar.astro +7 -36
- package/components/SidebarSublist.astro +8 -2
- package/components/SiteTitle.astro +1 -20
- package/components/SkipLink.astro +3 -5
- package/components/SocialIcons.astro +5 -31
- package/components/TableOfContents/TableOfContentsList.astro +1 -1
- package/components/TableOfContents/starlight-toc.ts +3 -1
- package/components/TableOfContents.astro +12 -15
- package/components/ThemeProvider.astro +1 -0
- package/components/ThemeSelect.astro +1 -4
- package/{layout → components}/TwoColumnContent.astro +2 -4
- package/constants.ts +4 -0
- package/index.astro +4 -2
- package/index.ts +10 -15
- package/integrations/virtual-user-config.ts +3 -0
- package/package.json +133 -4
- package/props.ts +1 -0
- package/schema.ts +3 -0
- package/schemas/components.ts +256 -0
- package/schemas/sidebar.ts +89 -0
- package/schemas/social.ts +65 -0
- package/style/reset.css +1 -1
- package/translations/ar.json +8 -8
- package/translations/index.ts +2 -0
- package/translations/vi.json +22 -0
- package/{components/TableOfContents → utils}/generateToC.ts +2 -1
- package/utils/navigation.ts +22 -5
- package/utils/route-data.ts +97 -0
- package/utils/routing.ts +10 -0
- package/utils/user-config.ts +15 -99
- package/utils/validateLogoImports.ts +21 -0
- package/virtual.d.ts +37 -0
- package/components/RightSidebar.astro +0 -36
- package/layout/Page.astro +0 -132
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { Props } from '../props';
|
|
3
|
+
|
|
4
|
+
// Built-in CSS styles.
|
|
5
|
+
import '../style/props.css';
|
|
6
|
+
import '../style/reset.css';
|
|
7
|
+
import '../style/shiki.css';
|
|
8
|
+
import '../style/util.css';
|
|
9
|
+
|
|
10
|
+
// Components — can override built-in CSS, but not user CSS.
|
|
11
|
+
import {
|
|
12
|
+
Banner,
|
|
13
|
+
ContentPanel,
|
|
14
|
+
PageTitle,
|
|
15
|
+
FallbackContentNotice,
|
|
16
|
+
Footer,
|
|
17
|
+
Header,
|
|
18
|
+
Head,
|
|
19
|
+
Hero,
|
|
20
|
+
MarkdownContent,
|
|
21
|
+
PageSidebar,
|
|
22
|
+
Sidebar,
|
|
23
|
+
SkipLink,
|
|
24
|
+
ThemeProvider,
|
|
25
|
+
PageFrame,
|
|
26
|
+
TwoColumnContent,
|
|
27
|
+
} from 'virtual:starlight/components';
|
|
28
|
+
|
|
29
|
+
// Remark component CSS (needs to override `MarkdownContent.astro`)
|
|
30
|
+
import '../style/asides.css';
|
|
31
|
+
|
|
32
|
+
// Important that this is the last import so it can override built-in styles.
|
|
33
|
+
import 'virtual:starlight/user-css';
|
|
34
|
+
|
|
35
|
+
const pagefindEnabled =
|
|
36
|
+
Astro.props.entry.slug !== '404' &&
|
|
37
|
+
!Astro.props.entry.slug.endsWith('/404') &&
|
|
38
|
+
Astro.props.entry.data.pagefind !== false;
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
<html
|
|
42
|
+
lang={Astro.props.lang}
|
|
43
|
+
dir={Astro.props.dir}
|
|
44
|
+
data-has-toc={Boolean(Astro.props.toc)}
|
|
45
|
+
data-has-sidebar={Astro.props.hasSidebar}
|
|
46
|
+
data-has-hero={Boolean(Astro.props.entry.data.hero)}
|
|
47
|
+
>
|
|
48
|
+
<head>
|
|
49
|
+
<Head {...Astro.props} />
|
|
50
|
+
<style>
|
|
51
|
+
html:not([data-has-toc]) {
|
|
52
|
+
--sl-mobile-toc-height: 0rem;
|
|
53
|
+
}
|
|
54
|
+
html:not([data-has-sidebar]) {
|
|
55
|
+
--sl-content-width: 67.5rem;
|
|
56
|
+
}
|
|
57
|
+
/* Add scroll padding to ensure anchor headings aren't obscured by nav */
|
|
58
|
+
html {
|
|
59
|
+
/* Additional padding is needed to account for the mobile TOC */
|
|
60
|
+
scroll-padding-top: calc(1.5rem + var(--sl-nav-height) + var(--sl-mobile-toc-height));
|
|
61
|
+
}
|
|
62
|
+
main {
|
|
63
|
+
padding-bottom: 3vh;
|
|
64
|
+
}
|
|
65
|
+
@media (min-width: 50em) {
|
|
66
|
+
[data-has-sidebar] {
|
|
67
|
+
--sl-content-inline-start: var(--sl-sidebar-width);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
@media (min-width: 72em) {
|
|
71
|
+
html {
|
|
72
|
+
scroll-padding-top: calc(1.5rem + var(--sl-nav-height));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
</style>
|
|
76
|
+
<ThemeProvider {...Astro.props} />
|
|
77
|
+
</head>
|
|
78
|
+
<body>
|
|
79
|
+
<SkipLink {...Astro.props} />
|
|
80
|
+
<PageFrame {...Astro.props}>
|
|
81
|
+
<Header slot="header" {...Astro.props} />
|
|
82
|
+
{Astro.props.hasSidebar && <Sidebar slot="sidebar" {...Astro.props} />}
|
|
83
|
+
<TwoColumnContent {...Astro.props}>
|
|
84
|
+
<PageSidebar slot="right-sidebar" {...Astro.props} />
|
|
85
|
+
<main
|
|
86
|
+
data-pagefind-body={pagefindEnabled}
|
|
87
|
+
lang={Astro.props.entryMeta.lang}
|
|
88
|
+
dir={Astro.props.entryMeta.dir}
|
|
89
|
+
>
|
|
90
|
+
{/* TODO: Revisit how this logic flows. */}
|
|
91
|
+
<Banner {...Astro.props} />
|
|
92
|
+
{
|
|
93
|
+
Astro.props.entry.data.hero ? (
|
|
94
|
+
<ContentPanel {...Astro.props}>
|
|
95
|
+
<Hero {...Astro.props} />
|
|
96
|
+
<MarkdownContent {...Astro.props}>
|
|
97
|
+
<slot />
|
|
98
|
+
</MarkdownContent>
|
|
99
|
+
<Footer {...Astro.props} />
|
|
100
|
+
</ContentPanel>
|
|
101
|
+
) : (
|
|
102
|
+
<>
|
|
103
|
+
<ContentPanel {...Astro.props}>
|
|
104
|
+
<PageTitle {...Astro.props} />
|
|
105
|
+
{Astro.props.isFallback && <FallbackContentNotice {...Astro.props} />}
|
|
106
|
+
</ContentPanel>
|
|
107
|
+
<ContentPanel {...Astro.props}>
|
|
108
|
+
<MarkdownContent {...Astro.props}>
|
|
109
|
+
<slot />
|
|
110
|
+
</MarkdownContent>
|
|
111
|
+
<Footer {...Astro.props} />
|
|
112
|
+
</ContentPanel>
|
|
113
|
+
</>
|
|
114
|
+
)
|
|
115
|
+
}
|
|
116
|
+
</main>
|
|
117
|
+
</TwoColumnContent>
|
|
118
|
+
</PageFrame>
|
|
119
|
+
</body>
|
|
120
|
+
</html>
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
---
|
|
2
|
-
import
|
|
2
|
+
import type { Props } from '../props';
|
|
3
3
|
import { useTranslations } from '../utils/translations';
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
hasSidebar: boolean;
|
|
7
|
-
locale: string | undefined;
|
|
8
|
-
}
|
|
5
|
+
import { MobileMenuToggle } from 'virtual:starlight/components';
|
|
9
6
|
|
|
10
7
|
const { hasSidebar, locale } = Astro.props;
|
|
11
8
|
const t = useTranslations(locale);
|
|
@@ -16,9 +13,9 @@ const t = useTranslations(locale);
|
|
|
16
13
|
{
|
|
17
14
|
hasSidebar && (
|
|
18
15
|
<nav class="sidebar" aria-label={t('sidebarNav.accessibleLabel')}>
|
|
19
|
-
<MobileMenuToggle {
|
|
16
|
+
<MobileMenuToggle {...Astro.props} />
|
|
20
17
|
<div id="starlight__sidebar" class="sidebar-pane">
|
|
21
|
-
<div class="sidebar-content">
|
|
18
|
+
<div class="sidebar-content sl-flex">
|
|
22
19
|
<slot name="sidebar" />
|
|
23
20
|
</div>
|
|
24
21
|
</div>
|
|
@@ -60,6 +57,7 @@ const t = useTranslations(locale);
|
|
|
60
57
|
padding-top: var(--sl-nav-height);
|
|
61
58
|
width: 100%;
|
|
62
59
|
background-color: var(--sl-color-black);
|
|
60
|
+
overflow-y: auto;
|
|
63
61
|
}
|
|
64
62
|
|
|
65
63
|
:global([aria-expanded='true']) ~ .sidebar-pane {
|
|
@@ -68,7 +66,17 @@ const t = useTranslations(locale);
|
|
|
68
66
|
|
|
69
67
|
.sidebar-content {
|
|
70
68
|
height: 100%;
|
|
71
|
-
|
|
69
|
+
min-height: max-content;
|
|
70
|
+
padding: 1rem var(--sl-sidebar-pad-x) 0;
|
|
71
|
+
flex-direction: column;
|
|
72
|
+
gap: 1rem;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
@media (min-width: 50rem) {
|
|
76
|
+
.sidebar-content::after {
|
|
77
|
+
content: '';
|
|
78
|
+
padding-bottom: 1px;
|
|
79
|
+
}
|
|
72
80
|
}
|
|
73
81
|
|
|
74
82
|
.main-frame {
|
|
@@ -1,16 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
---
|
|
2
|
+
import type { Props } from '../props';
|
|
3
|
+
|
|
4
|
+
import { TableOfContents, MobileTableOfContents } from 'virtual:starlight/components';
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
{
|
|
8
|
+
Astro.props.toc && (
|
|
9
|
+
<>
|
|
10
|
+
<div class="lg:sl-hidden">
|
|
11
|
+
<MobileTableOfContents {...Astro.props} />
|
|
12
|
+
</div>
|
|
13
|
+
<div class="right-sidebar-panel sl-hidden lg:sl-block">
|
|
14
|
+
<div class="sl-container">
|
|
15
|
+
<TableOfContents {...Astro.props} />
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
</>
|
|
19
|
+
)
|
|
20
|
+
}
|
|
6
21
|
|
|
7
22
|
<style>
|
|
8
23
|
.right-sidebar-panel {
|
|
9
24
|
padding: 1rem var(--sl-sidebar-pad-x);
|
|
10
25
|
}
|
|
11
|
-
.right-sidebar-panel + .right-sidebar-panel {
|
|
12
|
-
border-top: 1px solid var(--sl-color-hairline);
|
|
13
|
-
}
|
|
14
26
|
.sl-container {
|
|
15
27
|
width: calc(var(--sl-sidebar-width) - 2 * var(--sl-sidebar-pad-x));
|
|
16
28
|
}
|
|
@@ -26,7 +38,7 @@
|
|
|
26
38
|
font-size: var(--sl-text-xs);
|
|
27
39
|
text-decoration: none;
|
|
28
40
|
color: var(--sl-color-gray-3);
|
|
29
|
-
|
|
41
|
+
overflow-wrap: anywhere;
|
|
30
42
|
}
|
|
31
43
|
.right-sidebar-panel :global(a:hover) {
|
|
32
44
|
color: var(--sl-color-white);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { PAGE_TITLE_ID } from '../constants';
|
|
3
|
+
import type { Props } from '../props';
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<h1 id={PAGE_TITLE_ID}>{Astro.props.entry.data.title}</h1>
|
|
7
|
+
|
|
8
|
+
<style>
|
|
9
|
+
h1 {
|
|
10
|
+
margin-top: 1rem;
|
|
11
|
+
font-size: var(--sl-text-h1);
|
|
12
|
+
line-height: var(--sl-line-height-headings);
|
|
13
|
+
font-weight: 600;
|
|
14
|
+
color: var(--sl-color-white);
|
|
15
|
+
}
|
|
16
|
+
</style>
|
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
---
|
|
2
|
-
import type { Link } from '../utils/navigation';
|
|
3
2
|
import { useTranslations } from '../utils/translations';
|
|
4
3
|
import Icon from '../user-components/Icon.astro';
|
|
4
|
+
import type { Props } from '../props';
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
next: Link | undefined;
|
|
9
|
-
dir: 'ltr' | 'rtl';
|
|
10
|
-
locale: string | undefined;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const { prev, next, dir, locale } = Astro.props;
|
|
6
|
+
const { dir, locale, pagination } = Astro.props;
|
|
7
|
+
const { prev, next } = pagination;
|
|
14
8
|
const isRtl = dir === 'rtl';
|
|
15
9
|
const t = useTranslations(locale);
|
|
16
10
|
---
|
package/components/Search.astro
CHANGED
|
@@ -2,10 +2,7 @@
|
|
|
2
2
|
import '@pagefind/default-ui/css/ui.css';
|
|
3
3
|
import { useTranslations } from '../utils/translations';
|
|
4
4
|
import Icon from '../user-components/Icon.astro';
|
|
5
|
-
|
|
6
|
-
interface Props {
|
|
7
|
-
locale: string | undefined;
|
|
8
|
-
}
|
|
5
|
+
import type { Props } from '../props';
|
|
9
6
|
|
|
10
7
|
const t = useTranslations(Astro.props.locale);
|
|
11
8
|
const pagefindTranslations = {
|
|
@@ -129,6 +126,9 @@ const pagefindTranslations = {
|
|
|
129
126
|
</script>
|
|
130
127
|
|
|
131
128
|
<style>
|
|
129
|
+
site-search {
|
|
130
|
+
display: contents;
|
|
131
|
+
}
|
|
132
132
|
button[data-open-modal] {
|
|
133
133
|
display: flex;
|
|
134
134
|
align-items: center;
|
|
@@ -405,7 +405,7 @@ const pagefindTranslations = {
|
|
|
405
405
|
|
|
406
406
|
#starlight__search .pagefind-ui__result-excerpt {
|
|
407
407
|
font-size: calc(1rem * var(--pagefind-ui-scale));
|
|
408
|
-
|
|
408
|
+
overflow-wrap: anywhere;
|
|
409
409
|
}
|
|
410
410
|
|
|
411
411
|
#starlight__search mark {
|
package/components/Sidebar.astro
CHANGED
|
@@ -1,42 +1,13 @@
|
|
|
1
1
|
---
|
|
2
|
-
import type {
|
|
3
|
-
import LanguageSelect from './LanguageSelect.astro';
|
|
4
|
-
import SidebarSublist from './SidebarSublist.astro';
|
|
5
|
-
import ThemeSelect from './ThemeSelect.astro';
|
|
2
|
+
import type { Props } from '../props';
|
|
6
3
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
locale: string | undefined;
|
|
10
|
-
}
|
|
4
|
+
import { MobileMenuFooter } from 'virtual:starlight/components';
|
|
5
|
+
import SidebarSublist from './SidebarSublist.astro';
|
|
11
6
|
|
|
12
|
-
const { sidebar
|
|
7
|
+
const { sidebar } = Astro.props;
|
|
13
8
|
---
|
|
14
9
|
|
|
15
|
-
<
|
|
16
|
-
|
|
17
|
-
<
|
|
18
|
-
<ThemeSelect {locale} />
|
|
19
|
-
<LanguageSelect {locale} />
|
|
20
|
-
</div>
|
|
10
|
+
<SidebarSublist sublist={sidebar} />
|
|
11
|
+
<div class="md:sl-hidden">
|
|
12
|
+
<MobileMenuFooter {...Astro.props} />
|
|
21
13
|
</div>
|
|
22
|
-
|
|
23
|
-
<style>
|
|
24
|
-
.sidebar {
|
|
25
|
-
height: 100%;
|
|
26
|
-
padding: 1rem var(--sl-sidebar-pad-x);
|
|
27
|
-
flex-direction: column;
|
|
28
|
-
gap: 1rem;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
.mobile-preferences {
|
|
32
|
-
justify-content: space-between;
|
|
33
|
-
border-top: 1px solid var(--sl-color-gray-6);
|
|
34
|
-
padding: 0.5rem 0;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
@media (min-width: 50rem) {
|
|
38
|
-
.sidebar > :global(:nth-last-child(2)) {
|
|
39
|
-
padding-bottom: 1rem;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
</style>
|
|
@@ -17,7 +17,8 @@ interface Props {
|
|
|
17
17
|
<a
|
|
18
18
|
href={entry.href}
|
|
19
19
|
aria-current={entry.isCurrent && 'page'}
|
|
20
|
-
class:list={{ large: !Astro.props.nested }}
|
|
20
|
+
class:list={[{ large: !Astro.props.nested }, entry.attrs.class]}
|
|
21
|
+
{...entry.attrs}
|
|
21
22
|
>
|
|
22
23
|
<span>{entry.label}</span>
|
|
23
24
|
{entry.badge && (
|
|
@@ -35,7 +36,7 @@ interface Props {
|
|
|
35
36
|
open={flattenSidebar(entry.entries).some((i) => i.isCurrent) || !entry.collapsed}
|
|
36
37
|
>
|
|
37
38
|
<summary>
|
|
38
|
-
<
|
|
39
|
+
<span class="large">{entry.label}</span>
|
|
39
40
|
<Icon name="right-caret" class="caret" size="1.25rem" />
|
|
40
41
|
</summary>
|
|
41
42
|
<Astro.self sublist={entry.entries} nested />
|
|
@@ -53,6 +54,10 @@ interface Props {
|
|
|
53
54
|
padding: 0;
|
|
54
55
|
}
|
|
55
56
|
|
|
57
|
+
li {
|
|
58
|
+
overflow-wrap: anywhere;
|
|
59
|
+
}
|
|
60
|
+
|
|
56
61
|
ul ul li {
|
|
57
62
|
margin-inline-start: var(--sl-sidebar-item-padding-inline);
|
|
58
63
|
border-inline-start: 1px solid var(--sl-color-hairline-light);
|
|
@@ -84,6 +89,7 @@ interface Props {
|
|
|
84
89
|
|
|
85
90
|
.caret {
|
|
86
91
|
transition: transform 0.2s ease-in-out;
|
|
92
|
+
flex-shrink: 0;
|
|
87
93
|
}
|
|
88
94
|
:global([dir='rtl']) .caret {
|
|
89
95
|
transform: rotateZ(180deg);
|
|
@@ -2,26 +2,7 @@
|
|
|
2
2
|
import { logos } from 'virtual:starlight/user-images';
|
|
3
3
|
import config from 'virtual:starlight/user-config';
|
|
4
4
|
import { pathWithBase } from '../utils/base';
|
|
5
|
-
|
|
6
|
-
interface Props {
|
|
7
|
-
locale: string | undefined;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
if (config.logo) {
|
|
11
|
-
let err: string | undefined;
|
|
12
|
-
if ('src' in config.logo) {
|
|
13
|
-
if (!logos.dark || !logos.light) {
|
|
14
|
-
err = `Could not resolve logo import for "${config.logo.src}" (logo.src)`;
|
|
15
|
-
}
|
|
16
|
-
} else {
|
|
17
|
-
if (!logos.dark) {
|
|
18
|
-
err = `Could not resolve logo import for "${config.logo.dark}" (logo.dark)`;
|
|
19
|
-
} else if (!logos.light) {
|
|
20
|
-
err = `Could not resolve logo import for "${config.logo.light}" (logo.light)`;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
if (err) throw new Error(err);
|
|
24
|
-
}
|
|
5
|
+
import type { Props } from '../props';
|
|
25
6
|
|
|
26
7
|
const href = pathWithBase(Astro.props.locale || '/');
|
|
27
8
|
---
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
---
|
|
2
|
+
import { PAGE_TITLE_ID } from '../constants';
|
|
2
3
|
import { useTranslations } from '../utils/translations';
|
|
3
|
-
|
|
4
|
-
interface Props {
|
|
5
|
-
locale: string | undefined;
|
|
6
|
-
}
|
|
4
|
+
import type { Props } from '../props';
|
|
7
5
|
|
|
8
6
|
const t = useTranslations(Astro.props.locale);
|
|
9
7
|
---
|
|
10
8
|
|
|
11
|
-
<a href=
|
|
9
|
+
<a href={`#${PAGE_TITLE_ID}`}>{t('skipLink.label')}</a>
|
|
12
10
|
|
|
13
11
|
<style>
|
|
14
12
|
a {
|
|
@@ -1,44 +1,22 @@
|
|
|
1
1
|
---
|
|
2
2
|
import config from 'virtual:starlight/user-config';
|
|
3
3
|
import Icon from '../user-components/Icon.astro';
|
|
4
|
+
import type { Props } from '../props';
|
|
4
5
|
|
|
5
6
|
type Platform = keyof NonNullable<typeof config.social>;
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
github: 'GitHub',
|
|
9
|
-
gitlab: 'GitLab',
|
|
10
|
-
bitbucket: 'Bitbucket',
|
|
11
|
-
discord: 'Discord',
|
|
12
|
-
gitter: 'Gitter',
|
|
13
|
-
twitter: 'Twitter',
|
|
14
|
-
mastodon: 'Mastodon',
|
|
15
|
-
codeberg: 'Codeberg',
|
|
16
|
-
codePen: 'CodePen',
|
|
17
|
-
youtube: 'YouTube',
|
|
18
|
-
threads: 'Threads',
|
|
19
|
-
linkedin: 'LinkedIn',
|
|
20
|
-
twitch: 'Twitch',
|
|
21
|
-
microsoftTeams: 'Microsoft Teams',
|
|
22
|
-
instagram: 'Instagram',
|
|
23
|
-
stackOverflow: 'Stack Overflow',
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
const links = Object.entries(config.social || {}).filter(([, url]) => Boolean(url)) as [
|
|
27
|
-
platform: Platform,
|
|
28
|
-
url: string,
|
|
29
|
-
][];
|
|
7
|
+
type SocialConfig = NonNullable<NonNullable<typeof config.social>[Platform]>;
|
|
8
|
+
const links = Object.entries(config.social || {}) as [Platform, SocialConfig][];
|
|
30
9
|
---
|
|
31
10
|
|
|
32
11
|
{
|
|
33
12
|
links.length > 0 && (
|
|
34
13
|
<>
|
|
35
|
-
{links.map(([platform, url]) => (
|
|
14
|
+
{links.map(([platform, { label, url }]) => (
|
|
36
15
|
<a href={url} rel="me" class="sl-flex">
|
|
37
|
-
<span class="sr-only">{
|
|
16
|
+
<span class="sr-only">{label}</span>
|
|
38
17
|
<Icon name={platform} />
|
|
39
18
|
</a>
|
|
40
19
|
))}
|
|
41
|
-
<div class="divider" />
|
|
42
20
|
</>
|
|
43
21
|
)
|
|
44
22
|
}
|
|
@@ -50,8 +28,4 @@ const links = Object.entries(config.social || {}).filter(([, url]) => Boolean(ur
|
|
|
50
28
|
a:hover {
|
|
51
29
|
opacity: 0.66;
|
|
52
30
|
}
|
|
53
|
-
.divider {
|
|
54
|
-
height: 2rem;
|
|
55
|
-
border-inline-end: 1px solid var(--sl-color-gray-5);
|
|
56
|
-
}
|
|
57
31
|
</style>
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { PAGE_TITLE_ID } from '../../constants';
|
|
2
|
+
|
|
1
3
|
export class StarlightTOC extends HTMLElement {
|
|
2
4
|
private _current = this.querySelector('a[aria-current="true"]') as HTMLAnchorElement | null;
|
|
3
5
|
private minH = parseInt(this.dataset.minH || '2', 10);
|
|
@@ -20,7 +22,7 @@ export class StarlightTOC extends HTMLElement {
|
|
|
20
22
|
const isHeading = (el: Element): el is HTMLHeadingElement => {
|
|
21
23
|
if (el instanceof HTMLHeadingElement) {
|
|
22
24
|
// Special case for page title h1
|
|
23
|
-
if (
|
|
25
|
+
if (el.id === PAGE_TITLE_ID) return true;
|
|
24
26
|
// Check the heading level is within the user-configured limits for the ToC
|
|
25
27
|
const level = el.tagName[1];
|
|
26
28
|
if (level) {
|
|
@@ -1,24 +1,21 @@
|
|
|
1
1
|
---
|
|
2
2
|
import { useTranslations } from '../utils/translations';
|
|
3
3
|
import TableOfContentsList from './TableOfContents/TableOfContentsList.astro';
|
|
4
|
-
import type {
|
|
4
|
+
import type { Props } from '../props';
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
toc: TocItem[];
|
|
8
|
-
locale: string | undefined;
|
|
9
|
-
maxHeadingLevel: number;
|
|
10
|
-
minHeadingLevel: number;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const { locale, toc, maxHeadingLevel, minHeadingLevel } = Astro.props;
|
|
6
|
+
const { locale, toc } = Astro.props;
|
|
14
7
|
const t = useTranslations(locale);
|
|
15
8
|
---
|
|
16
9
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
<
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
10
|
+
{
|
|
11
|
+
toc && (
|
|
12
|
+
<starlight-toc data-min-h={toc.minHeadingLevel} data-max-h={toc.maxHeadingLevel}>
|
|
13
|
+
<nav aria-labelledby="starlight__on-this-page">
|
|
14
|
+
<h2 id="starlight__on-this-page">{t('tableOfContents.onThisPage')}</h2>
|
|
15
|
+
<TableOfContentsList toc={toc.items} />
|
|
16
|
+
</nav>
|
|
17
|
+
</starlight-toc>
|
|
18
|
+
)
|
|
19
|
+
}
|
|
23
20
|
|
|
24
21
|
<script src="./TableOfContents/starlight-toc"></script>
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
hasToC: boolean;
|
|
4
|
-
}
|
|
2
|
+
import type { Props } from '../props';
|
|
5
3
|
---
|
|
6
4
|
|
|
7
5
|
<div class="lg:sl-flex">
|
|
8
6
|
{
|
|
9
|
-
Astro.props.
|
|
7
|
+
Astro.props.toc && (
|
|
10
8
|
<aside class="right-sidebar-container">
|
|
11
9
|
<div class="right-sidebar">
|
|
12
10
|
<slot name="right-sidebar" />
|
package/constants.ts
ADDED
package/index.astro
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
import type { InferGetStaticPropsType } from 'astro';
|
|
3
|
+
import { generateRouteData } from './utils/route-data';
|
|
3
4
|
import { paths } from './utils/routing';
|
|
4
5
|
|
|
5
|
-
import Page from './
|
|
6
|
+
import Page from './components/Page.astro';
|
|
6
7
|
|
|
7
8
|
export async function getStaticPaths() {
|
|
8
9
|
return paths;
|
|
@@ -10,6 +11,7 @@ export async function getStaticPaths() {
|
|
|
10
11
|
|
|
11
12
|
type Props = InferGetStaticPropsType<typeof getStaticPaths>;
|
|
12
13
|
const { Content, headings } = await Astro.props.entry.render();
|
|
14
|
+
const route = generateRouteData({ props: { ...Astro.props, headings }, url: Astro.url });
|
|
13
15
|
---
|
|
14
16
|
|
|
15
|
-
<Page {...
|
|
17
|
+
<Page {...route}><Content /></Page>
|
package/index.ts
CHANGED
|
@@ -10,7 +10,7 @@ import { errorMap } from './utils/error-map';
|
|
|
10
10
|
import { StarlightConfigSchema, type StarlightUserConfig } from './utils/user-config';
|
|
11
11
|
import { rehypeRtlCodeSupport } from './integrations/code-rtl-support';
|
|
12
12
|
|
|
13
|
-
export default function StarlightIntegration(opts: StarlightUserConfig): AstroIntegration
|
|
13
|
+
export default function StarlightIntegration(opts: StarlightUserConfig): AstroIntegration {
|
|
14
14
|
const parsedConfig = StarlightConfigSchema.safeParse(opts, { errorMap });
|
|
15
15
|
|
|
16
16
|
if (!parsedConfig.success) {
|
|
@@ -34,7 +34,15 @@ export default function StarlightIntegration(opts: StarlightUserConfig): AstroIn
|
|
|
34
34
|
pattern: '[...slug]',
|
|
35
35
|
entryPoint: '@astrojs/starlight/index.astro',
|
|
36
36
|
});
|
|
37
|
+
const integrations: AstroIntegration[] = [];
|
|
38
|
+
if (!config.integrations.find(({ name }) => name === '@astrojs/sitemap')) {
|
|
39
|
+
integrations.push(starlightSitemap(userConfig));
|
|
40
|
+
}
|
|
41
|
+
if (!config.integrations.find(({ name }) => name === '@astrojs/mdx')) {
|
|
42
|
+
integrations.push(mdx());
|
|
43
|
+
}
|
|
37
44
|
const newConfig: AstroUserConfig = {
|
|
45
|
+
integrations,
|
|
38
46
|
vite: {
|
|
39
47
|
plugins: [vitePluginStarlightUserConfig(userConfig, config)],
|
|
40
48
|
},
|
|
@@ -50,19 +58,6 @@ export default function StarlightIntegration(opts: StarlightUserConfig): AstroIn
|
|
|
50
58
|
updateConfig(newConfig);
|
|
51
59
|
},
|
|
52
60
|
|
|
53
|
-
'astro:config:done': ({ config }) => {
|
|
54
|
-
const integrations = config.integrations.map(({ name }) => name);
|
|
55
|
-
for (const builtin of ['@astrojs/mdx', '@astrojs/sitemap']) {
|
|
56
|
-
if (integrations.filter((name) => name === builtin).length > 1) {
|
|
57
|
-
throw new Error(
|
|
58
|
-
`Found more than one instance of ${builtin}.\n` +
|
|
59
|
-
`Starlight includes ${builtin} by default.\n` +
|
|
60
|
-
'Please remove it from your integrations array in astro.config.mjs'
|
|
61
|
-
);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
},
|
|
65
|
-
|
|
66
61
|
'astro:build:done': ({ dir }) => {
|
|
67
62
|
const targetDir = fileURLToPath(dir);
|
|
68
63
|
const cwd = dirname(fileURLToPath(import.meta.url));
|
|
@@ -78,5 +73,5 @@ export default function StarlightIntegration(opts: StarlightUserConfig): AstroIn
|
|
|
78
73
|
},
|
|
79
74
|
};
|
|
80
75
|
|
|
81
|
-
return
|
|
76
|
+
return Starlight;
|
|
82
77
|
}
|
|
@@ -29,6 +29,9 @@ export function vitePluginStarlightUserConfig(
|
|
|
29
29
|
opts.logo.light
|
|
30
30
|
)}; export const logos = { dark, light };`
|
|
31
31
|
: 'export const logos = {};',
|
|
32
|
+
'virtual:starlight/components': Object.entries(opts.components)
|
|
33
|
+
.map(([name, path]) => `export { default as ${name} } from ${resolveId(path)};`)
|
|
34
|
+
.join(''),
|
|
32
35
|
} satisfies Record<string, string>;
|
|
33
36
|
|
|
34
37
|
/** Mapping names prefixed with `\0` to their original form. */
|