feat(docs): Docusaurus multi-versioning, Developer Portal starter kit (#34271)

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Evan Rusackas
2025-08-22 09:53:01 -07:00
committed by GitHub
parent 2b2cc96f11
commit 0a45a89786
71 changed files with 16791 additions and 1809 deletions

View File

@@ -0,0 +1,121 @@
/**
* 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 <DocVersionBanner {...props} />;
}
// 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: (
<a href={versionUrl}>
{v.label}
{v.name === version.name && ' (current)'}
{v.name === preferredVersion?.name && ' (preferred)'}
</a>
),
};
});
return (
<>
<DocVersionBanner {...props} />
{isVersioned && (
<div className={styles.versionBanner}>
<div className={styles.versionContainer}>
<span className={styles.versionLabel}>Version:</span>
<Dropdown menu={{ items }} trigger={['click']}>
<a
onClick={e => e.preventDefault()}
className={styles.versionSelector}
>
{version.label} <DownOutlined />
</a>
</Dropdown>
</div>
</div>
)}
</>
);
}

View File

@@ -0,0 +1,49 @@
/**
* 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);
}