feat(v2): editUrl function for advanced use-cases (#4121)

* EditUrl function

* normalize blog/docs regarding the editUrl feature + editUrl function

* editUrl fn => always inject posix style relative paths, make tests more reliable
(see also https://github.com/facebook/docusaurus/issues/4124)

* fix editUrl on windows
This commit is contained in:
Sébastien Lorber 2021-01-29 15:35:25 +01:00 committed by GitHub
parent 15c50e2ecb
commit be7b5dca78
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 368 additions and 69 deletions

View file

@ -15,6 +15,7 @@ import {
MetadataOptions,
VersionMetadata,
PluginOptions,
EditUrlFunction,
} from '../types';
import {LoadContext} from '@docusaurus/types';
import {DEFAULT_PLUGIN_ID} from '@docusaurus/core/lib/constants';
@ -285,6 +286,45 @@ describe('simple site', () => {
});
});
test('docs with function editUrl', async () => {
const hardcodedEditUrl = 'hardcoded-edit-url';
const editUrlFunction: EditUrlFunction = jest.fn(() => hardcodedEditUrl);
const {siteDir, context, options, currentVersion} = await loadSite({
options: {
editUrl: editUrlFunction,
},
});
const testUtilsLocal = createTestUtils({
siteDir,
context,
options,
versionMetadata: currentVersion,
});
await testUtilsLocal.testMeta(path.join('foo', 'baz.md'), {
version: 'current',
id: 'foo/baz',
unversionedId: 'foo/baz',
isDocsHomePage: false,
permalink: '/docs/foo/bazSlug.html',
slug: '/foo/bazSlug.html',
title: 'baz',
editUrl: hardcodedEditUrl,
description: 'Images',
});
expect(editUrlFunction).toHaveBeenCalledTimes(1);
expect(editUrlFunction).toHaveBeenCalledWith({
version: 'current',
versionDocsDirPath: 'docs',
docPath: path.posix.join('foo', 'baz.md'),
locale: 'en',
});
});
test('docs with last update time and author', async () => {
const {siteDir, context, options, currentVersion} = await loadSite({
options: {
@ -595,6 +635,47 @@ describe('versioned site', () => {
);
});
test('doc with editUrl function', async () => {
const hardcodedEditUrl = 'hardcoded-edit-url';
const editUrlFunction: EditUrlFunction = jest.fn(() => hardcodedEditUrl);
const {siteDir, context, options, version100} = await loadSite({
options: {
editUrl: editUrlFunction,
},
});
const testUtilsLocal = createTestUtils({
siteDir,
context,
options,
versionMetadata: version100,
});
await testUtilsLocal.testMeta(path.join('hello.md'), {
id: 'version-1.0.0/hello',
unversionedId: 'hello',
isDocsHomePage: false,
permalink: '/docs/1.0.0/hello',
slug: '/hello',
title: 'hello',
description: 'Hello 1.0.0 ! (translated en)',
version: '1.0.0',
source:
'@site/i18n/en/docusaurus-plugin-content-docs/version-1.0.0/hello.md',
editUrl: hardcodedEditUrl,
});
expect(editUrlFunction).toHaveBeenCalledTimes(1);
expect(editUrlFunction).toHaveBeenCalledWith({
version: '1.0.0',
versionDocsDirPath: 'versioned_docs/version-1.0.0',
docPath: path.join('hello.md'),
locale: 'en',
});
});
test('translated doc with editUrl', async () => {
const {siteDir, context, options, version100} = await loadSite({
options: {
@ -657,11 +738,11 @@ describe('versioned site', () => {
});
});
test('translated fr doc with editUrl and editLocalizedDocs=true', async () => {
test('translated fr doc with editUrl and editLocalizedFiles=true', async () => {
const {siteDir, context, options, version100} = await loadSite({
options: {
editUrl: 'https://github.com/facebook/docusaurus/edit/master/website',
editLocalizedDocs: true,
editLocalizedFiles: true,
},
locale: 'fr',
});
@ -689,12 +770,12 @@ describe('versioned site', () => {
});
});
test('translated fr doc with editUrl and editLocalizedDocs=true + editCurrentVersion=true', async () => {
test('translated fr doc with editUrl and editLocalizedFiles=true + editCurrentVersion=true', async () => {
const {siteDir, context, options, version100} = await loadSite({
options: {
editUrl: 'https://github.com/facebook/docusaurus/edit/master/website',
editCurrentVersion: true,
editLocalizedDocs: true,
editLocalizedFiles: true,
},
locale: 'fr',
});

View file

@ -39,7 +39,7 @@ describe('normalizeDocsPluginOptions', () => {
includeCurrentVersion: false,
disableVersioning: true,
editCurrentVersion: true,
editLocalizedDocs: true,
editLocalizedFiles: true,
versions: {
current: {
path: 'next',

View file

@ -13,6 +13,7 @@ import {
getFolderContainingFile,
normalizeUrl,
parseMarkdownString,
posixPath,
} from '@docusaurus/utils';
import {LoadContext} from '@docusaurus/types';
@ -120,14 +121,29 @@ export function processDocMetadata({
const relativeFilePath = path.relative(docsDirPath, filePath);
const isLocalized = docsDirPath === versionMetadata.docsDirPathLocalized;
function getDocEditUrl() {
if (typeof options.editUrl === 'function') {
return options.editUrl({
version: versionMetadata.versionName,
versionDocsDirPath: posixPath(
path.relative(siteDir, versionMetadata.docsDirPath),
),
docPath: posixPath(relativeFilePath),
locale: context.i18n.currentLocale,
});
} else if (typeof options.editUrl === 'string') {
const isLocalized = docsDirPath === versionMetadata.docsDirPathLocalized;
const baseVersionEditUrl =
isLocalized && options.editLocalizedFiles
? versionMetadata.versionEditUrlLocalized
: versionMetadata.versionEditUrl;
return getEditUrl(relativeFilePath, baseVersionEditUrl);
} else {
return undefined;
}
}
const versionEditUrl =
isLocalized && options.editLocalizedDocs
? versionMetadata.versionEditUrlLocalized
: versionMetadata.versionEditUrl;
const docsEditUrl = getEditUrl(relativeFilePath, versionEditUrl);
const docsEditUrl = getDocEditUrl();
const {frontMatter = {}, excerpt} = parseMarkdownString(content);
const {sidebar_label, custom_edit_url} = frontMatter;

View file

@ -38,7 +38,7 @@ export const DEFAULT_OPTIONS: Omit<PluginOptions, 'id'> = {
lastVersion: undefined,
versions: {},
editCurrentVersion: false,
editLocalizedDocs: false,
editLocalizedFiles: false,
};
const VersionOptionsSchema = Joi.object({
@ -52,9 +52,9 @@ const VersionsOptionsSchema = Joi.object()
export const OptionsSchema = Joi.object({
path: Joi.string().default(DEFAULT_OPTIONS.path),
editUrl: URISchema,
editUrl: Joi.alternatives().try(URISchema, Joi.function()),
editCurrentVersion: Joi.boolean().default(DEFAULT_OPTIONS.editCurrentVersion),
editLocalizedDocs: Joi.boolean().default(DEFAULT_OPTIONS.editLocalizedDocs),
editLocalizedFiles: Joi.boolean().default(DEFAULT_OPTIONS.editLocalizedFiles),
routeBasePath: Joi.string()
// '' not allowed, see https://github.com/facebook/docusaurus/issues/3374
// .allow('') ""

View file

@ -31,12 +31,19 @@ export type VersionMetadata = {
routePriority: number | undefined; // -1 for the latest docs
};
export type EditUrlFunction = (editUrlParams: {
version: string;
versionDocsDirPath: string;
docPath: string;
locale: string;
}) => string | undefined;
export type MetadataOptions = {
routeBasePath: string;
homePageId?: string;
editUrl?: string;
editUrl?: string | EditUrlFunction;
editCurrentVersion: boolean;
editLocalizedDocs: boolean;
editLocalizedFiles: boolean;
showLastUpdateTime?: boolean;
showLastUpdateAuthor?: boolean;
};

View file

@ -211,6 +211,12 @@ function getVersionEditUrls({
return undefined;
}
// if the user is using the functional form of editUrl,
// he has total freedom and we can't compute a "version edit url"
if (typeof editUrl === 'function') {
return undefined;
}
const editDirPath = editCurrentVersion ? currentVersionPath : docsDirPath;
const editDirPathLocalized = editCurrentVersion
? getDocsDirPathLocalized({