feat(v2): docs, make numberPrefixParser configurable, better defaults, minor breaking-changes (#4655)

* make number prefix parsing logic configurable

* Make numberPrefixParser configurable + rename frontmatter + avoid parsing date/version patterns by default

* add more tests

* more test cases
This commit is contained in:
Sébastien Lorber 2021-04-21 12:06:06 +02:00 committed by GitHub
parent d0d29f43cc
commit c04e613ffe
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 325 additions and 82 deletions

View file

@ -781,6 +781,7 @@ Object {
"dirName": ".",
"type": "autogenerated",
},
"numberPrefixParser": [Function],
"version": Object {
"contentPath": "docs",
"versionName": "current",

View file

@ -6,53 +6,114 @@
*/
import {
extractNumberPrefix,
DefaultNumberPrefixParser,
DisabledNumberPrefixParser,
stripNumberPrefix,
stripPathNumberPrefixes,
} from '../numberPrefix';
const BadNumberPrefixPatterns = [
const IgnoredNumberPrefixPatterns = [
// Patterns without number prefix
'MyDoc',
'a1-My Doc',
'My Doc-000',
'My Doc - 1',
'My Doc - 02',
'Hey - 03 - My Doc',
'00abc01-My Doc',
'My 001- Doc',
'My -001 Doc',
// ignore common date-like patterns: https://github.com/facebook/docusaurus/issues/4640
'2021-01-31 - Doc',
'31-01-2021 - Doc',
'2021_01_31 - Doc',
'31_01_2021 - Doc',
'2021.01.31 - Doc',
'31.01.2021 - Doc',
'2021-01 - Doc',
'2021_01 - Doc',
'2021.01 - Doc',
'01-2021 - Doc',
'01_2021 - Doc',
'01.2021 - Doc',
// date patterns without suffix
'2021-01-31',
'2021-01',
'21-01-31',
'21-01',
'2021_01_31',
'2021_01',
'21_01_31',
'21_01',
'01_31',
'01',
'2021',
'01',
// ignore common versioning patterns: https://github.com/facebook/docusaurus/issues/4653
'8.0',
'8.0.0',
'14.2.16',
'18.2',
'8.0 - Doc',
'8.0.0 - Doc',
'8_0',
'8_0_0',
'14_2_16',
'18_2',
'8.0 - Doc',
'8.0.0 - Doc',
];
describe('stripNumberPrefix', () => {
function stripNumberPrefixDefault(str: string) {
return stripNumberPrefix(str, DefaultNumberPrefixParser);
}
test('should strip number prefix if present', () => {
expect(stripNumberPrefix('1-My Doc')).toEqual('My Doc');
expect(stripNumberPrefix('01-My Doc')).toEqual('My Doc');
expect(stripNumberPrefix('001-My Doc')).toEqual('My Doc');
expect(stripNumberPrefix('001 - My Doc')).toEqual('My Doc');
expect(stripNumberPrefix('001 - My Doc')).toEqual('My Doc');
expect(stripNumberPrefix('999 - My Doc')).toEqual('My Doc');
expect(stripNumberPrefixDefault('1-My Doc')).toEqual('My Doc');
expect(stripNumberPrefixDefault('01-My Doc')).toEqual('My Doc');
expect(stripNumberPrefixDefault('001-My Doc')).toEqual('My Doc');
expect(stripNumberPrefixDefault('001 - My Doc')).toEqual('My Doc');
expect(stripNumberPrefixDefault('001 - My Doc')).toEqual('My Doc');
expect(stripNumberPrefixDefault('999 - My Doc')).toEqual(
'My Doc',
);
//
expect(stripNumberPrefix('1---My Doc')).toEqual('My Doc');
expect(stripNumberPrefix('01---My Doc')).toEqual('My Doc');
expect(stripNumberPrefix('001---My Doc')).toEqual('My Doc');
expect(stripNumberPrefix('001 --- My Doc')).toEqual('My Doc');
expect(stripNumberPrefix('001 --- My Doc')).toEqual('My Doc');
expect(stripNumberPrefix('999 --- My Doc')).toEqual('My Doc');
expect(stripNumberPrefixDefault('1---My Doc')).toEqual('My Doc');
expect(stripNumberPrefixDefault('01---My Doc')).toEqual('My Doc');
expect(stripNumberPrefixDefault('001---My Doc')).toEqual('My Doc');
expect(stripNumberPrefixDefault('001 --- My Doc')).toEqual('My Doc');
expect(stripNumberPrefixDefault('001 --- My Doc')).toEqual(
'My Doc',
);
expect(stripNumberPrefixDefault('999 --- My Doc')).toEqual(
'My Doc',
);
//
expect(stripNumberPrefix('1___My Doc')).toEqual('My Doc');
expect(stripNumberPrefix('01___My Doc')).toEqual('My Doc');
expect(stripNumberPrefix('001___My Doc')).toEqual('My Doc');
expect(stripNumberPrefix('001 ___ My Doc')).toEqual('My Doc');
expect(stripNumberPrefix('001 ___ My Doc')).toEqual('My Doc');
expect(stripNumberPrefix('999 ___ My Doc')).toEqual('My Doc');
expect(stripNumberPrefixDefault('1___My Doc')).toEqual('My Doc');
expect(stripNumberPrefixDefault('01___My Doc')).toEqual('My Doc');
expect(stripNumberPrefixDefault('001___My Doc')).toEqual('My Doc');
expect(stripNumberPrefixDefault('001 ___ My Doc')).toEqual('My Doc');
expect(stripNumberPrefixDefault('001 ___ My Doc')).toEqual(
'My Doc',
);
expect(stripNumberPrefixDefault('999 ___ My Doc')).toEqual(
'My Doc',
);
//
expect(stripNumberPrefix('1.My Doc')).toEqual('My Doc');
expect(stripNumberPrefix('01.My Doc')).toEqual('My Doc');
expect(stripNumberPrefix('001.My Doc')).toEqual('My Doc');
expect(stripNumberPrefix('001 . My Doc')).toEqual('My Doc');
expect(stripNumberPrefix('001 . My Doc')).toEqual('My Doc');
expect(stripNumberPrefix('999 . My Doc')).toEqual('My Doc');
expect(stripNumberPrefixDefault('1.My Doc')).toEqual('My Doc');
expect(stripNumberPrefixDefault('01.My Doc')).toEqual('My Doc');
expect(stripNumberPrefixDefault('001.My Doc')).toEqual('My Doc');
expect(stripNumberPrefixDefault('001 . My Doc')).toEqual('My Doc');
expect(stripNumberPrefixDefault('001 . My Doc')).toEqual('My Doc');
expect(stripNumberPrefixDefault('999 . My Doc')).toEqual(
'My Doc',
);
});
test('should not strip number prefix if pattern does not match', () => {
BadNumberPrefixPatterns.forEach((badPattern) => {
expect(stripNumberPrefix(badPattern)).toEqual(badPattern);
IgnoredNumberPrefixPatterns.forEach((badPattern) => {
expect(stripNumberPrefixDefault(badPattern)).toEqual(badPattern);
});
});
});
@ -62,51 +123,74 @@ describe('stripPathNumberPrefix', () => {
expect(
stripPathNumberPrefixes(
'0-MyRootFolder0/1 - MySubFolder1/2. MyDeepFolder2/3 _MyDoc3',
DefaultNumberPrefixParser,
),
).toEqual('MyRootFolder0/MySubFolder1/MyDeepFolder2/MyDoc3');
});
test('should strip number prefixes in paths with custom parser', () => {
function stripPathNumberPrefixCustom(str: string) {
return {
filename: str.substring(1, str.length),
numberPrefix: 0,
};
}
expect(
stripPathNumberPrefixes('aaaa/bbbb/cccc', stripPathNumberPrefixCustom),
).toEqual('aaa/bbb/ccc');
});
test('should strip number prefixes in paths with disabled parser', () => {
expect(
stripPathNumberPrefixes(
'0-MyRootFolder0/1 - MySubFolder1/2. MyDeepFolder2/3 _MyDoc3',
DisabledNumberPrefixParser,
),
).toEqual('0-MyRootFolder0/1 - MySubFolder1/2. MyDeepFolder2/3 _MyDoc3');
});
});
describe('extractNumberPrefix', () => {
describe('DefaultNumberPrefixParser', () => {
test('should extract number prefix if present', () => {
expect(extractNumberPrefix('0-My Doc')).toEqual({
expect(DefaultNumberPrefixParser('0-My Doc')).toEqual({
filename: 'My Doc',
numberPrefix: 0,
});
expect(extractNumberPrefix('1-My Doc')).toEqual({
expect(DefaultNumberPrefixParser('1-My Doc')).toEqual({
filename: 'My Doc',
numberPrefix: 1,
});
expect(extractNumberPrefix('01-My Doc')).toEqual({
expect(DefaultNumberPrefixParser('01-My Doc')).toEqual({
filename: 'My Doc',
numberPrefix: 1,
});
expect(extractNumberPrefix('001-My Doc')).toEqual({
expect(DefaultNumberPrefixParser('001-My Doc')).toEqual({
filename: 'My Doc',
numberPrefix: 1,
});
expect(extractNumberPrefix('001 - My Doc')).toEqual({
expect(DefaultNumberPrefixParser('001 - My Doc')).toEqual({
filename: 'My Doc',
numberPrefix: 1,
});
expect(extractNumberPrefix('001 - My Doc')).toEqual({
expect(DefaultNumberPrefixParser('001 - My Doc')).toEqual({
filename: 'My Doc',
numberPrefix: 1,
});
expect(extractNumberPrefix('999 - My Doc')).toEqual({
expect(DefaultNumberPrefixParser('999 - My Doc')).toEqual({
filename: 'My Doc',
numberPrefix: 999,
});
expect(extractNumberPrefix('0046036 - My Doc')).toEqual({
expect(DefaultNumberPrefixParser('0046036 - My Doc')).toEqual({
filename: 'My Doc',
numberPrefix: 46036,
});
});
test('should not extract number prefix if pattern does not match', () => {
BadNumberPrefixPatterns.forEach((badPattern) => {
expect(extractNumberPrefix(badPattern)).toEqual({
IgnoredNumberPrefixPatterns.forEach((badPattern) => {
expect(DefaultNumberPrefixParser(badPattern)).toEqual({
filename: badPattern,
numberPrefix: undefined,
});

View file

@ -8,6 +8,10 @@
import {OptionsSchema, DEFAULT_OPTIONS} from '../options';
import {normalizePluginOptions} from '@docusaurus/utils-validation';
import {DefaultSidebarItemsGenerator} from '../sidebarItemsGenerator';
import {
DefaultNumberPrefixParser,
DisabledNumberPrefixParser,
} from '../numberPrefix';
// the type of remark/rehype plugins is function
const markdownPluginsFunctionStub = () => {};
@ -28,6 +32,7 @@ describe('normalizeDocsPluginOptions', () => {
include: ['**/*.{md,mdx}'], // Extensions to include.
sidebarPath: 'my-sidebar', // Path to sidebar configuration for showing a list of markdown pages.
sidebarItemsGenerator: DefaultSidebarItemsGenerator,
numberPrefixParser: DefaultNumberPrefixParser,
docLayoutComponent: '@theme/DocPage',
docItemComponent: '@theme/DocItem',
remarkPlugins: [markdownPluginsObjectStub],
@ -84,6 +89,46 @@ describe('normalizeDocsPluginOptions', () => {
expect(error).toBe(undefined);
});
test('should accept numberPrefixParser function', () => {
function customNumberPrefixParser() {}
expect(
normalizePluginOptions(OptionsSchema, {
...DEFAULT_OPTIONS,
numberPrefixParser: customNumberPrefixParser,
}),
).toEqual({
...DEFAULT_OPTIONS,
id: 'default',
numberPrefixParser: customNumberPrefixParser,
});
});
test('should accept numberPrefixParser false', () => {
expect(
normalizePluginOptions(OptionsSchema, {
...DEFAULT_OPTIONS,
numberPrefixParser: false,
}),
).toEqual({
...DEFAULT_OPTIONS,
id: 'default',
numberPrefixParser: DisabledNumberPrefixParser,
});
});
test('should accept numberPrefixParser true', () => {
expect(
normalizePluginOptions(OptionsSchema, {
...DEFAULT_OPTIONS,
numberPrefixParser: true,
}),
).toEqual({
...DEFAULT_OPTIONS,
id: 'default',
numberPrefixParser: DefaultNumberPrefixParser,
});
});
test('should reject admonitions true', async () => {
const admonitionsTrue = {
...DEFAULT_OPTIONS,

View file

@ -12,12 +12,14 @@ import {
import {DefaultCategoryCollapsedValue} from '../sidebars';
import {Sidebar, SidebarItemsGenerator} from '../types';
import fs from 'fs-extra';
import {DefaultNumberPrefixParser} from '../numberPrefix';
describe('DefaultSidebarItemsGenerator', () => {
function testDefaultSidebarItemsGenerator(
options: Partial<Parameters<SidebarItemsGenerator>[0]>,
) {
return DefaultSidebarItemsGenerator({
numberPrefixParser: DefaultNumberPrefixParser,
item: {
type: 'autogenerated',
dirName: '.',
@ -60,6 +62,7 @@ describe('DefaultSidebarItemsGenerator', () => {
test('generates simple flat sidebar', async () => {
const sidebarSlice = await DefaultSidebarItemsGenerator({
numberPrefixParser: DefaultNumberPrefixParser,
item: {
type: 'autogenerated',
dirName: '.',
@ -127,6 +130,7 @@ describe('DefaultSidebarItemsGenerator', () => {
});
const sidebarSlice = await DefaultSidebarItemsGenerator({
numberPrefixParser: DefaultNumberPrefixParser,
item: {
type: 'autogenerated',
dirName: '.',
@ -234,6 +238,7 @@ describe('DefaultSidebarItemsGenerator', () => {
});
const sidebarSlice = await DefaultSidebarItemsGenerator({
numberPrefixParser: DefaultNumberPrefixParser,
item: {
type: 'autogenerated',
dirName: 'subfolder/subsubfolder',