Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 4 commits into from
Apr 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -781,6 +781,7 @@ Object {
"dirName": ".",
"type": "autogenerated",
},
"numberPrefixParser": [Function],
"version": Object {
"contentPath": "docs",
"versionName": "current",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
});
});
Expand All @@ -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,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 = () => {};
Expand All @@ -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],
Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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: '.',
Expand Down Expand Up @@ -60,6 +62,7 @@ describe('DefaultSidebarItemsGenerator', () => {

test('generates simple flat sidebar', async () => {
const sidebarSlice = await DefaultSidebarItemsGenerator({
numberPrefixParser: DefaultNumberPrefixParser,
item: {
type: 'autogenerated',
dirName: '.',
Expand Down Expand Up @@ -127,6 +130,7 @@ describe('DefaultSidebarItemsGenerator', () => {
});

const sidebarSlice = await DefaultSidebarItemsGenerator({
numberPrefixParser: DefaultNumberPrefixParser,
item: {
type: 'autogenerated',
dirName: '.',
Expand Down Expand Up @@ -234,6 +238,7 @@ describe('DefaultSidebarItemsGenerator', () => {
});

const sidebarSlice = await DefaultSidebarItemsGenerator({
numberPrefixParser: DefaultNumberPrefixParser,
item: {
type: 'autogenerated',
dirName: 'subfolder/subsubfolder',
Expand Down
19 changes: 13 additions & 6 deletions packages/docusaurus-plugin-content-docs/src/docFrontMatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,13 @@ type DocFrontMatter = {
sidebar_label?: string;
sidebar_position?: number;
custom_edit_url?: string;
strip_number_prefixes?: boolean;
parse_number_prefixes?: boolean;
};

// NOTE: we don't add any default value on purpose here
// We don't want default values to magically appear in doc metadatas and props
// While the user did not provide those values explicitly
// We use default values in code instead
const DocFrontMatterSchema = Joi.object<DocFrontMatter>({
id: Joi.string(),
title: Joi.string(),
Expand All @@ -27,11 +31,14 @@ const DocFrontMatterSchema = Joi.object<DocFrontMatter>({
sidebar_label: Joi.string(),
sidebar_position: Joi.number(),
custom_edit_url: Joi.string().allow(null),
strip_number_prefixes: Joi.boolean(),
}).unknown();
parse_number_prefixes: Joi.boolean(),
});

export function assertDocFrontMatter(
export function validateDocFrontMatter(
frontMatter: Record<string, unknown>,
): asserts frontMatter is DocFrontMatter {
Joi.attempt(frontMatter, DocFrontMatterSchema);
): DocFrontMatter {
return Joi.attempt(frontMatter, DocFrontMatterSchema, {
convert: true,
allowUnknown: true,
});
}
Loading