forked from withastro/starlight
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.ts
126 lines (119 loc) · 4.82 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import mdx from '@astrojs/mdx';
import type { AstroIntegration } from 'astro';
import { spawn } from 'node:child_process';
import { dirname, relative } from 'node:path';
import { fileURLToPath } from 'node:url';
import { starlightAsides, starlightDirectivesRestorationIntegration } from './integrations/asides';
import { starlightExpressiveCode } from './integrations/expressive-code/index';
import { starlightSitemap } from './integrations/sitemap';
import { vitePluginStarlightUserConfig } from './integrations/virtual-user-config';
import { rehypeRtlCodeSupport } from './integrations/code-rtl-support';
import { createTranslationSystemFromFs } from './utils/translations-fs';
import { runPlugins, type StarlightUserConfigWithPlugins } from './utils/plugins';
import { processI18nConfig } from './utils/i18n';
import type { StarlightConfig } from './types';
export default function StarlightIntegration({
plugins,
...opts
}: StarlightUserConfigWithPlugins): AstroIntegration {
let userConfig: StarlightConfig;
return {
name: '@astrojs/starlight',
hooks: {
'astro:config:setup': async ({
command,
config,
injectRoute,
isRestart,
logger,
updateConfig,
}) => {
// Run plugins to get the updated configuration and any extra Astro integrations to load.
const pluginResult = await runPlugins(opts, plugins, {
command,
config,
isRestart,
logger,
});
// Process the Astro and Starlight configurations for i18n and translations.
const { astroI18nConfig, starlightConfig } = processI18nConfig(
pluginResult.starlightConfig,
config.i18n
);
const { integrations } = pluginResult;
userConfig = starlightConfig;
const useTranslations = createTranslationSystemFromFs(starlightConfig, config);
if (!starlightConfig.disable404Route) {
injectRoute({
pattern: '404',
entrypoint: '@astrojs/starlight/404.astro',
// Ensure page is pre-rendered even when project is on server output mode
prerender: true,
});
}
injectRoute({
pattern: '[...slug]',
entrypoint: '@astrojs/starlight/index.astro',
// Ensure page is pre-rendered even when project is on server output mode
prerender: true,
});
// Add built-in integrations only if they are not already added by the user through the
// config or by a plugin.
const allIntegrations = [...config.integrations, ...integrations];
if (!allIntegrations.find(({ name }) => name === 'astro-expressive-code')) {
integrations.push(...starlightExpressiveCode({ starlightConfig, useTranslations }));
}
if (!allIntegrations.find(({ name }) => name === '@astrojs/sitemap')) {
integrations.push(starlightSitemap(starlightConfig));
}
if (!allIntegrations.find(({ name }) => name === '@astrojs/mdx')) {
integrations.push(mdx({ optimize: true }));
}
// Add Starlight directives restoration integration at the end of the list so that remark
// plugins injected by Starlight plugins through Astro integrations can handle text and
// leaf directives before they are transformed back to their original form.
integrations.push(starlightDirectivesRestorationIntegration());
// Add integrations immediately after Starlight in the config array.
// e.g. if a user has `integrations: [starlight(), tailwind()]`, then the order will be
// `[starlight(), expressiveCode(), sitemap(), mdx(), tailwind()]`.
// This ensures users can add integrations before/after Starlight and we respect that order.
const selfIndex = config.integrations.findIndex((i) => i.name === '@astrojs/starlight');
config.integrations.splice(selfIndex + 1, 0, ...integrations);
updateConfig({
vite: {
plugins: [vitePluginStarlightUserConfig(starlightConfig, config)],
},
markdown: {
remarkPlugins: [
...starlightAsides({ starlightConfig, astroConfig: config, useTranslations }),
],
rehypePlugins: [rehypeRtlCodeSupport()],
shikiConfig:
// Configure Shiki theme if the user is using the default github-dark theme.
config.markdown.shikiConfig.theme !== 'github-dark' ? {} : { theme: 'css-variables' },
},
scopedStyleStrategy: 'where',
// If not already configured, default to prefetching all links on hover.
prefetch: config.prefetch ?? { prefetchAll: true },
experimental: {
globalRoutePriority: true,
},
i18n: astroI18nConfig,
});
},
'astro:build:done': ({ dir }) => {
if (!userConfig.pagefind) return;
const targetDir = fileURLToPath(dir);
const cwd = dirname(fileURLToPath(import.meta.url));
const relativeDir = relative(cwd, targetDir);
return new Promise<void>((resolve) => {
spawn('npx', ['-y', 'pagefind', '--site', relativeDir], {
stdio: 'inherit',
shell: true,
cwd,
}).on('close', () => resolve());
});
},
},
};
}