@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.
Files changed (76) hide show
  1. package/404.astro +17 -17
  2. package/CHANGELOG.md +40 -2
  3. package/components/CallToAction.astro +32 -35
  4. package/components/ContentPanel.astro +18 -18
  5. package/components/EditLink.astro +23 -23
  6. package/components/FallbackContentNotice.astro +16 -18
  7. package/components/Footer.astro +28 -34
  8. package/components/HeadSEO.astro +69 -75
  9. package/components/Header.astro +47 -51
  10. package/components/Hero.astro +108 -121
  11. package/components/Icons.ts +73 -71
  12. package/components/LanguageSelect.astro +31 -31
  13. package/components/LastUpdated.astro +16 -18
  14. package/components/MarkdownContent.astro +105 -117
  15. package/components/MobileMenuToggle.astro +80 -80
  16. package/components/PrevNextLinks.astro +60 -60
  17. package/components/RightSidebar.astro +17 -17
  18. package/components/RightSidebarPanel.astro +41 -41
  19. package/components/Search.astro +293 -306
  20. package/components/Select.astro +64 -65
  21. package/components/Sidebar.astro +23 -23
  22. package/components/SidebarSublist.astro +96 -95
  23. package/components/SiteTitle.astro +65 -63
  24. package/components/SkipLink.astro +17 -17
  25. package/components/SocialIcons.astro +36 -34
  26. package/components/TableOfContents/MobileTableOfContents.astro +124 -124
  27. package/components/TableOfContents/TableOfContentsList.astro +64 -69
  28. package/components/TableOfContents/generateToC.ts +41 -43
  29. package/components/TableOfContents/starlight-toc.ts +84 -90
  30. package/components/TableOfContents.astro +8 -8
  31. package/components/ThemeProvider.astro +28 -32
  32. package/components/ThemeSelect.astro +66 -71
  33. package/global.d.ts +3 -3
  34. package/index.astro +1 -1
  35. package/index.ts +52 -59
  36. package/integrations/asides.ts +109 -111
  37. package/integrations/sitemap.ts +10 -13
  38. package/integrations/virtual-user-config.ts +37 -37
  39. package/layout/Page.astro +84 -72
  40. package/layout/PageFrame.astro +67 -69
  41. package/layout/TwoColumnContent.astro +40 -42
  42. package/package.json +2 -2
  43. package/schema.ts +126 -113
  44. package/schemas/favicon.ts +40 -0
  45. package/schemas/head.ts +12 -23
  46. package/schemas/i18n.ts +146 -160
  47. package/schemas/logo.ts +22 -22
  48. package/schemas/prevNextLink.ts +14 -14
  49. package/schemas/tableOfContents.ts +14 -18
  50. package/style/asides.css +27 -27
  51. package/style/props.css +168 -172
  52. package/style/reset.css +13 -13
  53. package/style/shiki.css +11 -11
  54. package/style/util.css +30 -30
  55. package/translations/fr.json +21 -21
  56. package/translations/index.ts +4 -4
  57. package/translations/it.json +20 -20
  58. package/translations/tr.json +1 -1
  59. package/translations/zh.json +0 -1
  60. package/user-components/Card.astro +50 -54
  61. package/user-components/CardGrid.astro +21 -21
  62. package/user-components/Icon.astro +19 -21
  63. package/user-components/TabItem.astro +3 -3
  64. package/user-components/Tabs.astro +113 -117
  65. package/user-components/rehype-tabs.ts +72 -72
  66. package/utils/base.ts +6 -6
  67. package/utils/git.ts +55 -55
  68. package/utils/head.ts +56 -54
  69. package/utils/i18n.ts +3 -3
  70. package/utils/localizedUrl.ts +25 -25
  71. package/utils/navigation.ts +225 -203
  72. package/utils/routing.ts +74 -85
  73. package/utils/slugs.ts +41 -51
  74. package/utils/translations.ts +26 -32
  75. package/utils/user-config.ts +278 -278
  76. package/virtual.d.ts +8 -8
