From aeb8e9da5158f6406a07098bdb0830ab04265ed8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Lorber?= Date: Mon, 14 Jun 2021 20:04:39 +0200 Subject: [PATCH] fix(v2): sitemap plugin should handle siteConfig.trailingSlash automatically (#4950) * create new @docusaurus/utils-common and move applyTrailingSlash there * sitemap plugin should handle siteConfig.trailingSlash automatically * typo --- .husky/.gitignore | 2 +- .../docusaurus-plugin-sitemap/package.json | 1 + .../src/__tests__/pluginOptionSchema.test.ts | 7 ++++- .../src/createSitemap.ts | 13 ++++++++- .../src/pluginOptionSchema.ts | 8 +++++- packages/docusaurus-utils-common/README.md | 3 ++ packages/docusaurus-utils-common/package.json | 27 ++++++++++++++++++ .../src}/__tests__/applyTrailingSlash.test.ts | 21 ++++++++++++++ .../src}/applyTrailingSlash.tsx | 2 ++ packages/docusaurus-utils-common/src/index.ts | 8 ++++++ .../docusaurus-utils-common/tsconfig.json | 10 +++++++ .../src/validationUtils.ts | 28 +++++++++++++------ packages/docusaurus-utils/README.md | 2 +- packages/docusaurus-utils/src/index.ts | 8 ++++-- packages/docusaurus/package.json | 1 + .../docusaurus/src/client/exports/Link.tsx | 2 +- .../server/plugins/applyRouteTrailingSlash.ts | 18 ++---------- .../__tests__/__snapshots__/base.test.ts.snap | 1 - 18 files changed, 127 insertions(+), 35 deletions(-) create mode 100644 packages/docusaurus-utils-common/README.md create mode 100644 packages/docusaurus-utils-common/package.json rename packages/{docusaurus/src/client/exports => docusaurus-utils-common/src}/__tests__/applyTrailingSlash.test.ts (81%) rename packages/{docusaurus/src/client/exports => docusaurus-utils-common/src}/applyTrailingSlash.tsx (94%) create mode 100644 packages/docusaurus-utils-common/src/index.ts create mode 100644 packages/docusaurus-utils-common/tsconfig.json diff --git a/.husky/.gitignore b/.husky/.gitignore index c9cdc63b0701..31354ec13899 100644 --- a/.husky/.gitignore +++ b/.husky/.gitignore @@ -1 +1 @@ -_ \ No newline at end of file +_ diff --git a/packages/docusaurus-plugin-sitemap/package.json b/packages/docusaurus-plugin-sitemap/package.json index 15921d8e03b1..b7be5318a65a 100644 --- a/packages/docusaurus-plugin-sitemap/package.json +++ b/packages/docusaurus-plugin-sitemap/package.json @@ -20,6 +20,7 @@ "@docusaurus/core": "2.0.0-beta.0", "@docusaurus/types": "2.0.0-beta.0", "@docusaurus/utils": "2.0.0-beta.0", + "@docusaurus/utils-common": "2.0.0-beta.0", "@docusaurus/utils-validation": "2.0.0-beta.0", "fs-extra": "^10.0.0", "sitemap": "^7.0.0", diff --git a/packages/docusaurus-plugin-sitemap/src/__tests__/pluginOptionSchema.test.ts b/packages/docusaurus-plugin-sitemap/src/__tests__/pluginOptionSchema.test.ts index 263faf8fa26b..a7decf8298f3 100644 --- a/packages/docusaurus-plugin-sitemap/src/__tests__/pluginOptionSchema.test.ts +++ b/packages/docusaurus-plugin-sitemap/src/__tests__/pluginOptionSchema.test.ts @@ -30,8 +30,13 @@ describe('normalizeSitemapPluginOptions', () => { priority: 0.9, trailingSlash: false, }; - const {value} = await PluginOptionSchema.validate(userOptions); + const {value, warning} = await PluginOptionSchema.validate(userOptions); expect(value).toEqual(userOptions); + + expect(warning?.details?.length).toEqual(1); + expect(warning?.details[0].message).toMatchInlineSnapshot( + `"Option \\"trailingSlash\\" of the sitemap plugin is deprecated: Please use the new Docusaurus global trailingSlash config instead, and the sitemaps plugin will use it."`, + ); }); test('should reject out-of-range priority inputs', () => { diff --git a/packages/docusaurus-plugin-sitemap/src/createSitemap.ts b/packages/docusaurus-plugin-sitemap/src/createSitemap.ts index 823d8a1ce00e..86a82829732a 100644 --- a/packages/docusaurus-plugin-sitemap/src/createSitemap.ts +++ b/packages/docusaurus-plugin-sitemap/src/createSitemap.ts @@ -9,6 +9,7 @@ import {SitemapStream, streamToPromise} from 'sitemap'; import {PluginOptions} from './types'; import {DocusaurusConfig} from '@docusaurus/types'; import {addTrailingSlash} from '@docusaurus/utils'; +import {applyTrailingSlash} from '@docusaurus/utils-common'; export default async function createSitemap( siteConfig: DocusaurusConfig, @@ -25,11 +26,21 @@ export default async function createSitemap( hostname, }); + function applySitemapTrailingSlash(routePath: string): string { + // kept for retrocompatibility + // TODO remove deprecated trailingSlash option before 2022 + if (options.trailingSlash) { + return addTrailingSlash(routePath); + } else { + return applyTrailingSlash(routePath, trailingSlash); + } + } + routesPaths .filter((route) => !route.endsWith('404.html')) .map((routePath) => sitemapStream.write({ - url: trailingSlash ? addTrailingSlash(routePath) : routePath, + url: applySitemapTrailingSlash(routePath), changefreq, priority, }), diff --git a/packages/docusaurus-plugin-sitemap/src/pluginOptionSchema.ts b/packages/docusaurus-plugin-sitemap/src/pluginOptionSchema.ts index 5ba16df2a6ac..ff407ba1dc32 100644 --- a/packages/docusaurus-plugin-sitemap/src/pluginOptionSchema.ts +++ b/packages/docusaurus-plugin-sitemap/src/pluginOptionSchema.ts @@ -25,5 +25,11 @@ export const PluginOptionSchema = Joi.object({ .valid(...Object.values(EnumChangefreq)) .default(DEFAULT_OPTIONS.changefreq), priority: Joi.number().min(0).max(1).default(DEFAULT_OPTIONS.priority), - trailingSlash: Joi.bool().default(false), + trailingSlash: Joi.bool().default(false).warning('deprecate.error', { + msg: + 'Please use the new Docusaurus global trailingSlash config instead, and the sitemaps plugin will use it.', + }), +}).messages({ + 'deprecate.error': + 'Option {#label} of the sitemap plugin is deprecated: {#msg}', }); diff --git a/packages/docusaurus-utils-common/README.md b/packages/docusaurus-utils-common/README.md new file mode 100644 index 000000000000..9f4a6db4d136 --- /dev/null +++ b/packages/docusaurus-utils-common/README.md @@ -0,0 +1,3 @@ +# `@docusaurus/utils` + +Common (Node/Browser) utility functions for Docusaurus packages. diff --git a/packages/docusaurus-utils-common/package.json b/packages/docusaurus-utils-common/package.json new file mode 100644 index 000000000000..db1ea928ecab --- /dev/null +++ b/packages/docusaurus-utils-common/package.json @@ -0,0 +1,27 @@ +{ + "name": "@docusaurus/utils-common", + "version": "2.0.0-beta.0", + "description": "Common (Node/Browser) utility functions for Docusaurus packages.", + "main": "./lib/index.js", + "types": "./lib/index.d.ts", + "scripts": { + "build": "tsc", + "watch": "tsc --watch" + }, + "publishConfig": { + "access": "public" + }, + "repository": { + "type": "git", + "url": "https://github.com/facebook/docusaurus.git", + "directory": "packages/docusaurus-utils-common" + }, + "license": "MIT", + "dependencies": { + "@docusaurus/types": "2.0.0-beta.0", + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=12.13.0" + } +} diff --git a/packages/docusaurus/src/client/exports/__tests__/applyTrailingSlash.test.ts b/packages/docusaurus-utils-common/src/__tests__/applyTrailingSlash.test.ts similarity index 81% rename from packages/docusaurus/src/client/exports/__tests__/applyTrailingSlash.test.ts rename to packages/docusaurus-utils-common/src/__tests__/applyTrailingSlash.test.ts index 49ea78d2a21b..28e7ddac614f 100644 --- a/packages/docusaurus/src/client/exports/__tests__/applyTrailingSlash.test.ts +++ b/packages/docusaurus-utils-common/src/__tests__/applyTrailingSlash.test.ts @@ -86,4 +86,25 @@ describe('applyTrailingSlash', () => { '/abc/?search#anchor', ); }); + + test('should apply to fully qualified urls', () => { + expect( + applyTrailingSlash('https://xyz.com/abc?search#anchor', true), + ).toEqual('https://xyz.com/abc/?search#anchor'); + expect( + applyTrailingSlash('https://xyz.com/abc?search#anchor', false), + ).toEqual('https://xyz.com/abc?search#anchor'); + expect( + applyTrailingSlash('https://xyz.com/abc?search#anchor', undefined), + ).toEqual('https://xyz.com/abc?search#anchor'); + expect( + applyTrailingSlash('https://xyz.com/abc/?search#anchor', true), + ).toEqual('https://xyz.com/abc/?search#anchor'); + expect( + applyTrailingSlash('https://xyz.com/abc/?search#anchor', false), + ).toEqual('https://xyz.com/abc?search#anchor'); + expect( + applyTrailingSlash('https://xyz.com/abc/?search#anchor', undefined), + ).toEqual('https://xyz.com/abc/?search#anchor'); + }); }); diff --git a/packages/docusaurus/src/client/exports/applyTrailingSlash.tsx b/packages/docusaurus-utils-common/src/applyTrailingSlash.tsx similarity index 94% rename from packages/docusaurus/src/client/exports/applyTrailingSlash.tsx rename to packages/docusaurus-utils-common/src/applyTrailingSlash.tsx index e49c27d0114c..fb3fb9bf854e 100644 --- a/packages/docusaurus/src/client/exports/applyTrailingSlash.tsx +++ b/packages/docusaurus-utils-common/src/applyTrailingSlash.tsx @@ -14,12 +14,14 @@ export default function applyTrailingSlash( return path; } + // TODO deduplicate: also present in @docusaurus/utils function addTrailingSlash(str: string): string { return str.endsWith('/') ? str : `${str}/`; } function removeTrailingSlash(str: string): string { return str.endsWith('/') ? str.slice(0, -1) : str; } + // undefined = legacy retrocompatible behavior if (typeof trailingSlash === 'undefined') { return path; diff --git a/packages/docusaurus-utils-common/src/index.ts b/packages/docusaurus-utils-common/src/index.ts new file mode 100644 index 000000000000..67b2928466b5 --- /dev/null +++ b/packages/docusaurus-utils-common/src/index.ts @@ -0,0 +1,8 @@ +/** + * 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. + */ + +export {default as applyTrailingSlash} from './applyTrailingSlash'; diff --git a/packages/docusaurus-utils-common/tsconfig.json b/packages/docusaurus-utils-common/tsconfig.json new file mode 100644 index 000000000000..3d7f423b9601 --- /dev/null +++ b/packages/docusaurus-utils-common/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "incremental": true, + "tsBuildInfoFile": "./lib/.tsbuildinfo", + "rootDir": "src", + "outDir": "lib", + "noEmitHelpers": false + } +} diff --git a/packages/docusaurus-utils-validation/src/validationUtils.ts b/packages/docusaurus-utils-validation/src/validationUtils.ts index 4ad56e53ab6d..7b20ce7244d1 100644 --- a/packages/docusaurus-utils-validation/src/validationUtils.ts +++ b/packages/docusaurus-utils-validation/src/validationUtils.ts @@ -35,6 +35,15 @@ export const logValidationBugReportHint = (): void => { ); }; +function printWarning(warning?: Joi.ValidationError) { + if (warning) { + const warningMessages = warning.details + .map(({message}) => message) + .join('\n'); + console.log(chalk.yellow(warningMessages)); + } +} + export function normalizePluginOptions( schema: Joi.ObjectSchema, options: Partial, @@ -44,9 +53,12 @@ export function normalizePluginOptions( const finalSchema = schema.append({ id: PluginIdSchema, }); - const {error, value} = finalSchema.validate(options, { + const {error, warning, value} = finalSchema.validate(options, { convert: false, }); + + printWarning(warning); + if (error) { logValidationBugReportHint(); if (isValidationDisabledEscapeHatch) { @@ -56,6 +68,7 @@ export function normalizePluginOptions( throw error; } } + return value; } @@ -68,10 +81,12 @@ export function normalizeThemeConfig( // otherwise one theme would fail validating the data of another theme const finalSchema = schema.unknown(); - const {error, value} = finalSchema.validate(themeConfig, { + const {error, warning, value} = finalSchema.validate(themeConfig, { convert: false, }); + printWarning(warning); + if (error) { logValidationBugReportHint(); if (isValidationDisabledEscapeHatch) { @@ -112,6 +127,8 @@ export function validateFrontMatter( abortEarly: false, }); + printWarning(warning); + if (error) { const frontMatterString = JSON.stringify(frontMatter, null, 2); const errorDetails = error.details; @@ -132,12 +149,5 @@ export function validateFrontMatter( throw error; } - if (warning) { - const warningMessages = warning.details - .map(({message}) => message) - .join('\n'); - console.log(chalk.yellow(warningMessages)); - } - return value; } diff --git a/packages/docusaurus-utils/README.md b/packages/docusaurus-utils/README.md index 7699467d05ff..802548eb3d54 100644 --- a/packages/docusaurus-utils/README.md +++ b/packages/docusaurus-utils/README.md @@ -1,3 +1,3 @@ # `@docusaurus/utils` -Node validation utility functions for Docusaurus packages. +Node utility functions for Docusaurus packages. diff --git a/packages/docusaurus-utils/src/index.ts b/packages/docusaurus-utils/src/index.ts index d04642722e9c..a82682616802 100644 --- a/packages/docusaurus-utils/src/index.ts +++ b/packages/docusaurus-utils/src/index.ts @@ -313,13 +313,15 @@ export function resolvePathname(to: string, from?: string): string { export function addLeadingSlash(str: string): string { return str.startsWith('/') ? str : `/${str}`; } -export function addTrailingSlash(str: string): string { - return str.endsWith('/') ? str : `${str}/`; -} + export function addTrailingPathSeparator(str: string): string { return str.endsWith(path.sep) ? str : `${str}${path.sep}`; } +// TODO deduplicate: also present in @docusaurus/utils-common +export function addTrailingSlash(str: string): string { + return str.endsWith('/') ? str : `${str}/`; +} export function removeTrailingSlash(str: string): string { return removeSuffix(str, '/'); } diff --git a/packages/docusaurus/package.json b/packages/docusaurus/package.json index dbd407fa524a..8aaf9ee259f7 100644 --- a/packages/docusaurus/package.json +++ b/packages/docusaurus/package.json @@ -51,6 +51,7 @@ "@docusaurus/react-loadable": "5.5.0", "@docusaurus/types": "2.0.0-beta.0", "@docusaurus/utils": "2.0.0-beta.0", + "@docusaurus/utils-common": "2.0.0-beta.0", "@docusaurus/utils-validation": "2.0.0-beta.0", "@slorber/static-site-generator-webpack-plugin": "^4.0.0", "@svgr/webpack": "^5.5.0", diff --git a/packages/docusaurus/src/client/exports/Link.tsx b/packages/docusaurus/src/client/exports/Link.tsx index 9fcaa3c5313d..ddf79516c923 100644 --- a/packages/docusaurus/src/client/exports/Link.tsx +++ b/packages/docusaurus/src/client/exports/Link.tsx @@ -13,7 +13,7 @@ import isInternalUrl from './isInternalUrl'; import ExecutionEnvironment from './ExecutionEnvironment'; import {useLinksCollector} from '../LinksCollector'; import {useBaseUrlUtils} from './useBaseUrl'; -import applyTrailingSlash from './applyTrailingSlash'; +import {applyTrailingSlash} from '@docusaurus/utils-common'; import type {LinkProps} from '@docusaurus/Link'; import type docusaurus from '../docusaurus'; diff --git a/packages/docusaurus/src/server/plugins/applyRouteTrailingSlash.ts b/packages/docusaurus/src/server/plugins/applyRouteTrailingSlash.ts index b1b118a5543e..acac5aac53bf 100644 --- a/packages/docusaurus/src/server/plugins/applyRouteTrailingSlash.ts +++ b/packages/docusaurus/src/server/plugins/applyRouteTrailingSlash.ts @@ -6,7 +6,7 @@ */ import {RouteConfig} from '@docusaurus/types'; -import {addTrailingSlash, removeTrailingSlash} from '@docusaurus/utils'; +import {applyTrailingSlash} from '@docusaurus/utils-common'; export default function applyRouteTrailingSlash( route: RouteConfig, @@ -17,23 +17,9 @@ export default function applyRouteTrailingSlash( return route; } - function getNewRoutePath() { - // undefined = legacy retrocompatible behavior - if (typeof trailingSlash === 'undefined') { - return route.path; - } - // The trailing slash should be handled before the ?search#hash ! - // For routing #anchor is normally not possible, but querystring remains possible - const [pathname] = route.path.split(/[#?]/); - const newPathname = trailingSlash - ? addTrailingSlash(pathname) - : removeTrailingSlash(pathname); - return route.path.replace(pathname, newPathname); - } - return { ...route, - path: getNewRoutePath(), + path: applyTrailingSlash(route.path, trailingSlash), ...(route.routes && { routes: route.routes.map((subroute) => applyRouteTrailingSlash(subroute, trailingSlash), diff --git a/packages/docusaurus/src/webpack/__tests__/__snapshots__/base.test.ts.snap b/packages/docusaurus/src/webpack/__tests__/__snapshots__/base.test.ts.snap index 2994ee31f32b..779a2399337f 100644 --- a/packages/docusaurus/src/webpack/__tests__/__snapshots__/base.test.ts.snap +++ b/packages/docusaurus/src/webpack/__tests__/__snapshots__/base.test.ts.snap @@ -10,7 +10,6 @@ Object { "@docusaurus/Link": "../../client/exports/Link.tsx", "@docusaurus/Noop": "../../client/exports/Noop.ts", "@docusaurus/Translate": "../../client/exports/Translate.tsx", - "@docusaurus/applyTrailingSlash": "../../client/exports/applyTrailingSlash.tsx", "@docusaurus/constants": "../../client/exports/constants.ts", "@docusaurus/context": "../../client/exports/context.ts", "@docusaurus/isInternalUrl": "../../client/exports/isInternalUrl.ts",