{entry.label}
diff --git a/packages/starlight/index.astro b/packages/starlight/index.astro
deleted file mode 100644
index 74ba7b1c9b..0000000000
--- a/packages/starlight/index.astro
+++ /dev/null
@@ -1,19 +0,0 @@
----
-import type { InferGetStaticPropsType } from 'astro';
-import { generateRouteData } from './utils/route-data';
-import { paths } from './utils/routing';
-
-import Page from './components/Page.astro';
-
-export const prerender = true;
-
-export async function getStaticPaths() {
- return paths;
-}
-
-type Props = InferGetStaticPropsType
;
-const { Content, headings } = await Astro.props.entry.render();
-const route = generateRouteData({ props: { ...Astro.props, headings }, url: Astro.url });
----
-
-
diff --git a/packages/starlight/index.ts b/packages/starlight/index.ts
index 4a1d7bcfb0..8ea3c9c93e 100644
--- a/packages/starlight/index.ts
+++ b/packages/starlight/index.ts
@@ -57,17 +57,20 @@ export default function StarlightIntegration({
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,
+ entrypoint: starlightConfig.prerender
+ ? '@astrojs/starlight/routes/static/404.astro'
+ : '@astrojs/starlight/routes/ssr/404.astro',
+ prerender: starlightConfig.prerender,
});
}
injectRoute({
pattern: '[...slug]',
- entrypoint: '@astrojs/starlight/index.astro',
- // Ensure page is pre-rendered even when project is on server output mode
- prerender: true,
+ entrypoint: starlightConfig.prerender
+ ? '@astrojs/starlight/routes/static/index.astro'
+ : '@astrojs/starlight/routes/ssr/index.astro',
+ prerender: starlightConfig.prerender,
});
+
// 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];
@@ -80,6 +83,7 @@ export default function StarlightIntegration({
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.
@@ -94,7 +98,9 @@ export default function StarlightIntegration({
updateConfig({
vite: {
- plugins: [vitePluginStarlightUserConfig(starlightConfig, config, pluginTranslations)],
+ plugins: [
+ vitePluginStarlightUserConfig(command, starlightConfig, config, pluginTranslations),
+ ],
},
markdown: {
remarkPlugins: [
diff --git a/packages/starlight/integrations/virtual-user-config.ts b/packages/starlight/integrations/virtual-user-config.ts
index 027a11e96a..52f60badd4 100644
--- a/packages/starlight/integrations/virtual-user-config.ts
+++ b/packages/starlight/integrations/virtual-user-config.ts
@@ -1,7 +1,8 @@
-import type { AstroConfig, ViteUserConfig } from 'astro';
+import type { AstroConfig, HookParameters, ViteUserConfig } from 'astro';
import { resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import type { StarlightConfig } from '../utils/user-config';
+import { getAllNewestCommitDate } from '../utils/git';
import type { PluginTranslations } from '../utils/plugins';
function resolveVirtualModuleId(id: T): `\0${T}` {
@@ -10,6 +11,7 @@ function resolveVirtualModuleId(id: T): `\0${T}` {
/** Vite plugin that exposes Starlight user config and project context via virtual modules. */
export function vitePluginStarlightUserConfig(
+ command: HookParameters<'astro:config:setup'>['command'],
opts: StarlightConfig,
{
build,
@@ -31,6 +33,17 @@ export function vitePluginStarlightUserConfig(
const resolveId = (id: string, base = root) =>
JSON.stringify(id.startsWith('.') ? resolve(fileURLToPath(base), id) : id);
+ /**
+ * Resolves a path to a Starlight file relative to this file.
+ * @example
+ * resolveLocalPath('../utils/git.ts');
+ * // => '"/users/houston/docs/node_modules/@astrojs/starlight/utils/git.ts"'
+ */
+ const resolveLocalPath = (path: string) =>
+ JSON.stringify(fileURLToPath(new URL(path, import.meta.url)));
+
+ const docsPath = resolve(fileURLToPath(srcDir), 'content/docs');
+
const virtualComponentModules = Object.fromEntries(
Object.entries(opts.components).map(([name, path]) => [
`virtual:starlight/components/${name}`,
@@ -47,6 +60,13 @@ export function vitePluginStarlightUserConfig(
srcDir,
trailingSlash,
})}`,
+ 'virtual:starlight/git-info':
+ (command !== 'build'
+ ? `import { makeAPI } from ${resolveLocalPath('../utils/git.ts')};` +
+ `const api = makeAPI(${JSON.stringify(docsPath)});`
+ : `import { makeAPI } from ${resolveLocalPath('../utils/gitInlined.ts')};` +
+ `const api = makeAPI(${JSON.stringify(getAllNewestCommitDate(docsPath))});`) +
+ 'export const getNewestCommitDate = api.getNewestCommitDate;',
'virtual:starlight/user-css': opts.customCss.map((id) => `import ${resolveId(id)};`).join(''),
'virtual:starlight/user-images': opts.logo
? 'src' in opts.logo
diff --git a/packages/starlight/package.json b/packages/starlight/package.json
index 5f89dcac55..0dbd0b5527 100644
--- a/packages/starlight/package.json
+++ b/packages/starlight/package.json
@@ -1,6 +1,6 @@
{
"name": "@astrojs/starlight",
- "version": "0.26.4",
+ "version": "0.27.1",
"description": "Build beautiful, high-performance documentation websites with Astro",
"scripts": {
"test": "vitest",
@@ -171,8 +171,7 @@
"types": "./integrations/expressive-code/hast.d.ts",
"default": "./integrations/expressive-code/hast.mjs"
},
- "./index.astro": "./index.astro",
- "./404.astro": "./404.astro",
+ "./routes/*": "./routes/*",
"./style/markdown.css": "./style/markdown.css"
},
"peerDependencies": {
@@ -184,7 +183,8 @@
"@types/node": "^18.16.19",
"@vitest/coverage-v8": "^1.6.0",
"astro": "^4.15.3",
- "vitest": "^1.6.0"
+ "vitest": "^1.6.0",
+ "linkedom": "^0.18.4"
},
"dependencies": {
"@astrojs/mdx": "^3.1.3",
diff --git a/packages/starlight/routes/common.astro b/packages/starlight/routes/common.astro
new file mode 100644
index 0000000000..eab058a918
--- /dev/null
+++ b/packages/starlight/routes/common.astro
@@ -0,0 +1,16 @@
+---
+import { generateRouteData } from '../utils/route-data';
+import type { Route } from '../utils/routing';
+import Page from '../components/Page.astro';
+
+export type Props = {
+ route: Route;
+};
+
+const { route } = Astro.props;
+
+const { Content, headings } = await route.entry.render();
+const routeData = generateRouteData({ props: { ...route, headings }, url: Astro.url });
+---
+
+
diff --git a/packages/starlight/routes/ssr/404.astro b/packages/starlight/routes/ssr/404.astro
new file mode 100644
index 0000000000..9376b3105b
--- /dev/null
+++ b/packages/starlight/routes/ssr/404.astro
@@ -0,0 +1,7 @@
+---
+import FourOhFour from '../static/404.astro';
+
+export const prerender = false;
+---
+
+
diff --git a/packages/starlight/routes/ssr/index.astro b/packages/starlight/routes/ssr/index.astro
new file mode 100644
index 0000000000..9625bd5795
--- /dev/null
+++ b/packages/starlight/routes/ssr/index.astro
@@ -0,0 +1,14 @@
+---
+import { getRouteBySlugParam } from '../../utils/routing';
+import CommonPage from '../common.astro';
+
+export const prerender = false;
+
+const route = getRouteBySlugParam(Astro.params.slug);
+
+if (route === undefined) {
+ return new Response(null, { status: 404 });
+}
+---
+
+
diff --git a/packages/starlight/404.astro b/packages/starlight/routes/static/404.astro
similarity index 62%
rename from packages/starlight/404.astro
rename to packages/starlight/routes/static/404.astro
index 15cabd6a23..aa6e4afa49 100644
--- a/packages/starlight/404.astro
+++ b/packages/starlight/routes/static/404.astro
@@ -1,12 +1,11 @@
---
import { getEntry } from 'astro:content';
import config from 'virtual:starlight/user-config';
-import EmptyContent from './components/EmptyMarkdown.md';
-import Page from './components/Page.astro';
-import { generateRouteData } from './utils/route-data';
-import type { StarlightDocsEntry } from './utils/routing';
-import { useTranslations } from './utils/translations';
-import { BuiltInDefaultLocale } from './utils/i18n';
+import EmptyContent from '../../components/EmptyMarkdown.md';
+import type { Route, StarlightDocsEntry } from '../../utils/routing';
+import { useTranslations } from '../../utils/translations';
+import { BuiltInDefaultLocale } from '../../utils/i18n';
+import CommonPage from '../common.astro';
export const prerender = true;
@@ -42,11 +41,7 @@ const fallbackEntry: StarlightDocsEntry = {
const userEntry = await getEntry('docs', '404');
const entry = userEntry || fallbackEntry;
-const { Content, headings } = await entry.render();
-const route = generateRouteData({
- props: { ...entryMeta, entryMeta, headings, entry, id: entry.id, slug: entry.slug },
- url: Astro.url,
-});
+const route: Route = { ...entryMeta, entryMeta, entry, id: entry.id, slug: entry.slug };
---
-
+
diff --git a/packages/starlight/routes/static/index.astro b/packages/starlight/routes/static/index.astro
new file mode 100644
index 0000000000..dfa6f259d5
--- /dev/null
+++ b/packages/starlight/routes/static/index.astro
@@ -0,0 +1,15 @@
+---
+import type { InferGetStaticPropsType } from 'astro';
+import { paths } from '../../utils/routing';
+import CommonPage from '../common.astro';
+
+export const prerender = true;
+
+export async function getStaticPaths() {
+ return paths;
+}
+
+type Props = InferGetStaticPropsType;
+---
+
+
diff --git a/packages/starlight/utils/git.ts b/packages/starlight/utils/git.ts
index d69bd259ea..e593788367 100644
--- a/packages/starlight/utils/git.ts
+++ b/packages/starlight/utils/git.ts
@@ -1,7 +1,22 @@
-import { basename, dirname } from 'node:path';
+/**
+ * Git module to be used from the dev server and from the integration.
+ */
+
+import { basename, dirname, relative, resolve } from 'node:path';
+import { realpathSync } from 'node:fs';
import { spawnSync } from 'node:child_process';
-export function getNewestCommitDate(file: string) {
+export type GitAPI = {
+ getNewestCommitDate: (file: string) => Date;
+};
+
+export const makeAPI = (directory: string): GitAPI => {
+ return {
+ getNewestCommitDate: (file) => getNewestCommitDate(resolve(directory, file)),
+ };
+};
+
+export function getNewestCommitDate(file: string): Date {
const result = spawnSync('git', ['log', '--format=%ct', '--max-count=1', basename(file)], {
cwd: dirname(file),
encoding: 'utf-8',
@@ -22,3 +37,76 @@ export function getNewestCommitDate(file: string) {
const date = new Date(timestamp * 1000);
return date;
}
+
+function getRepoRoot(directory: string): string {
+ const result = spawnSync('git', ['rev-parse', '--show-toplevel'], {
+ cwd: directory,
+ encoding: 'utf-8',
+ });
+
+ if (result.error) {
+ return directory;
+ }
+
+ try {
+ return realpathSync(result.stdout.trim());
+ } catch {
+ return directory;
+ }
+}
+
+export function getAllNewestCommitDate(directory: string): [string, number][] {
+ const repoRoot = getRepoRoot(directory);
+
+ const gitLog = spawnSync(
+ 'git',
+ [
+ 'log',
+ // Format each history entry as t:
+ '--format=t:%ct',
+ // In each entry include the name and status for each modified file
+ '--name-status',
+ '--',
+ directory,
+ ],
+ {
+ cwd: repoRoot,
+ encoding: 'utf-8',
+ }
+ );
+
+ if (gitLog.error) {
+ return [];
+ }
+
+ let runningDate = Date.now();
+ const latestDates = new Map();
+
+ for (const logLine of gitLog.stdout.split('\n')) {
+ if (logLine.startsWith('t:')) {
+ // t:
+ runningDate = Number.parseInt(logLine.slice(2)) * 1000;
+ }
+
+ // - Added files take the format `A\t`
+ // - Modified files take the format `M\t`
+ // - Deleted files take the format `D\t`
+ // - Renamed files take the format `R\t\t`
+ // - Copied files take the format `C\t\t`
+ // The name of the file as of the commit being processed is always
+ // the last part of the log line.
+ const tabSplit = logLine.lastIndexOf('\t');
+ if (tabSplit === -1) continue;
+ const fileName = logLine.slice(tabSplit + 1);
+
+ const currentLatest = latestDates.get(fileName) || 0;
+ latestDates.set(fileName, Math.max(currentLatest, runningDate));
+ }
+
+ return Array.from(latestDates.entries()).map(([file, date]) => {
+ const fileFullPath = resolve(repoRoot, file);
+ const fileInDirectory = relative(directory, fileFullPath);
+
+ return [fileInDirectory, date];
+ });
+}
diff --git a/packages/starlight/utils/gitInlined.ts b/packages/starlight/utils/gitInlined.ts
new file mode 100644
index 0000000000..387e67ad78
--- /dev/null
+++ b/packages/starlight/utils/gitInlined.ts
@@ -0,0 +1,20 @@
+/**
+ * Git module to be used on production build results.
+ * The API is based on inlined git information.
+ */
+
+import type { GitAPI, getAllNewestCommitDate } from './git';
+
+type InlinedData = ReturnType;
+
+export const makeAPI = (data: InlinedData): GitAPI => {
+ const trackedDocsFiles = new Map(data);
+
+ return {
+ getNewestCommitDate: (file) => {
+ const timestamp = trackedDocsFiles.get(file);
+ if (!timestamp) throw new Error(`Failed to retrieve the git history for file "${file}"`);
+ return new Date(timestamp);
+ },
+ };
+};
diff --git a/packages/starlight/utils/plugins.ts b/packages/starlight/utils/plugins.ts
index b4d4118c12..1f9364bf3e 100644
--- a/packages/starlight/utils/plugins.ts
+++ b/packages/starlight/utils/plugins.ts
@@ -2,6 +2,7 @@ import type { AstroIntegration } from 'astro';
import { z } from 'astro/zod';
import { StarlightConfigSchema, type StarlightUserConfig } from '../utils/user-config';
import { parseWithFriendlyErrors } from '../utils/error-map';
+import { AstroError } from 'astro/errors';
import type { UserI18nSchema } from './translations';
/**
@@ -82,6 +83,14 @@ export async function runPlugins(
});
}
+ if (context.config.output === 'static' && !starlightConfig.prerender) {
+ throw new AstroError(
+ 'Starlight’s `prerender: false` option requires `output: "hybrid"` or `"server"` in your Astro config.',
+ 'Either set `output` in your Astro config or set `prerender: true` in the Starlight options.\n\n' +
+ 'Learn more about rendering modes in the Astro docs: https://docs.astro.build/en/basics/rendering-modes/'
+ );
+ }
+
return { integrations, starlightConfig, pluginTranslations };
}
diff --git a/packages/starlight/utils/route-data.ts b/packages/starlight/utils/route-data.ts
index 28763e681b..c64571f982 100644
--- a/packages/starlight/utils/route-data.ts
+++ b/packages/starlight/utils/route-data.ts
@@ -1,9 +1,8 @@
import type { MarkdownHeading } from 'astro';
-import { fileURLToPath } from 'node:url';
import project from 'virtual:starlight/project-context';
import config from 'virtual:starlight/user-config';
import { generateToC, type TocItem } from './generateToC';
-import { getNewestCommitDate } from './git';
+import { getNewestCommitDate } from 'virtual:starlight/git-info';
import { getPrevNextLinks, getSidebar, type SidebarEntry } from './navigation';
import { ensureTrailingSlash } from './path';
import type { Route } from './routing';
@@ -83,11 +82,10 @@ function getLastUpdated({ entry }: PageProps): Date | undefined {
const { lastUpdated: configLastUpdated } = config;
if (frontmatterLastUpdated ?? configLastUpdated) {
- const currentFilePath = fileURLToPath(new URL('src/content/docs/' + entry.id, project.root));
try {
return frontmatterLastUpdated instanceof Date
? frontmatterLastUpdated
- : getNewestCommitDate(currentFilePath);
+ : getNewestCommitDate(entry.id);
} catch {
// If the git command fails, ignore the error.
return undefined;
diff --git a/packages/starlight/utils/routing.ts b/packages/starlight/utils/routing.ts
index a0b15fd386..b365fb5f8e 100644
--- a/packages/starlight/utils/routing.ts
+++ b/packages/starlight/utils/routing.ts
@@ -100,6 +100,19 @@ function getRoutes(): Route[] {
}
export const routes = getRoutes();
+function getParamRouteMapping(): ReadonlyMap {
+ const map = new Map();
+ for (const route of routes) {
+ map.set(slugToParam(route.slug), route);
+ }
+ return map;
+}
+const routesBySlugParam = getParamRouteMapping();
+
+export function getRouteBySlugParam(slugParam: string | undefined): Route | undefined {
+ return routesBySlugParam.get(slugParam?.replace(/\/$/, '') || undefined);
+}
+
function getPaths(): Path[] {
return routes.map((route) => ({
params: { slug: slugToParam(route.slug) },
diff --git a/packages/starlight/utils/user-config.ts b/packages/starlight/utils/user-config.ts
index 296b8c8402..9a47db4c34 100644
--- a/packages/starlight/utils/user-config.ts
+++ b/packages/starlight/utils/user-config.ts
@@ -195,7 +195,7 @@ const UserConfigSchema = z.object({
* Set to `false` to disable indexing your site with Pagefind.
* This will also hide the default search UI if in use.
*/
- pagefind: z.boolean().default(true),
+ pagefind: z.boolean().optional(),
/** Specify paths to components that should override Starlight’s default components */
components: ComponentConfigSchema(),
@@ -209,6 +209,13 @@ const UserConfigSchema = z.object({
/** Disable Starlight's default 404 page. */
disable404Route: z.boolean().default(false).describe("Disable Starlight's default 404 page."),
+ /**
+ * Define whether Starlight pages should be prerendered or not.
+ * Defaults to always prerender Starlight pages, even when the project is
+ * set to "server" output mode.
+ */
+ prerender: z.boolean().default(true),
+
/** Enable displaying a “Built with Starlight” link in your site’s footer. */
credits: z
.boolean()
@@ -216,8 +223,16 @@ const UserConfigSchema = z.object({
.describe('Enable displaying a “Built with Starlight” link in your site’s footer.'),
});
-export const StarlightConfigSchema = UserConfigSchema.strict().transform(
- ({ title, locales, defaultLocale, ...config }, ctx) => {
+export const StarlightConfigSchema = UserConfigSchema.strict()
+ .transform((config) => ({
+ ...config,
+ // Pagefind only defaults to true if prerender is also true.
+ pagefind: config.pagefind ?? config.prerender,
+ }))
+ .refine((config) => !(!config.prerender && config.pagefind), {
+ message: 'Pagefind search is not support with prerendering disabled.',
+ })
+ .transform(({ title, locales, defaultLocale, ...config }, ctx) => {
const configuredLocales = Object.keys(locales ?? {});
// This is a multilingual site (more than one locale configured) or a monolingual site with
@@ -286,8 +301,7 @@ export const StarlightConfigSchema = UserConfigSchema.strict().transform(
defaultLocale: defaultLocaleConfig,
locales: undefined,
} as const;
- }
-);
+ });
export type StarlightConfig = z.infer;
export type StarlightUserConfig = z.input;
diff --git a/packages/starlight/virtual.d.ts b/packages/starlight/virtual.d.ts
index 684f16a1de..f7475aa8c4 100644
--- a/packages/starlight/virtual.d.ts
+++ b/packages/starlight/virtual.d.ts
@@ -14,6 +14,10 @@ declare module 'virtual:starlight/project-context' {
export default ProjectContext;
}
+declare module 'virtual:starlight/git-info' {
+ export function getNewestCommitDate(file: string): Date;
+}
+
declare module 'virtual:starlight/user-css' {}
declare module 'virtual:starlight/user-images' {
diff --git a/packages/starlight/vitest.config.ts b/packages/starlight/vitest.config.ts
index ce012eacc8..e15ce18747 100644
--- a/packages/starlight/vitest.config.ts
+++ b/packages/starlight/vitest.config.ts
@@ -21,10 +21,10 @@ export default defineConfig({
],
thresholds: {
autoUpdate: true,
- lines: 80.11,
- functions: 92.85,
- branches: 91.23,
- statements: 80.11,
+ lines: 89.53,
+ functions: 94.08,
+ branches: 93.07,
+ statements: 89.53,
},
},
},
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 9a84306d31..f1a7357413 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -76,7 +76,7 @@ importers:
examples/basics:
dependencies:
'@astrojs/starlight':
- specifier: ^0.26.4
+ specifier: ^0.27.1
version: link:../../packages/starlight
astro:
specifier: ^4.15.3
@@ -91,10 +91,28 @@ importers:
specifier: workspace:*
version: link:../../packages/starlight
+ examples/markdoc:
+ dependencies:
+ '@astrojs/markdoc':
+ specifier: ^0.11.4
+ version: 0.11.4(astro@4.15.3)
+ '@astrojs/starlight':
+ specifier: ^0.27.1
+ version: link:../../packages/starlight
+ '@astrojs/starlight-markdoc':
+ specifier: ^0.1.0
+ version: link:../../packages/markdoc
+ astro:
+ specifier: ^4.15.3
+ version: 4.15.3(@types/node@18.16.19)(typescript@5.4.5)
+ sharp:
+ specifier: ^0.32.5
+ version: 0.32.6
+
examples/tailwind:
dependencies:
'@astrojs/starlight':
- specifier: ^0.26.4
+ specifier: ^0.27.1
version: link:../../packages/starlight
'@astrojs/starlight-tailwind':
specifier: ^2.0.3
@@ -137,6 +155,19 @@ importers:
specifier: ^1.3.8
version: 1.3.8
+ packages/markdoc:
+ dependencies:
+ '@astrojs/markdoc':
+ specifier: ^0.11.4
+ version: 0.11.4(astro@4.15.3)
+ '@astrojs/starlight':
+ specifier: '>=0.23.0'
+ version: link:../starlight
+ devDependencies:
+ vitest:
+ specifier: ^1.6.0
+ version: 1.6.0(@types/node@18.16.19)
+
packages/starlight:
dependencies:
'@astrojs/mdx':
@@ -221,6 +252,9 @@ importers:
astro:
specifier: ^4.15.3
version: 4.15.3(@types/node@18.16.19)(typescript@5.4.5)
+ linkedom:
+ specifier: ^0.18.4
+ version: 0.18.4
vitest:
specifier: ^1.6.0
version: 1.6.0(@types/node@18.16.19)
@@ -243,6 +277,27 @@ importers:
specifier: ^4.15.3
version: 4.15.3(@types/node@18.16.19)(typescript@5.4.5)
+ packages/starlight/__e2e__/fixtures/git:
+ dependencies:
+ '@astrojs/starlight':
+ specifier: workspace:*
+ version: link:../../..
+ astro:
+ specifier: ^4.15.3
+ version: 4.15.3(@types/node@18.16.19)(typescript@5.4.5)
+
+ packages/starlight/__e2e__/fixtures/ssr:
+ dependencies:
+ '@astrojs/node':
+ specifier: ^8.3.2
+ version: 8.3.3(astro@4.15.3)
+ '@astrojs/starlight':
+ specifier: workspace:*
+ version: link:../../..
+ astro:
+ specifier: ^4.15.3
+ version: 4.15.3(@types/node@18.16.19)(typescript@5.4.5)
+
packages/tailwind:
dependencies:
'@astrojs/starlight':
@@ -483,6 +538,27 @@ packages:
- typescript
dev: true
+ /@astrojs/markdoc@0.11.4(astro@4.15.3):
+ resolution: {integrity: sha512-6s60ZpsODsEvws57TEpUPXq5Uo+eSHsTVUUAQbbkSL+nQHIy1tR7tI6vbbO2y/VOLj214kATAc18/iRjFp2TbQ==}
+ engines: {node: ^18.17.1 || ^20.3.0 || >=21.0.0}
+ peerDependencies:
+ astro: ^3.0.0 || ^4.0.0
+ dependencies:
+ '@astrojs/internal-helpers': 0.4.1
+ '@astrojs/markdown-remark': 5.2.0
+ '@astrojs/prism': 3.1.0
+ '@markdoc/markdoc': 0.4.0
+ astro: 4.15.3(@types/node@18.16.19)(typescript@5.4.5)
+ esbuild: 0.21.5
+ github-slugger: 2.0.0
+ gray-matter: 4.0.3
+ htmlparser2: 9.1.0
+ transitivePeerDependencies:
+ - '@types/react'
+ - react
+ - supports-color
+ dev: false
+
/@astrojs/markdown-remark@5.2.0:
resolution: {integrity: sha512-vWGM24KZXz11jR3JO+oqYU3T2qpuOi4uGivJ9SQLCAI01+vEkHC60YJMRvHPc+hwd60F7euNs1PeOEixIIiNQw==}
dependencies:
@@ -533,6 +609,18 @@ packages:
- supports-color
dev: false
+ /@astrojs/node@8.3.3(astro@4.15.3):
+ resolution: {integrity: sha512-idrKhnnPSi0ABV+PCQsRQqVNwpOvVDF/+fkwcIiE8sr9J8EMvW9g/oyAt8T4X2OBJ8FUzYPL8klfCdG7r0eB5g==}
+ peerDependencies:
+ astro: ^4.2.0
+ dependencies:
+ astro: 4.15.3(@types/node@18.16.19)(typescript@5.4.5)
+ send: 0.18.0
+ server-destroy: 1.0.1
+ transitivePeerDependencies:
+ - supports-color
+ dev: false
+
/@astrojs/prism@3.1.0:
resolution: {integrity: sha512-Z9IYjuXSArkAUx3N6xj6+Bnvx8OdUSHA8YoOgyepp3+zJmtVYJIl/I18GozdJVW1p5u/CNpl3Km7/gwTJK85cw==}
engines: {node: ^18.17.1 || ^20.3.0 || >=21.0.0}
@@ -1582,6 +1670,21 @@ packages:
read-yaml-file: 1.1.0
dev: true
+ /@markdoc/markdoc@0.4.0:
+ resolution: {integrity: sha512-fSh4P3Y4E7oaKYc2oNzSIJVPDto7SMzAuQN1Iyx53UxzleA6QzRdNWRxmiPqtVDaDi5dELd2yICoG91csrGrAw==}
+ engines: {node: '>=14.7.0'}
+ peerDependencies:
+ '@types/react': '*'
+ react: '*'
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ react:
+ optional: true
+ optionalDependencies:
+ '@types/markdown-it': 12.2.3
+ dev: false
+
/@mdx-js/mdx@3.0.1:
resolution: {integrity: sha512-eIQ4QTrOWyL3LWEe/bu6Taqzq2HQvHcyTMaOrI95P2/LmJE7AsfPfgJGuFLPVqBUE1BC1rik3VIhU+s9u72arA==}
dependencies:
@@ -1908,11 +2011,32 @@ packages:
dependencies:
'@types/unist': 3.0.0
+ /@types/linkify-it@5.0.0:
+ resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==}
+ requiresBuild: true
+ dev: false
+ optional: true
+
+ /@types/markdown-it@12.2.3:
+ resolution: {integrity: sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==}
+ requiresBuild: true
+ dependencies:
+ '@types/linkify-it': 5.0.0
+ '@types/mdurl': 2.0.0
+ dev: false
+ optional: true
+
/@types/mdast@4.0.4:
resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==}
dependencies:
'@types/unist': 3.0.0
+ /@types/mdurl@2.0.0:
+ resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==}
+ requiresBuild: true
+ dev: false
+ optional: true
+
/@types/mdx@2.0.5:
resolution: {integrity: sha512-76CqzuD6Q7LC+AtbPqrvD9AqsN0k8bsYo2bM2J8pmNldP1aIPAbzUQ7QbobyXL4eLr1wK5x8FZFe8eF/ubRuBg==}
dev: false
@@ -2862,6 +2986,10 @@ packages:
engines: {node: '>=4'}
hasBin: true
+ /cssom@0.5.0:
+ resolution: {integrity: sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==}
+ dev: true
+
/csv-generate@3.4.3:
resolution: {integrity: sha512-w/T+rqR0vwvHqWs/1ZyMDWtHHSJaN06klRqJXBEpDJaM/+dZkso0OKh1VcuuYvK3XM53KysVNq8Ko/epCK8wOw==}
dev: true
@@ -2893,6 +3021,17 @@ packages:
resolution: {integrity: sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==}
dev: true
+ /debug@2.6.9:
+ resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+ dependencies:
+ ms: 2.0.0
+ dev: false
+
/debug@4.3.5:
resolution: {integrity: sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==}
engines: {node: '>=6.0'}
@@ -2972,10 +3111,20 @@ packages:
engines: {node: '>=0.4.0'}
dev: true
+ /depd@2.0.0:
+ resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
+ engines: {node: '>= 0.8'}
+ dev: false
+
/dequal@2.0.3:
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
engines: {node: '>=6'}
+ /destroy@1.2.0:
+ resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
+ engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
+ dev: false
+
/detect-indent@6.1.0:
resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==}
engines: {node: '>=8'}
@@ -3038,18 +3187,15 @@ packages:
domelementtype: 2.3.0
domhandler: 5.0.3
entities: 4.5.0
- dev: true
/domelementtype@2.3.0:
resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==}
- dev: true
/domhandler@5.0.3:
resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==}
engines: {node: '>= 4'}
dependencies:
domelementtype: 2.3.0
- dev: true
/domutils@3.1.0:
resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==}
@@ -3057,7 +3203,6 @@ packages:
dom-serializer: 2.0.0
domelementtype: 2.3.0
domhandler: 5.0.3
- dev: true
/dotenv@8.6.0:
resolution: {integrity: sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==}
@@ -3075,6 +3220,10 @@ packages:
/eastasianwidth@0.2.0:
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
+ /ee-first@1.1.1:
+ resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
+ dev: false
+
/electron-to-chromium@1.5.16:
resolution: {integrity: sha512-2gQpi2WYobXmz2q23FrOBYTLcI1O/P4heW3eqX+ldmPVDQELRqhiebV380EhlGG12NtnX1qbK/FHpN0ba+7bLA==}
@@ -3094,6 +3243,11 @@ packages:
/emoji-regex@9.2.2:
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
+ /encodeurl@1.0.2:
+ resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==}
+ engines: {node: '>= 0.8'}
+ dev: false
+
/end-of-stream@1.4.4:
resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==}
dependencies:
@@ -3223,6 +3377,10 @@ packages:
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
engines: {node: '>=6'}
+ /escape-html@1.0.3:
+ resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
+ dev: false
+
/escape-string-regexp@1.0.5:
resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
engines: {node: '>=0.8.0'}
@@ -3278,6 +3436,11 @@ packages:
dependencies:
'@types/estree': 1.0.5
+ /etag@1.8.1:
+ resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
+ engines: {node: '>= 0.6'}
+ dev: false
+
/event-stream@3.3.4:
resolution: {integrity: sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==}
dependencies:
@@ -3469,6 +3632,11 @@ packages:
resolution: {integrity: sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==}
dev: false
+ /fresh@0.5.2:
+ resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==}
+ engines: {node: '>= 0.6'}
+ dev: false
+
/from@0.1.7:
resolution: {integrity: sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==}
dev: true
@@ -4009,9 +4177,28 @@ packages:
entities: 4.5.0
dev: true
+ /htmlparser2@9.1.0:
+ resolution: {integrity: sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==}
+ dependencies:
+ domelementtype: 2.3.0
+ domhandler: 5.0.3
+ domutils: 3.1.0
+ entities: 4.5.0
+
/http-cache-semantics@4.1.1:
resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==}
+ /http-errors@2.0.0:
+ resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==}
+ engines: {node: '>= 0.8'}
+ dependencies:
+ depd: 2.0.0
+ inherits: 2.0.4
+ setprototypeof: 1.2.0
+ statuses: 2.0.1
+ toidentifier: 1.0.1
+ dev: false
+
/https-proxy-agent@5.0.1:
resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==}
engines: {node: '>= 6'}
@@ -4450,6 +4637,16 @@ packages:
/lines-and-columns@1.2.4:
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
+ /linkedom@0.18.4:
+ resolution: {integrity: sha512-JhLErxMIEOKByMi3fURXgI1fYOzR87L1Cn0+MI9GlMckFrqFZpV1SUGox1jcKtsKN3y6JgclcQf0FzZT//BuGw==}
+ dependencies:
+ css-select: 5.1.0
+ cssom: 0.5.0
+ html-escaper: 3.0.3
+ htmlparser2: 9.1.0
+ uhyphen: 0.2.0
+ dev: true
+
/lite-youtube-embed@0.3.2:
resolution: {integrity: sha512-b1dgKyF4PHhinonmr3PB172Nj0qQgA/7DE9EmeIXHR1ksnFEC2olWjNJyJGdsN2cleKHRjjsmrziKlwXtPlmLQ==}
dev: false
@@ -5134,6 +5331,12 @@ packages:
mime-db: 1.52.0
dev: true
+ /mime@1.6.0:
+ resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==}
+ engines: {node: '>=4'}
+ hasBin: true
+ dev: false
+
/mimic-fn@2.1.0:
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
engines: {node: '>=6'}
@@ -5201,6 +5404,10 @@ packages:
resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==}
engines: {node: '>=10'}
+ /ms@2.0.0:
+ resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
+ dev: false
+
/ms@2.1.2:
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
dev: true
@@ -5354,6 +5561,13 @@ packages:
object-keys: 1.1.1
dev: true
+ /on-finished@2.4.1:
+ resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
+ engines: {node: '>= 0.8'}
+ dependencies:
+ ee-first: 1.1.1
+ dev: false
+
/once@1.4.0:
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
dependencies:
@@ -5946,6 +6160,11 @@ packages:
engines: {node: '>=8'}
dev: true
+ /range-parser@1.2.1:
+ resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==}
+ engines: {node: '>= 0.6'}
+ dev: false
+
/rc@1.2.8:
resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==}
hasBin: true
@@ -6335,10 +6554,39 @@ packages:
engines: {node: '>=10'}
hasBin: true
+ /send@0.18.0:
+ resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==}
+ engines: {node: '>= 0.8.0'}
+ dependencies:
+ debug: 2.6.9
+ depd: 2.0.0
+ destroy: 1.2.0
+ encodeurl: 1.0.2
+ escape-html: 1.0.3
+ etag: 1.8.1
+ fresh: 0.5.2
+ http-errors: 2.0.0
+ mime: 1.6.0
+ ms: 2.1.3
+ on-finished: 2.4.1
+ range-parser: 1.2.1
+ statuses: 2.0.1
+ transitivePeerDependencies:
+ - supports-color
+ dev: false
+
+ /server-destroy@1.0.1:
+ resolution: {integrity: sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ==}
+ dev: false
+
/set-blocking@2.0.0:
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
dev: true
+ /setprototypeof@1.2.0:
+ resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
+ dev: false
+
/sharp@0.32.6:
resolution: {integrity: sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w==}
engines: {node: '>=14.15.0'}
@@ -6603,6 +6851,11 @@ packages:
- supports-color
dev: true
+ /statuses@2.0.1:
+ resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
+ engines: {node: '>= 0.8'}
+ dev: false
+
/std-env@3.7.0:
resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==}
dev: true
@@ -6929,6 +7182,11 @@ packages:
dependencies:
is-number: 7.0.0
+ /toidentifier@1.0.1:
+ resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
+ engines: {node: '>=0.6'}
+ dev: false
+
/tr46@0.0.3:
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
dev: true
@@ -7049,6 +7307,10 @@ packages:
resolution: {integrity: sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA==}
dev: true
+ /uhyphen@0.2.0:
+ resolution: {integrity: sha512-qz3o9CHXmJJPGBdqzab7qAYuW8kQGKNEuoHFYrBwV6hWIMcpAmxDLXojcHfFr9US1Pe6zUswEIJIbLI610fuqA==}
+ dev: true
+
/ultramatter@0.0.4:
resolution: {integrity: sha512-1f/hO3mR+/Hgue4eInOF/Qm/wzDqwhYha4DxM0hre9YIUyso3fE2XtrAU6B4njLqTC8CM49EZaYgsVSa+dXHGw==}
dev: false