mirror of
https://github.com/facebook/docusaurus.git
synced 2025-06-12 15:52:39 +02:00
feat(v2): docs versioning ❄️🔥 (#1983)
* wip: versioning * wip again * nits lint * refactor metadata code so that we can have inobject properties optimization, fix typing * remove buggy permalink code * modify versioned docs fixture such that foo/baz only exists in v1.0.0 * refactor metadata.ts so that there is less transformon object * more refactoring * reduce test fixtures, refactoring * refactoring readability * finish metadata part * refactor with readdir * first pass of implementation * fix mdx laoder * split generated routes by version for performance & smaller bundle * test data for demo * refactor with set * more tests * typo * fix typo * better temporary ui * stronger typing & docsVersion command * add 100% test coverage for docsVersion command * more test and delete manual docs cut * cut 2.0.0-alpha.35 docs * cut alpha.36 instead * copyright * delete versioned docs * stronger test on metadata * update typo
This commit is contained in:
parent
c413cff212
commit
9829f56b1e
45 changed files with 1852 additions and 395 deletions
134
packages/docusaurus-plugin-content-docs/src/version.ts
Normal file
134
packages/docusaurus-plugin-content-docs/src/version.ts
Normal file
|
@ -0,0 +1,134 @@
|
|||
/**
|
||||
* Copyright (c) 2017-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {
|
||||
getVersionsJSONFile,
|
||||
getVersionedDocsDir,
|
||||
getVersionedSidebarsDir,
|
||||
} from './env';
|
||||
import fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
import {Sidebar, SidebarItemCategory, PathOptions} from './types';
|
||||
import loadSidebars from './sidebars';
|
||||
|
||||
export function docsVersion(
|
||||
version: string | null | undefined,
|
||||
siteDir: string,
|
||||
options: PathOptions,
|
||||
) {
|
||||
if (!version) {
|
||||
throw new Error(
|
||||
'No version tag specified!. Pass the version you wish to create as an argument. Ex: 1.0.0',
|
||||
);
|
||||
}
|
||||
if (version.includes('/') || version.includes('\\')) {
|
||||
throw new Error(
|
||||
`Invalid version tag specified! Do not include slash (/) or (\\). Try something like: 1.0.0`,
|
||||
);
|
||||
}
|
||||
if (version.length > 32) {
|
||||
throw new Error(
|
||||
'Invalid version tag specified! Length must <= 32 characters. Try something like: 1.0.0',
|
||||
);
|
||||
}
|
||||
|
||||
// Since we are going to create `version-${version}` folder, we need to make sure its a valid path name
|
||||
if (/[<>:"\/\\|?*\x00-\x1F]/g.test(version)) {
|
||||
throw new Error(
|
||||
'Invalid version tag specified! Please ensure its a valid pathname too. Try something like: 1.0.0',
|
||||
);
|
||||
}
|
||||
|
||||
if (/^\.\.?$/.test(version)) {
|
||||
throw new Error(
|
||||
'Invalid version tag specified! Do not name your version "." or "..". Try something like: 1.0.0',
|
||||
);
|
||||
}
|
||||
|
||||
// Load existing versions
|
||||
let versions = [];
|
||||
const versionsJSONFile = getVersionsJSONFile(siteDir);
|
||||
if (fs.existsSync(versionsJSONFile)) {
|
||||
versions = JSON.parse(fs.readFileSync(versionsJSONFile, 'utf8'));
|
||||
}
|
||||
|
||||
// Check if version already exist
|
||||
if (versions.includes(version)) {
|
||||
throw new Error(
|
||||
'This version already exists!. Use a version tag that does not already exist.',
|
||||
);
|
||||
}
|
||||
|
||||
const {path: docsPath, sidebarPath} = options;
|
||||
|
||||
// Copy docs files
|
||||
const docsDir = path.join(siteDir, docsPath);
|
||||
if (fs.existsSync(docsDir) && fs.readdirSync(docsDir).length > 0) {
|
||||
const versionedDir = getVersionedDocsDir(siteDir);
|
||||
const newVersionDir = path.join(versionedDir, `version-${version}`);
|
||||
fs.copySync(docsDir, newVersionDir);
|
||||
} else {
|
||||
throw new Error('There is no docs to version !');
|
||||
}
|
||||
|
||||
// Load current sidebar and create a new versioned sidebars file
|
||||
if (fs.existsSync(sidebarPath)) {
|
||||
const loadedSidebars: Sidebar = loadSidebars([sidebarPath]);
|
||||
|
||||
// Transform id in original sidebar to versioned id
|
||||
const normalizeCategory = (
|
||||
category: SidebarItemCategory,
|
||||
): SidebarItemCategory => {
|
||||
const items = category.items.map(item => {
|
||||
switch (item.type) {
|
||||
case 'category':
|
||||
return normalizeCategory(item);
|
||||
case 'ref':
|
||||
case 'doc':
|
||||
return {
|
||||
type: item.type,
|
||||
id: `version-${version}/${item.id}`,
|
||||
};
|
||||
}
|
||||
return item;
|
||||
});
|
||||
return {...category, items};
|
||||
};
|
||||
|
||||
const versionedSidebar: Sidebar = Object.entries(loadedSidebars).reduce(
|
||||
(acc: Sidebar, [sidebarId, sidebarItemCategories]) => {
|
||||
const newVersionedSidebarId = `version-${version}/${sidebarId}`;
|
||||
acc[
|
||||
newVersionedSidebarId
|
||||
] = sidebarItemCategories.map(sidebarItemCategory =>
|
||||
normalizeCategory(sidebarItemCategory),
|
||||
);
|
||||
return acc;
|
||||
},
|
||||
{},
|
||||
);
|
||||
|
||||
const versionedSidebarsDir = getVersionedSidebarsDir(siteDir);
|
||||
const newSidebarFile = path.join(
|
||||
versionedSidebarsDir,
|
||||
`version-${version}-sidebars.json`,
|
||||
);
|
||||
fs.ensureDirSync(path.dirname(newSidebarFile));
|
||||
fs.writeFileSync(
|
||||
newSidebarFile,
|
||||
`${JSON.stringify(versionedSidebar, null, 2)}\n`,
|
||||
'utf8',
|
||||
);
|
||||
}
|
||||
|
||||
// update versions.json file
|
||||
versions.unshift(version);
|
||||
fs.ensureDirSync(path.dirname(versionsJSONFile));
|
||||
fs.writeFileSync(versionsJSONFile, `${JSON.stringify(versions, null, 2)}\n`);
|
||||
|
||||
console.log(`Version ${version} created!`);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue