@astrojs/starlight 0.12.1 → 0.13.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 (51) hide show
  1. package/CHANGELOG.md +77 -0
  2. package/components/Icons.ts +2 -0
  3. package/components/Search.astro +3 -2
  4. package/components/SiteTitle.astro +2 -2
  5. package/index.ts +17 -1
  6. package/integrations/asides.ts +17 -14
  7. package/integrations/expressive-code/exports.ts +36 -0
  8. package/integrations/expressive-code/index.ts +156 -0
  9. package/integrations/expressive-code/themes/night-owl-dark.jsonc +1796 -0
  10. package/integrations/expressive-code/themes/night-owl-light.jsonc +1695 -0
  11. package/integrations/expressive-code/theming.ts +108 -0
  12. package/integrations/expressive-code/translations.ts +26 -0
  13. package/integrations/shared/pathToLocale.ts +32 -0
  14. package/integrations/virtual-user-config.ts +14 -2
  15. package/package.json +3 -1
  16. package/schemas/expressiveCode.ts +13 -0
  17. package/schemas/i18n.ts +28 -2
  18. package/schemas/social.ts +2 -0
  19. package/translations/ar.json +5 -1
  20. package/translations/cs.json +5 -1
  21. package/translations/da.json +5 -1
  22. package/translations/de.json +5 -1
  23. package/translations/en.json +5 -1
  24. package/translations/es.json +5 -1
  25. package/translations/fa.json +5 -1
  26. package/translations/fr.json +5 -1
  27. package/translations/gl.json +5 -1
  28. package/translations/he.json +5 -1
  29. package/translations/hi.json +26 -0
  30. package/translations/id.json +5 -1
  31. package/translations/index.ts +4 -0
  32. package/translations/it.json +5 -1
  33. package/translations/ja.json +5 -1
  34. package/translations/ko.json +5 -1
  35. package/translations/nb.json +5 -1
  36. package/translations/nl.json +5 -1
  37. package/translations/pt.json +5 -1
  38. package/translations/ro.json +26 -0
  39. package/translations/ru.json +5 -1
  40. package/translations/sv.json +5 -1
  41. package/translations/tr.json +5 -1
  42. package/translations/uk.json +5 -1
  43. package/translations/vi.json +5 -1
  44. package/translations/zh-CN.json +5 -1
  45. package/utils/base.ts +4 -4
  46. package/utils/createPathFormatter.ts +57 -0
  47. package/utils/format-path.ts +7 -0
  48. package/utils/navigation.ts +21 -10
  49. package/utils/path.ts +15 -0
  50. package/utils/user-config.ts +7 -0
  51. package/virtual.d.ts +9 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,82 @@
1
1
  # @astrojs/starlight
2
2
 