package/404.astro CHANGED
@@ -14,22 +14,22 @@ const entryMeta = { dir, lang, locale };
14
14
  const t = useTranslations(locale);
15
15
 
16
16
  const fallbackEntry: StarlightDocsEntry = {
17
- slug: '404',
18
- id: '404.md' as StarlightDocsEntry['id'],
19
- body: '',
20
- collection: 'docs',
21
- data: {
22
- title: '404',
23
- template: 'splash',
24
- editUrl: false,
25
- head: [],
26
- hero: { tagline: t('404.text'), actions: [] },
27
- },
28
- render: async () => ({
29
- Content: EmptyContent,
30
- headings: [],
31
- remarkPluginFrontmatter: {},
32
- }),
17
+ slug: '404',
18
+ id: '404.md' as StarlightDocsEntry['id'],
19
+ body: '',
20
+ collection: 'docs',
21
+ data: {
22
+ title: '404',
23
+ template: 'splash',
24
+ editUrl: false,
25
+ head: [],
26
+ hero: { tagline: t('404.text'), actions: [] },
27
+ },
28
+ render: async () => ({
29
+ Content: EmptyContent,
30
+ headings: [],
31
+ remarkPluginFrontmatter: {},
32
+ }),
33
33
  };
34
34
 
35
35
  const userEntry = await getEntry('docs', '404');
@@ -38,5 +38,5 @@ const { Content, headings } = await entry.render();
38
38
  ---
39
39
 
40
40
  <Page {headings} entry={entry} id={entry.id} slug={entry.slug} {...entryMeta} {entryMeta}>
41
- <Content />
41
+ <Content />
42
42
  </Page>
package/CHANGELOG.md CHANGED
@@ -1,5 +1,43 @@
1
1
  # @astrojs/starlight
2
2
 
