Skip to content

Commit

Permalink
fix(v2): sitemap plugin should handle siteConfig.trailingSlash automa…
Browse files Browse the repository at this point in the history
…tically (facebook#4950)

* create new @docusaurus/utils-common and move applyTrailingSlash there

* sitemap plugin should handle siteConfig.trailingSlash automatically

* typo
  • Loading branch information
slorber authored Jun 14, 2021
1 parent 4e5f0fe commit aeb8e9d
Show file tree
Hide file tree
Showing 18 changed files with 127 additions and 35 deletions.
2 changes: 1 addition & 1 deletion .husky/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1 @@
_
_
1 change: 1 addition & 0 deletions packages/docusaurus-plugin-sitemap/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand Down
13 changes: 12 additions & 1 deletion packages/docusaurus-plugin-sitemap/src/createSitemap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
}),
Expand Down
8 changes: 7 additions & 1 deletion packages/docusaurus-plugin-sitemap/src/pluginOptionSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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}',
});
3 changes: 3 additions & 0 deletions packages/docusaurus-utils-common/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# `@docusaurus/utils`

Common (Node/Browser) utility functions for Docusaurus packages.
27 changes: 27 additions & 0 deletions packages/docusaurus-utils-common/package.json
Original file line number Diff line number Diff line change
@@ -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"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
8 changes: 8 additions & 0 deletions packages/docusaurus-utils-common/src/index.ts
Original file line number Diff line number Diff line change
@@ -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';
10 changes: 10 additions & 0 deletions packages/docusaurus-utils-common/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"incremental": true,
"tsBuildInfoFile": "./lib/.tsbuildinfo",
"rootDir": "src",
"outDir": "lib",
"noEmitHelpers": false
}
}
28 changes: 19 additions & 9 deletions packages/docusaurus-utils-validation/src/validationUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<T extends {id?: string}>(
schema: Joi.ObjectSchema<T>,
options: Partial<T>,
Expand All @@ -44,9 +53,12 @@ export function normalizePluginOptions<T extends {id?: string}>(
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) {
Expand All @@ -56,6 +68,7 @@ export function normalizePluginOptions<T extends {id?: string}>(
throw error;
}
}

return value;
}

Expand All @@ -68,10 +81,12 @@ export function normalizeThemeConfig<T>(
// 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) {
Expand Down Expand Up @@ -112,6 +127,8 @@ export function validateFrontMatter<T>(
abortEarly: false,
});

printWarning(warning);

if (error) {
const frontMatterString = JSON.stringify(frontMatter, null, 2);
const errorDetails = error.details;
Expand All @@ -132,12 +149,5 @@ export function validateFrontMatter<T>(
throw error;
}

if (warning) {
const warningMessages = warning.details
.map(({message}) => message)
.join('\n');
console.log(chalk.yellow(warningMessages));
}

return value;
}
2 changes: 1 addition & 1 deletion packages/docusaurus-utils/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# `@docusaurus/utils`

Node validation utility functions for Docusaurus packages.
Node utility functions for Docusaurus packages.
8 changes: 5 additions & 3 deletions packages/docusaurus-utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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, '/');
}
Expand Down
1 change: 1 addition & 0 deletions packages/docusaurus/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
2 changes: 1 addition & 1 deletion packages/docusaurus/src/client/exports/Link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
18 changes: 2 additions & 16 deletions packages/docusaurus/src/server/plugins/applyRouteTrailingSlash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down

0 comments on commit aeb8e9d

Please sign in to comment.