From d1e9a5df06c0470ca5a09c6a316bbb785bd96987 Mon Sep 17 00:00:00 2001 From: Evan Rusackas Date: Wed, 13 May 2026 20:14:52 -0700 Subject: [PATCH] chore(docs): clean up version-cutting tooling and finish developer_portal rename (#39837) Co-authored-by: Claude Code --- .rat-excludes | 3 + docs/DOCS_CLAUDE.md | 33 ++- docs/README.md | 56 +++- docs/components/versions.json | 1 - docs/developer_docs/versions.json | 1 - docs/developer_portal_versions.json | 1 - docs/package.json | 6 +- docs/scripts/manage-versions.mjs | 251 +++++++++++++++--- docs/src/theme/DocVersionBadge/index.js | 28 +- docs/src/theme/DocVersionBanner/index.js | 121 --------- .../theme/DocVersionBanner/styles.module.css | 49 ---- docs/tutorials_versions.json | 3 - 12 files changed, 297 insertions(+), 256 deletions(-) delete mode 100644 docs/components/versions.json delete mode 100644 docs/developer_docs/versions.json delete mode 100644 docs/developer_portal_versions.json delete mode 100644 docs/src/theme/DocVersionBanner/index.js delete mode 100644 docs/src/theme/DocVersionBanner/styles.module.css delete mode 100644 docs/tutorials_versions.json diff --git a/.rat-excludes b/.rat-excludes index 44cf26ac6a3..30b1ef1da9d 100644 --- a/.rat-excludes +++ b/.rat-excludes @@ -43,6 +43,9 @@ _build/* _static/* .buildinfo searchindex.js +# auto-generated by docs/scripts/convert-api-sidebar.mjs from openapi.json +sidebar.js +sidebar.ts # auto generated requirements/* # vendorized diff --git a/docs/DOCS_CLAUDE.md b/docs/DOCS_CLAUDE.md index 1ac49462afe..3e60b73b0d3 100644 --- a/docs/DOCS_CLAUDE.md +++ b/docs/DOCS_CLAUDE.md @@ -31,8 +31,9 @@ You are currently in the `/docs` subdirectory of the Apache Superset repository. ├── superset-frontend/ # React/TypeScript frontend └── docs/ # Documentation site (YOU ARE HERE) ├── docs/ # Main documentation content - ├── developer_portal/ # Developer guides (currently disabled) - ├── components/ # Component playground (currently disabled) + ├── admin_docs/ # Admin-focused guides + ├── developer_docs/ # Developer guides + ├── components/ # Component playground └── docusaurus.config.ts # Site configuration ``` @@ -46,12 +47,19 @@ yarn build # Build production site yarn serve # Serve built site locally # Version Management (USE THESE, NOT docusaurus commands) +# The add scripts auto-run `generate:smart` so auto-gen content (database +# pages, API reference, component pages) is fresh before snapshotting. +# For maximum-detail databases.json, drop the `database-diagnostics` +# artifact from Python-Integration CI at src/data/databases.json before +# cutting. See README.md "Before You Cut". yarn version:add:docs # Add new docs version -yarn version:add:developer_portal # Add developer portal version +yarn version:add:admin_docs # Add admin docs version +yarn version:add:developer_docs # Add developer docs version yarn version:add:components # Add components version yarn version:remove:docs # Remove docs version -yarn version:remove:developer_portal # Remove developer portal version -yarn version:remove:components # Remove components version +yarn version:remove:admin_docs # Remove admin docs version +yarn version:remove:developer_docs # Remove developer docs version +yarn version:remove:components # Remove components version # Quality Checks yarn typecheck # TypeScript validation @@ -95,15 +103,14 @@ docs/ └── [security guides] ``` -### Developer Portal (`/developer_portal`) - Currently Disabled -When enabled, contains developer-focused content: -- API documentation -- Architecture guides -- CLI tools -- Code examples +### Admin Docs (`/admin_docs`) +Admin-focused content: installation, configuration, security. -### Component Playground (`/components`) - Currently Disabled -When enabled, provides interactive component examples for UI development. +### Developer Docs (`/developer_docs`) +Developer-focused content: API documentation, architecture guides, CLI tools, code examples. + +### Component Playground (`/components`) +Interactive component examples for UI development. ## 📝 Documentation Standards diff --git a/docs/README.md b/docs/README.md index 6f3a6b4902e..f5b8e719445 100644 --- a/docs/README.md +++ b/docs/README.md @@ -37,23 +37,45 @@ Each section maintains its own version history and can be versioned independentl To create a new version for any section, use the Docusaurus version command with the appropriate plugin ID or use our automated scripts: +#### Before You Cut + +The cut snapshots whatever's on disk into a frozen historical version, including auto-generated content (database pages from `superset/db_engine_specs/`, API reference from `static/resources/openapi.json`, component pages from Storybook stories). The cut script refreshes these via `generate:smart` before snapshotting, but the **`databases.json` diagnostics file** needs special care to capture full detail: + +1. **Canonical release cut**: download the `database-diagnostics` artifact from a green `Python-Integration` run on master, place it at `docs/src/data/databases.json`, then run the cut script with `--skip-generate` to preserve it. This is what the production deploy uses and includes full Flask-context diagnostics (driver versions, feature support matrix, etc.). +2. **Local dev cut**: just run the script normally. `generate:smart` will regenerate `databases.json` using your local Flask environment — accurate to whatever drivers/extras you have installed, but typically less complete than the CI artifact. +3. **No Flask available**: also fine — the database generator falls back to AST parsing of engine spec files. The MDX pages are still correct; only the diagnostics JSON is leaner. + +Also: confirm `master` CI is green, and that your local checkout matches the SHA you intend to cut from. + #### Using Automated Scripts (Required) -**⚠️ Important:** Always use these custom commands instead of the native Docusaurus commands. These scripts ensure that both the Docusaurus versioning system AND the `versions-config.json` file are updated correctly. +**⚠️ Important:** Always use these custom commands instead of the native Docusaurus commands. These scripts ensure that both the Docusaurus versioning system AND the `versions-config.json` file are updated correctly, AND that auto-generated content is refreshed before snapshotting. ```bash # Main Documentation yarn version:add:docs 1.2.0 -# Developer Portal -yarn version:add:developer_portal 1.2.0 +# Admin Docs +yarn version:add:admin_docs 1.2.0 -# Component Playground (when enabled) +# Developer Docs +yarn version:add:developer_docs 1.2.0 + +# Component Playground yarn version:add:components 1.2.0 ``` +What the script does: +1. Refreshes auto-generated content via `generate:smart` (database pages, API reference, component pages). +2. Calls `yarn docusaurus docs:version` (or the per-section equivalent) to snapshot the section. +3. Freezes any data-file imports (`@site/static/*.json`, `../../data/*.json`) into a snapshot-local `_versioned_data/` dir so the historical version doesn't silently mutate when the source files change. +4. Adjusts relative import paths (`../../src/...` → `../../../src/...`) for files now one directory deeper. +5. Updates `versions-config.json` and `
_versions.json`. + **Do NOT use** the native Docusaurus commands directly (`yarn docusaurus docs:version`), as they will: - ❌ Create version files but NOT update `versions-config.json` +- ❌ Skip auto-gen refresh, freezing whatever was on disk +- ❌ Skip data-import freezing, leaving the snapshot pointed at live data - ❌ Cause versions to not appear in dropdown menus - ❌ Require manual fixes to synchronize the configuration @@ -91,8 +113,11 @@ If creating versions manually, you'll need to: # Main Documentation yarn version:remove:docs 1.0.0 -# Developer Portal -yarn version:remove:developer_portal 1.0.0 +# Admin Docs +yarn version:remove:admin_docs 1.0.0 + +# Developer Docs +yarn version:remove:developer_docs 1.0.0 # Component Playground yarn version:remove:components 1.0.0 @@ -103,17 +128,20 @@ To manually remove a version: 1. **Delete the version folder** from the appropriate location: - Main docs: `versioned_docs/version-X.X.X/` (no prefix for main) - - Developer Portal: `developer_portal_versioned_docs/version-X.X.X/` + - Admin Docs: `admin_docs_versioned_docs/version-X.X.X/` + - Developer Docs: `developer_docs_versioned_docs/version-X.X.X/` - Components: `components_versioned_docs/version-X.X.X/` 2. **Delete the version metadata file**: - Main docs: `versioned_sidebars/version-X.X.X-sidebars.json` (no prefix) - - Developer Portal: `developer_portal_versioned_sidebars/version-X.X.X-sidebars.json` + - Admin Docs: `admin_docs_versioned_sidebars/version-X.X.X-sidebars.json` + - Developer Docs: `developer_docs_versioned_sidebars/version-X.X.X-sidebars.json` - Components: `components_versioned_sidebars/version-X.X.X-sidebars.json` 3. **Update the versions list file**: - Main docs: `versions.json` - - Developer Portal: `developer_portal_versions.json` + - Admin Docs: `admin_docs_versions.json` + - Developer Docs: `developer_docs_versions.json` - Components: `components_versions.json` 4. **Update configuration**: @@ -145,12 +173,12 @@ docs: { } ``` -#### Developer Portal & Components (custom plugins) +#### Developer Docs & Components (custom plugins) ```typescript { - id: 'developer_portal', - path: 'developer_portal', - routeBasePath: 'developer_portal', + id: 'developer_docs', + path: 'developer_docs', + routeBasePath: 'developer-docs', includeCurrentVersion: true, lastVersion: '1.1.0', // Default version onlyIncludeVersions: ['current', '1.1.0', '1.0.0'], @@ -194,7 +222,7 @@ For other issues: #### Broken Links in Versioned Documentation When creating a new version, links in the documentation are preserved as-is. Common issues: -- **Cross-section links**: Links between sections (e.g., from developer_portal to docs) need to be version-aware +- **Cross-section links**: Links between sections (e.g., from developer_docs to docs) need to be version-aware - **Absolute vs relative paths**: Use relative paths within the same section - **Version-specific URLs**: Update hardcoded URLs to use version variables diff --git a/docs/components/versions.json b/docs/components/versions.json deleted file mode 100644 index fe51488c706..00000000000 --- a/docs/components/versions.json +++ /dev/null @@ -1 +0,0 @@ -[] diff --git a/docs/developer_docs/versions.json b/docs/developer_docs/versions.json deleted file mode 100644 index fe51488c706..00000000000 --- a/docs/developer_docs/versions.json +++ /dev/null @@ -1 +0,0 @@ -[] diff --git a/docs/developer_portal_versions.json b/docs/developer_portal_versions.json deleted file mode 100644 index fe51488c706..00000000000 --- a/docs/developer_portal_versions.json +++ /dev/null @@ -1 +0,0 @@ -[] diff --git a/docs/package.json b/docs/package.json index 4d4836958cc..af522416ebe 100644 --- a/docs/package.json +++ b/docs/package.json @@ -33,10 +33,12 @@ "version:add": "node scripts/manage-versions.mjs add", "version:remove": "node scripts/manage-versions.mjs remove", "version:add:docs": "node scripts/manage-versions.mjs add docs", - "version:add:developer_portal": "node scripts/manage-versions.mjs add developer_portal", + "version:add:admin_docs": "node scripts/manage-versions.mjs add admin_docs", + "version:add:developer_docs": "node scripts/manage-versions.mjs add developer_docs", "version:add:components": "node scripts/manage-versions.mjs add components", "version:remove:docs": "node scripts/manage-versions.mjs remove docs", - "version:remove:developer_portal": "node scripts/manage-versions.mjs remove developer_portal", + "version:remove:admin_docs": "node scripts/manage-versions.mjs remove admin_docs", + "version:remove:developer_docs": "node scripts/manage-versions.mjs remove developer_docs", "version:remove:components": "node scripts/manage-versions.mjs remove components" }, "dependencies": { diff --git a/docs/scripts/manage-versions.mjs b/docs/scripts/manage-versions.mjs index d96dfc355a9..2318344157c 100644 --- a/docs/scripts/manage-versions.mjs +++ b/docs/scripts/manage-versions.mjs @@ -30,9 +30,11 @@ const __dirname = path.dirname(__filename); const CONFIG_FILE = path.join(__dirname, '..', 'versions-config.json'); // Parse command line arguments -const args = process.argv.slice(2); +const rawArgs = process.argv.slice(2); +const skipGenerate = rawArgs.includes('--skip-generate'); +const args = rawArgs.filter((a) => a !== '--skip-generate'); const command = args[0]; // 'add' or 'remove' -const section = args[1]; // 'docs', 'developer_portal', or 'components' +const section = args[1]; // 'docs', 'admin_docs', 'developer_docs', or 'components' const version = args[2]; // version string like '1.2.0' function loadConfig() { @@ -43,36 +45,158 @@ function saveConfig(config) { fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2) + '\n'); } -function fixVersionedImports(version) { - const versionedDocsPath = path.join(__dirname, '..', 'versioned_docs', `version-${version}`); +function freezeDataImports(section, version) { + // MDX files can `import` JSON/YAML data from outside the section, either + // via escaping relative paths (e.g. country-map-tools.mdx imports + // `../../data/countries.json`) or via the `@site/` alias (e.g. + // feature-flags.mdx imports `@site/static/feature-flags.json`). Without + // intervention the snapshot keeps reading the live file, so the + // historical version's content silently changes whenever the data file + // is updated. Copy each escaping data import into a snapshot-local + // `_versioned_data/` dir and rewrite the import to point there. + const sectionRoot = section === 'docs' + ? path.join(__dirname, '..', 'docs') + : path.join(__dirname, '..', section); + const docsRoot = path.join(__dirname, '..'); + const versionedDocsDir = section === 'docs' + ? `versioned_docs/version-${version}` + : `${section}_versioned_docs/version-${version}`; + const versionedDocsPath = path.join(__dirname, '..', versionedDocsDir); + const frozenDataDir = path.join(versionedDocsPath, '_versioned_data'); - // Files that need import path fixes - const filesToFix = [ - 'contributing/resources.mdx', - 'configuration/country-map-tools.mdx' - ]; + if (!fs.existsSync(versionedDocsPath)) { + return; + } - console.log(` Fixing relative imports in versioned docs...`); + console.log(` Freezing data imports in ${versionedDocsDir}...`); - filesToFix.forEach(filePath => { - const fullPath = path.join(versionedDocsPath, filePath); - if (fs.existsSync(fullPath)) { - let content = fs.readFileSync(fullPath, 'utf8'); + // Matches data file imports in two flavors: + // `from '../../foo/bar.json'` (relative, must escape one or more dirs) + // `from '@site/static/foo.json'` (Docusaurus site-root alias) + const dataImportRe = /(from\s+['"])((?:\.\.\/)+|@site\/)([^'"\s]+\.(?:json|ya?ml))(['"])/g; - // Fix imports that go up two directories to go up three instead - content = content.replace( - /from ['"]\.\.\/\.\.\/src\//g, - "from '../../../src/" - ); - content = content.replace( - /from ['"]\.\.\/\.\.\/data\//g, - "from '../../../data/" - ); - - fs.writeFileSync(fullPath, content); - console.log(` Fixed imports in ${filePath}`); + function freezeOne(fullPath, depth, prefix, pathSpec, importPath, suffix) { + let resolvedSource; + if (pathSpec === '@site/') { + // `@site/...` always resolves relative to the docs root. + resolvedSource = path.join(docsRoot, importPath); + } else { + // Relative path — must escape the file's depth within the section + // to point at content outside the section. Imports that stay inside + // are copied wholesale by Docusaurus, so we leave them alone. + const upCount = pathSpec.match(/\.\.\//g).length; + if (upCount <= depth) return null; + const relativeFromVersioned = path.relative(versionedDocsPath, fullPath); + const originalDir = path.dirname(path.join(sectionRoot, relativeFromVersioned)); + resolvedSource = path.resolve(originalDir, pathSpec + importPath); } - }); + // Skip imports that land inside the section root — those get copied + // with the section snapshot already. + const relFromSection = path.relative(sectionRoot, resolvedSource); + if (!relFromSection.startsWith('..')) return null; + const relFromDocsRoot = path.relative(docsRoot, resolvedSource); + if (relFromDocsRoot.startsWith('..') || !fs.existsSync(resolvedSource)) { + return null; + } + const destPath = path.join(frozenDataDir, relFromDocsRoot); + fs.mkdirSync(path.dirname(destPath), { recursive: true }); + fs.copyFileSync(resolvedSource, destPath); + const rewritten = path + .relative(path.dirname(fullPath), destPath) + .split(path.sep) + .join('/'); + const finalImport = rewritten.startsWith('.') ? rewritten : `./${rewritten}`; + return `${prefix}${finalImport}${suffix}`; + } + + function walk(dir, depth) { + for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { + const fullPath = path.join(dir, entry.name); + if (entry.isDirectory()) { + if (entry.name.startsWith('_')) continue; + walk(fullPath, depth + 1); + } else if (entry.isFile() && /\.(md|mdx)$/.test(entry.name)) { + const original = fs.readFileSync(fullPath, 'utf8'); + let inFence = false; + let mutated = false; + const updated = original.split('\n').map(line => { + if (/^\s*(```|~~~)/.test(line)) { + inFence = !inFence; + return line; + } + if (inFence) return line; + return line.replace(dataImportRe, (match, prefix, pathSpec, importPath, suffix) => { + const rewritten = freezeOne(fullPath, depth, prefix, pathSpec, importPath, suffix); + if (rewritten === null) return match; + mutated = true; + return rewritten; + }); + }).join('\n'); + if (mutated) { + fs.writeFileSync(fullPath, updated); + const rel = path.relative(versionedDocsPath, fullPath); + console.log(` Froze data imports in ${rel}`); + } + } + } + } + + walk(versionedDocsPath, 0); +} + +function fixVersionedImports(section, version) { + // Versioned content lands one directory deeper than the source content, + // so any `../../src/` or `../../data/` imports in .md/.mdx files need + // an extra `../` to keep reaching docs/src and docs/data. + const versionedDocsDir = section === 'docs' + ? `versioned_docs/version-${version}` + : `${section}_versioned_docs/version-${version}`; + const versionedDocsPath = path.join(__dirname, '..', versionedDocsDir); + + if (!fs.existsSync(versionedDocsPath)) { + return; + } + + console.log(` Fixing relative imports in ${versionedDocsDir}...`); + + // Imports whose `../` count exceeds the file's depth within the section + // escape the section root, so they need one extra `../` once the file + // lives one level deeper inside the snapshot dir. Imports that stay + // inside the section are unaffected (the section copies wholesale). + function walk(dir, depth) { + for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { + const fullPath = path.join(dir, entry.name); + if (entry.isDirectory()) { + walk(fullPath, depth + 1); + } else if (entry.isFile() && /\.(md|mdx)$/.test(entry.name)) { + const original = fs.readFileSync(fullPath, 'utf8'); + // Track fenced code blocks so we don't rewrite import samples inside + // ```ts / ```js (etc.) blocks that are documentation, not real imports. + let inFence = false; + const updated = original.split('\n').map(line => { + if (/^\s*(```|~~~)/.test(line)) { + inFence = !inFence; + return line; + } + if (inFence) return line; + return line.replace( + /(from\s+['"])((?:\.\.\/)+)/g, + (match, prefix, dots) => { + const upCount = dots.match(/\.\.\//g).length; + return upCount > depth ? `${prefix}../${dots}` : match; + }, + ); + }).join('\n'); + if (updated !== original) { + fs.writeFileSync(fullPath, updated); + const rel = path.relative(versionedDocsPath, fullPath); + console.log(` Fixed imports in ${rel}`); + } + } + } + } + + walk(versionedDocsPath, 0); } function addVersion(section, version) { @@ -91,6 +215,28 @@ function addVersion(section, version) { console.log(`Creating version ${version} for ${section}...`); + // Refresh auto-generated content (database pages, API reference, + // component playground) so the snapshot captures the current state of + // master rather than whatever happened to be on disk. `generate:smart` + // hashes its inputs and skips unchanged generators, so this is cheap + // when the dev already has fresh output. + // + // Use --skip-generate if you've placed a CI-artifact databases.json + // (the `database-diagnostics` artifact from Python-Integration) and + // want to preserve it instead of letting the local env regenerate it. + // See docs/README.md "Before You Cut" for the canonical release flow. + if (skipGenerate) { + console.log(` Skipping auto-gen refresh (--skip-generate set)`); + } else { + console.log(` Refreshing auto-generated docs...`); + try { + execSync('yarn run generate:smart', { stdio: 'inherit' }); + } catch (error) { + console.error(`Failed to refresh auto-generated docs: ${error.message}`); + process.exit(1); + } + } + // Run Docusaurus version command const docusaurusCommand = section === 'docs' ? `yarn docusaurus docs:version ${version}` @@ -103,10 +249,12 @@ function addVersion(section, version) { process.exit(1); } - // Fix relative imports in versioned docs (for main docs section only) - if (section === 'docs') { - fixVersionedImports(version); - } + // Freeze data imports BEFORE adjusting paths, so the depth-aware rewriter + // doesn't process the now-local imports we just rewrote. + freezeDataImports(section, version); + + // Fix relative imports in versioned content + fixVersionedImports(section, version); // Update config // Add to onlyIncludeVersions array (after 'current') @@ -121,10 +269,15 @@ function addVersion(section, version) { banner: 'none' }; - // Optionally update lastVersion if this is the first non-current version - if (config[section].onlyIncludeVersions.length === 2) { - config[section].lastVersion = version; - } + // Note: we deliberately do NOT auto-bump `lastVersion` to the new + // version. Superset's docs site keeps `lastVersion: 'current'` so + // the canonical URLs (`/user-docs/...`, `/admin-docs/...`, + // `/developer-docs/...`, `/components/...`) always render master + // content; cut versions are accessed only via their explicit version + // segment. (`/docs/...` paths are legacy and handled via per-page + // redirects in docusaurus.config.ts — not a current canonical + // form.) If you want a different policy, edit versions-config.json + // after cutting. saveConfig(config); console.log(`✅ Version ${version} added successfully to ${section}`); @@ -185,8 +338,17 @@ function removeVersion(section, version) { const versionIndex = versions.indexOf(version); if (versionIndex > -1) { versions.splice(versionIndex, 1); - fs.writeFileSync(versionsJsonPath, JSON.stringify(versions, null, 2) + '\n'); - console.log(` Updated ${versionsJsonFile}`); + if (versions.length === 0) { + // Sections with no versions shouldn't carry an empty versions file + // on disk — Docusaurus doesn't require it, and an empty `[]` file + // gets picked up by `docusaurus version` and snapshotted into the + // next cut. + fs.unlinkSync(versionsJsonPath); + console.log(` Removed empty ${versionsJsonFile}`); + } else { + fs.writeFileSync(versionsJsonPath, JSON.stringify(versions, null, 2) + '\n'); + console.log(` Updated ${versionsJsonFile}`); + } } } @@ -211,17 +373,20 @@ function removeVersion(section, version) { function printUsage() { console.log(` Usage: - node scripts/manage-versions.js add
- node scripts/manage-versions.js remove
+ node scripts/manage-versions.mjs add
[--skip-generate] + node scripts/manage-versions.mjs remove
Where: - - section: 'docs', 'developer_portal', or 'components' + - section: 'docs', 'developer_docs', 'admin_docs', or 'components' - version: version string (e.g., '1.2.0', '2.0.0') + - --skip-generate: skip refreshing auto-generated docs before snapshotting + (use when you've already placed a fresh databases.json + from CI and want to preserve it) Examples: - node scripts/manage-versions.js add docs 2.0.0 - node scripts/manage-versions.js add developer_portal 1.3.0 - node scripts/manage-versions.js remove components 1.0.0 + node scripts/manage-versions.mjs add docs 2.0.0 + node scripts/manage-versions.mjs add developer_docs 1.3.0 + node scripts/manage-versions.mjs remove components 1.0.0 `); } diff --git a/docs/src/theme/DocVersionBadge/index.js b/docs/src/theme/DocVersionBadge/index.js index a76ced7e254..23b87463cb5 100644 --- a/docs/src/theme/DocVersionBadge/index.js +++ b/docs/src/theme/DocVersionBadge/index.js @@ -30,19 +30,30 @@ import { DownOutlined } from '@ant-design/icons'; import styles from './styles.module.css'; +// Map each versioned plugin id to the URL prefix it actually serves +// content from. Three of the four routeBasePath values differ from +// their pluginId — the default preset-classic docs plugin lives at +// `/user-docs`, and admin_docs / developer_docs use hyphens in their +// URLs even though the plugin ids use underscores. Without this map +// the basePath derivation below would mis-split the pathname for +// those sections and the version dropdown would jump to the section +// root instead of preserving the current page. +// +// Keep in sync with the `routeBasePath` values in docusaurus.config.ts. +const PLUGIN_ID_TO_BASE_PATH = { + default: '/user-docs', + components: '/components', + admin_docs: '/admin-docs', + developer_docs: '/developer-docs', +}; + export default function DocVersionBadge() { const activePlugin = useActivePlugin(); const { pathname } = useLocation(); const pluginId = activePlugin?.pluginId; const [versionedPath, setVersionedPath] = React.useState(''); - // Show version selector for all versioned sections - const isVersioned = [ - 'default', // main docs - 'components', - 'tutorials', - 'developer_portal', - ].includes(pluginId); + const isVersioned = pluginId && pluginId in PLUGIN_ID_TO_BASE_PATH; const { preferredVersion } = useDocsPreferredVersion(pluginId); const versions = useVersions(pluginId); @@ -53,7 +64,8 @@ export default function DocVersionBadge() { if (!pathname || !version || !pluginId) return; let relativePath = ''; - const basePath = pluginId === 'default' ? '/docs' : `/${pluginId}`; + const basePath = PLUGIN_ID_TO_BASE_PATH[pluginId]; + if (!basePath) return; // Handle different version path patterns if (pathname.includes(basePath)) { diff --git a/docs/src/theme/DocVersionBanner/index.js b/docs/src/theme/DocVersionBanner/index.js deleted file mode 100644 index 3704128bedc..00000000000 --- a/docs/src/theme/DocVersionBanner/index.js +++ /dev/null @@ -1,121 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import React, { useState, useEffect } from 'react'; -import DocVersionBanner from '@theme-original/DocVersionBanner'; -import { - useActivePlugin, - useDocsVersion, - useVersions, -} from '@docusaurus/plugin-content-docs/client'; -import { useLocation } from '@docusaurus/router'; -import { useDocsPreferredVersion } from '@docusaurus/theme-common'; -import { Dropdown } from 'antd'; -import { DownOutlined } from '@ant-design/icons'; - -import styles from './styles.module.css'; - -export default function DocVersionBannerWrapper(props) { - const activePlugin = useActivePlugin(); - const { pathname } = useLocation(); - const pluginId = activePlugin?.pluginId; - const [versionedPath, setVersionedPath] = useState(''); - - // Only show version selector for tutorials - // Main docs, components, and developer_portal use the DocVersionBadge component instead - const isVersioned = pluginId && ['tutorials'].includes(pluginId); - - const { preferredVersion } = useDocsPreferredVersion(pluginId); - const versions = useVersions(pluginId); - const version = useDocsVersion(); - - // Early return if required data is not available - if (!isVersioned || !versions || !version) { - return ; - } - - // Extract the current page path relative to the version - useEffect(() => { - if (!pathname || !version || !pluginId) return; - - let relativePath = ''; - - // Handle different version path patterns - if (pathname.includes(`/${pluginId}/`)) { - // Extract the part after the version - // Example: /components/1.1.0/ui-components/button -> /ui-components/button - const parts = pathname.split(`/${pluginId}/`); - if (parts.length > 1) { - const afterPluginId = parts[1]; - // Find where the version part ends - const versionParts = afterPluginId.split('/'); - if (versionParts.length > 1) { - // Remove the version part and join the rest - relativePath = '/' + versionParts.slice(1).join('/'); - } - } - } - - setVersionedPath(relativePath); - }, [pathname, version, pluginId]); - - // Create dropdown items for version selection - const items = versions.map(v => { - // Construct the URL for this version, preserving the current page - // v.path is the version-specific path like "1.0.0" or "next" - let versionUrl = v.path; - - if (versionedPath) { - // Construct the full URL with the version and the current page path - versionUrl = v.path + versionedPath; - } - - return { - key: v.name, - label: ( - - {v.label} - {v.name === version.name && ' (current)'} - {v.name === preferredVersion?.name && ' (preferred)'} - - ), - }; - }); - - return ( - <> - - {isVersioned && ( - - )} - - ); -} diff --git a/docs/src/theme/DocVersionBanner/styles.module.css b/docs/src/theme/DocVersionBanner/styles.module.css deleted file mode 100644 index 3f16c162865..00000000000 --- a/docs/src/theme/DocVersionBanner/styles.module.css +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -.versionBanner { - background-color: var(--ifm-color-emphasis-100); - padding: 0.5rem 1rem; - margin-bottom: 1rem; - border-bottom: 1px solid var(--ifm-color-emphasis-200); -} - -.versionContainer { - display: flex; - align-items: center; - max-width: var(--ifm-container-width); - margin: 0 auto; - padding: 0 var(--ifm-spacing-horizontal); -} - -.versionLabel { - font-weight: bold; - margin-right: 0.5rem; -} - -.versionSelector { - cursor: pointer; - color: var(--ifm-color-primary); - font-weight: 500; -} - -.versionSelector:hover { - text-decoration: none; - color: var(--ifm-color-primary-darker); -} diff --git a/docs/tutorials_versions.json b/docs/tutorials_versions.json deleted file mode 100644 index 5e1abcd8a61..00000000000 --- a/docs/tutorials_versions.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - "1.0.0" -]