Skip to content

Commit 3efcd3c

Browse files
authored
[codex] Fix user API environment toggle paths (#145)
* Fix user API environment toggle paths * Handle API environment root paths
1 parent dbbfaca commit 3efcd3c

2 files changed

Lines changed: 110 additions & 21 deletions

File tree

‎src/components/UserRelatedApiEnvironmentNotice/paths.js‎

Lines changed: 47 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,25 @@
11
const PROD_CATEGORY_PATH = '/docs/category/user-related-apis';
22
const PRELIVE_CATEGORY_PATH = '/docs/category/user-related-apis-pre-live';
3-
const PROD_LATEST_PREFIX = '/docs/user_related_apis_versioned/';
4-
const PRELIVE_PREFIX = '/docs/user_related_apis_prelive/';
3+
const PROD_LATEST_ROOT = '/docs/user_related_apis_versioned';
4+
const PRELIVE_ROOT = '/docs/user_related_apis_prelive';
5+
const PROD_LATEST_PREFIX = `${PROD_LATEST_ROOT}/`;
6+
const PRELIVE_PREFIX = `${PRELIVE_ROOT}/`;
57
const PROD_VERSION_PREFIX_REGEX = /^\d+\.\d+\.\d+(\/|$)/;
68

9+
const normalizePath = (value) =>
10+
value && value !== '/' ? value.replace(/\/+$/, '') : value;
11+
const isPathInTree = (pathname, rootPath) =>
12+
pathname === rootPath || pathname.startsWith(`${rootPath}/`);
13+
const isApiTreeRoot = (pathname) =>
14+
pathname === PROD_LATEST_ROOT || pathname === PRELIVE_ROOT;
15+
const hasAvailablePath = (availablePaths, targetPath) => {
16+
const normalizedTargetPath = normalizePath(targetPath);
17+
18+
return (
19+
availablePaths.has(normalizedTargetPath) ||
20+
availablePaths.has(`${normalizedTargetPath}/`)
21+
);
22+
};
723
const stripPrefix = (value, prefix) => value.slice(prefix.length);
824
const getFallbackPath = (environment) =>
925
environment === 'production' ? PROD_CATEGORY_PATH : PRELIVE_CATEGORY_PATH;
@@ -15,7 +31,7 @@ function getUserRelatedDocsAvailablePaths(allDocsData) {
1531
pluginData?.versions?.forEach((version) => {
1632
version?.docs?.forEach((doc) => {
1733
if (typeof doc?.path === 'string') {
18-
paths.add(doc.path);
34+
paths.add(normalizePath(doc.path));
1935
}
2036
});
2137
});
@@ -25,16 +41,18 @@ function getUserRelatedDocsAvailablePaths(allDocsData) {
2541
}
2642

2743
function getUserRelatedDocsEnvironment(pathname) {
44+
const normalizedPathname = normalizePath(pathname);
45+
2846
if (
29-
pathname === PROD_CATEGORY_PATH ||
30-
pathname.startsWith(PROD_LATEST_PREFIX)
47+
normalizedPathname === PROD_CATEGORY_PATH ||
48+
isPathInTree(normalizedPathname, PROD_LATEST_ROOT)
3149
) {
3250
return 'production';
3351
}
3452

3553
if (
36-
pathname === PRELIVE_CATEGORY_PATH ||
37-
pathname.startsWith(PRELIVE_PREFIX)
54+
normalizedPathname === PRELIVE_CATEGORY_PATH ||
55+
isPathInTree(normalizedPathname, PRELIVE_ROOT)
3856
) {
3957
return 'pre-live';
4058
}
@@ -43,36 +61,45 @@ function getUserRelatedDocsEnvironment(pathname) {
4361
}
4462

4563
function getTargetPath(pathname, targetEnvironment) {
46-
const currentEnvironment = getUserRelatedDocsEnvironment(pathname);
64+
const normalizedPathname = normalizePath(pathname);
65+
const currentEnvironment = getUserRelatedDocsEnvironment(normalizedPathname);
4766
const fallbackPath = getFallbackPath(targetEnvironment);
4867
let targetPath = fallbackPath;
4968

5069
if (currentEnvironment && currentEnvironment === targetEnvironment) {
5170
return {
5271
fallbackPath,
53-
targetPath: pathname,
72+
targetPath: normalizedPathname,
5473
};
5574
}
5675

5776
if (targetEnvironment === 'production') {
58-
if (pathname === PRELIVE_CATEGORY_PATH) {
77+
if (normalizedPathname === PRELIVE_CATEGORY_PATH) {
5978
targetPath = PROD_CATEGORY_PATH;
60-
} else if (pathname.startsWith(PRELIVE_PREFIX)) {
61-
targetPath = `${PROD_LATEST_PREFIX}${stripPrefix(pathname, PRELIVE_PREFIX)}`;
79+
} else if (isPathInTree(normalizedPathname, PRELIVE_ROOT)) {
80+
targetPath =
81+
normalizedPathname === PRELIVE_ROOT
82+
? PROD_LATEST_ROOT
83+
: `${PROD_LATEST_PREFIX}${stripPrefix(normalizedPathname, PRELIVE_PREFIX)}`;
6284
}
6385
} else if (targetEnvironment === 'pre-live') {
64-
if (pathname === PROD_CATEGORY_PATH) {
86+
if (normalizedPathname === PROD_CATEGORY_PATH) {
6587
targetPath = PRELIVE_CATEGORY_PATH;
66-
} else if (pathname.startsWith(PROD_LATEST_PREFIX)) {
67-
const relativePath = stripPrefix(pathname, PROD_LATEST_PREFIX);
88+
} else if (isPathInTree(normalizedPathname, PROD_LATEST_ROOT)) {
89+
const relativePath =
90+
normalizedPathname === PROD_LATEST_ROOT
91+
? ''
92+
: stripPrefix(normalizedPathname, PROD_LATEST_PREFIX);
6893
const normalizedRelativePath = relativePath.replace(PROD_VERSION_PREFIX_REGEX, '');
6994

70-
targetPath = `${PRELIVE_PREFIX}${normalizedRelativePath}`;
95+
targetPath = normalizedRelativePath
96+
? `${PRELIVE_PREFIX}${normalizedRelativePath}`
97+
: PRELIVE_ROOT;
7198
}
7299
} else {
73100
return {
74-
fallbackPath: pathname,
75-
targetPath: pathname,
101+
fallbackPath: normalizedPathname,
102+
targetPath: normalizedPathname,
76103
};
77104
}
78105

@@ -84,10 +111,10 @@ function getTargetPath(pathname, targetEnvironment) {
84111

85112
function getUserRelatedDocsTarget(pathname, targetEnvironment, options = {}) {
86113
const { fallbackPath, targetPath } = getTargetPath(pathname, targetEnvironment);
87-
const hasExplicitDocTarget = targetPath !== fallbackPath;
114+
const hasExplicitDocTarget = targetPath !== fallbackPath && !isApiTreeRoot(targetPath);
88115
const hasEquivalentDoc = !hasExplicitDocTarget || !options.availablePaths
89116
? true
90-
: options.availablePaths.has(targetPath);
117+
: hasAvailablePath(options.availablePaths, targetPath);
91118
const path = hasEquivalentDoc ? targetPath : fallbackPath;
92119

93120
return {

‎tests/user-related-env-paths.test.cjs‎

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,31 @@ test('detects production and pre-live user-related docs routes', () => {
2525
getUserRelatedDocsEnvironment('/docs/user_related_apis_prelive/get-user-profile'),
2626
'pre-live',
2727
);
28+
assert.equal(
29+
getUserRelatedDocsEnvironment('/docs/user_related_apis_versioned/get-user-profile/'),
30+
'production',
31+
);
32+
assert.equal(
33+
getUserRelatedDocsEnvironment('/docs/user_related_apis_prelive/get-user-profile/'),
34+
'pre-live',
35+
);
36+
assert.equal(getUserRelatedDocsEnvironment('/docs/user_related_apis_versioned'), 'production');
37+
assert.equal(getUserRelatedDocsEnvironment('/docs/user_related_apis_versioned/'), 'production');
38+
assert.equal(getUserRelatedDocsEnvironment('/docs/user_related_apis_prelive'), 'pre-live');
39+
assert.equal(getUserRelatedDocsEnvironment('/docs/user_related_apis_prelive/'), 'pre-live');
2840
assert.equal(getUserRelatedDocsEnvironment('/docs/category/user-related-apis'), 'production');
41+
assert.equal(
42+
getUserRelatedDocsEnvironment('/docs/category/user-related-apis/'),
43+
'production',
44+
);
2945
assert.equal(
3046
getUserRelatedDocsEnvironment('/docs/category/user-related-apis-pre-live'),
3147
'pre-live',
3248
);
49+
assert.equal(
50+
getUserRelatedDocsEnvironment('/docs/category/user-related-apis-pre-live/'),
51+
'pre-live',
52+
);
3353
assert.equal(getUserRelatedDocsEnvironment('/docs/category/content-apis'), null);
3454
});
3555

@@ -55,6 +75,20 @@ test('maps the current doc route between production and pre-live trees', () => {
5575
),
5676
'/docs/user_related_apis_versioned/get-user-profile',
5777
);
78+
assert.equal(
79+
getUserRelatedDocsPath(
80+
'/docs/user_related_apis_prelive/get-user-profile/',
81+
'production',
82+
),
83+
'/docs/user_related_apis_versioned/get-user-profile',
84+
);
85+
assert.equal(
86+
getUserRelatedDocsPath(
87+
'/docs/user_related_apis_versioned/1.0.0/get-user-profile/',
88+
'pre-live',
89+
),
90+
'/docs/user_related_apis_prelive/get-user-profile',
91+
);
5892
assert.equal(
5993
getUserRelatedDocsPath(
6094
'/docs/user_related_apis_versioned/get-user-profile',
@@ -73,6 +107,18 @@ test('maps the current doc route between production and pre-live trees', () => {
73107
getUserRelatedDocsPath('/docs/category/user-related-apis', 'pre-live'),
74108
'/docs/category/user-related-apis-pre-live',
75109
);
110+
assert.equal(
111+
getUserRelatedDocsPath('/docs/category/user-related-apis/', 'pre-live'),
112+
'/docs/category/user-related-apis-pre-live',
113+
);
114+
assert.equal(
115+
getUserRelatedDocsPath('/docs/user_related_apis_versioned/', 'pre-live'),
116+
'/docs/user_related_apis_prelive',
117+
);
118+
assert.equal(
119+
getUserRelatedDocsPath('/docs/user_related_apis_prelive/', 'production'),
120+
'/docs/user_related_apis_versioned',
121+
);
76122
assert.equal(
77123
getUserRelatedDocsPath('/docs/category/user-related-apis-pre-live', 'production'),
78124
'/docs/category/user-related-apis',
@@ -128,6 +174,22 @@ test('falls back to the environment category when the target doc does not exist'
128174
);
129175
assert.equal(versionedProdToPreliveTarget.path, '/docs/user_related_apis_prelive/get-user-profile');
130176
assert.equal(versionedProdToPreliveTarget.hasEquivalentDoc, true);
177+
178+
const trailingSlashTarget = getUserRelatedDocsTarget(
179+
'/docs/user_related_apis_prelive/get-user-profile/',
180+
'production',
181+
{ availablePaths },
182+
);
183+
assert.equal(trailingSlashTarget.path, '/docs/user_related_apis_versioned/get-user-profile');
184+
assert.equal(trailingSlashTarget.hasEquivalentDoc, true);
185+
186+
const rootTarget = getUserRelatedDocsTarget(
187+
'/docs/user_related_apis_versioned/',
188+
'pre-live',
189+
{ availablePaths },
190+
);
191+
assert.equal(rootTarget.path, '/docs/user_related_apis_prelive');
192+
assert.equal(rootTarget.hasEquivalentDoc, true);
131193
});
132194

133195
test('collects available docs paths from Docusaurus docs data', () => {
@@ -137,7 +199,7 @@ test('collects available docs paths from Docusaurus docs data', () => {
137199
{
138200
docs: [
139201
{ path: '/docs/user_related_apis_versioned/get-user-profile' },
140-
{ path: '/docs/user_related_apis_prelive/get-sync-mutations' },
202+
{ path: '/docs/user_related_apis_prelive/get-sync-mutations/' },
141203
],
142204
},
143205
],

0 commit comments

Comments
 (0)