Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/quick-apes-grab.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@astrojs/starlight": patch
---

Fixes invalid `<head>` output when configuration is missing:
- Omits `<meta property="og:description" />` if Starlight’s `description` option is unset
- Omits `<link rel="canonical" />` and `<meta property="og:url" />` if Astro’s `site` option is unset
15 changes: 13 additions & 2 deletions packages/starlight/__tests__/head/head.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,15 @@ test('places the default favicon below any user provided icons', () => {
expect(defaultFaviconIndex).toBeGreaterThan(userFaviconIndex);
});

function getTestHead(heads: HeadConfig = [], route = routes[0]!): HeadConfig {
test('omits meta og:url tag when site is not set', () => {
const head = getTestHead(undefined, undefined, false);

const ogUrlExists = head.some((tag) => tag.tag === 'meta' && tag.attrs?.property === 'og:url');

expect(ogUrlExists).toBe(false);
});

function getTestHead(heads: HeadConfig = [], route = routes[0]!, setSite?: boolean): HeadConfig {
return generateRouteData({
props: {
...route,
Expand All @@ -190,6 +198,9 @@ function getTestHead(heads: HeadConfig = [], route = routes[0]!): HeadConfig {
},
},
},
context: getRouteDataTestContext(),
context:
setSite === undefined
? getRouteDataTestContext()
: getRouteDataTestContext(undefined, setSite),
}).head;
}
8 changes: 6 additions & 2 deletions packages/starlight/__tests__/test-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,15 @@ export async function mockedCollectionConfig(docsUserSchema?: Parameters<typeof
};
}

export function getRouteDataTestContext(pathname?: string): RouteDataContext {
export function getRouteDataTestContext(
pathname?: string,
setSite: boolean = true
): RouteDataContext {
const site = new URL('https://example.com');

return {
generator: 'Astro',
site,
url: pathname ? new URL(pathname, site) : site,
site: setSite ? site : undefined,
};
}
12 changes: 9 additions & 3 deletions packages/starlight/utils/head.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ export function getHead(
attrs: { name: 'viewport', content: 'width=device-width, initial-scale=1' },
},
{ tag: 'title', content: `${data.title} ${config.titleDelimiter} ${siteTitle}` },
{ tag: 'link', attrs: { rel: 'canonical', href: canonicalHref } },
...(canonicalHref !== undefined
? ([{ tag: 'link', attrs: { rel: 'canonical', href: canonicalHref } }] as const)
: []),
{ tag: 'meta', attrs: { name: 'generator', content: context.generator } },
{
tag: 'meta',
Expand All @@ -51,9 +53,13 @@ export function getHead(
// OpenGraph Tags
{ tag: 'meta', attrs: { property: 'og:title', content: data.title } },
{ tag: 'meta', attrs: { property: 'og:type', content: 'article' } },
{ tag: 'meta', attrs: { property: 'og:url', content: canonicalHref } },
...(canonicalHref !== undefined
? ([{ tag: 'meta', attrs: { property: 'og:url', content: canonicalHref } }] as const)
: []),
{ tag: 'meta', attrs: { property: 'og:locale', content: lang } },
{ tag: 'meta', attrs: { property: 'og:description', content: description } },
...(description !== undefined
? ([{ tag: 'meta', attrs: { property: 'og:description', content: description } }] as const)
: []),
{ tag: 'meta', attrs: { property: 'og:site_name', content: siteTitle } },
// Twitter Tags
{
Expand Down