@astrojs/starlight 0.5.6 → 0.6.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 +17 -17
- package/CHANGELOG.md +40 -2
- package/components/CallToAction.astro +32 -35
- package/components/ContentPanel.astro +18 -18
- package/components/EditLink.astro +23 -23
- package/components/FallbackContentNotice.astro +16 -18
- package/components/Footer.astro +28 -34
- package/components/HeadSEO.astro +69 -75
- package/components/Header.astro +47 -51
- package/components/Hero.astro +108 -121
- package/components/Icons.ts +73 -71
- package/components/LanguageSelect.astro +31 -31
- package/components/LastUpdated.astro +16 -18
- package/components/MarkdownContent.astro +105 -117
- package/components/MobileMenuToggle.astro +80 -80
- package/components/PrevNextLinks.astro +60 -60
- package/components/RightSidebar.astro +17 -17
- package/components/RightSidebarPanel.astro +41 -41
- package/components/Search.astro +293 -306
- package/components/Select.astro +64 -65
- package/components/Sidebar.astro +23 -23
- package/components/SidebarSublist.astro +96 -95
- package/components/SiteTitle.astro +65 -63
- package/components/SkipLink.astro +17 -17
- package/components/SocialIcons.astro +36 -34
- package/components/TableOfContents/MobileTableOfContents.astro +124 -124
- package/components/TableOfContents/TableOfContentsList.astro +64 -69
- package/components/TableOfContents/generateToC.ts +41 -43
- package/components/TableOfContents/starlight-toc.ts +84 -90
- package/components/TableOfContents.astro +8 -8
- package/components/ThemeProvider.astro +28 -32
- package/components/ThemeSelect.astro +66 -71
- package/global.d.ts +3 -3
- package/index.astro +1 -1
- package/index.ts +52 -59
- package/integrations/asides.ts +109 -111
- package/integrations/sitemap.ts +10 -13
- package/integrations/virtual-user-config.ts +37 -37
- package/layout/Page.astro +84 -72
- package/layout/PageFrame.astro +67 -69
- package/layout/TwoColumnContent.astro +40 -42
- package/package.json +2 -2
- package/schema.ts +126 -113
- package/schemas/favicon.ts +40 -0
- package/schemas/head.ts +12 -23
- package/schemas/i18n.ts +146 -160
- package/schemas/logo.ts +22 -22
- package/schemas/prevNextLink.ts +14 -14
- package/schemas/tableOfContents.ts +14 -18
- package/style/asides.css +27 -27
- package/style/props.css +168 -172
- package/style/reset.css +13 -13
- package/style/shiki.css +11 -11
- package/style/util.css +30 -30
- package/translations/fr.json +21 -21
- package/translations/index.ts +4 -4
- package/translations/it.json +20 -20
- package/translations/tr.json +1 -1
- package/translations/zh.json +0 -1
- package/user-components/Card.astro +50 -54
- package/user-components/CardGrid.astro +21 -21
- package/user-components/Icon.astro +19 -21
- package/user-components/TabItem.astro +3 -3
- package/user-components/Tabs.astro +113 -117
- package/user-components/rehype-tabs.ts +72 -72
- package/utils/base.ts +6 -6
- package/utils/git.ts +55 -55
- package/utils/head.ts +56 -54
- package/utils/i18n.ts +3 -3
- package/utils/localizedUrl.ts +25 -25
- package/utils/navigation.ts +225 -203
- package/utils/routing.ts +74 -85
- package/utils/slugs.ts +41 -51
- package/utils/translations.ts +26 -32
- package/utils/user-config.ts +278 -278
- package/virtual.d.ts +8 -8
|
@@ -3,67 +3,63 @@ import Icon from './Icon.astro';
|
|
|
3
3
|
import type { Icons } from '../components/Icons';
|
|
4
4
|
|
|
5
5
|
interface Props {
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
icon?: keyof typeof Icons;
|
|
7
|
+
title: string;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
const { icon, title } = Astro.props;
|
|
11
11
|
---
|
|
12
12
|
|
|
13
13
|
<article class="card flex">
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
<p class="title flex">
|
|
15
|
+
{icon && <Icon name={icon} class="icon" size="1.333em" />}
|
|
16
|
+
<span set:html={title} />
|
|
17
|
+
</p>
|
|
18
|
+
<div class="body"><slot /></div>
|
|
19
19
|
</article>
|
|
20
20
|
|
|
21
21
|
<style>
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
calc(0.5rem + 1vw),
|
|
66
|
-
var(--sl-text-body)
|
|
67
|
-
);
|
|
68
|
-
}
|
|
22
|
+
.card {
|
|
23
|
+
--sl-card-border: var(--sl-color-purple);
|
|
24
|
+
--sl-card-bg: var(--sl-color-purple-low);
|
|
25
|
+
border: 1px solid var(--sl-color-gray-5);
|
|
26
|
+
background-color: var(--sl-color-black);
|
|
27
|
+
padding: clamp(1rem, calc(0.125rem + 3vw), 2.5rem);
|
|
28
|
+
flex-direction: column;
|
|
29
|
+
gap: clamp(0.5rem, calc(0.125rem + 1vw), 1rem);
|
|
30
|
+
}
|
|
31
|
+
.card:nth-child(4n + 1) {
|
|
32
|
+
--sl-card-border: var(--sl-color-orange);
|
|
33
|
+
--sl-card-bg: var(--sl-color-orange-low);
|
|
34
|
+
}
|
|
35
|
+
.card:nth-child(4n + 3) {
|
|
36
|
+
--sl-card-border: var(--sl-color-green);
|
|
37
|
+
--sl-card-bg: var(--sl-color-green-low);
|
|
38
|
+
}
|
|
39
|
+
.card:nth-child(4n + 4) {
|
|
40
|
+
--sl-card-border: var(--sl-color-red);
|
|
41
|
+
--sl-card-bg: var(--sl-color-red-low);
|
|
42
|
+
}
|
|
43
|
+
.card:nth-child(4n + 5) {
|
|
44
|
+
--sl-card-border: var(--sl-color-blue);
|
|
45
|
+
--sl-card-bg: var(--sl-color-blue-low);
|
|
46
|
+
}
|
|
47
|
+
.title {
|
|
48
|
+
font-weight: 600;
|
|
49
|
+
font-size: var(--sl-text-h4);
|
|
50
|
+
color: var(--sl-color-white);
|
|
51
|
+
line-height: var(--sl-line-height-headings);
|
|
52
|
+
gap: 1rem;
|
|
53
|
+
align-items: center;
|
|
54
|
+
}
|
|
55
|
+
.card .icon {
|
|
56
|
+
border: 1px solid var(--sl-card-border);
|
|
57
|
+
background-color: var(--sl-card-bg);
|
|
58
|
+
padding: 0.2em;
|
|
59
|
+
border-radius: 0.25rem;
|
|
60
|
+
}
|
|
61
|
+
.card .body {
|
|
62
|
+
margin: 0;
|
|
63
|
+
font-size: clamp(var(--sl-text-sm), calc(0.5rem + 1vw), var(--sl-text-body));
|
|
64
|
+
}
|
|
69
65
|
</style>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
interface Props {
|
|
3
|
-
|
|
3
|
+
stagger?: boolean;
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
const { stagger = false } = Astro.props;
|
|
@@ -9,27 +9,27 @@ const { stagger = false } = Astro.props;
|
|
|
9
9
|
<div class:list={['card-grid', { stagger }]}><slot /></div>
|
|
10
10
|
|
|
11
11
|
<style>
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
.card-grid {
|
|
13
|
+
display: grid;
|
|
14
|
+
gap: 1rem;
|
|
15
|
+
}
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
.card-grid > :global(*) {
|
|
18
|
+
margin-top: 0 !important;
|
|
19
|
+
}
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
21
|
+
@media (min-width: 50rem) {
|
|
22
|
+
.card-grid {
|
|
23
|
+
grid-template-columns: 1fr 1fr;
|
|
24
|
+
gap: 1.5rem;
|
|
25
|
+
}
|
|
26
|
+
.stagger {
|
|
27
|
+
--stagger-height: 5rem;
|
|
28
|
+
padding-bottom: var(--stagger-height);
|
|
29
|
+
}
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
.stagger > :global(*):nth-child(2n) {
|
|
32
|
+
transform: translateY(var(--stagger-height));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
35
|
</style>
|
|
@@ -2,34 +2,32 @@
|
|
|
2
2
|
import { Icons } from '../components/Icons';
|
|
3
3
|
|
|
4
4
|
interface Props {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
name: keyof typeof Icons;
|
|
6
|
+
label?: string;
|
|
7
|
+
color?: string;
|
|
8
|
+
size?: string;
|
|
9
|
+
class?: string;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
const { name, label, size = '1em', color } = Astro.props;
|
|
13
|
-
const a11yAttrs = label
|
|
14
|
-
? ({ 'aria-label': label } as const)
|
|
15
|
-
: ({ 'aria-hidden': 'true' } as const);
|
|
13
|
+
const a11yAttrs = label ? ({ 'aria-label': label } as const) : ({ 'aria-hidden': 'true' } as const);
|
|
16
14
|
---
|
|
17
15
|
|
|
18
16
|
<svg
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
17
|
+
{...a11yAttrs}
|
|
18
|
+
class={Astro.props.class}
|
|
19
|
+
width="16"
|
|
20
|
+
height="16"
|
|
21
|
+
viewBox="0 0 24 24"
|
|
22
|
+
fill="currentColor"
|
|
23
|
+
set:html={Icons[name]}
|
|
26
24
|
/>
|
|
27
25
|
|
|
28
26
|
<style define:vars={{ 'sl-icon-color': color, 'sl-icon-size': size }}>
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
27
|
+
svg {
|
|
28
|
+
color: var(--sl-icon-color);
|
|
29
|
+
font-size: var(--sl-icon-size, 1em);
|
|
30
|
+
width: 1em;
|
|
31
|
+
height: 1em;
|
|
32
|
+
}
|
|
35
33
|
</style>
|
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
import { TabItemTagname } from './rehype-tabs';
|
|
3
3
|
|
|
4
4
|
interface Props {
|
|
5
|
-
|
|
5
|
+
label: string;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
const { label } = Astro.props;
|
|
9
9
|
|
|
10
10
|
if (!label) {
|
|
11
|
-
|
|
11
|
+
throw new Error('Missing prop `label` on `<TabItem>` component.');
|
|
12
12
|
}
|
|
13
13
|
---
|
|
14
14
|
|
|
15
15
|
<TabItemTagname data-label={label}>
|
|
16
|
-
|
|
16
|
+
<slot />
|
|
17
17
|
</TabItemTagname>
|
|
@@ -6,138 +6,134 @@ const { html, panels } = processPanels(panelHtml);
|
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
<starlight-tabs>
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
9
|
+
{
|
|
10
|
+
panels && (
|
|
11
|
+
<div class="tablist-wrapper not-content">
|
|
12
|
+
<ul role="tablist">
|
|
13
|
+
{panels.map(({ label, panelId, tabId }, idx) => (
|
|
14
|
+
<li role="presentation" class="tab">
|
|
15
|
+
<a
|
|
16
|
+
role="tab"
|
|
17
|
+
href={'#' + panelId}
|
|
18
|
+
id={tabId}
|
|
19
|
+
aria-selected={idx === 0 && 'true'}
|
|
20
|
+
tabindex={idx !== 0 ? -1 : 0}
|
|
21
|
+
>
|
|
22
|
+
{label}
|
|
23
|
+
</a>
|
|
24
|
+
</li>
|
|
25
|
+
))}
|
|
26
|
+
</ul>
|
|
27
|
+
</div>
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
<Fragment set:html={html} />
|
|
31
31
|
</starlight-tabs>
|
|
32
32
|
|
|
33
33
|
<style>
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
starlight-tabs {
|
|
35
|
+
display: block;
|
|
36
|
+
}
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
.tablist-wrapper {
|
|
39
|
+
overflow-x: auto;
|
|
40
|
+
}
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
42
|
+
[role='tablist'] {
|
|
43
|
+
display: flex;
|
|
44
|
+
list-style: none;
|
|
45
|
+
border-bottom: 2px solid var(--sl-color-gray-5);
|
|
46
|
+
padding: 0;
|
|
47
|
+
}
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
49
|
+
.tab {
|
|
50
|
+
margin-bottom: -2px;
|
|
51
|
+
}
|
|
52
|
+
.tab > [role='tab'] {
|
|
53
|
+
display: block;
|
|
54
|
+
padding: 0 1.25rem;
|
|
55
|
+
text-decoration: none;
|
|
56
|
+
border-bottom: 2px solid var(--sl-color-gray-5);
|
|
57
|
+
color: var(--sl-color-gray-3);
|
|
58
|
+
outline-offset: var(--sl-outline-offset-inside);
|
|
59
|
+
}
|
|
60
|
+
.tab [role='tab'][aria-selected] {
|
|
61
|
+
color: var(--sl-color-white);
|
|
62
|
+
border-color: var(--sl-color-text-accent);
|
|
63
|
+
font-weight: 600;
|
|
64
|
+
}
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
.tablist-wrapper ~ :global([role='tabpanel']) {
|
|
67
|
+
margin-top: 1rem;
|
|
68
|
+
}
|
|
69
69
|
</style>
|
|
70
70
|
|
|
71
71
|
<script>
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
class StarlightTabs extends HTMLElement {
|
|
73
|
+
tabs: HTMLAnchorElement[];
|
|
74
|
+
panels: HTMLElement[];
|
|
75
75
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
];
|
|
82
|
-
this.panels = [
|
|
83
|
-
...this.querySelectorAll<HTMLElement>('[role="tabpanel"]'),
|
|
84
|
-
];
|
|
76
|
+
constructor() {
|
|
77
|
+
super();
|
|
78
|
+
const tablist = this.querySelector<HTMLUListElement>('[role="tablist"]')!;
|
|
79
|
+
this.tabs = [...tablist.querySelectorAll<HTMLAnchorElement>('[role="tab"]')];
|
|
80
|
+
this.panels = [...this.querySelectorAll<HTMLElement>('[role="tabpanel"]')];
|
|
85
81
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
82
|
+
this.tabs.forEach((tab, i) => {
|
|
83
|
+
// Handle clicks for mouse users
|
|
84
|
+
tab.addEventListener('click', (e) => {
|
|
85
|
+
e.preventDefault();
|
|
86
|
+
const currentTab = tablist.querySelector('[aria-selected]');
|
|
87
|
+
if (e.currentTarget !== currentTab) {
|
|
88
|
+
this.switchTab(e.currentTarget as HTMLAnchorElement, i);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
95
91
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
92
|
+
// Handle keyboard input
|
|
93
|
+
tab.addEventListener('keydown', (e) => {
|
|
94
|
+
const index = this.tabs.indexOf(e.currentTarget as any);
|
|
95
|
+
// Work out which key the user is pressing and
|
|
96
|
+
// Calculate the new tab's index where appropriate
|
|
97
|
+
const nextIndex =
|
|
98
|
+
e.key === 'ArrowLeft'
|
|
99
|
+
? index - 1
|
|
100
|
+
: e.key === 'ArrowRight'
|
|
101
|
+
? index + 1
|
|
102
|
+
: e.key === 'Home'
|
|
103
|
+
? 0
|
|
104
|
+
: e.key === 'End'
|
|
105
|
+
? this.tabs.length - 1
|
|
106
|
+
: null;
|
|
107
|
+
if (nextIndex === null) return;
|
|
108
|
+
if (this.tabs[nextIndex]) {
|
|
109
|
+
e.preventDefault();
|
|
110
|
+
this.switchTab(this.tabs[nextIndex], nextIndex);
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
}
|
|
119
115
|
|
|
120
|
-
|
|
121
|
-
|
|
116
|
+
switchTab(newTab: HTMLAnchorElement | null | undefined, index: number) {
|
|
117
|
+
if (!newTab) return;
|
|
122
118
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
119
|
+
// Mark all tabs as unselected and hide all tab panels.
|
|
120
|
+
this.tabs.forEach((tab) => {
|
|
121
|
+
tab.removeAttribute('aria-selected');
|
|
122
|
+
tab.setAttribute('tabindex', '-1');
|
|
123
|
+
});
|
|
124
|
+
this.panels.forEach((oldPanel) => {
|
|
125
|
+
oldPanel.hidden = true;
|
|
126
|
+
});
|
|
131
127
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
128
|
+
// Show new panel and mark new tab as selected.
|
|
129
|
+
const newPanel = this.panels[index];
|
|
130
|
+
if (newPanel) newPanel.hidden = false;
|
|
131
|
+
// Restore active tab to the default tab order.
|
|
132
|
+
newTab.removeAttribute('tabindex');
|
|
133
|
+
newTab.setAttribute('aria-selected', 'true');
|
|
134
|
+
newTab.focus();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
141
137
|
|
|
142
|
-
|
|
138
|
+
customElements.define('starlight-tabs', StarlightTabs);
|
|
143
139
|
</script>
|