Skip to content

Commit e7edc4f

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 5b28f03 commit e7edc4f

File tree

7 files changed

+229
-49
lines changed

7 files changed

+229
-49
lines changed

website/docusaurus.config.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ module.exports = {
246246
versionPersistence: 'localStorage',
247247
sidebar: {
248248
hideable: true,
249+
autoCollapseCategories: true,
249250
},
250251
},
251252
navbar: {
@@ -269,7 +270,7 @@ module.exports = {
269270
position: 'left',
270271
},
271272
{
272-
to: '/api',
273+
type: 'custom-api',
273274
label: 'API',
274275
position: 'left',
275276
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: 15 additions & 36 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';
@@ -35,46 +35,25 @@ function DocNavbarItem({
3535
);
3636
}
3737

38-
function ApiNavbarItem(ctx) {
38+
function ApiNavbarItem({ to, ...props }) {
39+
const { preferredVersion } = useDocsPreferredVersion();
40+
41+
let apiPath = 'api';
42+
if (preferredVersion) {
43+
if (preferredVersion.name === 'current') {
44+
apiPath = 'api/next';
45+
} else if (!preferredVersion.isLast) {
46+
apiPath = `api/${preferredVersion.name}`;
47+
}
48+
}
49+
3950
return (
4051
<DefaultNavbarItem
4152
exact
42-
{...ctx}
43-
label={ctx.label}
44-
to={`api/${ctx.to}`}
53+
{...props}
54+
to={to ? `${apiPath}/${to}` : apiPath}
4555
/>
4656
);
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-
// );
7857
}
7958

8059
const ComponentTypes = {
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
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+
const API_ROUTE_BASE = 'api';
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+
// ---------------------------------------------------------------------------
66+
// API-page awareness
67+
// ---------------------------------------------------------------------------
68+
69+
/** Detect whether the user is currently on an API reference page and, if so,
70+
* determine which version they are viewing. */
71+
function useApiVersionInfo(baseUrl, versions) {
72+
const { pathname } = useLocation();
73+
const apiPrefix = `${baseUrl}${API_ROUTE_BASE}`;
74+
75+
if (!pathname.startsWith(apiPrefix)) {
76+
return null;
77+
}
78+
79+
const afterApi = pathname.slice(apiPrefix.length);
80+
const segments = afterApi.split('/').filter(Boolean);
81+
const versionNames = new Set(versions.map((v) => v.name));
82+
83+
if (segments.length > 0 && segments[0] === 'next') {
84+
return { currentVersionName: 'current' };
85+
}
86+
87+
if (segments.length > 0 && versionNames.has(segments[0])) {
88+
return { currentVersionName: segments[0] };
89+
}
90+
91+
// No version segment → latest (isLast) version.
92+
const lastVersion = versions.find((v) => v.isLast);
93+
return { currentVersionName: lastVersion?.name };
94+
}
95+
96+
/** Build the API index path for a given version. */
97+
function getApiVersionPath(version, baseUrl) {
98+
const apiBase = `${baseUrl}${API_ROUTE_BASE}`;
99+
if (version.isLast) {
100+
return apiBase;
101+
}
102+
if (version.name === 'current') {
103+
return `${apiBase}/next`;
104+
}
105+
return `${apiBase}/${version.name}`;
106+
}
107+
108+
// ---------------------------------------------------------------------------
109+
// Component
110+
// ---------------------------------------------------------------------------
111+
112+
export default function DocsVersionDropdownNavbarItem({
113+
mobile,
114+
docsPluginId,
115+
dropdownActiveClassDisabled,
116+
dropdownItemsBefore,
117+
dropdownItemsAfter,
118+
versions: configs,
119+
...props
120+
}) {
121+
const { siteConfig } = useDocusaurusContext();
122+
const { baseUrl } = siteConfig;
123+
const search = useHistorySelector((history) => history.location.search);
124+
const hash = useHistorySelector((history) => history.location.hash);
125+
const activeDocContext = useActiveDocContext(docsPluginId);
126+
const { savePreferredVersionName } = useDocsPreferredVersion(docsPluginId);
127+
const versionItems = useVersionItems({ docsPluginId, configs });
128+
const displayedVersionItem = useDisplayedVersionItem({ docsPluginId, versionItems });
129+
130+
const versions = useVersions(docsPluginId);
131+
const apiInfo = useApiVersionInfo(baseUrl, versions);
132+
const isOnApiPage = apiInfo !== null;
133+
134+
function versionItemToLink({ version, label }) {
135+
if (isOnApiPage) {
136+
const apiPath = getApiVersionPath(version, baseUrl);
137+
return {
138+
label,
139+
to: `${apiPath}${search}${hash}`,
140+
isActive: () => version.name === apiInfo.currentVersionName,
141+
onClick: () => savePreferredVersionName(version.name),
142+
};
143+
}
144+
145+
const targetDoc = getVersionTargetDoc(version, activeDocContext);
146+
return {
147+
label,
148+
to: `${targetDoc.path}${search}${hash}`,
149+
isActive: () => version === activeDocContext.activeVersion,
150+
onClick: () => savePreferredVersionName(version.name),
151+
};
152+
}
153+
154+
// When on an API page, show the version matching the current API path.
155+
let effectiveDisplayedItem = displayedVersionItem;
156+
if (isOnApiPage) {
157+
const match = versionItems.find((vi) => vi.version.name === apiInfo.currentVersionName);
158+
if (match) {
159+
effectiveDisplayedItem = match;
160+
}
161+
}
162+
163+
const items = [...dropdownItemsBefore, ...versionItems.map(versionItemToLink), ...dropdownItemsAfter];
164+
165+
const dropdownLabel =
166+
mobile && items.length > 1
167+
? translate({
168+
id: 'theme.navbar.mobileVersionsDropdown.label',
169+
message: 'Versions',
170+
description: 'The label for the navbar versions dropdown on mobile view',
171+
})
172+
: effectiveDisplayedItem.label;
173+
174+
let dropdownTo;
175+
if (mobile && items.length > 1) {
176+
dropdownTo = undefined;
177+
} else if (isOnApiPage) {
178+
dropdownTo = getApiVersionPath(effectiveDisplayedItem.version, baseUrl);
179+
} else {
180+
dropdownTo = getVersionTargetDoc(effectiveDisplayedItem.version, activeDocContext).path;
181+
}
182+
183+
if (items.length <= 1) {
184+
return (
185+
<DefaultNavbarItem
186+
{...props}
187+
mobile={mobile}
188+
label={dropdownLabel}
189+
to={dropdownTo}
190+
isActive={dropdownActiveClassDisabled ? () => false : undefined}
191+
/>
192+
);
193+
}
194+
195+
return (
196+
<DropdownNavbarItem
197+
{...props}
198+
mobile={mobile}
199+
label={dropdownLabel}
200+
to={dropdownTo}
201+
items={items}
202+
isActive={dropdownActiveClassDisabled ? () => false : undefined}
203+
/>
204+
);
205+
}

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)