@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.
- package/CHANGELOG.md +77 -0
- package/components/Icons.ts +2 -0
- package/components/Search.astro +3 -2
- package/components/SiteTitle.astro +2 -2
- package/index.ts +17 -1
- package/integrations/asides.ts +17 -14
- package/integrations/expressive-code/exports.ts +36 -0
- package/integrations/expressive-code/index.ts +156 -0
- package/integrations/expressive-code/themes/night-owl-dark.jsonc +1796 -0
- package/integrations/expressive-code/themes/night-owl-light.jsonc +1695 -0
- package/integrations/expressive-code/theming.ts +108 -0
- package/integrations/expressive-code/translations.ts +26 -0
- package/integrations/shared/pathToLocale.ts +32 -0
- package/integrations/virtual-user-config.ts +14 -2
- package/package.json +3 -1
- package/schemas/expressiveCode.ts +13 -0
- package/schemas/i18n.ts +28 -2
- package/schemas/social.ts +2 -0
- package/translations/ar.json +5 -1
- package/translations/cs.json +5 -1
- package/translations/da.json +5 -1
- package/translations/de.json +5 -1
- package/translations/en.json +5 -1
- package/translations/es.json +5 -1
- package/translations/fa.json +5 -1
- package/translations/fr.json +5 -1
- package/translations/gl.json +5 -1
- package/translations/he.json +5 -1
- package/translations/hi.json +26 -0
- package/translations/id.json +5 -1
- package/translations/index.ts +4 -0
- package/translations/it.json +5 -1
- package/translations/ja.json +5 -1
- package/translations/ko.json +5 -1
- package/translations/nb.json +5 -1
- package/translations/nl.json +5 -1
- package/translations/pt.json +5 -1
- package/translations/ro.json +26 -0
- package/translations/ru.json +5 -1
- package/translations/sv.json +5 -1
- package/translations/tr.json +5 -1
- package/translations/uk.json +5 -1
- package/translations/vi.json +5 -1
- package/translations/zh-CN.json +5 -1
- package/utils/base.ts +4 -4
- package/utils/createPathFormatter.ts +57 -0
- package/utils/format-path.ts +7 -0
- package/utils/navigation.ts +21 -10
- package/utils/path.ts +15 -0
- package/utils/user-config.ts +7 -0
- 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
|
package/components/Icons.ts
CHANGED
|
@@ -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
|
};
|
package/components/Search.astro
CHANGED
|
@@ -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 =
|
|
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: [
|
|
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.
|
package/integrations/asides.ts
CHANGED
|
@@ -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 =
|
|
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
|
+
};
|