3
+ ## 0.13.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#1023](https://github.com/withastro/starlight/pull/1023) [`a3b80f7`](https://github.com/withastro/starlight/commit/a3b80f71037504f2b8d7f1a641924215091122bb) Thanks [@kevinzunigacuellar](https://github.com/kevinzunigacuellar)! - Respect the `trailingSlash` and `build.format` Astro options when creating Starlight navigation links.
8
+
9
+ ⚠️ **Potentially breaking change:**
10
+ This change will cause small changes in link formatting for most sites.
11
+ These are unlikely to break anything, but if you care about link formatting, you may want to change some Astro settings.
12
+
13
+ If you want to preserve Starlight’s previous behavior, set `trailingSlash: 'always'` in your `astro.config.mjs`:
14
+
15
+ ```js
16
+ import { defineConfig } from 'astro/config';
17
+ import starlight from '@astrojs/starlight';
18
+
19
+ export default defineConfig({
20
+ trailingSlash: 'always',
21
+ integrations: [
22
+ starlight({
23
+ // ...
24
+ }),
25
+ ],
26
+ });
27
+ ```
28
+
29
+ - [#742](https://github.com/withastro/starlight/pull/742) [`c6a4bcb`](https://github.com/withastro/starlight/commit/c6a4bcb7982c54c513f20c96a9b2aaf9ac09094b) Thanks [@hippotastic](https://github.com/hippotastic)! - Adds Expressive Code as Starlight’s default code block renderer
30
+
31
+ ⚠️ **Potentially breaking change:**
32
+ This addition changes how Markdown code blocks are rendered. By default, Starlight will now use [Expressive Code](https://github.com/expressive-code/expressive-code/tree/main/packages/astro-expressive-code).
33
+ If you were already customizing how code blocks are rendered and don't want to use the [features provided by Expressive Code](https://starlight.astro.build/guides/authoring-content/#expressive-code-features), you can preserve the previous behavior by setting the new config option `expressiveCode` to `false`.
34
+
35
+ If you had previously added Expressive Code manually to your Starlight project, you can now remove the manual set-up in `astro.config.mjs`:
36
+
37
+ - Move your configuration to Starlight’s new `expressiveCode` option.
38
+ - Remove the `astro-expressive-code` integration.
39
+
40
+ For example:
41
+
42
+ ```diff
43
+ import starlight from '@astrojs/starlight';
44
+ import { defineConfig } from 'astro/config';
45
+ - import expressiveCode from 'astro-expressive-code';
46
+
47
+ export default defineConfig({
48
+ integrations: [
49
+ - expressiveCode({
50
+ - themes: ['rose-pine'],
51
+ - }),
52
+ starlight({
53
+ title: 'My docs',
54
+ + expressiveCode: {
55
+ + themes: ['rose-pine'],
56
+ + },
57
+ }),
58
+ ],
59
+ });
60
+ ```
61
+
62
+ Note that the built-in Starlight version of Expressive Code sets some opinionated defaults that are different from the `astro-expressive-code` defaults. You may need to set some `styleOverrides` if you wish to keep styles exactly the same.
63
+
64
+ - [#517](https://github.com/withastro/starlight/pull/517) [`5b549cb`](https://github.com/withastro/starlight/commit/5b549cb634f51d28bf9a7f92ad0d82c1671e788a) Thanks [@liruifengv](https://github.com/liruifengv)! - Add i18n support for default aside labels
65
+
66
+ ### Patch Changes
67
+
68
+ - [#1088](https://github.com/withastro/starlight/pull/1088) [`4fe5537`](https://github.com/withastro/starlight/commit/4fe553749a6708fdb119b12a2dbc6b10a980bde1) Thanks [@Lootjs](https://github.com/Lootjs)! - i18n(ru): added Russian aside labels translation
69
+
70
+ - [#1083](https://github.com/withastro/starlight/pull/1083) [`e03a653`](https://github.com/withastro/starlight/commit/e03a65313365b7dbe6095727b28b4e639c446f68) Thanks [@at-the-vr](https://github.com/at-the-vr)! - i18n(hi): Add Hindi language support
71
+
72
+ - [#1075](https://github.com/withastro/starlight/pull/1075) [`2f2adf2`](https://github.com/withastro/starlight/commit/2f2adf29f2a13d5ff0f1577207210745a5ae7405) Thanks [@russbiggs](https://github.com/russbiggs)! - Add Slack social link icon
73
+
74
+ - [#1065](https://github.com/withastro/starlight/pull/1065) [`2d72ed6`](https://github.com/withastro/starlight/commit/2d72ed67c666b26eae44649e70aecef3db815d19) Thanks [@HiDeoo](https://github.com/HiDeoo)! - Ignore search keyboard shortcuts for elements with contents that are editable
75
+
76
+ - [#1081](https://github.com/withastro/starlight/pull/1081) [`f27f781`](https://github.com/withastro/starlight/commit/f27f781556d37e73d0b1d902de745b67f8e4f24d) Thanks [@farisphp](https://github.com/farisphp)! - i18n(id): Add Indonesian aside labels translation
77
+
78
+ - [#1082](https://github.com/withastro/starlight/pull/1082) [`ce27486`](https://github.com/withastro/starlight/commit/ce27486fabd3884ed4bca9372ebd72a0597ab765) Thanks [@bogdaaamn](https://github.com/bogdaaamn)! - i18n(ro): Add Romanian UI translations
79
+
3
80
  ## 0.12.1
4
81
 
5
82
  ### Patch Changes
@@ -99,4 +99,6 @@ export const Icons = {
99
99
  '<path d="M14.41 16.87a3.38 3.38 0 0 1-2.37.63 3.37 3.37 0 0 1-2.36-.63 1 1 0 0 0-1.42 1.41 5.11 5.11 0 0 0 3.78 1.22 5.12 5.12 0 0 0 3.78-1.22 1 1 0 1 0-1.41-1.41ZM9.2 15a1 1 0 1 0-1-1 1 1 0 0 0 1 1Zm6-2a1 1 0 1 0 1 1 1 1 0 0 0-1-1Zm7.8-1.22a3.77 3.77 0 0 0-6.8-2.26 16.5 16.5 0 0 0-3.04-.48l.85-5.7 2.09.7a3 3 0 0 0 6-.06v-.02a3.03 3.03 0 0 0-3-2.96 2.98 2.98 0 0 0-2.34 1.16l-3.24-1.1a1 1 0 0 0-1.3.8l-1.09 7.17a16.66 16.66 0 0 0-3.34.49 3.77 3.77 0 0 0-6.22 4.23A4.86 4.86 0 0 0 1 16c0 3.92 4.83 7 11 7s11-3.08 11-7a4.86 4.86 0 0 0-.57-2.25 3.78 3.78 0 0 0 .57-1.97ZM19.1 3a1 1 0 1 1-1 1 1.02 1.02 0 0 1 1-1ZM4.77 10a1.76 1.76 0 0 1 .88.25A9.98 9.98 0 0 0 3 11.92v-.14A1.78 1.78 0 0 1 4.78 10ZM12 21c-4.88 0-9-2.29-9-5s4.12-5 9-5 9 2.29 9 5-4.12 5-9 5Zm8.99-9.08a9.98 9.98 0 0 0-2.65-1.67 1.76 1.76 0 0 1 .88-.25A1.78 1.78 0 0 1 21 11.78l-.01.14Z"/>',
100
100
  patreon:
101
101
  '<path d="M22.04 7.6c0-2.8-2.19-5.1-4.75-5.93a15.19 15.19 0 0 0-10.44.55C3.16 3.96 2 7.78 1.95 11.58c-.02 3.12.3 11.36 4.94 11.42 3.45.04 3.97-4.4 5.56-6.55 1.14-1.52 2.6-1.95 4.4-2.4 3.1-.76 5.2-3.2 5.2-6.44Z"/>',
102
+ slack:
103
+ '<path d="M5.042 15.165a2.528 2.528 0 0 1-2.52 2.523A2.528 2.528 0 0 1 0 15.165a2.527 2.527 0 0 1 2.522-2.52h2.52v2.52Zm1.271 0a2.527 2.527 0 0 1 2.521-2.52 2.527 2.527 0 0 1 2.521 2.52v6.313A2.528 2.528 0 0 1 8.834 24a2.528 2.528 0 0 1-2.521-2.522v-6.313ZM8.834 5.042a2.528 2.528 0 0 1-2.521-2.52A2.528 2.528 0 0 1 8.834 0a2.528 2.528 0 0 1 2.521 2.522v2.52H8.834Zm0 1.271a2.528 2.528 0 0 1 2.521 2.521 2.528 2.528 0 0 1-2.521 2.521H2.522A2.528 2.528 0 0 1 0 8.834a2.528 2.528 0 0 1 2.522-2.521h6.312Zm10.122 2.521a2.528 2.528 0 0 1 2.522-2.521A2.528 2.528 0 0 1 24 8.834a2.528 2.528 0 0 1-2.522 2.521h-2.522V8.834Zm-1.268 0a2.528 2.528 0 0 1-2.523 2.521 2.527 2.527 0 0 1-2.52-2.521V2.522A2.527 2.527 0 0 1 15.165 0a2.528 2.528 0 0 1 2.523 2.522v6.312Zm-2.523 10.122a2.528 2.528 0 0 1 2.523 2.522A2.528 2.528 0 0 1 15.165 24a2.527 2.527 0 0 1-2.52-2.522v-2.522h2.52Zm0-1.268a2.527 2.527 0 0 1-2.52-2.523 2.526 2.526 0 0 1 2.52-2.52h6.313A2.527 2.527 0 0 1 24 15.165a2.528 2.528 0 0 1-2.522 2.523h-6.313Z"/>',
102
104
  };
@@ -89,8 +89,9 @@ const pagefindTranslations = {
89
89
  // Listen for `/` and `cmd + k` keyboard shortcuts.
90
90
  window.addEventListener('keydown', (e) => {
91
91
  const isInput =
92
- document.activeElement &&
93
- ['input', 'select', 'textarea'].includes(document.activeElement.tagName.toLowerCase());
92
+ document.activeElement instanceof HTMLElement &&
93
+ (['input', 'select', 'textarea'].includes(document.activeElement.tagName.toLowerCase()) ||
94
+ document.activeElement.isContentEditable);
94
95
  if (e.metaKey === true && e.key === 'k') {
95
96
  dialog.open ? closeModal() : openModal();
96
97
  e.preventDefault();
@@ -1,10 +1,10 @@
1
1
  ---
2
2
  import { logos } from 'virtual:starlight/user-images';
3
3
  import config from 'virtual:starlight/user-config';
4
- import { pathWithBase } from '../utils/base';
5
4
  import type { Props } from '../props';
5
+ import { formatPath } from '../utils/format-path';
6
6
 
7
- const href = pathWithBase(Astro.props.locale || '/');
7
+ const href = formatPath(Astro.props.locale || '/');
8
8
  ---
9
9
 
10
10
  <a {href} class="site-title sl-flex">
package/index.ts CHANGED
@@ -4,6 +4,7 @@ import { spawn } from 'node:child_process';
4
4
  import { dirname, relative } from 'node:path';
5
5
  import { fileURLToPath } from 'node:url';
6
6
  import { starlightAsides } from './integrations/asides';
7
+ import { starlightExpressiveCode } from './integrations/expressive-code';
7
8
  import { starlightSitemap } from './integrations/sitemap';
8
9
  import { vitePluginStarlightUserConfig } from './integrations/virtual-user-config';
9
10
  import { errorMap } from './utils/error-map';
@@ -37,6 +38,15 @@ export default function StarlightIntegration(opts: StarlightUserConfig): AstroIn
37
38
  entryPoint: '@astrojs/starlight/index.astro',
38
39
  });
39
40
  const integrations: AstroIntegration[] = [];
41
+ if (!config.integrations.find(({ name }) => name === 'astro-expressive-code')) {
42
+ integrations.push(
43
+ ...starlightExpressiveCode({
44
+ starlightConfig: userConfig,
45
+ astroConfig: config,
46
+ useTranslations,
47
+ })
48
+ );
49
+ }
40
50
  if (!config.integrations.find(({ name }) => name === '@astrojs/sitemap')) {
41
51
  integrations.push(starlightSitemap(userConfig));
42
52
  }
@@ -49,7 +59,13 @@ export default function StarlightIntegration(opts: StarlightUserConfig): AstroIn
49
59
  plugins: [vitePluginStarlightUserConfig(userConfig, config)],
50
60
  },
51
61
  markdown: {
52
- remarkPlugins: [...starlightAsides()],
62
+ remarkPlugins: [
63
+ ...starlightAsides({
64
+ starlightConfig: userConfig,
65
+ astroConfig: config,
66
+ useTranslations,
67
+ }),
68
+ ],
53
69
  rehypePlugins: [rehypeRtlCodeSupport()],
54
70
  shikiConfig:
55
71
  // Configure Shiki theme if the user is using the default github-dark theme.
@@ -1,10 +1,19 @@
1
- import type { AstroUserConfig } from 'astro';
1
+ import type { AstroConfig, AstroUserConfig } from 'astro';
2
2
  import { h as _h, s as _s, type Properties } from 'hastscript';
3
3
  import type { Paragraph as P, Root } from 'mdast';
4
4
  import remarkDirective from 'remark-directive';
5
5
  import type { Plugin, Transformer } from 'unified';
6
6
  import { remove } from 'unist-util-remove';
7
7
  import { visit } from 'unist-util-visit';
8
+ import type { StarlightConfig } from '../types';
9
+ import type { createTranslationSystemFromFs } from '../utils/translations-fs';
10
+ import { pathToLocale } from './shared/pathToLocale';
11
+
12
+ interface AsidesOptions {
13
+ starlightConfig: { locales: StarlightConfig['locales'] };
14
+ astroConfig: { root: AstroConfig['root']; srcDir: AstroConfig['srcDir'] };
15
+ useTranslations: ReturnType<typeof createTranslationSystemFromFs>;
16
+ }
8
17
 
9
18
  /** Hacky function that generates an mdast HTML tree ready for conversion to HTML by rehype. */
10
19
  function h(el: string, attrs: Properties = {}, children: any[] = []): P {
@@ -50,19 +59,11 @@ function s(el: string, attrs: Properties = {}, children: any[] = []): P {
50
59
  * </Aside>
51
60
  * ```
52
61
  */
53
- function remarkAsides(): Plugin<[], Root> {
62
+ function remarkAsides(options: AsidesOptions): Plugin<[], Root> {
54
63
  type Variant = 'note' | 'tip' | 'caution' | 'danger';
55
64
  const variants = new Set(['note', 'tip', 'caution', 'danger']);
56
65
  const isAsideVariant = (s: string): s is Variant => variants.has(s);
57
66
 
58
- // TODO: hook these up for i18n once the design for translating strings is ready
59
- const defaultTitles = {
60
- note: 'Note',
61
- tip: 'Tip',
62
- caution: 'Caution',
63
- danger: 'Danger',
64
- };
65
-
66
67
  const iconPaths = {
67
68
  // Information icon
68
69
  note: [
@@ -95,7 +96,9 @@ function remarkAsides(): Plugin<[], Root> {
95
96
  ],
96
97
  };
97
98
 
98
- const transformer: Transformer<Root> = (tree) => {
99
+ const transformer: Transformer<Root> = (tree, file) => {
100
+ const locale = pathToLocale(file.history[0], options);
101
+ const t = options.useTranslations(locale);
99
102
  visit(tree, (node, index, parent) => {
100
103
  if (!parent || index === null || node.type !== 'containerDirective') {
101
104
  return;
@@ -107,7 +110,7 @@ function remarkAsides(): Plugin<[], Root> {
107
110
  // its children, but we want to pass it as the title prop to <Aside>, so
108
111
  // we iterate over the children, find a directive label, store it for the
109
112
  // title prop, and remove the paragraph from children.
110
- let title = defaultTitles[variant];
113
+ let title = t(`aside.${variant}`);
111
114
  remove(node, (child): boolean | void => {
112
115
  if (child.data?.directiveLabel) {
113
116
  if (
@@ -157,6 +160,6 @@ function remarkAsides(): Plugin<[], Root> {
157
160
 
158
161
  type RemarkPlugins = NonNullable<NonNullable<AstroUserConfig['markdown']>['remarkPlugins']>;
159
162
 
160
- export function starlightAsides(): RemarkPlugins {
161
- return [remarkDirective, remarkAsides()];
163
+ export function starlightAsides(options: AsidesOptions): RemarkPlugins {
164
+ return [remarkDirective, remarkAsides(options)];
162
165
  }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @file This file is exported by Starlight as `@astrojs/starlight/expressive-code`
3
+ * and can be used in your site's configuration to customize Expressive Code.
4
+ *
5
+ * It provides access to all of the Expressive Code classes and functions without having
6
+ * to install `astro-expressive-code` as an additional dependency into your project
7
+ * (and thereby risiking version conflicts).
8
+ *
9
+ * For example, you can use this to load custom themes from a JSONC file (JSON with comments)
10
+ * that would otherwise be difficult to import, and pass them to the `themes` option:
11
+ *
12
+ * @example
13
+ * ```js
14
+ * // astro.config.mjs
15
+ * import fs from 'node:fs';
16
+ * import { defineConfig } from 'astro/config';
17
+ * import starlight from '@astrojs/starlight';
18
+ * import { ExpressiveCodeTheme } from '@astrojs/starlight/expressive-code';
19
+ *
20
+ * const jsoncString = fs.readFileSync(new URL(`./my-theme.jsonc`, import.meta.url), 'utf-8');
21
+ * const myTheme = ExpressiveCodeTheme.fromJSONString(jsoncString);
22
+ *
23
+ * export default defineConfig({
24
+ * integrations: [
25
+ * starlight({
26
+ * title: 'My Starlight site',
27
+ * expressiveCode: {
28
+ * themes: [myTheme],
29
+ * },
30
+ * }),
31
+ * ],
32
+ * });
33
+ * ```
34
+ */
35
+
36
+ export * from 'astro-expressive-code';
@@ -0,0 +1,156 @@
1
+ import {
2
+ astroExpressiveCode,
3
+ type AstroExpressiveCodeOptions,
4
+ addClassName,
5
+ } from 'astro-expressive-code';
6
+ import type { AstroConfig, AstroIntegration } from 'astro';
7
+ import type { StarlightConfig } from '../../types';
8
+ import type { createTranslationSystemFromFs } from '../../utils/translations-fs';
9
+ import { pathToLocale } from '../shared/pathToLocale';
10
+ import {
11
+ applyStarlightUiThemeColors,
12
+ preprocessThemes,
13
+ type ThemeObjectOrBundledThemeName,
14
+ } from './theming';
15
+ import { addTranslations } from './translations';
16
+
17
+ export type StarlightExpressiveCodeOptions = Omit<AstroExpressiveCodeOptions, 'themes'> & {
18
+ /**
19
+ * Set the themes used to style code blocks.
20
+ *
21
+ * See the [Expressive Code `themes` documentation](https://github.com/expressive-code/expressive-code/blob/main/packages/astro-expressive-code/README.md#themes)
22
+ * for details of the supported theme formats.
23
+ *
24
+ * Starlight uses the dark and light variants of Sarah Drasner’s
25
+ * [Night Owl theme](https://github.com/sdras/night-owl-vscode-theme) by default.
26
+ *
27
+ * If you provide at least one dark and one light theme, Starlight will automatically keep
28
+ * the active code block theme in sync with the current site theme. Configure this behavior
29
+ * with the [`useStarlightDarkModeSwitch`](#usestarlightdarkmodeswitch) option.
30
+ *
31
+ * Defaults to `['starlight-dark', 'starlight-light']`.
32
+ */
33
+ themes?: ThemeObjectOrBundledThemeName[] | undefined;
34
+ /**
35
+ * When `true`, code blocks automatically switch between light and dark themes when the
36
+ * site theme changes.
37
+ *
38
+ * When `false`, you must manually add CSS to handle switching between multiple themes.
39
+ *
40
+ * **Note**: When setting `themes`, you must provide at least one dark and one light theme
41
+ * for the Starlight dark mode switch to work.
42
+ *
43
+ * Defaults to `true`.
44
+ */
45
+ useStarlightDarkModeSwitch?: boolean | undefined;
46
+ /**
47
+ * When `true`, Starlight's CSS variables are used for the colors of code block UI elements
48
+ * (backgrounds, buttons, shadows etc.), matching the
49
+ * [site color theme](/guides/css-and-tailwind/#theming).
50
+ *
51
+ * When `false`, the colors provided by the active syntax highlighting theme are used for
52
+ * these elements.
53
+ *
54
+ * Defaults to `true` if the `themes` option is not set (= you are using Starlight's
55
+ * default themes), and `false` otherwise.
56
+ *
57
+ * **Note**: When manually setting this to `true` with your custom set of `themes`, you must
58
+ * provide at least one dark and one light theme to ensure proper color contrast.
59
+ */
60
+ useStarlightUiThemeColors?: boolean | undefined;
61
+ };
62
+
63
+ export const starlightExpressiveCode = ({
64
+ astroConfig,
65
+ starlightConfig,
66
+ useTranslations,
67
+ }: {
68
+ astroConfig: Pick<AstroConfig, 'root' | 'srcDir'>;
69
+ starlightConfig: StarlightConfig;
70
+ useTranslations: ReturnType<typeof createTranslationSystemFromFs>;
71
+ }): AstroIntegration[] => {
72
+ const { locales, expressiveCode } = starlightConfig;
73
+ if (expressiveCode === false) return [];
74
+ const config: StarlightExpressiveCodeOptions =
75
+ typeof expressiveCode === 'object' ? expressiveCode : {};
76
+
77
+ const {
78
+ themes: themesInput,
79
+ customizeTheme,
80
+ styleOverrides: { textMarkers: textMarkersStyleOverrides, ...otherStyleOverrides } = {},
81
+ useStarlightDarkModeSwitch,
82
+ useStarlightUiThemeColors = config.themes === undefined,
83
+ plugins = [],
84
+ ...rest
85
+ } = config;
86
+
87
+ // Handle the `themes` option
88
+ const themes = preprocessThemes(themesInput);
89
+ if (useStarlightUiThemeColors === true && themes.length < 2) {
90
+ console.warn(
91
+ `*** Warning: Using the config option "useStarlightUiThemeColors: true" ` +
92
+ `with a single theme is not recommended. For better color contrast, ` +
93
+ `please provide at least one dark and one light theme.\n`
94
+ );
95
+ }
96
+
97
+ // Add the `not-content` class to all rendered blocks to prevent them from being affected
98
+ // by Starlight's default content styles
99
+ plugins.push({
100
+ name: 'Starlight Plugin',
101
+ hooks: {
102
+ postprocessRenderedBlock: ({ renderData }) => {
103
+ addClassName(renderData.blockAst, 'not-content');
104
+ },
105
+ },
106
+ });
107
+
108
+ // Add Expressive Code UI translations (if any) for all defined locales
109
+ addTranslations(locales, useTranslations);
110
+
111
+ return [
112
+ astroExpressiveCode({
113
+ themes,
114
+ customizeTheme: (theme) => {
115
+ if (useStarlightUiThemeColors) {
116
+ applyStarlightUiThemeColors(theme);
117
+ }
118
+ if (customizeTheme) {
119
+ theme = customizeTheme(theme) ?? theme;
120
+ }
121
+ return theme;
122
+ },
123
+ themeCssSelector: (theme, { styleVariants }) => {
124
+ // If one dark and one light theme are available, and the user has not disabled it,
125
+ // generate theme CSS selectors compatible with Starlight's dark mode switch
126
+ if (useStarlightDarkModeSwitch !== false && styleVariants.length >= 2) {
127
+ const baseTheme = styleVariants[0]?.theme;
128
+ const altTheme = styleVariants.find((v) => v.theme.type !== baseTheme?.type)?.theme;
129
+ if (theme === baseTheme || theme === altTheme) return `[data-theme='${theme.type}']`;
130
+ }
131
+ // Return the default selector
132
+ return `[data-theme='${theme.name}']`;
133
+ },
134
+ styleOverrides: {
135
+ borderRadius: '0px',
136
+ borderWidth: '1px',
137
+ codePaddingBlock: '0.75rem',
138
+ codePaddingInline: '1rem',
139
+ codeFontFamily: 'var(--__sl-font-mono)',
140
+ codeFontSize: 'var(--sl-text-code)',
141
+ codeLineHeight: 'var(--sl-line-height)',
142
+ uiFontFamily: 'var(--__sl-font)',
143
+ textMarkers: {
144
+ lineDiffIndicatorMarginLeft: '0.25rem',
145
+ defaultChroma: '45',
146
+ backgroundOpacity: '60%',
147
+ ...textMarkersStyleOverrides,
148
+ },
149
+ ...otherStyleOverrides,
150
+ },
151
+ getBlockLocale: ({ file }) => pathToLocale(file.path, { starlightConfig, astroConfig }),
152
+ plugins,
153
+ ...rest,
154
+ }),
155
+ ];
156
+ };