@docusaurus/utils 2.0.0-beta.1 → 2.0.0-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/.tsbuildinfo +1 -1
- package/lib/constants.d.ts +19 -0
- package/lib/constants.js +26 -0
- package/lib/globUtils.d.ts +11 -0
- package/lib/globUtils.js +47 -0
- package/lib/{docuHash.d.ts → hashUtils.d.ts} +2 -0
- package/lib/{docuHash.js → hashUtils.js} +15 -5
- package/lib/index.d.ts +11 -9
- package/lib/index.js +44 -98
- package/lib/markdownLinks.js +19 -6
- package/lib/markdownParser.js +20 -12
- package/lib/mdxUtils.d.ts +16 -0
- package/lib/mdxUtils.js +30 -0
- package/lib/{getFilePathForRoutePath.d.ts → normalizeUrl.d.ts} +1 -1
- package/lib/normalizeUrl.js +66 -0
- package/lib/pathUtils.d.ts +0 -1
- package/lib/pathUtils.js +4 -11
- package/lib/slugger.d.ts +13 -0
- package/lib/slugger.js +18 -0
- package/lib/tags.d.ts +18 -0
- package/lib/tags.js +72 -0
- package/lib/webpackUtils.d.ts +29 -0
- package/lib/webpackUtils.js +109 -0
- package/package.json +23 -7
- package/src/__tests__/globUtils.test.ts +109 -0
- package/src/__tests__/{docuHash.test.ts → hashUtils.test.ts} +22 -1
- package/src/__tests__/index.test.ts +6 -110
- package/src/__tests__/markdownParser.test.ts +15 -2
- package/src/__tests__/mdxUtils.test.ts +133 -0
- package/src/__tests__/normalizeUrl.test.ts +117 -0
- package/src/__tests__/pathUtils.test.ts +5 -22
- package/src/__tests__/slugger.test.ts +27 -0
- package/src/__tests__/tags.test.ts +183 -0
- package/src/__tests__/webpackUtils.test.ts +33 -0
- package/src/constants.ts +38 -0
- package/src/deps.d.ts +14 -0
- package/src/globUtils.ts +63 -0
- package/src/{docuHash.ts → hashUtils.ts} +10 -1
- package/src/index.ts +23 -96
- package/src/markdownLinks.ts +19 -8
- package/src/markdownParser.ts +24 -17
- package/src/mdxUtils.ts +32 -0
- package/src/normalizeUrl.ts +80 -0
- package/src/pathUtils.ts +2 -9
- package/src/slugger.ts +24 -0
- package/src/tags.ts +100 -0
- package/src/webpackUtils.ts +144 -0
- package/lib/codeTranslationsUtils.d.ts +0 -11
- package/lib/codeTranslationsUtils.js +0 -50
- package/lib/getFilePathForRoutePath.js +0 -40
- package/src/__tests__/__fixtures__/defaultCodeTranslations/en.json +0 -4
- package/src/__tests__/__fixtures__/defaultCodeTranslations/fr-FR.json +0 -5
- package/src/__tests__/__fixtures__/defaultCodeTranslations/fr.json +0 -4
- package/src/__tests__/codeTranslationsUtils.test.ts +0 -112
- package/src/__tests__/getFilePathForRoutePath.test.ts +0 -87
- package/src/codeTranslationsUtils.ts +0 -56
- package/src/getFilePathForRoutePath.ts +0 -43
package/lib/tags.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.groupTaggedItems = exports.normalizeFrontMatterTags = exports.normalizeFrontMatterTag = void 0;
|
|
10
|
+
const lodash_1 = require("lodash");
|
|
11
|
+
const normalizeUrl_1 = require("./normalizeUrl");
|
|
12
|
+
function normalizeFrontMatterTag(tagsPath, frontMatterTag) {
|
|
13
|
+
function toTagObject(tagString) {
|
|
14
|
+
return {
|
|
15
|
+
label: tagString,
|
|
16
|
+
permalink: (0, lodash_1.kebabCase)(tagString),
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
// TODO maybe make ensure the permalink is valid url path?
|
|
20
|
+
function normalizeTagPermalink(permalink) {
|
|
21
|
+
// note: we always apply tagsPath on purpose
|
|
22
|
+
// for versioned docs, v1/doc.md and v2/doc.md tags with custom permalinks don't lead to the same created page
|
|
23
|
+
// tagsPath is different for each doc version
|
|
24
|
+
return (0, normalizeUrl_1.normalizeUrl)([tagsPath, permalink]);
|
|
25
|
+
}
|
|
26
|
+
const tag = typeof frontMatterTag === 'string'
|
|
27
|
+
? toTagObject(frontMatterTag)
|
|
28
|
+
: frontMatterTag;
|
|
29
|
+
return {
|
|
30
|
+
label: tag.label,
|
|
31
|
+
permalink: normalizeTagPermalink(tag.permalink),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
exports.normalizeFrontMatterTag = normalizeFrontMatterTag;
|
|
35
|
+
function normalizeFrontMatterTags(tagsPath, frontMatterTags) {
|
|
36
|
+
var _a;
|
|
37
|
+
const tags = (_a = frontMatterTags === null || frontMatterTags === void 0 ? void 0 : frontMatterTags.map((tag) => normalizeFrontMatterTag(tagsPath, tag))) !== null && _a !== void 0 ? _a : [];
|
|
38
|
+
return (0, lodash_1.uniqBy)(tags, (tag) => tag.permalink);
|
|
39
|
+
}
|
|
40
|
+
exports.normalizeFrontMatterTags = normalizeFrontMatterTags;
|
|
41
|
+
// Permits to group docs/blogPosts by tag (provided by FrontMatter)
|
|
42
|
+
// Note: groups are indexed by permalink, because routes must be unique in the end
|
|
43
|
+
// Labels may vary on 2 md files but they are normalized.
|
|
44
|
+
// Docs with label='some label' and label='some-label' should end-up in the same group/page in the end
|
|
45
|
+
// We can't create 2 routes /some-label because one would override the other
|
|
46
|
+
function groupTaggedItems(items, getItemTags) {
|
|
47
|
+
const result = {};
|
|
48
|
+
function handleItemTag(item, tag) {
|
|
49
|
+
var _a;
|
|
50
|
+
// Init missing tag groups
|
|
51
|
+
// TODO: it's not really clear what should be the behavior if 2 items have the same tag but the permalink is different for each
|
|
52
|
+
// For now, the first tag found wins
|
|
53
|
+
result[tag.permalink] = (_a = result[tag.permalink]) !== null && _a !== void 0 ? _a : {
|
|
54
|
+
tag,
|
|
55
|
+
items: [],
|
|
56
|
+
};
|
|
57
|
+
// Add item to group
|
|
58
|
+
result[tag.permalink].items.push(item);
|
|
59
|
+
}
|
|
60
|
+
items.forEach((item) => {
|
|
61
|
+
getItemTags(item).forEach((tag) => {
|
|
62
|
+
handleItemTag(item, tag);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
// If user add twice the same tag to a md doc (weird but possible),
|
|
66
|
+
// we don't want the item to appear twice in the list...
|
|
67
|
+
Object.values(result).forEach((group) => {
|
|
68
|
+
group.items = (0, lodash_1.uniq)(group.items);
|
|
69
|
+
});
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
72
|
+
exports.groupTaggedItems = groupTaggedItems;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import type { RuleSetRule } from 'webpack';
|
|
8
|
+
declare type AssetFolder = 'images' | 'files' | 'fonts' | 'medias';
|
|
9
|
+
declare type FileLoaderUtils = {
|
|
10
|
+
loaders: {
|
|
11
|
+
file: (options: {
|
|
12
|
+
folder: AssetFolder;
|
|
13
|
+
}) => RuleSetRule;
|
|
14
|
+
url: (options: {
|
|
15
|
+
folder: AssetFolder;
|
|
16
|
+
}) => RuleSetRule;
|
|
17
|
+
inlineMarkdownImageFileLoader: string;
|
|
18
|
+
inlineMarkdownLinkFileLoader: string;
|
|
19
|
+
};
|
|
20
|
+
rules: {
|
|
21
|
+
images: () => RuleSetRule;
|
|
22
|
+
fonts: () => RuleSetRule;
|
|
23
|
+
media: () => RuleSetRule;
|
|
24
|
+
svg: () => RuleSetRule;
|
|
25
|
+
otherAssets: () => RuleSetRule;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
export declare function getFileLoaderUtils(): FileLoaderUtils;
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.getFileLoaderUtils = void 0;
|
|
10
|
+
const tslib_1 = require("tslib");
|
|
11
|
+
const path_1 = (0, tslib_1.__importDefault)(require("path"));
|
|
12
|
+
const posixPath_1 = require("./posixPath");
|
|
13
|
+
const constants_1 = require("./constants");
|
|
14
|
+
// Inspired by https://github.com/gatsbyjs/gatsby/blob/8e6e021014da310b9cc7d02e58c9b3efe938c665/packages/gatsby/src/utils/webpack-utils.ts#L447
|
|
15
|
+
function getFileLoaderUtils() {
|
|
16
|
+
// files/images < urlLoaderLimit will be inlined as base64 strings directly in the html
|
|
17
|
+
const urlLoaderLimit = constants_1.WEBPACK_URL_LOADER_LIMIT;
|
|
18
|
+
// defines the path/pattern of the assets handled by webpack
|
|
19
|
+
const fileLoaderFileName = (folder) => `${constants_1.OUTPUT_STATIC_ASSETS_DIR_NAME}/${folder}/[name]-[hash].[ext]`;
|
|
20
|
+
const loaders = {
|
|
21
|
+
file: (options) => ({
|
|
22
|
+
loader: require.resolve(`file-loader`),
|
|
23
|
+
options: {
|
|
24
|
+
name: fileLoaderFileName(options.folder),
|
|
25
|
+
},
|
|
26
|
+
}),
|
|
27
|
+
url: (options) => ({
|
|
28
|
+
loader: require.resolve('url-loader'),
|
|
29
|
+
options: {
|
|
30
|
+
limit: urlLoaderLimit,
|
|
31
|
+
name: fileLoaderFileName(options.folder),
|
|
32
|
+
fallback: require.resolve('file-loader'),
|
|
33
|
+
},
|
|
34
|
+
}),
|
|
35
|
+
// TODO find a better solution to avoid conflicts with the ideal-image plugin
|
|
36
|
+
// TODO this may require a little breaking change for ideal-image users?
|
|
37
|
+
// Maybe with the ideal image plugin, all md images should be "ideal"?
|
|
38
|
+
// This is used to force url-loader+file-loader on markdown images
|
|
39
|
+
// https://webpack.js.org/concepts/loaders/#inline
|
|
40
|
+
inlineMarkdownImageFileLoader: `!${(0, posixPath_1.posixPath)(require.resolve('url-loader'))}?limit=${urlLoaderLimit}&name=${fileLoaderFileName('images')}&fallback=${(0, posixPath_1.posixPath)(require.resolve('file-loader'))}!`,
|
|
41
|
+
inlineMarkdownLinkFileLoader: `!${(0, posixPath_1.posixPath)(require.resolve('file-loader'))}?name=${fileLoaderFileName('files')}!`,
|
|
42
|
+
};
|
|
43
|
+
const rules = {
|
|
44
|
+
/**
|
|
45
|
+
* Loads image assets, inlines images via a data URI if they are below
|
|
46
|
+
* the size threshold
|
|
47
|
+
*/
|
|
48
|
+
images: () => ({
|
|
49
|
+
use: [loaders.url({ folder: 'images' })],
|
|
50
|
+
test: /\.(ico|jpg|jpeg|png|gif|webp)(\?.*)?$/,
|
|
51
|
+
}),
|
|
52
|
+
fonts: () => ({
|
|
53
|
+
use: [loaders.url({ folder: 'fonts' })],
|
|
54
|
+
test: /\.(woff|woff2|eot|ttf|otf)$/,
|
|
55
|
+
}),
|
|
56
|
+
/**
|
|
57
|
+
* Loads audio and video and inlines them via a data URI if they are below
|
|
58
|
+
* the size threshold
|
|
59
|
+
*/
|
|
60
|
+
media: () => ({
|
|
61
|
+
use: [loaders.url({ folder: 'medias' })],
|
|
62
|
+
test: /\.(mp4|webm|ogv|wav|mp3|m4a|aac|oga|flac)$/,
|
|
63
|
+
}),
|
|
64
|
+
svg: () => ({
|
|
65
|
+
test: /\.svg?$/,
|
|
66
|
+
oneOf: [
|
|
67
|
+
{
|
|
68
|
+
use: [
|
|
69
|
+
{
|
|
70
|
+
loader: require.resolve('@svgr/webpack'),
|
|
71
|
+
options: {
|
|
72
|
+
prettier: false,
|
|
73
|
+
svgo: true,
|
|
74
|
+
svgoConfig: {
|
|
75
|
+
plugins: [
|
|
76
|
+
{
|
|
77
|
+
name: 'preset-default',
|
|
78
|
+
params: {
|
|
79
|
+
overrides: {
|
|
80
|
+
removeViewBox: false,
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
},
|
|
86
|
+
titleProp: true,
|
|
87
|
+
ref: ![path_1.default],
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
// We don't want to use SVGR loader for non-React source code
|
|
92
|
+
// ie we don't want to use SVGR for CSS files...
|
|
93
|
+
issuer: {
|
|
94
|
+
and: [/\.(ts|tsx|js|jsx|md|mdx)$/],
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
use: [loaders.url({ folder: 'images' })],
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
}),
|
|
102
|
+
otherAssets: () => ({
|
|
103
|
+
use: [loaders.file({ folder: 'files' })],
|
|
104
|
+
test: /\.(pdf|doc|docx|xls|xlsx|zip|rar)$/,
|
|
105
|
+
}),
|
|
106
|
+
};
|
|
107
|
+
return { loaders, rules };
|
|
108
|
+
}
|
|
109
|
+
exports.getFileLoaderUtils = getFileLoaderUtils;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docusaurus/utils",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.10",
|
|
4
4
|
"description": "Node utility functions for Docusaurus packages.",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"types": "./lib/index.d.ts",
|
|
@@ -18,22 +18,38 @@
|
|
|
18
18
|
},
|
|
19
19
|
"license": "MIT",
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@
|
|
22
|
-
"@
|
|
23
|
-
"chalk": "^4.1.
|
|
21
|
+
"@mdx-js/runtime": "^1.6.22",
|
|
22
|
+
"@svgr/webpack": "^6.0.0",
|
|
23
|
+
"chalk": "^4.1.2",
|
|
24
24
|
"escape-string-regexp": "^4.0.0",
|
|
25
|
+
"file-loader": "^6.2.0",
|
|
25
26
|
"fs-extra": "^10.0.0",
|
|
27
|
+
"github-slugger": "^1.4.0",
|
|
28
|
+
"globby": "^11.0.4",
|
|
26
29
|
"gray-matter": "^4.0.3",
|
|
27
30
|
"lodash": "^4.17.20",
|
|
31
|
+
"micromatch": "^4.0.4",
|
|
32
|
+
"remark-mdx-remove-exports": "^1.6.22",
|
|
33
|
+
"remark-mdx-remove-imports": "^1.6.22",
|
|
28
34
|
"resolve-pathname": "^3.0.0",
|
|
29
|
-
"tslib": "^2.
|
|
35
|
+
"tslib": "^2.3.1",
|
|
36
|
+
"url-loader": "^4.1.1"
|
|
30
37
|
},
|
|
31
38
|
"engines": {
|
|
32
|
-
"node": ">=
|
|
39
|
+
"node": ">=14"
|
|
33
40
|
},
|
|
34
41
|
"devDependencies": {
|
|
42
|
+
"@docusaurus/types": "2.0.0-beta.10",
|
|
35
43
|
"@types/dedent": "^0.7.0",
|
|
44
|
+
"@types/github-slugger": "^1.3.0",
|
|
45
|
+
"@types/micromatch": "^4.0.2",
|
|
46
|
+
"@types/react-dom": "^17.0.1",
|
|
36
47
|
"dedent": "^0.7.0"
|
|
37
48
|
},
|
|
38
|
-
"
|
|
49
|
+
"peerDependencies": {
|
|
50
|
+
"react": "*",
|
|
51
|
+
"react-dom": "*",
|
|
52
|
+
"webpack": "5.x"
|
|
53
|
+
},
|
|
54
|
+
"gitHead": "6f4869af5721435d6995e63e2f24ac41646e34ea"
|
|
39
55
|
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
GlobExcludeDefault,
|
|
10
|
+
createMatcher,
|
|
11
|
+
createAbsoluteFilePathMatcher,
|
|
12
|
+
} from '../globUtils';
|
|
13
|
+
|
|
14
|
+
describe('createMatcher', () => {
|
|
15
|
+
const matcher = createMatcher(GlobExcludeDefault);
|
|
16
|
+
|
|
17
|
+
test('match default exclude MD/MDX partials correctly', () => {
|
|
18
|
+
expect(matcher('doc.md')).toEqual(false);
|
|
19
|
+
expect(matcher('category/doc.md')).toEqual(false);
|
|
20
|
+
expect(matcher('category/subcategory/doc.md')).toEqual(false);
|
|
21
|
+
//
|
|
22
|
+
expect(matcher('doc.mdx')).toEqual(false);
|
|
23
|
+
expect(matcher('category/doc.mdx')).toEqual(false);
|
|
24
|
+
expect(matcher('category/subcategory/doc.mdx')).toEqual(false);
|
|
25
|
+
//
|
|
26
|
+
expect(matcher('_doc.md')).toEqual(true);
|
|
27
|
+
expect(matcher('category/_doc.md')).toEqual(true);
|
|
28
|
+
expect(matcher('category/subcategory/_doc.md')).toEqual(true);
|
|
29
|
+
expect(matcher('_category/doc.md')).toEqual(true);
|
|
30
|
+
expect(matcher('_category/subcategory/doc.md')).toEqual(true);
|
|
31
|
+
expect(matcher('category/_subcategory/doc.md')).toEqual(true);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('match default exclude tests correctly', () => {
|
|
35
|
+
expect(matcher('xyz.js')).toEqual(false);
|
|
36
|
+
expect(matcher('xyz.ts')).toEqual(false);
|
|
37
|
+
expect(matcher('xyz.jsx')).toEqual(false);
|
|
38
|
+
expect(matcher('xyz.tsx')).toEqual(false);
|
|
39
|
+
expect(matcher('folder/xyz.js')).toEqual(false);
|
|
40
|
+
expect(matcher('folder/xyz.ts')).toEqual(false);
|
|
41
|
+
expect(matcher('folder/xyz.jsx')).toEqual(false);
|
|
42
|
+
expect(matcher('folder/xyz.tsx')).toEqual(false);
|
|
43
|
+
//
|
|
44
|
+
expect(matcher('xyz.test.js')).toEqual(true);
|
|
45
|
+
expect(matcher('xyz.test.ts')).toEqual(true);
|
|
46
|
+
expect(matcher('xyz.test.jsx')).toEqual(true);
|
|
47
|
+
expect(matcher('xyz.test.tsx')).toEqual(true);
|
|
48
|
+
expect(matcher('folder/xyz.test.js')).toEqual(true);
|
|
49
|
+
expect(matcher('folder/xyz.test.ts')).toEqual(true);
|
|
50
|
+
expect(matcher('folder/xyz.test.jsx')).toEqual(true);
|
|
51
|
+
expect(matcher('folder/xyz.test.tsx')).toEqual(true);
|
|
52
|
+
expect(matcher('folder/subfolder/xyz.test.js')).toEqual(true);
|
|
53
|
+
expect(matcher('folder/subfolder/xyz.test.ts')).toEqual(true);
|
|
54
|
+
expect(matcher('folder/subfolder/xyz.test.jsx')).toEqual(true);
|
|
55
|
+
expect(matcher('folder/subfolder/xyz.test.tsx')).toEqual(true);
|
|
56
|
+
//
|
|
57
|
+
expect(matcher('__tests__/subfolder/xyz.js')).toEqual(true);
|
|
58
|
+
expect(matcher('__tests__/subfolder/xyz.ts')).toEqual(true);
|
|
59
|
+
expect(matcher('__tests__/subfolder/xyz.jsx')).toEqual(true);
|
|
60
|
+
expect(matcher('__tests__/subfolder/xyz.tsx')).toEqual(true);
|
|
61
|
+
expect(matcher('folder/__tests__/xyz.js')).toEqual(true);
|
|
62
|
+
expect(matcher('folder/__tests__/xyz.ts')).toEqual(true);
|
|
63
|
+
expect(matcher('folder/__tests__/xyz.jsx')).toEqual(true);
|
|
64
|
+
expect(matcher('folder/__tests__/xyz.tsx')).toEqual(true);
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
describe('createAbsoluteFilePathMatcher', () => {
|
|
69
|
+
const rootFolders = ['/_root/docs', '/root/_docs/', '/__test__/website/src'];
|
|
70
|
+
|
|
71
|
+
const matcher = createAbsoluteFilePathMatcher(
|
|
72
|
+
GlobExcludeDefault,
|
|
73
|
+
rootFolders,
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
test('match default exclude MD/MDX partials correctly', () => {
|
|
77
|
+
expect(matcher('/_root/docs/myDoc.md')).toEqual(false);
|
|
78
|
+
expect(matcher('/_root/docs/myDoc.mdx')).toEqual(false);
|
|
79
|
+
expect(matcher('/root/_docs/myDoc.md')).toEqual(false);
|
|
80
|
+
expect(matcher('/root/_docs/myDoc.mdx')).toEqual(false);
|
|
81
|
+
expect(matcher('/_root/docs/category/myDoc.md')).toEqual(false);
|
|
82
|
+
expect(matcher('/_root/docs/category/myDoc.mdx')).toEqual(false);
|
|
83
|
+
expect(matcher('/root/_docs/category/myDoc.md')).toEqual(false);
|
|
84
|
+
expect(matcher('/root/_docs/category/myDoc.mdx')).toEqual(false);
|
|
85
|
+
//
|
|
86
|
+
expect(matcher('/_root/docs/_myDoc.md')).toEqual(true);
|
|
87
|
+
expect(matcher('/_root/docs/_myDoc.mdx')).toEqual(true);
|
|
88
|
+
expect(matcher('/root/_docs/_myDoc.md')).toEqual(true);
|
|
89
|
+
expect(matcher('/root/_docs/_myDoc.mdx')).toEqual(true);
|
|
90
|
+
expect(matcher('/_root/docs/_category/myDoc.md')).toEqual(true);
|
|
91
|
+
expect(matcher('/_root/docs/_category/myDoc.mdx')).toEqual(true);
|
|
92
|
+
expect(matcher('/root/_docs/_category/myDoc.md')).toEqual(true);
|
|
93
|
+
expect(matcher('/root/_docs/_category/myDoc.mdx')).toEqual(true);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
test('match default exclude tests correctly', () => {
|
|
97
|
+
expect(matcher('/__test__/website/src/xyz.js')).toEqual(false);
|
|
98
|
+
expect(matcher('/__test__/website/src/__test__/xyz.js')).toEqual(true);
|
|
99
|
+
expect(matcher('/__test__/website/src/xyz.test.js')).toEqual(true);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test('throw if file is not contained in any root doc', () => {
|
|
103
|
+
expect(() =>
|
|
104
|
+
matcher('/bad/path/myDoc.md'),
|
|
105
|
+
).toThrowErrorMatchingInlineSnapshot(
|
|
106
|
+
`"createAbsoluteFilePathMatcher unexpected error, absoluteFilePath=/bad/path/myDoc.md was not contained in any of the root folders [\\"/_root/docs\\",\\"/root/_docs/\\",\\"/__test__/website/src\\"]"`,
|
|
107
|
+
);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
@@ -5,7 +5,28 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import {docuHash} from '../
|
|
8
|
+
import {simpleHash, docuHash} from '../hashUtils';
|
|
9
|
+
|
|
10
|
+
describe('hashUtils', () => {
|
|
11
|
+
test('simpleHash', () => {
|
|
12
|
+
const asserts: Record<string, string> = {
|
|
13
|
+
'': 'd41',
|
|
14
|
+
'/foo-bar': '096',
|
|
15
|
+
'/foo/bar': '1df',
|
|
16
|
+
'/endi/lie': '9fa',
|
|
17
|
+
'/endi-lie': 'fd3',
|
|
18
|
+
'/yangshun/tay': '48d',
|
|
19
|
+
'/yangshun-tay': 'f3b',
|
|
20
|
+
'/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar':
|
|
21
|
+
'd46',
|
|
22
|
+
'/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/foo/bar/test1-test2':
|
|
23
|
+
'787',
|
|
24
|
+
};
|
|
25
|
+
Object.keys(asserts).forEach((str) => {
|
|
26
|
+
expect(simpleHash(str, 3)).toBe(asserts[str]);
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
});
|
|
9
30
|
|
|
10
31
|
describe('docuHash', () => {
|
|
11
32
|
test('docuHash works', () => {
|
|
@@ -12,7 +12,6 @@ import {
|
|
|
12
12
|
genChunkName,
|
|
13
13
|
idx,
|
|
14
14
|
getSubFolder,
|
|
15
|
-
normalizeUrl,
|
|
16
15
|
posixPath,
|
|
17
16
|
objectWithKeySorted,
|
|
18
17
|
aliasedSitePath,
|
|
@@ -218,113 +217,6 @@ describe('load utils', () => {
|
|
|
218
217
|
expect(getSubFolder(testE, 'docs')).toBeNull();
|
|
219
218
|
});
|
|
220
219
|
|
|
221
|
-
test('normalizeUrl', () => {
|
|
222
|
-
const asserts = [
|
|
223
|
-
{
|
|
224
|
-
input: ['/', ''],
|
|
225
|
-
output: '/',
|
|
226
|
-
},
|
|
227
|
-
{
|
|
228
|
-
input: ['', '/'],
|
|
229
|
-
output: '/',
|
|
230
|
-
},
|
|
231
|
-
{
|
|
232
|
-
input: ['/'],
|
|
233
|
-
output: '/',
|
|
234
|
-
},
|
|
235
|
-
{
|
|
236
|
-
input: [''],
|
|
237
|
-
output: '',
|
|
238
|
-
},
|
|
239
|
-
{
|
|
240
|
-
input: ['/', '/'],
|
|
241
|
-
output: '/',
|
|
242
|
-
},
|
|
243
|
-
{
|
|
244
|
-
input: ['/', 'docs'],
|
|
245
|
-
output: '/docs',
|
|
246
|
-
},
|
|
247
|
-
{
|
|
248
|
-
input: ['/', 'docs', 'en', 'next', 'blog'],
|
|
249
|
-
output: '/docs/en/next/blog',
|
|
250
|
-
},
|
|
251
|
-
{
|
|
252
|
-
input: ['/test/', '/docs', 'ro', 'doc1'],
|
|
253
|
-
output: '/test/docs/ro/doc1',
|
|
254
|
-
},
|
|
255
|
-
{
|
|
256
|
-
input: ['/test/', '/', 'ro', 'doc1'],
|
|
257
|
-
output: '/test/ro/doc1',
|
|
258
|
-
},
|
|
259
|
-
{
|
|
260
|
-
input: ['/', '/', '2020/02/29/leap-day'],
|
|
261
|
-
output: '/2020/02/29/leap-day',
|
|
262
|
-
},
|
|
263
|
-
{
|
|
264
|
-
input: ['', '/', 'ko', 'hello'],
|
|
265
|
-
output: '/ko/hello',
|
|
266
|
-
},
|
|
267
|
-
{
|
|
268
|
-
input: ['hello', 'world'],
|
|
269
|
-
output: 'hello/world',
|
|
270
|
-
},
|
|
271
|
-
{
|
|
272
|
-
input: ['http://www.google.com/', 'foo/bar', '?test=123'],
|
|
273
|
-
output: 'http://www.google.com/foo/bar?test=123',
|
|
274
|
-
},
|
|
275
|
-
{
|
|
276
|
-
input: ['http:', 'www.google.com///', 'foo/bar', '?test=123'],
|
|
277
|
-
output: 'http://www.google.com/foo/bar?test=123',
|
|
278
|
-
},
|
|
279
|
-
{
|
|
280
|
-
input: ['http://foobar.com', '', 'test'],
|
|
281
|
-
output: 'http://foobar.com/test',
|
|
282
|
-
},
|
|
283
|
-
{
|
|
284
|
-
input: ['http://foobar.com', '', 'test', '/'],
|
|
285
|
-
output: 'http://foobar.com/test/',
|
|
286
|
-
},
|
|
287
|
-
{
|
|
288
|
-
input: ['/', '', 'hello', '', '/', '/', '', '/', '/world'],
|
|
289
|
-
output: '/hello/world',
|
|
290
|
-
},
|
|
291
|
-
{
|
|
292
|
-
input: ['', '', '/tt', 'ko', 'hello'],
|
|
293
|
-
output: '/tt/ko/hello',
|
|
294
|
-
},
|
|
295
|
-
{
|
|
296
|
-
input: ['', '///hello///', '', '///world'],
|
|
297
|
-
output: '/hello/world',
|
|
298
|
-
},
|
|
299
|
-
{
|
|
300
|
-
input: ['', '/hello/', ''],
|
|
301
|
-
output: '/hello/',
|
|
302
|
-
},
|
|
303
|
-
{
|
|
304
|
-
input: ['', '/', ''],
|
|
305
|
-
output: '/',
|
|
306
|
-
},
|
|
307
|
-
{
|
|
308
|
-
input: ['///', '///'],
|
|
309
|
-
output: '/',
|
|
310
|
-
},
|
|
311
|
-
{
|
|
312
|
-
input: ['/', '/hello/world/', '///'],
|
|
313
|
-
output: '/hello/world/',
|
|
314
|
-
},
|
|
315
|
-
];
|
|
316
|
-
asserts.forEach((testCase) => {
|
|
317
|
-
expect(normalizeUrl(testCase.input)).toBe(testCase.output);
|
|
318
|
-
});
|
|
319
|
-
|
|
320
|
-
expect(() =>
|
|
321
|
-
// @ts-expect-error undefined for test
|
|
322
|
-
normalizeUrl(['http:example.com', undefined]),
|
|
323
|
-
).toThrowErrorMatchingInlineSnapshot(
|
|
324
|
-
`"Url must be a string. Received undefined"`,
|
|
325
|
-
);
|
|
326
|
-
});
|
|
327
|
-
|
|
328
220
|
test('isValidPathname', () => {
|
|
329
221
|
expect(isValidPathname('/')).toBe(true);
|
|
330
222
|
expect(isValidPathname('/hey')).toBe(true);
|
|
@@ -459,7 +351,9 @@ describe('mergeTranslations', () => {
|
|
|
459
351
|
|
|
460
352
|
describe('mapAsyncSequencial', () => {
|
|
461
353
|
function sleep(timeout: number): Promise<void> {
|
|
462
|
-
return new Promise((resolve) =>
|
|
354
|
+
return new Promise((resolve) => {
|
|
355
|
+
setTimeout(resolve, timeout);
|
|
356
|
+
});
|
|
463
357
|
}
|
|
464
358
|
|
|
465
359
|
test('map sequentially', async () => {
|
|
@@ -498,7 +392,9 @@ describe('mapAsyncSequencial', () => {
|
|
|
498
392
|
|
|
499
393
|
describe('findAsyncSequencial', () => {
|
|
500
394
|
function sleep(timeout: number): Promise<void> {
|
|
501
|
-
return new Promise((resolve) =>
|
|
395
|
+
return new Promise((resolve) => {
|
|
396
|
+
setTimeout(resolve, timeout);
|
|
397
|
+
});
|
|
502
398
|
}
|
|
503
399
|
|
|
504
400
|
test('find sequentially', async () => {
|
|
@@ -36,7 +36,7 @@ describe('createExcerpt', () => {
|
|
|
36
36
|
Nunc porttitor libero nec vulputate venenatis. Nam nec rhoncus mauris. Morbi tempus est et nibh maximus, tempus venenatis arcu lobortis.
|
|
37
37
|
`),
|
|
38
38
|
).toEqual(
|
|
39
|
-
// h1 title is skipped on purpose, because we don't want the page to have SEO
|
|
39
|
+
// h1 title is skipped on purpose, because we don't want the page to have SEO metadata title === description
|
|
40
40
|
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum ex urna, molestie et sagittis ut, varius ac justo.',
|
|
41
41
|
);
|
|
42
42
|
});
|
|
@@ -53,7 +53,7 @@ describe('createExcerpt', () => {
|
|
|
53
53
|
Nunc porttitor libero nec vulputate venenatis. Nam nec rhoncus mauris. Morbi tempus est et nibh maximus, tempus venenatis arcu lobortis.
|
|
54
54
|
`),
|
|
55
55
|
).toEqual(
|
|
56
|
-
// h1 title is skipped on purpose, because we don't want the page to have SEO
|
|
56
|
+
// h1 title is skipped on purpose, because we don't want the page to have SEO metadata title === description
|
|
57
57
|
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum ex urna, molestie et sagittis ut, varius ac justo.',
|
|
58
58
|
);
|
|
59
59
|
});
|
|
@@ -129,6 +129,19 @@ describe('createExcerpt', () => {
|
|
|
129
129
|
`),
|
|
130
130
|
).toEqual('Markdown title');
|
|
131
131
|
});
|
|
132
|
+
|
|
133
|
+
test('should create excerpt for content with various code blocks', () => {
|
|
134
|
+
expect(
|
|
135
|
+
createExcerpt(dedent`
|
|
136
|
+
\`\`\`jsx
|
|
137
|
+
import React from 'react';
|
|
138
|
+
import Layout from '@theme/Layout';
|
|
139
|
+
\`\`\`
|
|
140
|
+
|
|
141
|
+
Lorem \`ipsum\` dolor sit amet, consectetur \`adipiscing elit\`.
|
|
142
|
+
`),
|
|
143
|
+
).toEqual('Lorem ipsum dolor sit amet, consectetur adipiscing elit.');
|
|
144
|
+
});
|
|
132
145
|
});
|
|
133
146
|
|
|
134
147
|
describe('parseMarkdownContentTitle', () => {
|