Skip to content

Commit e96c2a8

Browse files
vdusekclaude
andcommitted
fix(docs): fix version switching for API reference pages
- Swizzle DocsVersionDropdownNavbarItem to navigate to correct API version paths - Make API navbar link respect the currently selected docs version - Collapse all sidebar categories by default and enable auto-collapse - Remove unreleased changelog section from versioned 1.6 docs Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent e1b4346 commit e96c2a8

File tree

8 files changed

+219
-51
lines changed

8 files changed

+219
-51
lines changed

website/docusaurus.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ module.exports = {
269269
position: 'left',
270270
},
271271
{
272-
to: '/api',
272+
type: 'custom-api',
273273
label: 'API',
274274
position: 'left',
275275
activeBaseRegex: 'api/(?!.*/changelog)',

website/sidebars.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ module.exports = {
44
{
55
type: 'category',
66
label: 'Introduction',
7-
collapsed: false,
7+
collapsed: true,
88
link: {
99
type: 'doc',
1010
id: 'introduction/introduction',

website/src/theme/NavbarItem/ComponentTypes.js

Lines changed: 8 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useActiveDocContext, useLayoutDoc } from '@docusaurus/plugin-content-docs/client';
1+
import { useActiveDocContext, useDocsPreferredVersion, useLayoutDoc } from '@docusaurus/plugin-content-docs/client';
22
import DefaultNavbarItem from '@theme/NavbarItem/DefaultNavbarItem';
33
import DocSidebarNavbarItem from '@theme/NavbarItem/DocSidebarNavbarItem';
44
import DocsVersionDropdownNavbarItem from '@theme/NavbarItem/DocsVersionDropdownNavbarItem';
@@ -9,8 +9,7 @@ import LocaleDropdownNavbarItem from '@theme/NavbarItem/LocaleDropdownNavbarItem
99
import SearchNavbarItem from '@theme/NavbarItem/SearchNavbarItem';
1010
import React from 'react';
1111

12-
// const versions = require('../../../versions.json');
13-
// const stable = versions[0];
12+
import { getApiPath } from './apiVersionUtils';
1413

1514
function DocNavbarItem({
1615
docId,
@@ -35,46 +34,17 @@ function DocNavbarItem({
3534
);
3635
}
3736

38-
function ApiNavbarItem(ctx) {
37+
function ApiNavbarItem({ to, ...props }) {
38+
const { preferredVersion } = useDocsPreferredVersion();
39+
const apiPath = preferredVersion ? getApiPath(preferredVersion) : 'api';
40+
3941
return (
4042
<DefaultNavbarItem
4143
exact
42-
{...ctx}
43-
label={ctx.label}
44-
to={`api/${ctx.to}`}
44+
{...props}
45+
to={to ? `${apiPath}/${to}` : apiPath}
4546
/>
4647
);
47-
48-
// let version = {};
49-
//
50-
// try {
51-
// // eslint-disable-next-line react-hooks/rules-of-hooks
52-
// version = useDocsVersion();
53-
// } catch {
54-
// version.version = stable;
55-
// }
56-
//
57-
// const { siteConfig } = useDocusaurusContext();
58-
//
59-
// if (siteConfig.presets[0][1].docs.disableVersioning || version.version === stable) {
60-
// return (
61-
// <DefaultNavbarItem
62-
// exact
63-
// {...ctx}
64-
// label={ctx.label}
65-
// to={`api/${ctx.to}`}
66-
// />
67-
// );
68-
// }
69-
//
70-
// return (
71-
// <DefaultNavbarItem
72-
// exact
73-
// {...ctx}
74-
// label={ctx.label}
75-
// to={`api/${version.version === 'current' ? 'next' : version.version}/${ctx.to}`}
76-
// />
77-
// );
7848
}
7949

8050
const ComponentTypes = {
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
/**
2+
* Swizzled DocsVersionDropdownNavbarItem that is aware of API reference pages.
3+
*
4+
* The upstream component only handles docs pages. When the user is browsing
5+
* the API reference (routes under /api), switching versions must navigate to
6+
* the matching API version path, not to a docs page.
7+
*/
8+
import React from 'react';
9+
import {
10+
useVersions,
11+
useActiveDocContext,
12+
useDocsVersionCandidates,
13+
useDocsPreferredVersion,
14+
} from '@docusaurus/plugin-content-docs/client';
15+
import { useLocation } from '@docusaurus/router';
16+
import { translate } from '@docusaurus/Translate';
17+
import { useHistorySelector } from '@docusaurus/theme-common';
18+
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
19+
import DefaultNavbarItem from '@theme/NavbarItem/DefaultNavbarItem';
20+
import DropdownNavbarItem from '@theme/NavbarItem/DropdownNavbarItem';
21+
22+
import { getApiVersionPath } from './apiVersionUtils';
23+
24+
function getVersionItems(versions, configs) {
25+
if (configs) {
26+
const versionMap = new Map(versions.map((version) => [version.name, version]));
27+
const toVersionItem = (name, config) => {
28+
const version = versionMap.get(name);
29+
if (!version) {
30+
throw new Error(
31+
`No docs version exist for name '${name}', please verify your 'docsVersionDropdown' navbar item versions config.\nAvailable version names:\n- ${versions.map((v) => `${v.name}`).join('\n- ')}`,
32+
);
33+
}
34+
return { version, label: config?.label ?? version.label };
35+
};
36+
if (Array.isArray(configs)) {
37+
return configs.map((name) => toVersionItem(name, undefined));
38+
}
39+
return Object.entries(configs).map(([name, config]) => toVersionItem(name, config));
40+
}
41+
return versions.map((version) => ({ version, label: version.label }));
42+
}
43+
44+
function useVersionItems({ docsPluginId, configs }) {
45+
const versions = useVersions(docsPluginId);
46+
return getVersionItems(versions, configs);
47+
}
48+
49+
function getVersionMainDoc(version) {
50+
return version.docs.find((doc) => doc.id === version.mainDocId);
51+
}
52+
53+
function getVersionTargetDoc(version, activeDocContext) {
54+
return activeDocContext.alternateDocVersions[version.name] ?? getVersionMainDoc(version);
55+
}
56+
57+
function useDisplayedVersionItem({ docsPluginId, versionItems }) {
58+
const candidates = useDocsVersionCandidates(docsPluginId);
59+
const candidateItems = candidates
60+
.map((candidate) => versionItems.find((vi) => vi.version === candidate))
61+
.filter((vi) => vi !== undefined);
62+
return candidateItems[0] ?? versionItems[0];
63+
}
64+
65+
/** Detect whether the user is currently on an API reference page and, if so,
66+
* determine which version they are viewing. */
67+
function useApiVersionInfo(baseUrl, versions) {
68+
const { pathname } = useLocation();
69+
const apiPrefix = `${baseUrl}api`;
70+
71+
if (!pathname.startsWith(apiPrefix)) {
72+
return null;
73+
}
74+
75+
const afterApi = pathname.slice(apiPrefix.length);
76+
const segments = afterApi.split('/').filter(Boolean);
77+
78+
if (segments.length > 0 && segments[0] === 'next') {
79+
return { currentVersionName: 'current' };
80+
}
81+
82+
if (segments.length > 0) {
83+
const versionNames = new Set(versions.map((v) => v.name));
84+
if (versionNames.has(segments[0])) {
85+
return { currentVersionName: segments[0] };
86+
}
87+
}
88+
89+
const lastVersion = versions.find((v) => v.isLast);
90+
return { currentVersionName: lastVersion?.name };
91+
}
92+
93+
export default function DocsVersionDropdownNavbarItem({
94+
mobile,
95+
docsPluginId,
96+
dropdownActiveClassDisabled,
97+
dropdownItemsBefore,
98+
dropdownItemsAfter,
99+
versions: configs,
100+
...props
101+
}) {
102+
const { siteConfig } = useDocusaurusContext();
103+
const { baseUrl } = siteConfig;
104+
const search = useHistorySelector((history) => history.location.search);
105+
const hash = useHistorySelector((history) => history.location.hash);
106+
const activeDocContext = useActiveDocContext(docsPluginId);
107+
const { savePreferredVersionName } = useDocsPreferredVersion(docsPluginId);
108+
const versionItems = useVersionItems({ docsPluginId, configs });
109+
const displayedVersionItem = useDisplayedVersionItem({ docsPluginId, versionItems });
110+
111+
const versions = useVersions(docsPluginId);
112+
const apiInfo = useApiVersionInfo(baseUrl, versions);
113+
const isOnApiPage = apiInfo !== null;
114+
115+
function versionItemToLink({ version, label }) {
116+
if (isOnApiPage) {
117+
const apiPath = getApiVersionPath(version, baseUrl);
118+
return {
119+
label,
120+
to: `${apiPath}${search}${hash}`,
121+
isActive: () => version.name === apiInfo.currentVersionName,
122+
onClick: () => savePreferredVersionName(version.name),
123+
};
124+
}
125+
126+
const targetDoc = getVersionTargetDoc(version, activeDocContext);
127+
return {
128+
label,
129+
to: `${targetDoc.path}${search}${hash}`,
130+
isActive: () => version === activeDocContext.activeVersion,
131+
onClick: () => savePreferredVersionName(version.name),
132+
};
133+
}
134+
135+
// When on an API page, show the version matching the current API path.
136+
let effectiveDisplayedItem = displayedVersionItem;
137+
if (isOnApiPage) {
138+
const match = versionItems.find((vi) => vi.version.name === apiInfo.currentVersionName);
139+
if (match) {
140+
effectiveDisplayedItem = match;
141+
}
142+
}
143+
144+
const items = [...dropdownItemsBefore, ...versionItems.map(versionItemToLink), ...dropdownItemsAfter];
145+
146+
const dropdownLabel =
147+
mobile && items.length > 1
148+
? translate({
149+
id: 'theme.navbar.mobileVersionsDropdown.label',
150+
message: 'Versions',
151+
description: 'The label for the navbar versions dropdown on mobile view',
152+
})
153+
: effectiveDisplayedItem.label;
154+
155+
let dropdownTo;
156+
if (mobile && items.length > 1) {
157+
dropdownTo = undefined;
158+
} else if (isOnApiPage) {
159+
dropdownTo = getApiVersionPath(effectiveDisplayedItem.version, baseUrl);
160+
} else {
161+
dropdownTo = getVersionTargetDoc(effectiveDisplayedItem.version, activeDocContext).path;
162+
}
163+
164+
if (items.length <= 1) {
165+
return (
166+
<DefaultNavbarItem
167+
{...props}
168+
mobile={mobile}
169+
label={dropdownLabel}
170+
to={dropdownTo}
171+
isActive={dropdownActiveClassDisabled ? () => false : undefined}
172+
/>
173+
);
174+
}
175+
176+
return (
177+
<DropdownNavbarItem
178+
{...props}
179+
mobile={mobile}
180+
label={dropdownLabel}
181+
to={dropdownTo}
182+
items={items}
183+
isActive={dropdownActiveClassDisabled ? () => false : undefined}
184+
/>
185+
);
186+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
const API_ROUTE_BASE = 'api';
2+
3+
/** Build the API path for a given version (relative, no baseUrl). */
4+
export function getApiPath(version) {
5+
if (version.isLast) {
6+
return API_ROUTE_BASE;
7+
}
8+
if (version.name === 'current') {
9+
return `${API_ROUTE_BASE}/next`;
10+
}
11+
return `${API_ROUTE_BASE}/${version.name}`;
12+
}
13+
14+
/** Build the full API path for a given version (with baseUrl prefix). */
15+
export function getApiVersionPath(version, baseUrl) {
16+
return `${baseUrl}${getApiPath(version)}`;
17+
}

website/versioned_docs/version-1.6/changelog.md

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,6 @@
22

33
All notable changes to this project will be documented in this file.
44

5-
<!-- git-cliff-unreleased-start -->
6-
## 1.6.1 - **not yet released**
7-
8-
### 🐛 Bug Fixes
9-
10-
- Handle invalid URLs in `RequestList` ([#1803](https://github.com/apify/crawlee-python/pull/1803)) ([0b2e3fc](https://github.com/apify/crawlee-python/commit/0b2e3fc5cbca371131b54085e052a6cda6361b0f)) by [@Mantisus](https://github.com/Mantisus), closes [#1802](https://github.com/apify/crawlee-python/issues/1802)
11-
12-
13-
<!-- git-cliff-unreleased-end -->
145
## [1.6.0](https://github.com/apify/crawlee-python/releases/tag/v1.6.0) (2026-03-20)
156

167
### 🚀 Features

website/versioned_sidebars/version-0.6-sidebars.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
{
55
"type": "category",
66
"label": "Introduction",
7-
"collapsed": false,
7+
"collapsed": true,
88
"link": {
99
"type": "doc",
1010
"id": "introduction/introduction"
@@ -24,6 +24,7 @@
2424
{
2525
"type": "category",
2626
"label": "Guides",
27+
"collapsed": true,
2728
"link": {
2829
"type": "generated-index",
2930
"title": "Guides",
@@ -42,6 +43,7 @@
4243
{
4344
"type": "category",
4445
"label": "Deployment",
46+
"collapsed": true,
4547
"link": {
4648
"type": "generated-index",
4749
"title": "Deployment guides",
@@ -67,6 +69,7 @@
6769
{
6870
"type": "category",
6971
"label": "Examples",
72+
"collapsed": true,
7073
"link": {
7174
"type": "generated-index",
7275
"title": "Examples",
@@ -85,6 +88,7 @@
8588
{
8689
"type": "category",
8790
"label": "Upgrading",
91+
"collapsed": true,
8892
"link": {
8993
"type": "generated-index",
9094
"title": "Upgrading",

website/versioned_sidebars/version-1.6-sidebars.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
{
55
"type": "category",
66
"label": "Introduction",
7-
"collapsed": false,
7+
"collapsed": true,
88
"link": {
99
"type": "doc",
1010
"id": "introduction/introduction"

0 commit comments

Comments
 (0)