3
+ ## 0.6.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#424](https://github.com/withastro/starlight/pull/424) [`4485d90`](https://github.com/withastro/starlight/commit/4485d90fbddf7c9458b43f9d9b7560b41ec9e98f) Thanks [@delucis](https://github.com/delucis)! - Add support for customising autogenerated sidebar link labels from page frontmatter, overriding the page title:
8
+
9
+ ```md
10
+ ---
11
+ title: About this project
12
+ sidebar:
13
+ label: About
14
+ ---
15
+ ```
16
+
17
+ - [#359](https://github.com/withastro/starlight/pull/359) [`e733311`](https://github.com/withastro/starlight/commit/e73331133b0e2574a139409ba76d97cc1bd52a82) Thanks [@IDurward](https://github.com/IDurward)! - Add support for defining the order of auto-generated link groups in the sidebar using a frontmatter value:
18
+
19
+ ```md
20
+ ---
21
+ title: Page to display first
22
+ sidebar:
23
+ order: 1
24
+ ---
25
+ ```
26
+
27
+ ### Patch Changes
28
+
29
+ - [#413](https://github.com/withastro/starlight/pull/413) [`5a9d8f1`](https://github.com/withastro/starlight/commit/5a9d8f11d59bd48322a1f2ff90e68333c3207ee1) Thanks [@delucis](https://github.com/delucis)! - Fix site title overflow bug for longer titles on narrow screens
30
+
31
+ - [#381](https://github.com/withastro/starlight/pull/381) [`6e62909`](https://github.com/withastro/starlight/commit/6e629095e78da4bfd422cd0a9cd9beb0d85d9a1a) Thanks [@lorenzolewis](https://github.com/lorenzolewis)! - Preserve order of `social` config in navbar
32
+
33
+ - [#419](https://github.com/withastro/starlight/pull/419) [`38ff53c`](https://github.com/withastro/starlight/commit/38ff53c216898efaa8c07394500e82da1d68ee8a) Thanks [@lorenzolewis](https://github.com/lorenzolewis)! - Improve styling of sidebar entries that wrap onto multiple lines
34
+
35
+ - [#418](https://github.com/withastro/starlight/pull/418) [`c7b2a4e`](https://github.com/withastro/starlight/commit/c7b2a4e9c8c55564be75f0c0901e38577ac764ec) Thanks [@delucis](https://github.com/delucis)! - Set `tab-size: 2` on content code blocks to override default browser value of `8`
36
+
37
+ - [#399](https://github.com/withastro/starlight/pull/399) [`31b8a5a`](https://github.com/withastro/starlight/commit/31b8a5aed2bca363c1b05c683b020e596b70bf4a) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Add new global `favicon` option defaulting to `'/favicon.svg'` to set the path of the default favicon for your website. Additional icons can be specified using the `head` option.
38
+
39
+ - [#414](https://github.com/withastro/starlight/pull/414) [`e951671`](https://github.com/withastro/starlight/commit/e95167174e3eab3790328b8e42517abcbca04ff3) Thanks [@delucis](https://github.com/delucis)! - Add GitLab to social link icons
40
+
3
41
  ## 0.5.6
4
42
 
5
43
  ### Patch Changes
@@ -313,8 +351,8 @@
313
351
 
314
352
  ```json
315
353
  {
316
- "search.label": "Suchen",
317
- "search.shortcutLabel": "(Drücke / zum Suchen)"
354
+ "search.label": "Suchen",
355
+ "search.shortcutLabel": "(Drücke / zum Suchen)"
318
356
  }
319
357
  ```
320
358
 
@@ -3,49 +3,46 @@ import Icon from '../user-components/Icon.astro';
3
3
  import type { Icons } from './Icons';
4
4
 
5
5
  interface Props {
6
- variant: 'primary' | 'secondary' | 'minimal';
7
- link: string;
8
- icon?:
9
- | undefined
10
- | { type: 'icon'; name: keyof typeof Icons }
11
- | { type: 'raw'; html: string };
6
+ variant: 'primary' | 'secondary' | 'minimal';
7
+ link: string;
8
+ icon?: undefined | { type: 'icon'; name: keyof typeof Icons } | { type: 'raw'; html: string };
12
9
  }
13
10
 
14
11
  const { link, variant, icon } = Astro.props;
15
12
  ---
16
13
 
17
14
  <a class:list={['flex action', variant]} href={link}>
18
- <slot />
19
- {icon?.type === 'icon' && <Icon name={icon.name} size="1.5rem" />}
20
- {icon?.type === 'raw' && <Fragment set:html={icon.html} />}
15
+ <slot />
16
+ {icon?.type === 'icon' && <Icon name={icon.name} size="1.5rem" />}
17
+ {icon?.type === 'raw' && <Fragment set:html={icon.html} />}
21
18
  </a>
22
19
 
23
20
  <style>
24
- .action {
25
- gap: 0.5em;
26
- align-items: center;
27
- border-radius: 999rem;
28
- padding: 0.5rem 1.125rem;
29
- color: var(--sl-color-white);
30
- line-height: 1.1875;
31
- text-decoration: none;
32
- font-size: var(--sl-text-sm);
33
- }
34
- .action.primary {
35
- background: var(--sl-color-text-accent);
36
- color: var(--sl-color-black);
37
- }
38
- .action.secondary {
39
- border: 1px solid;
40
- }
41
- .action.minimal {
42
- padding-inline: 0;
43
- }
21
+ .action {
22
+ gap: 0.5em;
23
+ align-items: center;
24
+ border-radius: 999rem;
25
+ padding: 0.5rem 1.125rem;
26
+ color: var(--sl-color-white);
27
+ line-height: 1.1875;
28
+ text-decoration: none;
29
+ font-size: var(--sl-text-sm);
30
+ }
31
+ .action.primary {
32
+ background: var(--sl-color-text-accent);
33
+ color: var(--sl-color-black);
34
+ }
35
+ .action.secondary {
36
+ border: 1px solid;
37
+ }
38
+ .action.minimal {
39
+ padding-inline: 0;
40
+ }
44
41
 
45
- @media (min-width: 50rem) {
46
- .action {
47
- font-size: var(--sl-text-base);
48
- padding: 1rem 1.25rem;
49
- }
50
- }
42
+ @media (min-width: 50rem) {
43
+ .action {
44
+ font-size: var(--sl-text-base);
45
+ padding: 1rem 1.25rem;
46
+ }
47
+ }
51
48
  </style>
@@ -1,25 +1,25 @@
1
1
  <div class="content-panel">
2
- <div class="container"><slot /></div>
2
+ <div class="container"><slot /></div>
3
3
  </div>
4
4
 
5
5
  <style>
6
- .content-panel {
7
- padding: 1.5rem var(--sl-content-pad-x);
8
- }
9
- .content-panel + .content-panel {
10
- border-top: 1px solid var(--sl-color-hairline);
11
- }
12
- .container {
13
- max-width: var(--sl-content-width);
14
- }
6
+ .content-panel {
7
+ padding: 1.5rem var(--sl-content-pad-x);
8
+ }
9
+ .content-panel + .content-panel {
10
+ border-top: 1px solid var(--sl-color-hairline);
11
+ }
12
+ .container {
13
+ max-width: var(--sl-content-width);
14
+ }
15
15
 
16
- .container > :global(* + *) {
17
- margin-top: 1.5rem;
18
- }
16
+ .container > :global(* + *) {
17
+ margin-top: 1.5rem;
18
+ }
19
19
 
20
- @media (min-width: 72rem) {
21
- .container {
22
- margin-inline: var(--sl-content-margin-inline, auto);
23
- }
24
- }
20
+ @media (min-width: 72rem) {
21
+ .container {
22
+ margin-inline: var(--sl-content-margin-inline, auto);
23
+ }
24
+ }
25
25
  </style>
@@ -5,9 +5,9 @@ import { useTranslations } from '../utils/translations';
5
5
  import Icon from '../user-components/Icon.astro';
6
6
 
7
7
  interface Props {
8
- data: CollectionEntry<'docs'>['data'];
9
- id: CollectionEntry<'docs'>['id'];
10
- locale: string | undefined;
8
+ data: CollectionEntry<'docs'>['data'];
9
+ id: CollectionEntry<'docs'>['id'];
10
+ locale: string | undefined;
11
11
  }
12
12
 
13
13
  const t = useTranslations(Astro.props.locale);
@@ -17,30 +17,30 @@ let { baseUrl } = config.editLink;
17
17
  if (baseUrl && baseUrl.at(-1) !== '/') baseUrl += '/';
18
18
 
19
19
  const url =
20
- typeof editUrl === 'string'
21
- ? editUrl
22
- : baseUrl
23
- ? baseUrl + 'src/content/docs/' + Astro.props.id
24
- : undefined;
20
+ typeof editUrl === 'string'
21
+ ? editUrl
22
+ : baseUrl
23
+ ? baseUrl + 'src/content/docs/' + Astro.props.id
24
+ : undefined;
25
25
  ---
26
26
 
27
27
  {
28
- editUrl !== false && url && (
29
- <a href={url} class="flex">
30
- <Icon name="pencil" size="1.2em" />
31
- {t('page.editLink')}
32
- </a>
33
- )
28
+ editUrl !== false && url && (
29
+ <a href={url} class="flex">
30
+ <Icon name="pencil" size="1.2em" />
31
+ {t('page.editLink')}
32
+ </a>
33
+ )
34
34
  }
35
35
 
36
36
  <style>
37
- a {
38
- gap: 0.5rem;
39
- align-items: center;
40
- text-decoration: none;
41
- color: var(--sl-color-gray-3);
42
- }
43
- a:hover {
44
- color: var(--sl-color-white);
45
- }
37
+ a {
38
+ gap: 0.5rem;
39
+ align-items: center;
40
+ text-decoration: none;
41
+ color: var(--sl-color-gray-3);
42
+ }
43
+ a:hover {
44
+ color: var(--sl-color-white);
45
+ }
46
46
  </style>
@@ -3,31 +3,29 @@ import { useTranslations } from '../utils/translations';
3
3
  import Icon from '../user-components/Icon.astro';
4
4
 
5
5
  interface Props {
6
- locale: string | undefined;
6
+ locale: string | undefined;
7
7
  }
8
8
 
9
9
  const t = useTranslations(Astro.props.locale);
10
10
  ---
11
11
 
12
12
  <p class="flex">
13
- <Icon
14
- name={'warning'}
15
- size="1.5em"
16
- color="var(--sl-color-orange-high)"
17
- /><span>{t('i18n.untranslatedContent')}</span>
13
+ <Icon name={'warning'} size="1.5em" color="var(--sl-color-orange-high)" /><span
14
+ >{t('i18n.untranslatedContent')}</span
15
+ >
18
16
  </p>
19
17
 
20
18
  <style>
21
- p {
22
- border: 1px solid var(--sl-color-orange);
23
- padding: 0.75em 1em;
24
- background-color: var(--sl-color-orange-low);
25
- color: var(--sl-color-orange-high);
26
- width: max-content;
27
- max-width: 100%;
28
- align-items: center;
29
- gap: 0.75em;
30
- font-size: var(--sl-text-body-sm);
31
- line-height: var(--sl-line-height-headings);
32
- }
19
+ p {
20
+ border: 1px solid var(--sl-color-orange);
21
+ padding: 0.75em 1em;
22
+ background-color: var(--sl-color-orange-low);
23
+ color: var(--sl-color-orange-high);
24
+ width: max-content;
25
+ max-width: 100%;
26
+ align-items: center;
27
+ gap: 0.75em;
28
+ font-size: var(--sl-text-body-sm);
29
+ line-height: var(--sl-line-height-headings);
30
+ }
33
31
  </style>
@@ -9,49 +9,43 @@ import PrevNextLinks from '../components/PrevNextLinks.astro';
9
9
  import EditLink from './EditLink.astro';
10
10
 
11
11
  interface Props extends LocaleData {
12
- entry: StarlightDocsEntry;
13
- sidebar: SidebarEntry[];
12
+ entry: StarlightDocsEntry;
13
+ sidebar: SidebarEntry[];
14
14
  }
15
15
 
16
16
  const { entry, dir, lang, locale, sidebar } = Astro.props;
17
17
  const prevNextLinks = getPrevNextLinks(sidebar, config.pagination, {
18
- prev: entry.data.prev,
19
- next: entry.data.next
18
+ prev: entry.data.prev,
19
+ next: entry.data.next,
20
20
  });
21
21
  ---
22
22
 
23
23
  <footer>
24
- <div class="meta flex">
25
- {
26
- config.editLink.baseUrl && (
27
- <EditLink data={entry.data} id={entry.id} {locale} />
28
- )
29
- }
30
- {
31
- (entry.data.lastUpdated ?? config.lastUpdated) && (
32
- <LastUpdated
33
- id={entry.id}
34
- {lang}
35
- lastUpdated={
36
- typeof entry.data.lastUpdated !== 'boolean'
37
- ? entry.data.lastUpdated
38
- : undefined
39
- }
40
- {locale}
41
- />
42
- )
43
- }
44
- </div>
45
- <PrevNextLinks {...prevNextLinks} {dir} {locale} />
24
+ <div class="meta flex">
25
+ {config.editLink.baseUrl && <EditLink data={entry.data} id={entry.id} {locale} />}
26
+ {
27
+ (entry.data.lastUpdated ?? config.lastUpdated) && (
28
+ <LastUpdated
29
+ id={entry.id}
30
+ {lang}
31
+ lastUpdated={
32
+ typeof entry.data.lastUpdated !== 'boolean' ? entry.data.lastUpdated : undefined
33
+ }
34
+ {locale}
35
+ />
36
+ )
37
+ }
38
+ </div>
39
+ <PrevNextLinks {...prevNextLinks} {dir} {locale} />
46
40
  </footer>
47
41
 
48
42
  <style>
49
- .meta {
50
- gap: 0.75rem 3rem;
51
- justify-content: space-between;
52
- flex-wrap: wrap;
53
- margin-block: 3rem 1.5rem;
54
- font-size: var(--sl-text-sm);
55
- color: var(--sl-color-gray-3);
56
- }
43
+ .meta {
44
+ gap: 0.75rem 3rem;
45
+ justify-content: space-between;
46
+ flex-wrap: wrap;
47
+ margin-block: 3rem 1.5rem;
48
+ font-size: var(--sl-text-sm);
49
+ color: var(--sl-color-gray-3);
50
+ }
57
51
  </style>
@@ -8,105 +8,99 @@ import { fileWithBase } from '../utils/base';
8
8
  import { version } from '../package.json';
9
9
 
10
10
  interface Props {
11
- data: CollectionEntry<'docs'>['data'];
12
- lang: string;
11
+ data: CollectionEntry<'docs'>['data'];
12
+ lang: string;
13
13
  }
14
14
 
15
15
  const { data, lang } = Astro.props;
16
16
 
17
- const canonical = Astro.site
18
- ? new URL(Astro.url.pathname, Astro.site)
19
- : undefined;
17
+ const canonical = Astro.site ? new URL(Astro.url.pathname, Astro.site) : undefined;
20
18
  const title = data.title || config.title;
21
19
  const description = data.description || config.description;
22
20
 
23
21
  const headDefaults: z.input<ReturnType<typeof HeadConfigSchema>> = [
24
- { tag: 'meta', attrs: { charset: 'utf-8' } },
25
- {
26
- tag: 'meta',
27
- attrs: { name: 'viewport', content: 'width=device-width, initial-scale=1' },
28
- },
29
- { tag: 'title', content: title },
30
- { tag: 'link', attrs: { rel: 'canonical', href: canonical?.href } },
31
- { tag: 'meta', attrs: { name: 'generator', content: Astro.generator } },
32
- {
33
- tag: 'meta',
34
- attrs: { name: 'generator', content: `Starlight v${version}` },
35
- },
36
- // Favicon
37
- {
38
- tag: 'link',
39
- attrs: {
40
- rel: 'shortcut icon',
41
- href: fileWithBase('/favicon.svg'),
42
- type: 'image/svg+xml',
43
- },
44
- },
45
- // OpenGraph Tags
46
- { tag: 'meta', attrs: { property: 'og:title', content: title } },
47
- { tag: 'meta', attrs: { property: 'og:type', content: 'article' } },
48
- { tag: 'meta', attrs: { property: 'og:url', content: canonical?.href } },
49
- { tag: 'meta', attrs: { property: 'og:locale', content: lang } },
50
- { tag: 'meta', attrs: { property: 'og:description', content: description } },
51
- { tag: 'meta', attrs: { property: 'og:site_name', content: config.title } },
52
- // Twitter Tags
53
- {
54
- tag: 'meta',
55
- attrs: { name: 'twitter:card', content: 'summary_large_image' },
56
- },
57
- { tag: 'meta', attrs: { name: 'twitter:title', content: title } },
58
- { tag: 'meta', attrs: { name: 'twitter:description', content: description } },
22
+ { tag: 'meta', attrs: { charset: 'utf-8' } },
23
+ {
24
+ tag: 'meta',
25
+ attrs: { name: 'viewport', content: 'width=device-width, initial-scale=1' },
26
+ },
27
+ { tag: 'title', content: title },
28
+ { tag: 'link', attrs: { rel: 'canonical', href: canonical?.href } },
29
+ { tag: 'meta', attrs: { name: 'generator', content: Astro.generator } },
30
+ {
31
+ tag: 'meta',
32
+ attrs: { name: 'generator', content: `Starlight v${version}` },
33
+ },
34
+ // Favicon
35
+ {
36
+ tag: 'link',
37
+ attrs: {
38
+ rel: 'shortcut icon',
39
+ href: fileWithBase(config.favicon.href),
40
+ type: config.favicon.type,
41
+ },
42
+ },
43
+ // OpenGraph Tags
44
+ { tag: 'meta', attrs: { property: 'og:title', content: title } },
45
+ { tag: 'meta', attrs: { property: 'og:type', content: 'article' } },
46
+ { tag: 'meta', attrs: { property: 'og:url', content: canonical?.href } },
47
+ { tag: 'meta', attrs: { property: 'og:locale', content: lang } },
48
+ { tag: 'meta', attrs: { property: 'og:description', content: description } },
49
+ { tag: 'meta', attrs: { property: 'og:site_name', content: config.title } },
50
+ // Twitter Tags
51
+ {
52
+ tag: 'meta',
53
+ attrs: { name: 'twitter:card', content: 'summary_large_image' },
54
+ },
55
+ { tag: 'meta', attrs: { name: 'twitter:title', content: title } },
56
+ { tag: 'meta', attrs: { name: 'twitter:description', content: description } },
59
57
  ];
60
58
 
61
59
  if (description)
62
- headDefaults.push({
63
- tag: 'meta',
64
- attrs: { name: 'description', content: description },
65
- });
60
+ headDefaults.push({
61
+ tag: 'meta',
62
+ attrs: { name: 'description', content: description },
63
+ });
66
64
 
67
65
  // Link to language alternates.
68
66
  if (canonical && config.isMultilingual) {
69
- for (const locale in config.locales) {
70
- const localeOpts = config.locales[locale];
71
- if (!localeOpts) continue;
72
- headDefaults.push({
73
- tag: 'link',
74
- attrs: {
75
- rel: 'alternate',
76
- hreflang: localeOpts.lang,
77
- href: localizedUrl(canonical, locale).href,
78
- },
79
- });
80
- }
67
+ for (const locale in config.locales) {
68
+ const localeOpts = config.locales[locale];
69
+ if (!localeOpts) continue;
70
+ headDefaults.push({
71
+ tag: 'link',
72
+ attrs: {
73
+ rel: 'alternate',
74
+ hreflang: localeOpts.lang,
75
+ href: localizedUrl(canonical, locale).href,
76
+ },
77
+ });
78
+ }
81
79
  }
82
80
 
83
81
  // Link to sitemap, but only when `site` is set.
84
82
  if (Astro.site) {
85
- headDefaults.push({
86
- tag: 'link',
87
- attrs: {
88
- rel: 'sitemap',
89
- href: fileWithBase('/sitemap-index.xml'),
90
- },
91
- });
83
+ headDefaults.push({
84
+ tag: 'link',
85
+ attrs: {
86
+ rel: 'sitemap',
87
+ href: fileWithBase('/sitemap-index.xml'),
88
+ },
89
+ });
92
90
  }
93
91
 
94
92
  // Link to Twitter account if set in Starlight config.
95
93
  if (config.social?.twitter) {
96
- headDefaults.push({
97
- tag: 'meta',
98
- attrs: {
99
- name: 'twitter:site',
100
- content: new URL(config.social.twitter).pathname,
101
- },
102
- });
94
+ headDefaults.push({
95
+ tag: 'meta',
96
+ attrs: {
97
+ name: 'twitter:site',
98
+ content: new URL(config.social.twitter).pathname,
99
+ },
100
+ });
103
101
  }
104
102
 
105
103
  const head = createHead(headDefaults, config.head, data.head);
106
104
  ---
107
105
 
108
- {
109
- head.map(({ tag: Tag, attrs, content }) => (
110
- <Tag {...attrs} set:html={content} />
111
- ))
112
- }
106
+ {head.map(({ tag: Tag, attrs, content }) => <Tag {...attrs} set:html={content} />)}