Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
65 changes: 65 additions & 0 deletions packages/astro-github-loader/src/github.link-transform.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,71 @@ describe("globalLinkTransform", () => {
);
});

it("should not early-return relative ./ links when .md-stripping global mappings exist", () => {
const files: ImportedFile[] = [
createImportedFile(
"docs/guide.md",
"src/content/docs/guide.md",
"[Subscriber](./subscriber.md)",
),
createImportedFile(
"docs/subscriber.md",
"src/content/docs/subscriber.md",
"# Subscriber",
),
];

const result = globalLinkTransform(files, {
stripPrefixes: ["src/content/docs"],
linkMappings: [
{
pattern: /\.md(#|$)/,
replacement: "$1",
global: true,
},
{
pattern: /\/index(\.md)?$/,
replacement: "/",
global: true,
},
],
logger,
});

// Should resolve via sourceToTargetMap, not early-return from .md stripping
expect(result[0].content).toBe("[Subscriber](/subscriber/)");
});

it("should not early-return relative ../ links when global mappings exist", () => {
const files: ImportedFile[] = [
createImportedFile(
"docs/guides/intro.md",
"src/content/docs/guides/intro.md",
"[Overview](../overview.md)",
),
createImportedFile(
"docs/overview.md",
"src/content/docs/overview.md",
"# Overview",
),
];

const result = globalLinkTransform(files, {
stripPrefixes: ["src/content/docs"],
linkMappings: [
{
pattern: /\.md(#|$)/,
replacement: "$1",
global: true,
},
],
logger,
});

// Should resolve via normalization + sourceToTargetMap
expect(result[0].content).toBe("[Overview](/overview/)");
});

it("should preserve anchors in transformed links", () => {
const files: ImportedFile[] = [
createImportedFile(
Expand Down
10 changes: 9 additions & 1 deletion packages/astro-github-loader/src/github.link-transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,15 @@ function transformLink(
// Bare-path links (e.g., "docs/markdown/autoapi/foo/") are repo-root-relative
// but normalizePath() treats them as file-relative, mangling the path.
// Applying global mappings first lets patterns match the link as written.
if (context.global.linkMappings) {
// Only for bare paths — relative (./, ../) and absolute (/) links must flow
// through normalizePath() first to avoid over-matching by generic global
// mappings like .md-stripping from generateStarlightLinkMappings().
const isBareBarePath =
!linkPath.startsWith("./") &&
!linkPath.startsWith("../") &&
!linkPath.startsWith("/") &&
!linkPath.includes("://");
if (isBareBarePath && context.global.linkMappings) {
const globalMappings = context.global.linkMappings.filter((m) => m.global);
if (globalMappings.length > 0) {
const rawMapped = applyLinkMappings(
Expand Down