Skip to content

Commit 4c784f6

Browse files
authored
fix: fix DM archive doc URL resolution (#701)
1 parent bceb026 commit 4c784f6

6 files changed

Lines changed: 214 additions & 21 deletions

File tree

gatsby/link-resolver/__tests__/link-resolver.test.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,48 @@ describe("resolveMarkdownLink", () => {
536536
expect(result).toBe("/tidb-in-kubernetes/stable/deploy");
537537
});
538538

539+
it("should resolve links from tidb-data-migration pages", () => {
540+
const result = resolveMarkdownLink(
541+
"/dm-overview",
542+
"/zh/tidb-data-migration/v5.3/quick-start-with-dm"
543+
);
544+
expect(result).toBe("/zh/tidb-data-migration/v5.3/dm-overview");
545+
});
546+
547+
it("should resolve links from tidb-data-migration pages without language prefix", () => {
548+
const result = resolveMarkdownLink(
549+
"/quick-start-with-dm",
550+
"/tidb-data-migration/v5.3/dm-overview"
551+
);
552+
expect(result).toBe("/tidb-data-migration/v5.3/quick-start-with-dm");
553+
});
554+
555+
it("should resolve nested links from tidb-data-migration pages using flattened doc URLs", () => {
556+
const result = resolveMarkdownLink(
557+
"/releases/2.0.7",
558+
"/zh/tidb-data-migration/v2.0/TOC"
559+
);
560+
expect(result).toBe("/zh/tidb-data-migration/v2.0/2.0.7");
561+
});
562+
563+
it("should preserve hash for tidb-data-migration links", () => {
564+
const result = resolveMarkdownLink(
565+
"/key-features#table-routing",
566+
"/zh/tidb-data-migration/v2.0/overview"
567+
);
568+
expect(result).toBe(
569+
"/zh/tidb-data-migration/v2.0/key-features#table-routing"
570+
);
571+
});
572+
573+
it("should resolve _index links from tidb-data-migration pages", () => {
574+
const result = resolveMarkdownLink(
575+
"/reference/_index",
576+
"/en/tidb-data-migration/v5.3/TOC"
577+
);
578+
expect(result).toBe("/tidb-data-migration/v5.3/reference");
579+
});
580+
539581
it("should not match non-tidb repo pages (pathConditions check)", () => {
540582
const result = resolveMarkdownLink(
541583
"/upgrade/upgrade-tidb-using-tiup",

gatsby/link-resolver/config.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,21 +88,21 @@ export const defaultLinkResolverConfig: LinkResolverConfig = {
8888
linkPattern: "/{...any}/{docname}",
8989
targetPattern: "/{lang}/tidb/stable/{docname}",
9090
},
91-
// Rule 4: tidb with branch pages (path-based mapping)
92-
// Current page: /{lang}/tidb/{branch}/{...any} (branch is already aliased, e.g., "stable", "v8.5")
93-
// Link: /{...any}/{docname} -> /{lang}/tidb/{branch}/{docname}
91+
// Rule 4: versioned docs with branch pages (path-based mapping)
92+
// Current page: /{lang}/{repo}/{branch}/{...any} (branch is already aliased, e.g., "stable", "v8.5")
93+
// Link: /{...any}/{docname} -> /{lang}/{repo}/{branch}/{docname}
9494
{
9595
pathPattern: "/{lang}/{repo}/{branch}/{...any}",
9696
pathConditions: {
97-
repo: ["tidb", "tidb-in-kubernetes"],
97+
repo: ["tidb", "tidb-in-kubernetes", "tidb-data-migration"],
9898
},
9999
linkPattern: "/{...folders}/_index",
100100
targetPattern: "/{lang}/{repo}/{branch}/{folders}",
101101
},
102102
{
103103
pathPattern: "/{lang}/{repo}/{branch}/{...any}",
104104
pathConditions: {
105-
repo: ["tidb", "tidb-in-kubernetes"],
105+
repo: ["tidb", "tidb-in-kubernetes", "tidb-data-migration"],
106106
},
107107
linkPattern: "/{...any}/{docname}",
108108
targetPattern: "/{lang}/{repo}/{branch}/{docname}",

gatsby/url-resolver/__tests__/url-resolver.test.ts

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,42 @@ describe("calculateFileUrl", () => {
214214
expect(url).toBe("/en/tidb/dev/page/");
215215
});
216216

217+
it("should resolve tidb-data-migration _index with release branch alias", () => {
218+
const absolutePath = path.join(
219+
sourceBasePath,
220+
"zh/tidb-data-migration/release-2.0/_index.md"
221+
);
222+
const url = calculateFileUrlWithConfig(absolutePath, testConfig);
223+
expect(url).toBe("/zh/tidb-data-migration/v2.0");
224+
});
225+
226+
it("should resolve tidb-data-migration pages with release branch alias", () => {
227+
const absolutePath = path.join(
228+
sourceBasePath,
229+
"zh/tidb-data-migration/release-2.0/overview.md"
230+
);
231+
const url = calculateFileUrlWithConfig(absolutePath, testConfig);
232+
expect(url).toBe("/zh/tidb-data-migration/v2.0/overview/");
233+
});
234+
235+
it("should resolve tidb-data-migration v1.0 pages with release branch alias", () => {
236+
const absolutePath = path.join(
237+
sourceBasePath,
238+
"zh/tidb-data-migration/release-1.0/overview.md"
239+
);
240+
const url = calculateFileUrlWithConfig(absolutePath, testConfig);
241+
expect(url).toBe("/zh/tidb-data-migration/v1.0/overview/");
242+
});
243+
244+
it("should resolve tidb-data-migration nested _index with folders", () => {
245+
const absolutePath = path.join(
246+
sourceBasePath,
247+
"zh/tidb-data-migration/release-2.0/releases/_index.md"
248+
);
249+
const url = calculateFileUrlWithConfig(absolutePath, testConfig);
250+
expect(url).toBe("/zh/tidb-data-migration/v2.0/releases");
251+
});
252+
217253
it("should resolve api folder", () => {
218254
const absolutePath = path.join(
219255
sourceBasePath,
@@ -469,6 +505,61 @@ describe("calculateFileUrl with defaultLanguage: 'en'", () => {
469505
// release-8.5 -> stable via branch-alias-tidb (exact match takes precedence)
470506
expect(url).toBe("/tidb/stable/alert-rules");
471507
});
508+
509+
it("should omit /en/ prefix for English tidb-data-migration files", () => {
510+
const absolutePath = path.join(
511+
sourceBasePath,
512+
"en/tidb-data-migration/release-5.3/dm-overview.md"
513+
);
514+
const url = calculateFileUrlWithConfig(
515+
absolutePath,
516+
configWithDefaultLang,
517+
true
518+
);
519+
expect(url).toBe("/tidb-data-migration/v5.3/dm-overview");
520+
});
521+
522+
it("should omit /en/ prefix for English tidb-data-migration release indexes", () => {
523+
const cases = [
524+
["release-5.3", "/tidb-data-migration/v5.3"],
525+
["release-2.0", "/tidb-data-migration/v2.0"],
526+
["release-1.0", "/tidb-data-migration/v1.0"],
527+
];
528+
529+
for (const [branch, expected] of cases) {
530+
const absolutePath = path.join(
531+
sourceBasePath,
532+
`en/tidb-data-migration/${branch}/_index.md`
533+
);
534+
const url = calculateFileUrlWithConfig(
535+
absolutePath,
536+
configWithDefaultLang,
537+
true
538+
);
539+
expect(url).toBe(expected);
540+
}
541+
});
542+
543+
it("should keep /zh/ prefix for Chinese tidb-data-migration release indexes", () => {
544+
const cases = [
545+
["release-5.3", "/zh/tidb-data-migration/v5.3"],
546+
["release-2.0", "/zh/tidb-data-migration/v2.0"],
547+
["release-1.0", "/zh/tidb-data-migration/v1.0"],
548+
];
549+
550+
for (const [branch, expected] of cases) {
551+
const absolutePath = path.join(
552+
sourceBasePath,
553+
`zh/tidb-data-migration/${branch}/_index.md`
554+
);
555+
const url = calculateFileUrlWithConfig(
556+
absolutePath,
557+
configWithDefaultLang,
558+
true
559+
);
560+
expect(url).toBe(expected);
561+
}
562+
});
472563
});
473564

474565
describe("calculateFileUrl with slug format (relative path)", () => {

gatsby/url-resolver/config.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,28 @@ export const defaultUrlResolverConfig: UrlResolverConfig = {
123123
ignoreIf: ["_index", "_docHome"],
124124
},
125125
},
126+
// tidb-data-migration index pages with folders (avoid URL collision)
127+
{
128+
sourcePattern:
129+
"/{lang}/tidb-data-migration/{branch}/{...folders}/{filename}",
130+
targetPattern:
131+
"/{lang}/tidb-data-migration/{branch:branch-alias-tidb-data-migration}/{folders}",
132+
conditions: { filename: ["_index"] },
133+
filenameTransform: {
134+
ignoreIf: ["_index"],
135+
},
136+
},
137+
// tidb-data-migration with branch and optional folders
138+
// /en/tidb-data-migration/release-5.3/{...folders}/{filename} -> /en/tidb-data-migration/v5.3/{filename}
139+
{
140+
sourcePattern:
141+
"/{lang}/tidb-data-migration/{branch}/{...folders}/{filename}",
142+
targetPattern:
143+
"/{lang}/tidb-data-migration/{branch:branch-alias-tidb-data-migration}/{filename}",
144+
filenameTransform: {
145+
ignoreIf: ["_index", "_docHome"],
146+
},
147+
},
126148
// Fallback: /{lang}/{repo}/{...any}/{filename} -> /{lang}/{repo}/{filename}
127149
{
128150
sourcePattern: "/{lang}/{repo}/{...any}/{filename}",
@@ -164,5 +186,15 @@ export const defaultUrlResolverConfig: UrlResolverConfig = {
164186
"release-*": "v*",
165187
},
166188
},
189+
// Branch alias for tidb-data-migration: used in {branch:branch-alias-tidb-data-migration}
190+
"branch-alias-tidb-data-migration": {
191+
mappings: {
192+
// Wildcard pattern: release-* -> v*
193+
// Examples:
194+
// release-5.3 -> v5.3
195+
// release-2.0 -> v2.0
196+
"release-*": "v*",
197+
},
198+
},
167199
},
168200
};

src/components/Layout/LeftNav/LeftNav.tsx

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
BuildType,
1616
TOCNamespace,
1717
CloudPlan,
18+
Repo,
1819
} from "shared/interface";
1920
import { NavItemConfig } from "../Header/HeaderNavConfigType";
2021
import LinkComponent from "components/Link";
@@ -41,6 +42,20 @@ interface LeftNavProps {
4142
namespace?: TOCNamespace;
4243
}
4344

45+
function shouldShowVersionSelect(
46+
namespace: TOCNamespace | undefined,
47+
repo: Repo,
48+
buildType: BuildType | undefined
49+
) {
50+
// DM has no active docs namespace on the main site; only its archived pages
51+
// need the version selector.
52+
return (
53+
namespace === TOCNamespace.TiDB ||
54+
namespace === TOCNamespace.TiDBInKubernetes ||
55+
(buildType === "archive" && repo === Repo.dm)
56+
);
57+
}
58+
4459
export function LeftNavDesktop(props: LeftNavProps) {
4560
const {
4661
data,
@@ -127,8 +142,7 @@ export function LeftNavDesktop(props: LeftNavProps) {
127142
</Box>
128143
)}
129144

130-
{(namespace === TOCNamespace.TiDB ||
131-
namespace === TOCNamespace.TiDBInKubernetes) && (
145+
{shouldShowVersionSelect(namespace, pathConfig.repo, buildType) && (
132146
<Box marginTop={1}>
133147
<VersionSelect
134148
name={name}
@@ -197,8 +211,7 @@ export function LeftNavMobile(props: LeftNavProps) {
197211
paddingLeft: "1.25rem",
198212
}}
199213
/>
200-
{(namespace === TOCNamespace.TiDB ||
201-
namespace === TOCNamespace.TiDBInKubernetes) && (
214+
{shouldShowVersionSelect(namespace, pathConfig.repo, buildType) && (
202215
<NativeVersionSelect
203216
name={name}
204217
pathConfig={pathConfig}

src/components/Layout/VersionSelect/VersionSelect.tsx

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,22 @@ function renderVersion(
3838
);
3939
}
4040

41+
function getArchivedVersions(pathConfig: PathConfig): (string | null)[] {
42+
const repoCfg = CONFIG.docs[pathConfig.repo] as {
43+
archived?: string[];
44+
};
45+
return repoCfg.archived || [];
46+
}
47+
48+
function getVersionOptions(
49+
pathConfig: PathConfig,
50+
isArchive: boolean
51+
): (string | null)[] {
52+
return isArchive
53+
? getArchivedVersions(pathConfig)
54+
: AllVersion[pathConfig.repo][pathConfig.locale];
55+
}
56+
4157
const VersionItems = (props: {
4258
versions: (string | null)[];
4359
availIn: string[];
@@ -200,11 +216,6 @@ const VersionItemsArchived = (props: {
200216
}) => {
201217
const { versions, availIn, pathConfig, name } = props;
202218

203-
const repoCfg = CONFIG.docs[pathConfig.repo] as {
204-
[key: string]: any;
205-
};
206-
const archiveList = (repoCfg?.archived as string[]) || [];
207-
208219
return (
209220
<>
210221
<FormLabel
@@ -217,7 +228,7 @@ const VersionItemsArchived = (props: {
217228
>
218229
Archive
219230
</FormLabel>
220-
{archiveList.map((version) => (
231+
{versions.map((version) => (
221232
<MenuItem
222233
disableRipple
223234
key={`menu-${version}`}
@@ -257,6 +268,8 @@ export default function VersionSelect(props: VersionSelectProps) {
257268
const [open, setOpen] = React.useState<boolean>(false);
258269
const handleClick = () => setOpen(true);
259270
const handleClose = () => setOpen(false);
271+
const isArchive = buildType === "archive";
272+
const versionOptions = getVersionOptions(pathConfig, isArchive);
260273

261274
return (
262275
<>
@@ -275,7 +288,7 @@ export default function VersionSelect(props: VersionSelectProps) {
275288
fontWeight: 700,
276289
}}
277290
>
278-
{buildType === "archive"
291+
{isArchive
279292
? renderVersion(pathConfig.version, pathConfig, true)
280293
: renderVersion(pathConfig.version, pathConfig)}
281294
</Typography>
@@ -290,9 +303,9 @@ export default function VersionSelect(props: VersionSelectProps) {
290303
"aria-labelledby": "version-select-button",
291304
}}
292305
>
293-
{buildType === "archive" ? (
306+
{isArchive ? (
294307
<VersionItemsArchived
295-
versions={AllVersion[pathConfig.repo][pathConfig.locale]}
308+
versions={versionOptions}
296309
availIn={availIn}
297310
pathConfig={pathConfig}
298311
name={name}
@@ -332,6 +345,8 @@ export function NativeVersionSelect(props: VersionSelectProps) {
332345
const { name, pathConfig, availIn, buildType } = props;
333346

334347
const { navigate: i18nNavigate, t, language } = useI18next();
348+
const isArchive = buildType === "archive";
349+
const versionOptions = getVersionOptions(pathConfig, isArchive);
335350

336351
const handleChange = (event: { target: { value: string } }) => {
337352
if (event.target.value === "archive") {
@@ -353,16 +368,16 @@ export function NativeVersionSelect(props: VersionSelectProps) {
353368
onChange={handleChange}
354369
input={<BootstrapInput />}
355370
>
356-
{AllVersion[pathConfig.repo][pathConfig.locale].map((version) => (
371+
{versionOptions.map((version) => (
357372
<option
358373
key={`${version}`}
359374
value={`${version}`}
360375
disabled={!availIn.includes(version || "")}
361376
>
362-
{renderVersion(version, pathConfig)}
377+
{renderVersion(version, pathConfig, isArchive)}
363378
</option>
364379
))}
365-
{buildType !== "archive" && (
380+
{!isArchive && (
366381
<option key="archive" value="archive">
367382
{t("navbar.archive-label")}
368383
</option>

0 commit comments

Comments
 (0)