summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHiDeoo2025-05-01 12:23:54 +0200
committerGitHub2025-05-01 12:23:54 +0200
commitb5232bcd201c2e3904bde2d7717fe6cfa06d6c82 (patch)
treee754799fe112fd8efa70e71484ba3bd14168a35a
parentd1f3c8b6583b93968af3c568f7af44b1b10326ec (diff)
downloadIT.starlight-b5232bcd201c2e3904bde2d7717fe6cfa06d6c82.tar.gz
IT.starlight-b5232bcd201c2e3904bde2d7717fe6cfa06d6c82.tar.bz2
IT.starlight-b5232bcd201c2e3904bde2d7717fe6cfa06d6c82.zip
Fix missing styles for dynamic routes rendering `<StarlightPage>` (#2905)
Co-authored-by: Chris Swithinbank <swithinbank@gmail.com> Co-authored-by: Chris Swithinbank <357379+delucis@users.noreply.github.com>
-rw-r--r--.changeset/long-waves-rush.md5
-rw-r--r--packages/starlight/__e2e__/components.test.ts20
-rw-r--r--packages/starlight/__e2e__/fixtures/basics/src/components/PurpleCard.astro8
-rw-r--r--packages/starlight/__e2e__/fixtures/basics/src/content/docs/head-propagation.mdx7
-rw-r--r--packages/starlight/__e2e__/fixtures/basics/src/pages/[...param].astro17
-rw-r--r--packages/starlight/routes/common.astro16
-rw-r--r--packages/starlight/utils/routing/data.ts17
7 files changed, 83 insertions, 7 deletions
diff --git a/.changeset/long-waves-rush.md b/.changeset/long-waves-rush.md
new file mode 100644
index 00000000..d279e10c
--- /dev/null
+++ b/.changeset/long-waves-rush.md
@@ -0,0 +1,5 @@
+---
+'@astrojs/starlight': patch
+---
+
+Fixes a potential issue for projects with dynamic routes added by an user, an Astro integration, or a Starlight plugin where some styles could end up being missing.
diff --git a/packages/starlight/__e2e__/components.test.ts b/packages/starlight/__e2e__/components.test.ts
index 6a1b7e5b..7b536c78 100644
--- a/packages/starlight/__e2e__/components.test.ts
+++ b/packages/starlight/__e2e__/components.test.ts
@@ -393,6 +393,26 @@ test.describe('anchor headings', () => {
});
});
+test.describe('head propagation', () => {
+ /**
+ * Due to a head propagation issue in development mode, dynamic routes alphabetically sorted
+ * before Starlight route (`[...slug]`) rendering the `<StarlightPage>` component can result in
+ * missing styles. The issue is workaround by having our call to `render` from `astro:content` to
+ * be in a specific file.
+ *
+ * @see https://github.com/withastro/astro/issues/13724
+ */
+ test('does not prevent head propagation in dev mode when rendering a dynamic route using the `<StarlightPage>` component', async ({
+ page,
+ makeServer,
+ }) => {
+ const starlight = await makeServer('dev', { mode: 'dev' });
+ await starlight.goto('/head-propagation');
+
+ await expect(page.getByTestId('purple-card')).toHaveCSS('background-color', 'rgb(128, 0, 128)');
+ });
+});
+
async function expectSelectedTab(tabs: Locator, label: string, panel?: string) {
expect(
(
diff --git a/packages/starlight/__e2e__/fixtures/basics/src/components/PurpleCard.astro b/packages/starlight/__e2e__/fixtures/basics/src/components/PurpleCard.astro
new file mode 100644
index 00000000..932cb3f3
--- /dev/null
+++ b/packages/starlight/__e2e__/fixtures/basics/src/components/PurpleCard.astro
@@ -0,0 +1,8 @@
+<div data-testid="purple-card">I am a purple card with white text.</div>
+
+<style>
+ div {
+ background-color: rgb(128, 0, 128);
+ color: rgb(255, 255, 255);
+ }
+</style>
diff --git a/packages/starlight/__e2e__/fixtures/basics/src/content/docs/head-propagation.mdx b/packages/starlight/__e2e__/fixtures/basics/src/content/docs/head-propagation.mdx
new file mode 100644
index 00000000..dd16e472
--- /dev/null
+++ b/packages/starlight/__e2e__/fixtures/basics/src/content/docs/head-propagation.mdx
@@ -0,0 +1,7 @@
+---
+title: Head Propagation
+---
+
+import PurpleCard from '../../components/PurpleCard.astro';
+
+<PurpleCard />
diff --git a/packages/starlight/__e2e__/fixtures/basics/src/pages/[...param].astro b/packages/starlight/__e2e__/fixtures/basics/src/pages/[...param].astro
new file mode 100644
index 00000000..db5d8675
--- /dev/null
+++ b/packages/starlight/__e2e__/fixtures/basics/src/pages/[...param].astro
@@ -0,0 +1,17 @@
+---
+import StarlightPage from '@astrojs/starlight/components/StarlightPage.astro';
+
+/**
+ * The name of this dynamic route is intentionally set to `[...param]` to test a head propagation
+ * issue that occurs for dynamic routes alphabetically sorted before the Starlight default route
+ * (`[...slug]`) rendering the `<StarlightPage>` component.
+ */
+
+export function getStaticPaths() {
+ return [{ params: { param: 'custom-page' } }];
+}
+---
+
+<StarlightPage frontmatter={{ title: 'A custom page' }}>
+ <p>This is a custom page</p>
+</StarlightPage>
diff --git a/packages/starlight/routes/common.astro b/packages/starlight/routes/common.astro
index b96ef3fb..a113dbb8 100644
--- a/packages/starlight/routes/common.astro
+++ b/packages/starlight/routes/common.astro
@@ -1,9 +1,21 @@
---
+import { render } from 'astro:content';
import Page from '../components/Page.astro';
-import { useRouteData } from '../utils/routing/data';
+import { getRoute, useRouteData } from '../utils/routing/data';
import { attachRouteDataAndRunMiddleware } from '../utils/routing/middleware';
-await attachRouteDataAndRunMiddleware(Astro, await useRouteData(Astro));
+const route = await getRoute(Astro);
+/**
+ * The call to `render` from `astro:content` is purposely made in this file to work around a
+ * development mode head propagation issue which is heavily tied to `astro:content` imports. Even
+ * though we have a test for this, refactoring and moving this code to a different file should be
+ * avoided for now until the linked issue which also contains more details is resolved.
+ *
+ * @see https://github.com/withastro/astro/issues/13724
+ */
+const renderResult = await render(route.entry);
+
+await attachRouteDataAndRunMiddleware(Astro, await useRouteData(Astro, route, renderResult));
const { Content, entry } = Astro.locals.starlightRoute;
---
diff --git a/packages/starlight/utils/routing/data.ts b/packages/starlight/utils/routing/data.ts
index 343f8dbb..8e1dcb25 100644
--- a/packages/starlight/utils/routing/data.ts
+++ b/packages/starlight/utils/routing/data.ts
@@ -15,7 +15,7 @@ import type {
import { formatPath } from '../format-path';
import { useTranslations } from '../translations';
import { BuiltInDefaultLocale } from '../i18n';
-import { getEntry, render } from 'astro:content';
+import { getEntry, type RenderResult } from 'astro:content';
import { getCollectionPathFromRoot } from '../collection';
import { getHead } from '../head';
@@ -25,11 +25,18 @@ export interface PageProps extends Route {
export type RouteDataContext = Pick<APIContext, 'generator' | 'site' | 'url'>;
-export async function useRouteData(context: APIContext): Promise<StarlightRouteData> {
- const route =
+export async function getRoute(context: APIContext): Promise<Route> {
+ return (
('slug' in context.params && getRouteBySlugParam(context.params.slug)) ||
- (await get404Route(context.locals));
- const { Content, headings } = await render(route.entry);
+ (await get404Route(context.locals))
+ );
+}
+
+export async function useRouteData(
+ context: APIContext,
+ route: Route,
+ { Content, headings }: RenderResult
+): Promise<StarlightRouteData> {
const routeData = generateRouteData({ props: { ...route, headings }, context });
return { ...routeData, Content };
}