From c2051456affd2662c4cd3d68d94b96079ed51063 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 2 Jun 2026 06:34:32 +0000 Subject: [PATCH 1/4] Initial plan From 35f362d63281fb978261d3204707ffa1f3020f8f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 2 Jun 2026 06:52:12 +0000 Subject: [PATCH 2/4] Fix broken Edit page link URL normalization Co-authored-by: IEvangelist <7679720+IEvangelist@users.noreply.github.com> --- .../src/components/starlight/EditLink.astro | 33 ++++++++++-- .../tests/unit/edit-link.vitest.test.ts | 53 +++++++++++++++++++ 2 files changed, 81 insertions(+), 5 deletions(-) create mode 100644 src/frontend/tests/unit/edit-link.vitest.test.ts diff --git a/src/frontend/src/components/starlight/EditLink.astro b/src/frontend/src/components/starlight/EditLink.astro index 53ef07036..691d5c5df 100644 --- a/src/frontend/src/components/starlight/EditLink.astro +++ b/src/frontend/src/components/starlight/EditLink.astro @@ -1,18 +1,41 @@ --- -import DefaultEditLink from '@astrojs/starlight/components/EditLink.astro'; - import { Icon } from '@astrojs/starlight/components'; const { editUrl } = Astro.locals.starlightRoute; +const normalizedEditUrl = normalizeGitHubEditUrl(editUrl); + +function normalizeGitHubEditUrl(url: URL | string | undefined): string | undefined { + if (!url) return undefined; + + const value = url.toString(); + + try { + const parsed = new URL(value); + + if (parsed.hostname !== 'github.com') return value; + + const segments = parsed.pathname.split('/').filter(Boolean); + if (segments.length < 4) return value; + + const [owner, repo, action, ...rest] = segments; + if (action === 'edit' || action === 'blob') return value; + + parsed.pathname = `/${owner}/${repo}/blob/${[action, ...rest].join('/')}`; + return parsed.toString(); + } catch { + return value; + } +} --- { - editUrl && ( + normalizedEditUrl && (
- + + - +
{Astro.locals.t('footer.translatePage' as any)} diff --git a/src/frontend/tests/unit/edit-link.vitest.test.ts b/src/frontend/tests/unit/edit-link.vitest.test.ts new file mode 100644 index 000000000..17d31f991 --- /dev/null +++ b/src/frontend/tests/unit/edit-link.vitest.test.ts @@ -0,0 +1,53 @@ +import { describe, expect, it } from 'vitest'; +import EditLink from '../../src/components/starlight/EditLink.astro'; +import { normalizeHtml, renderComponent, type StarlightRoute } from './astro-test-utils'; + +describe('starlight EditLink', () => { + it('normalizes malformed GitHub edit links missing /edit or /blob', async () => { + const starlightRoute: StarlightRoute = { + editUrl: + 'https://github.com/microsoft/aspire.dev/main/src/frontend/src/content/docs/whats-new/aspire-13-4.mdx', + entry: { + id: 'whats-new/aspire-13-4', + slug: 'whats-new/aspire-13-4', + filePath: 'src/content/docs/whats-new/aspire-13-4.mdx', + data: {}, + }, + }; + + const html = normalizeHtml( + await renderComponent(EditLink, { + locals: { starlightRoute }, + slots: { default: 'Edit page' }, + }) + ); + + expect(html).toContain( + 'href="https://github.com/microsoft/aspire.dev/blob/main/src/frontend/src/content/docs/whats-new/aspire-13-4.mdx"' + ); + }); + + it('preserves valid GitHub edit links', async () => { + const starlightRoute: StarlightRoute = { + editUrl: + 'https://github.com/microsoft/aspire.dev/edit/main/src/frontend/src/content/docs/whats-new/aspire-13-4.mdx', + entry: { + id: 'whats-new/aspire-13-4', + slug: 'whats-new/aspire-13-4', + filePath: 'src/content/docs/whats-new/aspire-13-4.mdx', + data: {}, + }, + }; + + const html = normalizeHtml( + await renderComponent(EditLink, { + locals: { starlightRoute }, + slots: { default: 'Edit page' }, + }) + ); + + expect(html).toContain( + 'href="https://github.com/microsoft/aspire.dev/edit/main/src/frontend/src/content/docs/whats-new/aspire-13-4.mdx"' + ); + }); +}); From b43b8148829ad44f55ae61feefe56c55ea3d7328 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 2 Jun 2026 06:54:22 +0000 Subject: [PATCH 3/4] Add regression coverage for Edit page URL normalization Co-authored-by: IEvangelist <7679720+IEvangelist@users.noreply.github.com> --- src/frontend/src/components/starlight/EditLink.astro | 2 +- src/frontend/tests/unit/edit-link.vitest.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/frontend/src/components/starlight/EditLink.astro b/src/frontend/src/components/starlight/EditLink.astro index 691d5c5df..b26d8c5d3 100644 --- a/src/frontend/src/components/starlight/EditLink.astro +++ b/src/frontend/src/components/starlight/EditLink.astro @@ -7,7 +7,7 @@ const normalizedEditUrl = normalizeGitHubEditUrl(editUrl); function normalizeGitHubEditUrl(url: URL | string | undefined): string | undefined { if (!url) return undefined; - const value = url.toString(); + const value = url instanceof URL ? url.toString() : url; try { const parsed = new URL(value); diff --git a/src/frontend/tests/unit/edit-link.vitest.test.ts b/src/frontend/tests/unit/edit-link.vitest.test.ts index 17d31f991..6b2e301ba 100644 --- a/src/frontend/tests/unit/edit-link.vitest.test.ts +++ b/src/frontend/tests/unit/edit-link.vitest.test.ts @@ -3,7 +3,7 @@ import EditLink from '../../src/components/starlight/EditLink.astro'; import { normalizeHtml, renderComponent, type StarlightRoute } from './astro-test-utils'; describe('starlight EditLink', () => { - it('normalizes malformed GitHub edit links missing /edit or /blob', async () => { + it('normalizes malformed GitHub links by inserting /blob/', async () => { const starlightRoute: StarlightRoute = { editUrl: 'https://github.com/microsoft/aspire.dev/main/src/frontend/src/content/docs/whats-new/aspire-13-4.mdx', From 9da64b47a753a0564493d396049f0158b4c387fd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 2 Jun 2026 18:14:03 +0000 Subject: [PATCH 4/4] Simplify: revert EditLink normalization, rely on correct astro config editLink.baseUrl Co-authored-by: IEvangelist <7679720+IEvangelist@users.noreply.github.com> --- .../src/components/starlight/EditLink.astro | 33 ++---------- .../tests/unit/edit-link.vitest.test.ts | 53 ------------------- 2 files changed, 5 insertions(+), 81 deletions(-) delete mode 100644 src/frontend/tests/unit/edit-link.vitest.test.ts diff --git a/src/frontend/src/components/starlight/EditLink.astro b/src/frontend/src/components/starlight/EditLink.astro index b26d8c5d3..53ef07036 100644 --- a/src/frontend/src/components/starlight/EditLink.astro +++ b/src/frontend/src/components/starlight/EditLink.astro @@ -1,41 +1,18 @@ --- +import DefaultEditLink from '@astrojs/starlight/components/EditLink.astro'; + import { Icon } from '@astrojs/starlight/components'; const { editUrl } = Astro.locals.starlightRoute; -const normalizedEditUrl = normalizeGitHubEditUrl(editUrl); - -function normalizeGitHubEditUrl(url: URL | string | undefined): string | undefined { - if (!url) return undefined; - - const value = url instanceof URL ? url.toString() : url; - - try { - const parsed = new URL(value); - - if (parsed.hostname !== 'github.com') return value; - - const segments = parsed.pathname.split('/').filter(Boolean); - if (segments.length < 4) return value; - - const [owner, repo, action, ...rest] = segments; - if (action === 'edit' || action === 'blob') return value; - - parsed.pathname = `/${owner}/${repo}/blob/${[action, ...rest].join('/')}`; - return parsed.toString(); - } catch { - return value; - } -} --- { - normalizedEditUrl && ( + editUrl && (
{Astro.locals.t('footer.translatePage' as any)} diff --git a/src/frontend/tests/unit/edit-link.vitest.test.ts b/src/frontend/tests/unit/edit-link.vitest.test.ts deleted file mode 100644 index 6b2e301ba..000000000 --- a/src/frontend/tests/unit/edit-link.vitest.test.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { describe, expect, it } from 'vitest'; -import EditLink from '../../src/components/starlight/EditLink.astro'; -import { normalizeHtml, renderComponent, type StarlightRoute } from './astro-test-utils'; - -describe('starlight EditLink', () => { - it('normalizes malformed GitHub links by inserting /blob/', async () => { - const starlightRoute: StarlightRoute = { - editUrl: - 'https://github.com/microsoft/aspire.dev/main/src/frontend/src/content/docs/whats-new/aspire-13-4.mdx', - entry: { - id: 'whats-new/aspire-13-4', - slug: 'whats-new/aspire-13-4', - filePath: 'src/content/docs/whats-new/aspire-13-4.mdx', - data: {}, - }, - }; - - const html = normalizeHtml( - await renderComponent(EditLink, { - locals: { starlightRoute }, - slots: { default: 'Edit page' }, - }) - ); - - expect(html).toContain( - 'href="https://github.com/microsoft/aspire.dev/blob/main/src/frontend/src/content/docs/whats-new/aspire-13-4.mdx"' - ); - }); - - it('preserves valid GitHub edit links', async () => { - const starlightRoute: StarlightRoute = { - editUrl: - 'https://github.com/microsoft/aspire.dev/edit/main/src/frontend/src/content/docs/whats-new/aspire-13-4.mdx', - entry: { - id: 'whats-new/aspire-13-4', - slug: 'whats-new/aspire-13-4', - filePath: 'src/content/docs/whats-new/aspire-13-4.mdx', - data: {}, - }, - }; - - const html = normalizeHtml( - await renderComponent(EditLink, { - locals: { starlightRoute }, - slots: { default: 'Edit page' }, - }) - ); - - expect(html).toContain( - 'href="https://github.com/microsoft/aspire.dev/edit/main/src/frontend/src/content/docs/whats-new/aspire-13-4.mdx"' - ); - }); -});