mirror of
https://github.com/facebook/docusaurus.git
synced 2025-04-28 17:57:48 +02:00
fix: improve sidebar accessibility structure (#8429)
This commit is contained in:
parent
37d8844506
commit
d2884f66ff
9 changed files with 38 additions and 274 deletions
|
@ -24,16 +24,19 @@ function DocSidebarDesktop({path, sidebar, onCollapse, isHidden}: Props) {
|
|||
} = useThemeConfig();
|
||||
|
||||
return (
|
||||
<div
|
||||
<nav
|
||||
className={clsx(
|
||||
styles.sidebar,
|
||||
hideOnScroll && styles.sidebarWithHideableNavbar,
|
||||
isHidden && styles.sidebarHidden,
|
||||
)}>
|
||||
{hideOnScroll && <Logo tabIndex={-1} className={styles.sidebarLogo} />}
|
||||
)}
|
||||
aria-label="docs sidebar">
|
||||
{hideOnScroll && (
|
||||
<Logo tabIndex={-1} className={styles.sidebarLogo} aria-hidden="true" />
|
||||
)}
|
||||
<Content path={path} sidebar={sidebar} />
|
||||
{hideable && <CollapseButton onClick={onCollapse} />}
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -47,7 +47,6 @@
|
|||
"combine-promises": "^1.1.0",
|
||||
"commander": "^5.1.0",
|
||||
"core-js": "^3.31.1",
|
||||
"del": "^6.1.1",
|
||||
"detect-port": "^1.5.1",
|
||||
"escape-html": "^1.0.3",
|
||||
"eta": "^2.2.0",
|
||||
|
|
|
@ -26,6 +26,7 @@ import type {
|
|||
} from '@docusaurus/types';
|
||||
import type {SiteCollectedData} from '../../common';
|
||||
import {BuildCLIOptions} from './build';
|
||||
import clearPath from '../utils/clearPath';
|
||||
|
||||
export type BuildLocaleParams = {
|
||||
siteDir: string;
|
||||
|
@ -77,6 +78,11 @@ export async function buildLocale({
|
|||
props,
|
||||
configureWebpackUtils,
|
||||
}),
|
||||
|
||||
// We also clear website/build dir
|
||||
// returns void, no useful result needed before compilation
|
||||
// See also https://github.com/facebook/docusaurus/pull/11037
|
||||
clearPath(outDir),
|
||||
]),
|
||||
);
|
||||
|
||||
|
|
|
@ -12,13 +12,14 @@ import {
|
|||
DEFAULT_BUILD_DIR_NAME,
|
||||
GENERATED_FILES_DIR_NAME,
|
||||
} from '@docusaurus/utils';
|
||||
import clearPath from './utils/clearPath';
|
||||
|
||||
async function removePath(entry: {path: string; description: string}) {
|
||||
if (!(await fs.pathExists(entry.path))) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await fs.remove(entry.path);
|
||||
await clearPath(entry.path);
|
||||
logger.success`Removed the ${entry.description} at path=${path.relative(
|
||||
process.cwd(),
|
||||
entry.path,
|
||||
|
|
22
packages/docusaurus/src/commands/utils/clearPath.ts
Normal file
22
packages/docusaurus/src/commands/utils/clearPath.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import path from 'path';
|
||||
import {rm} from 'fs/promises';
|
||||
import {PerfLogger} from '@docusaurus/logger';
|
||||
|
||||
/**
|
||||
* @param pathToClear
|
||||
*/
|
||||
export default async function clearPath(pathToClear: string): Promise<void> {
|
||||
return PerfLogger.async(
|
||||
`clearPath ${path.relative(process.cwd(), pathToClear)}`,
|
||||
async () => {
|
||||
await rm(pathToClear, {recursive: true, force: true});
|
||||
},
|
||||
);
|
||||
}
|
|
@ -13,7 +13,6 @@ import HtmlWebpackPlugin from 'html-webpack-plugin';
|
|||
import {getProgressBarPlugin} from '@docusaurus/bundler';
|
||||
import {createBaseConfig} from './base';
|
||||
import ChunkAssetPlugin from './plugins/ChunkAssetPlugin';
|
||||
import CleanWebpackPlugin from './plugins/CleanWebpackPlugin';
|
||||
import ForceTerminatePlugin from './plugins/ForceTerminatePlugin';
|
||||
import {createStaticDirectoriesCopyPlugin} from './plugins/StaticDirectoriesCopyPlugin';
|
||||
import type {
|
||||
|
@ -164,8 +163,6 @@ export async function createBuildClientConfig({
|
|||
{
|
||||
plugins: [
|
||||
new ForceTerminatePlugin(),
|
||||
// Remove/clean build folders before building bundles.
|
||||
new CleanWebpackPlugin({verbose: false}),
|
||||
// Visualize size of webpack output files with an interactive zoomable
|
||||
// tree map.
|
||||
bundleAnalyzer && new BundleAnalyzerPlugin(),
|
||||
|
|
|
@ -1,263 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
* Copyright (c) 2015 John Agan
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
// Forked from https://github.com/johnagan/clean-webpack-plugin
|
||||
// Modified to optimize performance for Docusaurus specific use case
|
||||
// More context: https://github.com/facebook/docusaurus/pull/1839
|
||||
|
||||
import path from 'path';
|
||||
import fs from 'fs-extra';
|
||||
import {sync as delSync} from 'del';
|
||||
import type {Compiler, Stats} from 'webpack';
|
||||
|
||||
export type Options = {
|
||||
/**
|
||||
* Write Logs to Console
|
||||
* (Always enabled when dry is true)
|
||||
*
|
||||
* default: false
|
||||
*/
|
||||
verbose?: boolean;
|
||||
|
||||
/**
|
||||
* Automatically remove all unused webpack assets on rebuild
|
||||
*
|
||||
* default: true
|
||||
*/
|
||||
cleanStaleWebpackAssets?: boolean;
|
||||
|
||||
/**
|
||||
* Do not allow removal of current webpack assets
|
||||
*
|
||||
* default: true
|
||||
*/
|
||||
protectWebpackAssets?: boolean;
|
||||
|
||||
/**
|
||||
* Removes files once prior to Webpack compilation
|
||||
* Not included in rebuilds (watch mode)
|
||||
*
|
||||
* Use !negative patterns to exclude files
|
||||
*
|
||||
* default: ['**\/*']
|
||||
*/
|
||||
cleanOnceBeforeBuildPatterns?: string[];
|
||||
};
|
||||
|
||||
export default class CleanWebpackPlugin {
|
||||
private readonly verbose: boolean;
|
||||
private readonly cleanStaleWebpackAssets: boolean;
|
||||
private readonly protectWebpackAssets: boolean;
|
||||
private readonly cleanOnceBeforeBuildPatterns: string[];
|
||||
private currentAssets: string[];
|
||||
private initialClean: boolean;
|
||||
private outputPath: string;
|
||||
|
||||
constructor(options: Options = {}) {
|
||||
this.verbose = options.verbose === true || false;
|
||||
|
||||
this.cleanStaleWebpackAssets =
|
||||
options.cleanStaleWebpackAssets === true ||
|
||||
options.cleanStaleWebpackAssets === false
|
||||
? options.cleanStaleWebpackAssets
|
||||
: true;
|
||||
|
||||
this.protectWebpackAssets =
|
||||
options.protectWebpackAssets === true ||
|
||||
options.protectWebpackAssets === false
|
||||
? options.protectWebpackAssets
|
||||
: true;
|
||||
|
||||
this.cleanOnceBeforeBuildPatterns = Array.isArray(
|
||||
options.cleanOnceBeforeBuildPatterns,
|
||||
)
|
||||
? options.cleanOnceBeforeBuildPatterns
|
||||
: ['**/*'];
|
||||
|
||||
/**
|
||||
* Store webpack build assets
|
||||
*/
|
||||
this.currentAssets = [];
|
||||
|
||||
/**
|
||||
* Only used with cleanOnceBeforeBuildPatterns
|
||||
*/
|
||||
this.initialClean = false;
|
||||
|
||||
this.outputPath = '';
|
||||
|
||||
this.apply = this.apply.bind(this);
|
||||
this.handleInitial = this.handleInitial.bind(this);
|
||||
this.handleDone = this.handleDone.bind(this);
|
||||
this.removeFiles = this.removeFiles.bind(this);
|
||||
}
|
||||
|
||||
apply(compiler: Compiler): void {
|
||||
if (!compiler.options.output.path) {
|
||||
console.warn(
|
||||
'clean-webpack-plugin: options.output.path not defined. Plugin disabled...',
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.outputPath = compiler.options.output.path;
|
||||
|
||||
const {hooks} = compiler;
|
||||
|
||||
if (this.cleanOnceBeforeBuildPatterns.length !== 0) {
|
||||
hooks.compile.tap('clean-webpack-plugin', () => {
|
||||
this.handleInitial();
|
||||
});
|
||||
}
|
||||
|
||||
hooks.done.tap('clean-webpack-plugin', (stats) => {
|
||||
this.handleDone(stats);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Initially remove files from output directory prior to build.
|
||||
*
|
||||
* Only happens once.
|
||||
*
|
||||
* Warning: It is recommended to initially clean your build directory outside
|
||||
* of webpack to minimize unexpected behavior.
|
||||
*/
|
||||
handleInitial(): void {
|
||||
if (this.initialClean) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
// eslint-disable-next-line no-restricted-properties
|
||||
fs.pathExistsSync(this.outputPath) &&
|
||||
// eslint-disable-next-line no-restricted-properties
|
||||
fs.statSync(this.outputPath).isFile()
|
||||
) {
|
||||
throw new Error(
|
||||
`A file '${this.outputPath}' already exists. Docusaurus needs this directory to save the build output. Either remove/change the file or choose a different build directory via '--out-dir'.`,
|
||||
);
|
||||
}
|
||||
|
||||
this.initialClean = true;
|
||||
|
||||
this.removeFiles(this.cleanOnceBeforeBuildPatterns);
|
||||
}
|
||||
|
||||
handleDone(stats: Stats): void {
|
||||
/**
|
||||
* Do nothing if there is a webpack error
|
||||
*/
|
||||
if (stats.hasErrors()) {
|
||||
if (this.verbose) {
|
||||
console.warn('clean-webpack-plugin: pausing due to webpack errors');
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch Webpack's output asset files
|
||||
*/
|
||||
const statsAssets =
|
||||
stats.toJson({
|
||||
all: false,
|
||||
assets: true,
|
||||
}).assets ?? [];
|
||||
const assets = statsAssets.map((asset: {name: string}) => asset.name);
|
||||
|
||||
/**
|
||||
* Get all files that were in the previous build but not the current
|
||||
*
|
||||
* (relies on del's cwd: outputPath option)
|
||||
*/
|
||||
const staleFiles = this.currentAssets.filter(
|
||||
(previousAsset) => !assets.includes(previousAsset),
|
||||
);
|
||||
|
||||
/**
|
||||
* Save assets for next compilation
|
||||
*/
|
||||
this.currentAssets = assets.sort();
|
||||
|
||||
const removePatterns: string[] = [];
|
||||
|
||||
/**
|
||||
* Remove unused webpack assets
|
||||
*/
|
||||
if (this.cleanStaleWebpackAssets && staleFiles.length !== 0) {
|
||||
removePatterns.push(...staleFiles);
|
||||
}
|
||||
|
||||
if (removePatterns.length !== 0) {
|
||||
this.removeFiles(removePatterns);
|
||||
}
|
||||
}
|
||||
|
||||
removeFiles(patterns: string[]): void {
|
||||
try {
|
||||
const deleted = delSync(patterns, {
|
||||
force: false,
|
||||
// Change context to build directory
|
||||
cwd: this.outputPath,
|
||||
dryRun: false,
|
||||
dot: true,
|
||||
ignore: this.protectWebpackAssets ? this.currentAssets : [],
|
||||
});
|
||||
|
||||
/**
|
||||
* Log if verbose is enabled
|
||||
*/
|
||||
if (this.verbose) {
|
||||
deleted.forEach((file) => {
|
||||
const filename = path.relative(process.cwd(), file);
|
||||
|
||||
/**
|
||||
* Use console.warn over .log
|
||||
* https://github.com/webpack/webpack/issues/1904
|
||||
* https://github.com/johnagan/clean-webpack-plugin/issues/11
|
||||
*/
|
||||
console.warn(`clean-webpack-plugin: removed ${filename}`);
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
const needsForce = (err as Error).message.includes(
|
||||
'Cannot delete files/folders outside the current working directory.',
|
||||
);
|
||||
|
||||
if (needsForce) {
|
||||
const message =
|
||||
'clean-webpack-plugin: Cannot delete files/folders outside the current working directory. Can be overridden with the "dangerouslyAllowCleanPatternsOutsideProject" option.';
|
||||
|
||||
throw new Error(message);
|
||||
}
|
||||
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
# Project Words - DO NOT TOUCH - This is updated through CI
|
||||
abernathyca
|
||||
Adriaan
|
||||
Agan
|
||||
alexbdebrie
|
||||
Alexey
|
||||
algoliasearch
|
||||
|
|
|
@ -7339,7 +7339,7 @@ define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0, de
|
|||
has-property-descriptors "^1.0.0"
|
||||
object-keys "^1.1.1"
|
||||
|
||||
del@^6.0.0, del@^6.1.1:
|
||||
del@^6.0.0:
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/del/-/del-6.1.1.tgz#3b70314f1ec0aa325c6b14eb36b95786671edb7a"
|
||||
integrity sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==
|
||||
|
|
Loading…
Add table
Reference in a new issue