Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions docs/docs/next/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
id: index
title: Next (Unreleased) Documentation
---

# Next (Unreleased) Documentation

This documentation is for the upcoming release and may change.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
18 changes: 18 additions & 0 deletions docs/docs/v1/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
id: index
title: v1 Documentation
slug: /
sidebar_label: Overview
---

# Zedux v1 Documentation

Welcome to the v1 documentation. This is for the old store-based API. For the new signal-based API, see the [v2 documentation](/docs/v2/).

## Getting Started

The complete v1 documentation starts at [Quick Start](/docs/v1/walkthrough/quick-start).

## Migration Guide

If you're upgrading from v1 to v2, see the [Migration Guide](/docs/v1/migrations/v2).
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
20 changes: 20 additions & 0 deletions docs/docs/v2/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
id: index
title: v2 Documentation
slug: /
sidebar_label: Overview
---

# Zedux v2 Documentation

Welcome to the v2 documentation. This section is being actively written as v2 PRs are merged.

As docs are completed, they will appear in the sidebar on the left.

## Looking for v1 Docs?

The complete v1 documentation is available at [/docs/v1/walkthrough/quick-start](/docs/v1/walkthrough/quick-start).

## Migration Guide

If you're upgrading from v1 to v2, see the [Migration Guide](/docs/v1/migrations/v2).
59 changes: 51 additions & 8 deletions docs/docusaurus.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ module.exports = {
},
items: [
{
to: 'docs/walkthrough/quick-start',
to: 'docs/v1/walkthrough/quick-start',
activeBasePath: 'docs',
label: 'Docs',
position: 'left',
Expand All @@ -78,6 +78,10 @@ module.exports = {
label: 'Blog',
position: 'left',
},
{
type: 'custom-versionSelector',
position: 'right',
},
{
href: 'https://github.com/Omnistac/zedux',
label: 'GitHub',
Expand All @@ -97,11 +101,11 @@ module.exports = {
items: [
{
label: 'Walkthrough',
to: 'docs/walkthrough/quick-start',
to: 'docs/v1/walkthrough/quick-start',
},
{
label: 'API',
to: 'docs/api/api-overview',
to: 'docs/v1/api/api-overview',
},
],
},
Expand Down Expand Up @@ -131,15 +135,54 @@ module.exports = {
copyright: `Copyright © 2017-${new Date().getFullYear()} Omnistac. Built with Docusaurus.`,
},
},
plugins: [PathsPlugin],
plugins: [
PathsPlugin,

// v1 docs (frozen)
[
'@docusaurus/plugin-content-docs',
{
id: 'v1',
path: 'docs/v1',
routeBasePath: 'docs/v1',
sidebarPath: require.resolve('./sidebars-v1.js'),
editUrl: 'https://github.com/Omnistac/zedux/edit/master/docs/docs/v1/',
},
],

// v2 docs (current stable)
[
'@docusaurus/plugin-content-docs',
{
id: 'v2',
path: 'docs/v2',
routeBasePath: 'docs/v2',
sidebarPath: require.resolve('./sidebars-v2.js'),
editUrl: 'https://github.com/Omnistac/zedux/edit/master/docs/docs/v2/',
},
],

// next docs (unreleased/development)
[
'@docusaurus/plugin-content-docs',
{
id: 'next',
path: 'docs/next',
routeBasePath: 'docs/next',
sidebarPath: require.resolve('./sidebars-next.js'),
editUrl: 'https://github.com/Omnistac/zedux/edit/master/docs/docs/next/',
},
],

// Version resolver for unversioned /docs/... URLs
require.resolve('./plugins/docs-version-resolver'),
],
presets: [
[
'@docusaurus/preset-classic',
{
docs: {
sidebarPath: require.resolve('./sidebars.js'),
editUrl: 'https://github.com/Omnistac/zedux/edit/master/docs/',
},
// Docs are handled by the plugins above
docs: false,
theme: {
customCss: require.resolve('./src/css/custom.css'),
},
Expand Down
189 changes: 189 additions & 0 deletions docs/plugins/docs-version-resolver.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
/**
* Docusaurus plugin for versioned documentation URL resolution
*
* This plugin creates routes for unversioned URLs (e.g., /docs/walkthrough/quick-start)
* that redirect to the appropriate versioned content based on:
* 1. Explicit redirects (for restructured content)
* 2. Current version's sidebar (if the doc is "ready")
* 3. Fallback to previous version with stale banner
*/

const { currentVersion, fallbackOrder, redirects } = require('../version-map')

// Import all sidebars
const sidebars = {
v1: require('../sidebars-v1'),
v2: require('../sidebars-v2'),
next: require('../sidebars-next'),
}

/**
* Recursively extract all doc paths from sidebar items
*/
function extractPaths(items) {
const paths = []
for (const item of items) {
if (typeof item === 'string') {
// Simple string reference: 'walkthrough/quick-start'
paths.push(item)
} else if (Array.isArray(item)) {
// Nested array - recurse into it
paths.push(...extractPaths(item))
} else if (item.type === 'category' && item.items) {
// Category with nested items: { type: 'category', label: '...', items: [...] }
paths.push(...extractPaths(item.items))
} else if (item.type === 'doc' && item.id) {
// Explicit doc reference: { type: 'doc', id: 'path' }
paths.push(item.id)
} else if (typeof item === 'object' && item !== null && !item.type) {
// Shorthand category: { Walkthrough: ['quick-start', ...] }
for (const value of Object.values(item)) {
if (Array.isArray(value)) {
paths.push(...extractPaths(value))
}
}
}
// Ignore 'link', 'html', 'ref', etc.
}
return paths
}

/**
* Extract all doc paths from a sidebar config
* Handles nested structures like { react: { About: [...], Walkthrough: [...] } }
*/
function extractSidebarPaths(sidebar) {
const allPaths = []

function processValue(value) {
if (Array.isArray(value)) {
// Array of items - extract doc paths
allPaths.push(...extractPaths(value))
} else if (typeof value === 'object' && value !== null) {
// Nested object like { About: [...], Walkthrough: [...] }
for (const nested of Object.values(value)) {
processValue(nested)
}
}
}

processValue(sidebar)
return new Set(allPaths)
}

// Pre-compute sidebar paths for each version
const sidebarPaths = {
v1: extractSidebarPaths(sidebars.v1),
v2: extractSidebarPaths(sidebars.v2),
next: extractSidebarPaths(sidebars.next),
}

/**
* Determine which version a doc path should resolve to
*/
function resolveVersion(docPath) {
// 1. Check explicit redirects first (for restructured content)
if (redirects[docPath]?.[currentVersion]) {
return {
type: 'redirect',
to: redirects[docPath][currentVersion],
}
}

// 2. If it's in the current version's sidebar → use current (no banner)
if (sidebarPaths[currentVersion].has(docPath)) {
return {
type: 'current',
version: currentVersion,
path: `/docs/${currentVersion}/${docPath}`,
}
}

// 3. Fallback: find the latest version that has it in sidebar
for (const version of fallbackOrder) {
if (version !== currentVersion && sidebarPaths[version].has(docPath)) {
return {
type: 'stale',
version,
path: `/docs/${version}/${docPath}`,
currentVersion,
}
}
}

return { type: 'notfound' }
}

/**
* Docusaurus plugin entry point
*/
module.exports = function docsVersionResolver(context, options) {
return {
name: 'docs-version-resolver',

async contentLoaded({ actions }) {
const { addRoute, createData, setGlobalData } = actions

// Expose version data to client-side components (e.g., VersionSelector)
setGlobalData({
sidebarPaths: Object.fromEntries(
Object.entries(sidebarPaths).map(([v, paths]) => [v, [...paths]])
),
redirects,
currentVersion,
})

// Collect all unique paths across all versions
const allPaths = new Set([
...sidebarPaths.v1,
...sidebarPaths.v2,
...sidebarPaths.next,
])

// Create a route for each path
for (const docPath of allPaths) {
const resolution = resolveVersion(docPath)

// Skip paths that don't resolve to anything
if (resolution.type === 'notfound') {
continue
}

// Create a data module with the resolution info
const dataPath = await createData(
`version-resolution-${docPath.replace(/\//g, '-')}.json`,
JSON.stringify(resolution)
)

// Add the unversioned route
addRoute({
path: `/docs/${docPath}`,
component: '@site/src/components/VersionedDocRedirect',
modules: {
resolution: dataPath,
},
exact: true,
})
}

// Also add a root /docs/ route that redirects to the current version
const rootResolution = await createData(
'version-resolution-root.json',
JSON.stringify({
type: 'current',
version: currentVersion,
path: `/docs/${currentVersion}/`,
})
)

addRoute({
path: '/docs',
component: '@site/src/components/VersionedDocRedirect',
modules: {
resolution: rootResolution,
},
exact: true,
})
},
}
}
18 changes: 18 additions & 0 deletions docs/sidebars-next.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// next (development) sidebar - for unreleased docs
//
// Docs added here live in docs/docs/next/ and are served at /docs/next/
// e.g. docs/docs/next/walkthrough/ecosystems.mdx → /docs/next/walkthrough/ecosystems
//
// To enable the "next" option in the version selector dropdown, uncomment
// the entry in src/theme/NavbarItem/VersionSelector.tsx (not required).
module.exports = {
react: [
'index', // Remove this once we add real docs
// Uncomment and populate sections as we write next docs:
// {
// type: 'category',
// label: 'About',
// items: ['about/introduction'],
// },
],
}
Loading