fix(v2): fix recent baseurl issues (#3093)

* try to fix the baseUrl related issues

* fix some newly detected broken links

* fix baseurl and broken link issues

* try to configure netlify to use baseUrl deployment

* add proper netlify settings?

* add proper netlify settings?

* add proper netlify settings?

* test commit

* try to fix the redirects

* cleanup working conf

* minor redirect fix
This commit is contained in:
Sébastien Lorber 2020-07-22 19:55:40 +02:00 committed by GitHub
parent 27f384a67c
commit 811c7ae4e9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 2639 additions and 146 deletions

3
.gitignore vendored
View file

@ -27,3 +27,6 @@ packages/docusaurus-plugin-debug/lib/
packages/docusaurus-plugin-sitemap/lib/
packages/docusaurus-plugin-ideal-image/lib/
packages/docusaurus-theme-classic/lib/
website/netlifyDeploy
_redirects

26
netlify.toml Normal file
View file

@ -0,0 +1,26 @@
# Note: this file's config override the Netlify UI admin config
# default/production build
[build]
base = "/"
command = "yarn netlify:build:production"
publish = "website/build"
# we build deploy previews with a /build/ baseUrl on purpose
# permits to test that baseUrl works fine (this often breaks!)
[context.deploy-preview]
command = "yarn netlify:build:deployPreview"
publish = "website/netlifyDeploy"
# TODO this does not seem to work
# workaroud: a _redirect file is created in website/netlifyDeploy
# can't we have context-based redirects with Netlify? :'(
[[context.deploy-preview.redirects]]
from = "/build/*"
to = "/build/404.html"
status = 200
[[context.deploy-preview.redirects]]
from = "/*"
to = "/build/"

View file

@ -7,20 +7,29 @@
"packages/docusaurus-init/templates/*"
],
"scripts": {
"testBaseUrl": "yarn build:v2:baseUrl && yarn serve:v2:baseUrl",
"start": "yarn build:packages && yarn start:v2",
"start:v1": "yarn workspace docusaurus-1-website start",
"start:v2": "yarn workspace docusaurus-2-website start",
"start:v2:watch": "nodemon --watch \"./packages/*/lib/**/*.*\" --exec \"yarn start:v2\"",
"start:v2:baseUrl": "BASE_URL='/build/' yarn start:v2",
"build": "yarn build:packages && yarn build:v2",
"build:packages": "lerna run build --no-private",
"build:v1": "yarn workspace docusaurus-1-website build",
"build:v2": "yarn workspace docusaurus-2-website build",
"build:v2:baseUrl": "BASE_URL='/build/' yarn build:v2",
"serve:v1": "serve website-1.x/build/docusaurus",
"serve:v2": "serve website/build",
"serve:v2:baseUrl": "serve website",
"serve:v2:ssl": "yarn serve:v2:ssl:gencert && yarn serve:v2:ssl:message && yarn serve:v2:ssl:serve",
"serve:v2:ssl:gencert": "openssl req -x509 -nodes -days 365 -newkey rsa:4096 -subj \"/C=US/ST=Docusaurus/L=Anywhere/O=Dis/CN=localhost\" -keyout ./website/.docusaurus/selfsigned.key -out ./website/.docusaurus/selfsigned.crt",
"serve:v2:ssl:message": "echo '\n\n\nServing Docusaurus with HTTPS on localhost requires to disable the Chrome security: chrome://flags/#allow-insecure-localhost\n\n\n'",
"serve:v2:ssl:serve": "serve website/build --ssl-cert ./website/.docusaurus/selfsigned.crt --ssl-key ./website/.docusaurus/selfsigned.key",
"netlify:build:production": "yarn build:v2",
"netlify:build:deployPreview": "yarn build:v2:baseUrl && yarn netlify:build:deployPreview:moveBuild && yarn netlify:build:deployPreview:redirects",
"netlify:build:deployPreview:moveBuild": "yarn rimraf website/netlifyDeploy && mkdir website/netlifyDeploy && mv website/build website/netlifyDeploy",
"netlify:build:deployPreview:redirects": "echo 'Writing Netlify baseUrl deployPreview _redirects file' && echo '/build/* /build/404.html 200' >> website/netlifyDeploy/_redirects && echo '/* /build/' >> website/netlifyDeploy/_redirects",
"netlify:test": "yarn netlify:build:deployPreview && yarn netlify dev --debug",
"changelog": "lerna-changelog",
"postinstall": "yarn build:packages",
"prettier": "prettier --config .prettierrc --write \"**/*.{js,ts}\"",
@ -37,8 +46,8 @@
"clear": "yarn rimraf website/.docusaurus && rimraf -rf website/node_modules/.cache && yarn lerna exec 'yarn rimraf lib' --ignore docusaurus"
},
"devDependencies": {
"@babel/core": "^7.9.0",
"@babel/cli": "^7.9.0",
"@babel/core": "^7.9.0",
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3",
"@babel/plugin-proposal-optional-chaining": "^7.9.0",
"@babel/preset-typescript": "^7.9.0",
@ -88,6 +97,7 @@
"lerna": "^3.19.0",
"lerna-changelog": "^1.0.1",
"lint-staged": "^10.1.2",
"netlify-cli": "^2.58.0",
"nodemon": "^2.0.4",
"prettier": "^2.0.2",
"react": "^16.8.4",

View file

@ -16,9 +16,9 @@
},
"dependencies": {
"@docusaurus/mdx-loader": "^2.0.0-alpha.58",
"@docusaurus/core": "^2.0.0-alpha.58",
"@docusaurus/types": "^2.0.0-alpha.58",
"@docusaurus/utils": "^2.0.0-alpha.58",
"@docusaurus/core": "2.0.0-alpha.58",
"@hapi/joi": "^17.1.1",
"feed": "^4.1.0",
"fs-extra": "^8.1.0",

View file

@ -19,6 +19,7 @@
},
"dependencies": {
"@docusaurus/mdx-loader": "^2.0.0-alpha.58",
"@docusaurus/core": "^2.0.0-alpha.58",
"@docusaurus/types": "^2.0.0-alpha.58",
"@docusaurus/utils": "^2.0.0-alpha.58",
"execa": "^3.4.0",
@ -33,8 +34,7 @@
"lodash.pickby": "^4.6.0",
"lodash.sortby": "^4.6.0",
"remark-admonitions": "^1.2.1",
"shelljs": "^0.8.4",
"@docusaurus/core": "^2.0.0-alpha.58"
"shelljs": "^0.8.4"
},
"peerDependencies": {
"react": "^16.8.4",

View file

@ -178,7 +178,7 @@ Object {
"pluginName": Object {
"pluginId": Object {
"latestVersionName": null,
"path": "docs",
"path": "/docs",
"versions": Array [
Object {
"docs": Array [
@ -469,7 +469,7 @@ Object {
"pluginName": Object {
"pluginId": Object {
"latestVersionName": "1.0.1",
"path": "docs",
"path": "/docs",
"versions": Array [
Object {
"docs": Array [

View file

@ -20,12 +20,12 @@ describe('docsClientUtils', () => {
test('getActivePlugin', () => {
const data: Record<string, GlobalPluginData> = {
pluginIosId: {
path: 'ios',
path: '/ios',
latestVersionName: 'xyz',
versions: [],
},
pluginAndroidId: {
path: 'android',
path: '/android',
latestVersionName: 'xyz',
versions: [],
},

View file

@ -30,7 +30,7 @@ export const getActivePlugin = (
const activeEntry = Object.entries(allPluginDatas).find(
([_id, pluginData]) => {
return !!matchPath(pathname, {
path: `/${pluginData.path}`,
path: pluginData.path,
exact: false,
strict: false,
});

View file

@ -323,7 +323,7 @@ Available document ids=
const {addRoute, createData, setGlobalData} = actions;
const pluginInstanceGlobalData: GlobalPluginData = {
path: options.path,
path: normalizeUrl([baseUrl, options.path]),
latestVersionName: versioning.latestVersion,
// Initialized empty, will be mutated
versions: [],

View file

@ -24,10 +24,6 @@ export default {
return children;
},
a: (props: ComponentProps<'a'>): JSX.Element => {
if (/\.[^./]+$/.test(props.href || '')) {
// eslint-disable-next-line jsx-a11y/anchor-has-content
return <a {...props} />;
}
return <Link {...props} />;
},
pre: (props: ComponentProps<'div'>): JSX.Element => (

View file

@ -28,10 +28,8 @@ function NavLink({
activeClassName?: string;
prependBaseUrlToHref?: string;
} & ComponentProps<'a'>) {
const toUrl = useBaseUrl(to);
const activeBaseUrl = useBaseUrl(activeBasePath);
const normalizedHref = useBaseUrl(href, {forcePrependBaseUrl: true});
return (
<Link
{...(href
@ -43,7 +41,7 @@ function NavLink({
: {
isNavLink: true,
activeClassName,
to: toUrl,
to,
...(activeBasePath || activeBaseRegex
? {
isActive: (_match, location) =>

View file

@ -11,6 +11,7 @@ import {NavLink, Link as RRLink} from 'react-router-dom';
import isInternalUrl from './isInternalUrl';
import ExecutionEnvironment from './ExecutionEnvironment';
import {useLinksCollector} from '../LinksCollector';
import {useBaseUrlUtils} from './useBaseUrl';
declare global {
interface Window {
@ -21,15 +22,37 @@ declare global {
interface Props {
readonly isNavLink?: boolean;
readonly to?: string;
readonly activeClassName?: string;
readonly href?: string;
readonly activeClassName?: string;
readonly children?: ReactNode;
// escape hatch in case broken links check is annoying for a specific link
readonly 'data-noBrokenLinkCheck'?: boolean;
}
function Link({isNavLink, activeClassName, ...props}: Props): JSX.Element {
function Link({
isNavLink,
to,
href,
activeClassName,
'data-noBrokenLinkCheck': noBrokenLinkCheck,
...props
}: Props): JSX.Element {
const {withBaseUrl} = useBaseUrlUtils();
const linksCollector = useLinksCollector();
const {to, href} = props;
const targetLink = to || href;
// IMPORTANT: using to or href should not change anything
// For example, MDX links will ALWAYS give us the href props
// Using one prop or the other should not be used to distinguish
// internal links (/docs/myDoc) from external links (https://github.com)
const targetLinkUnprefixed = to || href;
// Automatically apply base url in links
const targetLink =
typeof targetLinkUnprefixed !== 'undefined'
? withBaseUrl(targetLinkUnprefixed)
: undefined;
const isInternal = isInternalUrl(targetLink);
const preloaded = useRef(false);
const LinkComponent = isNavLink ? NavLink : RRLink;
@ -89,10 +112,7 @@ function Link({isNavLink, activeClassName, ...props}: Props): JSX.Element {
const isAnchorLink = targetLink?.startsWith('#') ?? false;
const isRegularHtmlLink = !targetLink || !isInternal || isAnchorLink;
if (targetLink && isInternal && !isAnchorLink) {
if (targetLink && targetLink.startsWith('/http')) {
console.log('collectLink', props);
}
if (targetLink && isInternal && !isAnchorLink && !noBrokenLinkCheck) {
linksCollector.collectLink(targetLink);
}

View file

@ -67,6 +67,8 @@ describe('useBaseUrl', () => {
expect(useBaseUrl('/hello/byebye', {absolute: true})).toEqual(
'https://v2.docusaurus.io/docusaurus/hello/byebye',
);
expect(useBaseUrl('/docusaurus/')).toEqual('/docusaurus/');
expect(useBaseUrl('/docusaurus/hello')).toEqual('/docusaurus/hello');
});
});
@ -125,5 +127,7 @@ describe('useBaseUrlUtils().withBaseUrl()', () => {
expect(withBaseUrl('/hello/byebye', {absolute: true})).toEqual(
'https://v2.docusaurus.io/docusaurus/hello/byebye',
);
expect(withBaseUrl('/docusaurus/')).toEqual('/docusaurus/');
expect(withBaseUrl('/docusaurus/hello')).toEqual('/docusaurus/hello');
});
});

View file

@ -6,11 +6,9 @@
*/
import useDocusaurusContext from './useDocusaurusContext';
import isInternalUrl from './isInternalUrl';
import {hasProtocol} from './isInternalUrl';
type BaseUrlOptions = Partial<{
// note: if the url has a protocol, we never prepend it
// (it never makes any sense to do so)
forcePrependBaseUrl: boolean;
absolute: boolean;
}>;
@ -25,7 +23,8 @@ function addBaseUrl(
return url;
}
if (!isInternalUrl(url)) {
// it never makes sense to add a base url to an url with a protocol
if (hasProtocol(url)) {
return url;
}
@ -33,7 +32,11 @@ function addBaseUrl(
return baseUrl + url;
}
const basePath = baseUrl + url.replace(/^\//, '');
// sometimes we try to add baseurl to an url that already has a baseurl
// we should avoid adding the baseurl twice
const shouldAddBaseUrl = !url.startsWith(baseUrl);
const basePath = shouldAddBaseUrl ? baseUrl + url.replace(/^\//, '') : url;
return absolute ? siteUrl + basePath : basePath;
}

View file

@ -39,7 +39,7 @@ export default async function build(
outDir,
generatedFilesDir,
plugins,
siteConfig: {onBrokenLinks},
siteConfig: {baseUrl, onBrokenLinks},
routes,
} = props;
@ -139,7 +139,13 @@ export default async function build(
}),
);
handleBrokenLinks({allCollectedLinks, routes, onBrokenLinks});
await handleBrokenLinks({
allCollectedLinks,
routes,
onBrokenLinks,
outDir,
baseUrl,
});
const relativeDir = path.relative(process.cwd(), outDir);
console.log(

View file

@ -11,5 +11,6 @@ export const CONFIG_FILE_NAME = 'docusaurus.config.js';
export const GENERATED_FILES_DIR_NAME = '.docusaurus';
export const SRC_DIR_NAME = 'src';
export const STATIC_DIR_NAME = 'static';
export const STATIC_ASSETS_DIR_NAME = 'assets'; // webpack file-loader files
export const THEME_PATH = `${SRC_DIR_NAME}/theme`;
export const DEFAULT_PORT = 3000;

View file

@ -5,7 +5,8 @@ exports[`brokenLinks getBrokenLinksErrorMessage 1`] = `
- Page path = /docs/mySourcePage:
-> link to ./myBrokenLink (resolved as: /docs/myBrokenLink)
-> link to ../otherBrokenLink (resolved as: /otherBrokenLink),
-> link to ../otherBrokenLink (resolved as: /otherBrokenLink)
- Page path = /otherSourcePage:
-> link to /badLink

View file

@ -8,8 +8,10 @@
import {matchRoutes, RouteConfig as RRRouteConfig} from 'react-router-config';
import resolvePathname from 'resolve-pathname';
import chalk from 'chalk';
import fs from 'fs-extra';
import {mapValues, pickBy, flatMap} from 'lodash';
import {RouteConfig, OnBrokenLinks} from '@docusaurus/types';
import {removePrefix} from '@docusaurus/utils';
function toReactRouterRoutes(routes: RouteConfig[]): RRRouteConfig[] {
// @ts-expect-error: types incompatible???
@ -107,37 +109,79 @@ export function getBrokenLinksErrorMessage(
return (
`Broken links found!` +
`${Object.entries(allBrokenLinks).map(([pagePath, brokenLinks]) =>
`${Object.entries(allBrokenLinks)
.map(([pagePath, brokenLinks]) =>
pageBrokenLinksMessage(pagePath, brokenLinks),
)}
)
.join('\n')}
`
);
}
export function handleBrokenLinks({
// If a file actually exist on the file system, we know the link is valid
// even if docusaurus does not know about this file, so we don't report it
async function filterExistingFileLinks({
baseUrl,
outDir,
allCollectedLinks,
}: {
baseUrl: string;
outDir: string;
allCollectedLinks: Record<string, string[]>;
}): Promise<Record<string, string[]>> {
// not easy to make this async :'(
function linkFileDoesNotExist(link: string): boolean {
const filePath = `${outDir}/${removePrefix(link, baseUrl)}`;
const exists = fs.existsSync(filePath);
return !exists;
}
return mapValues(allCollectedLinks, (links) => {
return links.filter(linkFileDoesNotExist);
});
}
export async function handleBrokenLinks({
allCollectedLinks,
onBrokenLinks,
routes,
baseUrl,
outDir,
}: {
allCollectedLinks: Record<string, string[]>;
onBrokenLinks: OnBrokenLinks;
routes: RouteConfig[];
baseUrl: string;
outDir: string;
}) {
if (onBrokenLinks === 'ignore') {
return;
}
const allBrokenLinks = getAllBrokenLinks({allCollectedLinks, routes});
// If we link to a file like /myFile.zip, and the file actually exist for the file system
// it is not a broken link, it may simply be a link to an existing static file...
const allCollectedLinksFiltered = await filterExistingFileLinks({
allCollectedLinks,
baseUrl,
outDir,
});
const allBrokenLinks = getAllBrokenLinks({
allCollectedLinks: allCollectedLinksFiltered,
routes,
});
const errorMessage = getBrokenLinksErrorMessage(allBrokenLinks);
if (errorMessage) {
const finalMessage = `${errorMessage}\nNote: it's possible to ignore broken links with the 'onBrokenLinks' Docusaurus configuration.\n\n`;
// Useful to ensure the CI fails in case of broken link
if (onBrokenLinks === 'throw') {
throw new Error(
`${errorMessage}\nNote: it's possible to ignore broken links with the 'onBrokenLinks' Docusaurus configuration.`,
);
throw new Error(finalMessage);
} else if (onBrokenLinks === 'error') {
console.error(chalk.red(errorMessage));
console.error(chalk.red(finalMessage));
} else if (onBrokenLinks === 'log') {
console.log(chalk.blue(errorMessage));
console.log(chalk.blue(finalMessage));
} else {
throw new Error(`unexpected onBrokenLinks value=${onBrokenLinks}`);
}

View file

@ -12,6 +12,7 @@ import webpack, {Configuration, Loader, RuleSetRule, Stats} from 'webpack';
import {TransformOptions} from '@babel/core';
import {ConfigureWebpackFn} from '@docusaurus/types';
import {version as cacheLoaderVersion} from 'cache-loader/package.json';
import {STATIC_ASSETS_DIR_NAME} from '../constants';
// Utility method to get style loaders
export function getStyleLoaders(
@ -174,14 +175,12 @@ export function compile(config: Configuration[]): Promise<void> {
// Inspired by https://github.com/gatsbyjs/gatsby/blob/8e6e021014da310b9cc7d02e58c9b3efe938c665/packages/gatsby/src/utils/webpack-utils.ts#L447
export function getFileLoaderUtils() {
const assetsRelativeRoot = 'assets/';
const loaders = {
file: (options = {}) => {
return {
loader: require.resolve(`file-loader`),
options: {
name: `${assetsRelativeRoot}[name]-[hash].[ext]`,
name: `${STATIC_ASSETS_DIR_NAME}/[name]-[hash].[ext]`,
...options,
},
};
@ -191,7 +190,7 @@ export function getFileLoaderUtils() {
loader: require.resolve(`url-loader`),
options: {
limit: 10000,
name: `${assetsRelativeRoot}[name]-[hash].[ext]`,
name: `${STATIC_ASSETS_DIR_NAME}[name]-[hash].[ext]`,
fallback: require.resolve(`file-loader`),
...options,
},

View file

@ -964,6 +964,7 @@ or
![](./assets/docusaurus-asset-example-banner.png)
```
The ES imports syntax also works:
```mdx

View file

@ -47,4 +47,4 @@ For themes that supports TypeScript theme components, you can add the `--typescr
npm run swizzle @docusaurus/theme-classic Footer --typescript
```
At this moment, the only official Docusaurus theme that supports TypeScript theme components is `@docusaurus/theme-classic`. If you are a Docusaurus theme package author who wants to add TypeScript support, see the [Lifecycle APIs docs](./lifecycle-apis#gettypescriptthemepath).
At this moment, the only official Docusaurus theme that supports TypeScript theme components is `@docusaurus/theme-classic`. If you are a Docusaurus theme package author who wants to add TypeScript support, see the [Lifecycle APIs docs](./lifecycle-apis.md#gettypescriptthemepath).

View file

@ -61,7 +61,7 @@ npm run docusaurus docs:version 1.1.0
When tagging a new version, the document versioning mechanism will:
- Copy the full `docs/` folder contents into a new `versioned_docs/version-<version>/` folder.
- Create a versioned sidebars file based from your current [sidebar](sidebar.md) configuration (if it exists) - saved as `versioned_sidebars/version-<version>-sidebars.json`.
- Create a versioned sidebars file based from your current [sidebar](docs.md#sidebar) configuration (if it exists) - saved as `versioned_sidebars/version-<version>-sidebars.json`.
- Append the new version number to `versions.json`.
## Files

View file

@ -14,12 +14,14 @@ const allDocHomesPaths = [
...versions.slice(1).map((version) => `/docs/${version}/`),
];
const baseUrl = process.env.BASE_URL || '/';
module.exports = {
title: 'Docusaurus',
tagline: 'Build optimized websites quickly, focus on your content',
organizationName: 'facebook',
projectName: 'docusaurus',
baseUrl: '/',
baseUrl,
url: 'https://v2.docusaurus.io',
onBrokenLinks: 'throw',
favicon: 'img/docusaurus.ico',
@ -189,7 +191,7 @@ module.exports = {
activeBaseRegex: `docs/next/(support|team|resources)`,
},
{
to: 'versions',
to: '/versions',
label: 'All versions',
position: 'right',
},

View file

@ -63,7 +63,7 @@ npm run docusaurus docs:version 1.1.0
When tagging a new version, the document versioning mechanism will:
- Copy the full `docs/` folder contents into a new `versioned_docs/version-<version>/` folder.
- Create a versioned sidebars file based from your current [sidebar](sidebar.md) configuration (if it exists). Saved it as `versioned_sidebars/version-<version>-sidebars.json`.
- Create a versioned sidebars file based from your current sidebar configuration (if it exists). Saved it as `versioned_sidebars/version-<version>-sidebars.json`.
- Append the new version number into `versions.json`.
## Files

View file

@ -61,7 +61,7 @@ npm run docusaurus docs:version 1.1.0
When tagging a new version, the document versioning mechanism will:
- Copy the full `docs/` folder contents into a new `versioned_docs/version-<version>/` folder.
- Create a versioned sidebars file based from your current [sidebar](sidebar.md) configuration (if it exists). Saved it as `versioned_sidebars/version-<version>-sidebars.json`.
- Create a versioned sidebars file based from your current [sidebar](docs.md#sidebar) configuration (if it exists). Saved it as `versioned_sidebars/version-<version>-sidebars.json`.
- Append the new version number into `versions.json`.
## Files

View file

@ -61,7 +61,7 @@ npm run docusaurus docs:version 1.1.0
When tagging a new version, the document versioning mechanism will:
- Copy the full `docs/` folder contents into a new `versioned_docs/version-<version>/` folder.
- Create a versioned sidebars file based from your current [sidebar](sidebar.md) configuration (if it exists) - saved as `versioned_sidebars/version-<version>-sidebars.json`.
- Create a versioned sidebars file based from your current [sidebar](docs.md#sidebar) configuration (if it exists) - saved as `versioned_sidebars/version-<version>-sidebars.json`.
- Append the new version number to `versions.json`.
## Files

View file

@ -61,7 +61,7 @@ npm run docusaurus docs:version 1.1.0
When tagging a new version, the document versioning mechanism will:
- Copy the full `docs/` folder contents into a new `versioned_docs/version-<version>/` folder.
- Create a versioned sidebars file based from your current [sidebar](sidebar.md) configuration (if it exists) - saved as `versioned_sidebars/version-<version>-sidebars.json`.
- Create a versioned sidebars file based from your current [sidebar](docs.md#sidebar) configuration (if it exists) - saved as `versioned_sidebars/version-<version>-sidebars.json`.
- Append the new version number to `versions.json`.
## Files

View file

@ -61,7 +61,7 @@ npm run docusaurus docs:version 1.1.0
When tagging a new version, the document versioning mechanism will:
- Copy the full `docs/` folder contents into a new `versioned_docs/version-<version>/` folder.
- Create a versioned sidebars file based from your current [sidebar](sidebar.md) configuration (if it exists) - saved as `versioned_sidebars/version-<version>-sidebars.json`.
- Create a versioned sidebars file based from your current [sidebar](docs.md#sidebar) configuration (if it exists) - saved as `versioned_sidebars/version-<version>-sidebars.json`.
- Append the new version number to `versions.json`.
## Files

View file

@ -61,7 +61,7 @@ npm run docusaurus docs:version 1.1.0
When tagging a new version, the document versioning mechanism will:
- Copy the full `docs/` folder contents into a new `versioned_docs/version-<version>/` folder.
- Create a versioned sidebars file based from your current [sidebar](sidebar.md) configuration (if it exists) - saved as `versioned_sidebars/version-<version>-sidebars.json`.
- Create a versioned sidebars file based from your current [sidebar](docs.md#sidebar) configuration (if it exists) - saved as `versioned_sidebars/version-<version>-sidebars.json`.
- Append the new version number to `versions.json`.
## Files

2557
yarn.lock

File diff suppressed because it is too large Load diff