@azerion/bunosaurus-plugin-content-pages 0.0.0-stage → 4.0.0
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/README.md +6 -2
- package/lib/content.d.ts +20 -0
- package/lib/content.js +123 -0
- package/lib/contentHelpers.d.ts +12 -0
- package/lib/contentHelpers.js +30 -0
- package/lib/frontMatter.d.ts +10 -0
- package/lib/frontMatter.js +27 -0
- package/lib/index.d.ts +10 -0
- package/lib/index.js +95 -0
- package/lib/options.d.ts +10 -0
- package/lib/options.js +51 -0
- package/lib/routes.d.ts +15 -0
- package/lib/routes.js +56 -0
- package/package.json +38 -4
- package/src/content.ts +204 -0
- package/src/contentHelpers.ts +33 -0
- package/src/frontMatter.ts +37 -0
- package/src/index.ts +135 -0
- package/src/options.ts +70 -0
- package/src/plugin-content-pages.d.ts +114 -0
- package/src/routes.ts +89 -0
package/README.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
-
#
|
|
1
|
+
# `@docusaurus/plugin-content-pages`
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Pages plugin for Docusaurus.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
See [plugin-content-pages documentation](https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-content-pages).
|
package/lib/content.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
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 ContentPaths } from '@docusaurus/utils';
|
|
8
|
+
import type { LoadContext } from '@docusaurus/types';
|
|
9
|
+
import type { PluginOptions, LoadedContent } from '@docusaurus/plugin-content-pages';
|
|
10
|
+
export declare function createPagesContentPaths({ context, options, }: {
|
|
11
|
+
context: LoadContext;
|
|
12
|
+
options: PluginOptions;
|
|
13
|
+
}): ContentPaths;
|
|
14
|
+
type LoadContentParams = {
|
|
15
|
+
context: LoadContext;
|
|
16
|
+
options: PluginOptions;
|
|
17
|
+
contentPaths: ContentPaths;
|
|
18
|
+
};
|
|
19
|
+
export declare function loadPagesContent(params: LoadContentParams): Promise<LoadedContent>;
|
|
20
|
+
export {};
|
package/lib/content.js
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
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.createPagesContentPaths = createPagesContentPaths;
|
|
10
|
+
exports.loadPagesContent = loadPagesContent;
|
|
11
|
+
const tslib_1 = require("tslib");
|
|
12
|
+
const node_path_1 = tslib_1.__importDefault(require("node:path"));
|
|
13
|
+
const utils_1 = require("@docusaurus/utils");
|
|
14
|
+
const glob_1 = require("@docusaurus/glob");
|
|
15
|
+
const fs_1 = require("@docusaurus/fs");
|
|
16
|
+
const frontMatter_1 = require("./frontMatter");
|
|
17
|
+
function createPagesContentPaths({ context, options, }) {
|
|
18
|
+
const { siteDir, localizationDir } = context;
|
|
19
|
+
const shouldTranslate = (0, utils_1.getLocaleConfig)(context.i18n).translate;
|
|
20
|
+
return {
|
|
21
|
+
contentPath: node_path_1.default.resolve(siteDir, options.path),
|
|
22
|
+
contentPathLocalized: shouldTranslate
|
|
23
|
+
? (0, utils_1.getPluginI18nPath)({
|
|
24
|
+
localizationDir,
|
|
25
|
+
pluginName: 'docusaurus-plugin-content-pages',
|
|
26
|
+
pluginId: options.id,
|
|
27
|
+
})
|
|
28
|
+
: undefined,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
const isMarkdownSource = (source) => source.endsWith('.md') || source.endsWith('.mdx');
|
|
32
|
+
async function loadPagesContent(params) {
|
|
33
|
+
const { options } = params;
|
|
34
|
+
const pagesFiles = await (0, glob_1.glob)(params.options.include, {
|
|
35
|
+
cwd: params.contentPaths.contentPath,
|
|
36
|
+
ignore: options.exclude,
|
|
37
|
+
});
|
|
38
|
+
async function doProcessPageSourceFile(relativeSource) {
|
|
39
|
+
try {
|
|
40
|
+
return await processPageSourceFile(relativeSource, params);
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
throw new Error(`Processing of page source file path=${relativeSource} failed.`, { cause: err });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return (await Promise.all(pagesFiles.map(doProcessPageSourceFile))).filter((res) => {
|
|
47
|
+
return res !== undefined;
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
async function processPageSourceFile(relativeSource, params) {
|
|
51
|
+
const { context, options, contentPaths } = params;
|
|
52
|
+
const { siteConfig, baseUrl, siteDir, i18n } = context;
|
|
53
|
+
const { vcs } = siteConfig;
|
|
54
|
+
const { editUrl } = options;
|
|
55
|
+
// Lookup in localized folder in priority
|
|
56
|
+
const contentPath = await (0, utils_1.getFolderContainingFile)((0, utils_1.getContentPathList)(contentPaths), relativeSource);
|
|
57
|
+
const source = node_path_1.default.join(contentPath, relativeSource);
|
|
58
|
+
const aliasedSourcePath = (0, utils_1.aliasedSitePath)(source, siteDir);
|
|
59
|
+
const filenameSlug = (0, utils_1.encodePath)((0, utils_1.fileToPath)(relativeSource));
|
|
60
|
+
if (!isMarkdownSource(relativeSource)) {
|
|
61
|
+
// For now, slug can't be customized for JSX pages
|
|
62
|
+
const slug = filenameSlug;
|
|
63
|
+
const permalink = (0, utils_1.normalizeUrl)([baseUrl, options.routeBasePath, slug]);
|
|
64
|
+
return {
|
|
65
|
+
type: 'jsx',
|
|
66
|
+
permalink,
|
|
67
|
+
source: aliasedSourcePath,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
const content = await fs_1.fs.readFile(source, 'utf-8');
|
|
71
|
+
const { frontMatter: unsafeFrontMatter, contentTitle, excerpt, } = await (0, utils_1.parseMarkdownFile)({
|
|
72
|
+
filePath: source,
|
|
73
|
+
fileContent: content,
|
|
74
|
+
parseFrontMatter: siteConfig.markdown.parseFrontMatter,
|
|
75
|
+
});
|
|
76
|
+
const frontMatter = (0, frontMatter_1.validatePageFrontMatter)(unsafeFrontMatter);
|
|
77
|
+
const slug = frontMatter.slug ?? filenameSlug;
|
|
78
|
+
const permalink = (0, utils_1.normalizeUrl)([baseUrl, options.routeBasePath, slug]);
|
|
79
|
+
const pagesDirPath = await (0, utils_1.getFolderContainingFile)((0, utils_1.getContentPathList)(contentPaths), relativeSource);
|
|
80
|
+
const pagesSourceAbsolute = node_path_1.default.join(pagesDirPath, relativeSource);
|
|
81
|
+
function getPagesEditUrl() {
|
|
82
|
+
const pagesPathRelative = node_path_1.default.relative(pagesDirPath, node_path_1.default.resolve(pagesSourceAbsolute));
|
|
83
|
+
if (typeof editUrl === 'function') {
|
|
84
|
+
return editUrl({
|
|
85
|
+
pagesDirPath: (0, utils_1.posixPath)(node_path_1.default.relative(siteDir, pagesDirPath)),
|
|
86
|
+
pagesPath: (0, utils_1.posixPath)(pagesPathRelative),
|
|
87
|
+
permalink,
|
|
88
|
+
locale: i18n.currentLocale,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
else if (typeof editUrl === 'string') {
|
|
92
|
+
const isLocalized = pagesDirPath === contentPaths.contentPathLocalized;
|
|
93
|
+
const fileContentPath = isLocalized &&
|
|
94
|
+
options.editLocalizedFiles &&
|
|
95
|
+
contentPaths.contentPathLocalized
|
|
96
|
+
? contentPaths.contentPathLocalized
|
|
97
|
+
: contentPaths.contentPath;
|
|
98
|
+
const contentPathEditUrl = (0, utils_1.normalizeUrl)([
|
|
99
|
+
editUrl,
|
|
100
|
+
(0, utils_1.posixPath)(node_path_1.default.relative(siteDir, fileContentPath)),
|
|
101
|
+
]);
|
|
102
|
+
return (0, utils_1.getEditUrl)(pagesPathRelative, contentPathEditUrl);
|
|
103
|
+
}
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
const lastUpdatedData = await (0, utils_1.readLastUpdateData)(source, options, frontMatter.last_update, vcs);
|
|
107
|
+
if ((0, utils_1.isDraft)({ frontMatter })) {
|
|
108
|
+
return undefined;
|
|
109
|
+
}
|
|
110
|
+
const unlisted = (0, utils_1.isUnlisted)({ frontMatter });
|
|
111
|
+
return {
|
|
112
|
+
type: 'mdx',
|
|
113
|
+
permalink,
|
|
114
|
+
source: aliasedSourcePath,
|
|
115
|
+
title: frontMatter.title ?? contentTitle,
|
|
116
|
+
description: frontMatter.description ?? excerpt,
|
|
117
|
+
frontMatter,
|
|
118
|
+
lastUpdatedBy: lastUpdatedData.lastUpdatedBy,
|
|
119
|
+
lastUpdatedAt: lastUpdatedData.lastUpdatedAt,
|
|
120
|
+
editUrl: getPagesEditUrl(),
|
|
121
|
+
unlisted,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
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 { LoadedContent, Metadata } from '@docusaurus/plugin-content-pages';
|
|
8
|
+
export declare function createContentHelpers(): {
|
|
9
|
+
updateContent: (content: LoadedContent) => void;
|
|
10
|
+
sourceToPage: Map<string, Metadata>;
|
|
11
|
+
sourceToPermalink: Map<string, string>;
|
|
12
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
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.createContentHelpers = createContentHelpers;
|
|
10
|
+
function indexPagesBySource(content) {
|
|
11
|
+
return new Map(content.map((page) => [page.source, page]));
|
|
12
|
+
}
|
|
13
|
+
// TODO this is bad, we should have a better way to do this (new lifecycle?)
|
|
14
|
+
// The source to page/permalink is a mutable map passed to the mdx loader
|
|
15
|
+
// See https://github.com/facebook/docusaurus/pull/10457
|
|
16
|
+
// See https://github.com/facebook/docusaurus/pull/10185
|
|
17
|
+
function createContentHelpers() {
|
|
18
|
+
const sourceToPage = new Map();
|
|
19
|
+
const sourceToPermalink = new Map();
|
|
20
|
+
// Mutable map update :/
|
|
21
|
+
function updateContent(content) {
|
|
22
|
+
sourceToPage.clear();
|
|
23
|
+
sourceToPermalink.clear();
|
|
24
|
+
indexPagesBySource(content).forEach((value, key) => {
|
|
25
|
+
sourceToPage.set(key, value);
|
|
26
|
+
sourceToPermalink.set(key, value.permalink);
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
return { updateContent, sourceToPage, sourceToPermalink };
|
|
30
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
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 { PageFrontMatter } from '@docusaurus/plugin-content-pages';
|
|
8
|
+
export declare function validatePageFrontMatter(frontMatter: {
|
|
9
|
+
[key: string]: unknown;
|
|
10
|
+
}): PageFrontMatter;
|
|
@@ -0,0 +1,27 @@
|
|
|
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.validatePageFrontMatter = validatePageFrontMatter;
|
|
10
|
+
const utils_validation_1 = require("@docusaurus/utils-validation");
|
|
11
|
+
/* eslint-disable camelcase */
|
|
12
|
+
const PageFrontMatterSchema = utils_validation_1.Joi.object({
|
|
13
|
+
// See https://github.com/facebook/docusaurus/issues/4591#issuecomment-822372398
|
|
14
|
+
title: utils_validation_1.Joi.string().allow(''),
|
|
15
|
+
// See https://github.com/facebook/docusaurus/issues/4591#issuecomment-822372398
|
|
16
|
+
description: utils_validation_1.Joi.string().allow(''),
|
|
17
|
+
keywords: utils_validation_1.Joi.array().items(utils_validation_1.Joi.string().required()),
|
|
18
|
+
image: utils_validation_1.URISchema,
|
|
19
|
+
slug: utils_validation_1.Joi.string(),
|
|
20
|
+
wrapperClassName: utils_validation_1.Joi.string(),
|
|
21
|
+
hide_table_of_contents: utils_validation_1.Joi.boolean(),
|
|
22
|
+
...utils_validation_1.FrontMatterTOCHeadingLevels,
|
|
23
|
+
last_update: utils_validation_1.FrontMatterLastUpdateSchema,
|
|
24
|
+
}).concat(utils_validation_1.ContentVisibilitySchema);
|
|
25
|
+
function validatePageFrontMatter(frontMatter) {
|
|
26
|
+
return (0, utils_validation_1.validateFrontMatter)(frontMatter, PageFrontMatterSchema);
|
|
27
|
+
}
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
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 { LoadContext, Plugin } from '@docusaurus/types';
|
|
8
|
+
import type { PluginOptions, LoadedContent } from '@docusaurus/plugin-content-pages';
|
|
9
|
+
export default function pluginContentPages(context: LoadContext, options: PluginOptions): Plugin<LoadedContent | null>;
|
|
10
|
+
export { validateOptions } from './options';
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
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.validateOptions = void 0;
|
|
10
|
+
exports.default = pluginContentPages;
|
|
11
|
+
const tslib_1 = require("tslib");
|
|
12
|
+
const node_path_1 = tslib_1.__importDefault(require("node:path"));
|
|
13
|
+
const utils_1 = require("@docusaurus/utils");
|
|
14
|
+
const glob_1 = require("@docusaurus/glob");
|
|
15
|
+
const mdx_loader_1 = require("@docusaurus/mdx-loader");
|
|
16
|
+
const fs_1 = require("@docusaurus/fs");
|
|
17
|
+
const routes_1 = require("./routes");
|
|
18
|
+
const content_1 = require("./content");
|
|
19
|
+
const contentHelpers_1 = require("./contentHelpers");
|
|
20
|
+
function pluginContentPages(context, options) {
|
|
21
|
+
const { siteConfig, siteDir, generatedFilesDir } = context;
|
|
22
|
+
const contentPaths = (0, content_1.createPagesContentPaths)({ context, options });
|
|
23
|
+
const contentHelpers = (0, contentHelpers_1.createContentHelpers)();
|
|
24
|
+
const pluginDataDirRoot = node_path_1.default.join(generatedFilesDir, 'docusaurus-plugin-content-pages');
|
|
25
|
+
const dataDir = node_path_1.default.join(pluginDataDirRoot, options.id);
|
|
26
|
+
function createPagesMDXLoaderRule() {
|
|
27
|
+
const { admonitions, rehypePlugins, remarkPlugins, recmaPlugins, beforeDefaultRehypePlugins, beforeDefaultRemarkPlugins, } = options;
|
|
28
|
+
const contentDirs = (0, utils_1.getContentPathList)(contentPaths);
|
|
29
|
+
return (0, mdx_loader_1.createMDXLoaderRule)({
|
|
30
|
+
include: contentDirs
|
|
31
|
+
// Trailing slash is important, see https://github.com/facebook/docusaurus/pull/3970
|
|
32
|
+
.map(utils_1.addTrailingPathSeparator),
|
|
33
|
+
options: {
|
|
34
|
+
admonitions,
|
|
35
|
+
remarkPlugins,
|
|
36
|
+
rehypePlugins,
|
|
37
|
+
recmaPlugins,
|
|
38
|
+
beforeDefaultRehypePlugins,
|
|
39
|
+
beforeDefaultRemarkPlugins,
|
|
40
|
+
staticDirs: siteConfig.staticDirectories.map((dir) => node_path_1.default.resolve(siteDir, dir)),
|
|
41
|
+
siteDir,
|
|
42
|
+
isMDXPartial: (0, glob_1.createAbsoluteFilePathMatcher)(options.exclude, contentDirs),
|
|
43
|
+
metadataPath: (mdxPath) => {
|
|
44
|
+
// Note that metadataPath must be the same/in-sync as
|
|
45
|
+
// the path from createData for each MDX.
|
|
46
|
+
const aliasedSource = (0, utils_1.aliasedSitePath)(mdxPath, siteDir);
|
|
47
|
+
return node_path_1.default.join(dataDir, `${(0, utils_1.docuHash)(aliasedSource)}.json`);
|
|
48
|
+
},
|
|
49
|
+
// createAssets converts relative paths to require() calls
|
|
50
|
+
createAssets: ({ frontMatter }) => ({
|
|
51
|
+
image: frontMatter.image,
|
|
52
|
+
}),
|
|
53
|
+
markdownConfig: siteConfig.markdown,
|
|
54
|
+
resolveMarkdownLink: ({ linkPathname, sourceFilePath }) => {
|
|
55
|
+
return (0, utils_1.resolveMarkdownLinkPathname)(linkPathname, {
|
|
56
|
+
sourceFilePath,
|
|
57
|
+
sourceToPermalink: contentHelpers.sourceToPermalink,
|
|
58
|
+
siteDir,
|
|
59
|
+
contentPaths,
|
|
60
|
+
});
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
const pagesMDXLoaderRule = createPagesMDXLoaderRule();
|
|
66
|
+
return {
|
|
67
|
+
name: 'docusaurus-plugin-content-pages',
|
|
68
|
+
getPathsToWatch() {
|
|
69
|
+
const { include } = options;
|
|
70
|
+
return (0, utils_1.getContentPathList)(contentPaths).flatMap((contentPath) => include.map((pattern) => `${contentPath}/${pattern}`));
|
|
71
|
+
},
|
|
72
|
+
async loadContent() {
|
|
73
|
+
if (!(await (0, fs_1.pathExists)(contentPaths.contentPath))) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
return (0, content_1.loadPagesContent)({ context, options, contentPaths });
|
|
77
|
+
},
|
|
78
|
+
async contentLoaded({ content, actions }) {
|
|
79
|
+
if (!content) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
contentHelpers.updateContent(content);
|
|
83
|
+
await (0, routes_1.createAllRoutes)({ content, options, actions });
|
|
84
|
+
},
|
|
85
|
+
configureWebpack() {
|
|
86
|
+
return {
|
|
87
|
+
module: {
|
|
88
|
+
rules: [pagesMDXLoaderRule],
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
var options_1 = require("./options");
|
|
95
|
+
Object.defineProperty(exports, "validateOptions", { enumerable: true, get: function () { return options_1.validateOptions; } });
|
package/lib/options.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
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 { OptionValidationContext } from '@docusaurus/types';
|
|
8
|
+
import type { PluginOptions, Options } from '@docusaurus/plugin-content-pages';
|
|
9
|
+
export declare const DEFAULT_OPTIONS: PluginOptions;
|
|
10
|
+
export declare function validateOptions({ validate, options, }: OptionValidationContext<Options, PluginOptions>): PluginOptions;
|
package/lib/options.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
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.DEFAULT_OPTIONS = void 0;
|
|
10
|
+
exports.validateOptions = validateOptions;
|
|
11
|
+
const utils_validation_1 = require("@docusaurus/utils-validation");
|
|
12
|
+
const utils_1 = require("@docusaurus/utils");
|
|
13
|
+
const glob_1 = require("@docusaurus/glob");
|
|
14
|
+
exports.DEFAULT_OPTIONS = {
|
|
15
|
+
id: utils_1.DEFAULT_PLUGIN_ID,
|
|
16
|
+
path: 'src/pages', // Path to data on filesystem, relative to site dir.
|
|
17
|
+
routeBasePath: '/', // URL Route.
|
|
18
|
+
include: ['**/*.{js,jsx,ts,tsx,md,mdx}'], // Extensions to include.
|
|
19
|
+
exclude: glob_1.GlobExcludeDefault,
|
|
20
|
+
mdxPageComponent: '@theme/MDXPage',
|
|
21
|
+
remarkPlugins: [],
|
|
22
|
+
rehypePlugins: [],
|
|
23
|
+
recmaPlugins: [],
|
|
24
|
+
beforeDefaultRehypePlugins: [],
|
|
25
|
+
beforeDefaultRemarkPlugins: [],
|
|
26
|
+
admonitions: true,
|
|
27
|
+
showLastUpdateTime: false,
|
|
28
|
+
showLastUpdateAuthor: false,
|
|
29
|
+
editLocalizedFiles: false,
|
|
30
|
+
};
|
|
31
|
+
const PluginOptionSchema = utils_validation_1.Joi.object({
|
|
32
|
+
path: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.path),
|
|
33
|
+
routeBasePath: utils_validation_1.RouteBasePathSchema.default(exports.DEFAULT_OPTIONS.routeBasePath),
|
|
34
|
+
include: utils_validation_1.Joi.array().items(utils_validation_1.Joi.string()).default(exports.DEFAULT_OPTIONS.include),
|
|
35
|
+
exclude: utils_validation_1.Joi.array().items(utils_validation_1.Joi.string()).default(exports.DEFAULT_OPTIONS.exclude),
|
|
36
|
+
mdxPageComponent: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.mdxPageComponent),
|
|
37
|
+
remarkPlugins: utils_validation_1.RemarkPluginsSchema.default(exports.DEFAULT_OPTIONS.remarkPlugins),
|
|
38
|
+
rehypePlugins: utils_validation_1.RehypePluginsSchema.default(exports.DEFAULT_OPTIONS.rehypePlugins),
|
|
39
|
+
recmaPlugins: utils_validation_1.RecmaPluginsSchema.default(exports.DEFAULT_OPTIONS.recmaPlugins),
|
|
40
|
+
beforeDefaultRehypePlugins: utils_validation_1.RehypePluginsSchema.default(exports.DEFAULT_OPTIONS.beforeDefaultRehypePlugins),
|
|
41
|
+
beforeDefaultRemarkPlugins: utils_validation_1.RemarkPluginsSchema.default(exports.DEFAULT_OPTIONS.beforeDefaultRemarkPlugins),
|
|
42
|
+
admonitions: utils_validation_1.AdmonitionsSchema.default(exports.DEFAULT_OPTIONS.admonitions),
|
|
43
|
+
showLastUpdateTime: utils_validation_1.Joi.bool().default(exports.DEFAULT_OPTIONS.showLastUpdateTime),
|
|
44
|
+
showLastUpdateAuthor: utils_validation_1.Joi.bool().default(exports.DEFAULT_OPTIONS.showLastUpdateAuthor),
|
|
45
|
+
editUrl: utils_validation_1.Joi.alternatives().try(utils_validation_1.URISchema, utils_validation_1.Joi.function()),
|
|
46
|
+
editLocalizedFiles: utils_validation_1.Joi.boolean().default(exports.DEFAULT_OPTIONS.editLocalizedFiles),
|
|
47
|
+
});
|
|
48
|
+
function validateOptions({ validate, options, }) {
|
|
49
|
+
const validatedOptions = validate(PluginOptionSchema, options);
|
|
50
|
+
return validatedOptions;
|
|
51
|
+
}
|
package/lib/routes.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
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 { PluginContentLoadedActions } from '@docusaurus/types';
|
|
8
|
+
import type { PluginOptions, LoadedContent } from '@docusaurus/plugin-content-pages';
|
|
9
|
+
type CreateAllRoutesParam = {
|
|
10
|
+
content: LoadedContent;
|
|
11
|
+
options: PluginOptions;
|
|
12
|
+
actions: PluginContentLoadedActions;
|
|
13
|
+
};
|
|
14
|
+
export declare function createAllRoutes(param: CreateAllRoutesParam): Promise<void>;
|
|
15
|
+
export {};
|
package/lib/routes.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
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.createAllRoutes = createAllRoutes;
|
|
10
|
+
const utils_1 = require("@docusaurus/utils");
|
|
11
|
+
function createPageRouteMetadata(metadata) {
|
|
12
|
+
const lastUpdatedAt = metadata.type === 'mdx' ? metadata.lastUpdatedAt : undefined;
|
|
13
|
+
return {
|
|
14
|
+
sourceFilePath: (0, utils_1.aliasedSitePathToRelativePath)(metadata.source),
|
|
15
|
+
lastUpdatedAt,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
async function createAllRoutes(param) {
|
|
19
|
+
const routes = await buildAllRoutes(param);
|
|
20
|
+
routes.forEach(param.actions.addRoute);
|
|
21
|
+
}
|
|
22
|
+
async function buildAllRoutes({ content, actions, options, }) {
|
|
23
|
+
const { createData } = actions;
|
|
24
|
+
async function buildMDXPageRoute(metadata) {
|
|
25
|
+
await createData(
|
|
26
|
+
// Note that this created data path must be in sync with
|
|
27
|
+
// metadataPath provided to mdx-loader.
|
|
28
|
+
`${(0, utils_1.docuHash)(metadata.source)}.json`, metadata);
|
|
29
|
+
return {
|
|
30
|
+
path: metadata.permalink,
|
|
31
|
+
component: options.mdxPageComponent,
|
|
32
|
+
exact: true,
|
|
33
|
+
metadata: createPageRouteMetadata(metadata),
|
|
34
|
+
modules: {
|
|
35
|
+
content: metadata.source,
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
async function buildJSXRoute(metadata) {
|
|
40
|
+
return {
|
|
41
|
+
path: metadata.permalink,
|
|
42
|
+
component: metadata.source,
|
|
43
|
+
exact: true,
|
|
44
|
+
metadata: createPageRouteMetadata(metadata),
|
|
45
|
+
modules: {
|
|
46
|
+
config: `@generated/docusaurus.config`,
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
async function buildPageRoute(metadata) {
|
|
51
|
+
return metadata.type === 'mdx'
|
|
52
|
+
? buildMDXPageRoute(metadata)
|
|
53
|
+
: buildJSXRoute(metadata);
|
|
54
|
+
}
|
|
55
|
+
return Promise.all(content.map(buildPageRoute));
|
|
56
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,40 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@azerion/bunosaurus-plugin-content-pages",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "4.0.0",
|
|
4
|
+
"description": "Pages plugin for Docusaurus.",
|
|
5
|
+
"main": "lib/index.js",
|
|
6
|
+
"types": "src/plugin-content-pages.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"watch": "tsc --watch"
|
|
10
|
+
},
|
|
11
|
+
"publishConfig": {
|
|
12
|
+
"access": "public"
|
|
13
|
+
},
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "https://github.com/azerion/bunosaurus.git",
|
|
17
|
+
"directory": "packages/docusaurus-plugin-content-pages"
|
|
18
|
+
},
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@docusaurus/core": "npm:@azerion/bunosaurus-core@4.0.0",
|
|
22
|
+
"@docusaurus/fs": "npm:@azerion/bunosaurus-fs@4.0.0",
|
|
23
|
+
"@docusaurus/glob": "npm:@azerion/bunosaurus-glob@4.0.0",
|
|
24
|
+
"@docusaurus/mdx-loader": "npm:@azerion/bunosaurus-mdx-loader@4.0.0",
|
|
25
|
+
"@docusaurus/types": "npm:@azerion/bunosaurus-types@4.0.0",
|
|
26
|
+
"@docusaurus/utils": "npm:@azerion/bunosaurus-utils@4.0.0",
|
|
27
|
+
"@docusaurus/utils-validation": "npm:@azerion/bunosaurus-utils-validation@4.0.0",
|
|
28
|
+
"tslib": "^2.8.1"
|
|
29
|
+
},
|
|
30
|
+
"peerDependencies": {
|
|
31
|
+
"react": "^19.3.0",
|
|
32
|
+
"react-dom": "^19.3.0"
|
|
33
|
+
},
|
|
34
|
+
"engines": {
|
|
35
|
+
"bun": ">=1.4.1"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"webpack": "^5.111.0"
|
|
39
|
+
}
|
|
40
|
+
}
|
package/src/content.ts
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
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 path from 'node:path';
|
|
9
|
+
import {
|
|
10
|
+
encodePath,
|
|
11
|
+
fileToPath,
|
|
12
|
+
aliasedSitePath,
|
|
13
|
+
getFolderContainingFile,
|
|
14
|
+
normalizeUrl,
|
|
15
|
+
parseMarkdownFile,
|
|
16
|
+
isUnlisted,
|
|
17
|
+
isDraft,
|
|
18
|
+
readLastUpdateData,
|
|
19
|
+
getEditUrl,
|
|
20
|
+
posixPath,
|
|
21
|
+
getPluginI18nPath,
|
|
22
|
+
getContentPathList,
|
|
23
|
+
getLocaleConfig,
|
|
24
|
+
type ContentPaths,
|
|
25
|
+
} from '@docusaurus/utils';
|
|
26
|
+
import {glob} from '@docusaurus/glob';
|
|
27
|
+
import {fs} from '@docusaurus/fs';
|
|
28
|
+
import {validatePageFrontMatter} from './frontMatter';
|
|
29
|
+
import type {LoadContext} from '@docusaurus/types';
|
|
30
|
+
import type {
|
|
31
|
+
PluginOptions,
|
|
32
|
+
Metadata,
|
|
33
|
+
LoadedContent,
|
|
34
|
+
} from '@docusaurus/plugin-content-pages';
|
|
35
|
+
|
|
36
|
+
export function createPagesContentPaths({
|
|
37
|
+
context,
|
|
38
|
+
options,
|
|
39
|
+
}: {
|
|
40
|
+
context: LoadContext;
|
|
41
|
+
options: PluginOptions;
|
|
42
|
+
}): ContentPaths {
|
|
43
|
+
const {siteDir, localizationDir} = context;
|
|
44
|
+
|
|
45
|
+
const shouldTranslate = getLocaleConfig(context.i18n).translate;
|
|
46
|
+
return {
|
|
47
|
+
contentPath: path.resolve(siteDir, options.path),
|
|
48
|
+
contentPathLocalized: shouldTranslate
|
|
49
|
+
? getPluginI18nPath({
|
|
50
|
+
localizationDir,
|
|
51
|
+
pluginName: 'docusaurus-plugin-content-pages',
|
|
52
|
+
pluginId: options.id,
|
|
53
|
+
})
|
|
54
|
+
: undefined,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const isMarkdownSource = (source: string) =>
|
|
59
|
+
source.endsWith('.md') || source.endsWith('.mdx');
|
|
60
|
+
|
|
61
|
+
type LoadContentParams = {
|
|
62
|
+
context: LoadContext;
|
|
63
|
+
options: PluginOptions;
|
|
64
|
+
contentPaths: ContentPaths;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export async function loadPagesContent(
|
|
68
|
+
params: LoadContentParams,
|
|
69
|
+
): Promise<LoadedContent> {
|
|
70
|
+
const {options} = params;
|
|
71
|
+
|
|
72
|
+
const pagesFiles = await glob(params.options.include, {
|
|
73
|
+
cwd: params.contentPaths.contentPath,
|
|
74
|
+
ignore: options.exclude,
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
async function doProcessPageSourceFile(relativeSource: string) {
|
|
78
|
+
try {
|
|
79
|
+
return await processPageSourceFile(relativeSource, params);
|
|
80
|
+
} catch (err) {
|
|
81
|
+
throw new Error(
|
|
82
|
+
`Processing of page source file path=${relativeSource} failed.`,
|
|
83
|
+
{cause: err},
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return (await Promise.all(pagesFiles.map(doProcessPageSourceFile))).filter(
|
|
89
|
+
(res): res is Metadata => {
|
|
90
|
+
return res !== undefined;
|
|
91
|
+
},
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async function processPageSourceFile(
|
|
96
|
+
relativeSource: string,
|
|
97
|
+
params: LoadContentParams,
|
|
98
|
+
): Promise<Metadata | undefined> {
|
|
99
|
+
const {context, options, contentPaths} = params;
|
|
100
|
+
const {siteConfig, baseUrl, siteDir, i18n} = context;
|
|
101
|
+
const {vcs} = siteConfig;
|
|
102
|
+
const {editUrl} = options;
|
|
103
|
+
|
|
104
|
+
// Lookup in localized folder in priority
|
|
105
|
+
const contentPath = await getFolderContainingFile(
|
|
106
|
+
getContentPathList(contentPaths),
|
|
107
|
+
relativeSource,
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
const source = path.join(contentPath, relativeSource);
|
|
111
|
+
const aliasedSourcePath = aliasedSitePath(source, siteDir);
|
|
112
|
+
|
|
113
|
+
const filenameSlug = encodePath(fileToPath(relativeSource));
|
|
114
|
+
|
|
115
|
+
if (!isMarkdownSource(relativeSource)) {
|
|
116
|
+
// For now, slug can't be customized for JSX pages
|
|
117
|
+
const slug = filenameSlug;
|
|
118
|
+
const permalink = normalizeUrl([baseUrl, options.routeBasePath, slug]);
|
|
119
|
+
return {
|
|
120
|
+
type: 'jsx',
|
|
121
|
+
permalink,
|
|
122
|
+
source: aliasedSourcePath,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const content = await fs.readFile(source, 'utf-8');
|
|
127
|
+
const {
|
|
128
|
+
frontMatter: unsafeFrontMatter,
|
|
129
|
+
contentTitle,
|
|
130
|
+
excerpt,
|
|
131
|
+
} = await parseMarkdownFile({
|
|
132
|
+
filePath: source,
|
|
133
|
+
fileContent: content,
|
|
134
|
+
parseFrontMatter: siteConfig.markdown.parseFrontMatter,
|
|
135
|
+
});
|
|
136
|
+
const frontMatter = validatePageFrontMatter(unsafeFrontMatter);
|
|
137
|
+
|
|
138
|
+
const slug = frontMatter.slug ?? filenameSlug;
|
|
139
|
+
const permalink = normalizeUrl([baseUrl, options.routeBasePath, slug]);
|
|
140
|
+
|
|
141
|
+
const pagesDirPath = await getFolderContainingFile(
|
|
142
|
+
getContentPathList(contentPaths),
|
|
143
|
+
relativeSource,
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
const pagesSourceAbsolute = path.join(pagesDirPath, relativeSource);
|
|
147
|
+
|
|
148
|
+
function getPagesEditUrl() {
|
|
149
|
+
const pagesPathRelative = path.relative(
|
|
150
|
+
pagesDirPath,
|
|
151
|
+
path.resolve(pagesSourceAbsolute),
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
if (typeof editUrl === 'function') {
|
|
155
|
+
return editUrl({
|
|
156
|
+
pagesDirPath: posixPath(path.relative(siteDir, pagesDirPath)),
|
|
157
|
+
pagesPath: posixPath(pagesPathRelative),
|
|
158
|
+
permalink,
|
|
159
|
+
locale: i18n.currentLocale,
|
|
160
|
+
});
|
|
161
|
+
} else if (typeof editUrl === 'string') {
|
|
162
|
+
const isLocalized = pagesDirPath === contentPaths.contentPathLocalized;
|
|
163
|
+
const fileContentPath =
|
|
164
|
+
isLocalized &&
|
|
165
|
+
options.editLocalizedFiles &&
|
|
166
|
+
contentPaths.contentPathLocalized
|
|
167
|
+
? contentPaths.contentPathLocalized
|
|
168
|
+
: contentPaths.contentPath;
|
|
169
|
+
|
|
170
|
+
const contentPathEditUrl = normalizeUrl([
|
|
171
|
+
editUrl,
|
|
172
|
+
posixPath(path.relative(siteDir, fileContentPath)),
|
|
173
|
+
]);
|
|
174
|
+
|
|
175
|
+
return getEditUrl(pagesPathRelative, contentPathEditUrl);
|
|
176
|
+
}
|
|
177
|
+
return undefined;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const lastUpdatedData = await readLastUpdateData(
|
|
181
|
+
source,
|
|
182
|
+
options,
|
|
183
|
+
frontMatter.last_update,
|
|
184
|
+
vcs,
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
if (isDraft({frontMatter})) {
|
|
188
|
+
return undefined;
|
|
189
|
+
}
|
|
190
|
+
const unlisted = isUnlisted({frontMatter});
|
|
191
|
+
|
|
192
|
+
return {
|
|
193
|
+
type: 'mdx',
|
|
194
|
+
permalink,
|
|
195
|
+
source: aliasedSourcePath,
|
|
196
|
+
title: frontMatter.title ?? contentTitle,
|
|
197
|
+
description: frontMatter.description ?? excerpt,
|
|
198
|
+
frontMatter,
|
|
199
|
+
lastUpdatedBy: lastUpdatedData.lastUpdatedBy,
|
|
200
|
+
lastUpdatedAt: lastUpdatedData.lastUpdatedAt,
|
|
201
|
+
editUrl: getPagesEditUrl(),
|
|
202
|
+
unlisted,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
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 type {LoadedContent, Metadata} from '@docusaurus/plugin-content-pages';
|
|
9
|
+
|
|
10
|
+
function indexPagesBySource(content: LoadedContent): Map<string, Metadata> {
|
|
11
|
+
return new Map(content.map((page) => [page.source, page]));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// TODO this is bad, we should have a better way to do this (new lifecycle?)
|
|
15
|
+
// The source to page/permalink is a mutable map passed to the mdx loader
|
|
16
|
+
// See https://github.com/facebook/docusaurus/pull/10457
|
|
17
|
+
// See https://github.com/facebook/docusaurus/pull/10185
|
|
18
|
+
export function createContentHelpers() {
|
|
19
|
+
const sourceToPage = new Map<string, Metadata>();
|
|
20
|
+
const sourceToPermalink = new Map<string, string>();
|
|
21
|
+
|
|
22
|
+
// Mutable map update :/
|
|
23
|
+
function updateContent(content: LoadedContent): void {
|
|
24
|
+
sourceToPage.clear();
|
|
25
|
+
sourceToPermalink.clear();
|
|
26
|
+
indexPagesBySource(content).forEach((value, key) => {
|
|
27
|
+
sourceToPage.set(key, value);
|
|
28
|
+
sourceToPermalink.set(key, value.permalink);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return {updateContent, sourceToPage, sourceToPermalink};
|
|
33
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
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
|
+
Joi,
|
|
10
|
+
validateFrontMatter,
|
|
11
|
+
FrontMatterTOCHeadingLevels,
|
|
12
|
+
ContentVisibilitySchema,
|
|
13
|
+
URISchema,
|
|
14
|
+
FrontMatterLastUpdateSchema,
|
|
15
|
+
} from '@docusaurus/utils-validation';
|
|
16
|
+
import type {PageFrontMatter} from '@docusaurus/plugin-content-pages';
|
|
17
|
+
/* eslint-disable camelcase */
|
|
18
|
+
|
|
19
|
+
const PageFrontMatterSchema = Joi.object<PageFrontMatter>({
|
|
20
|
+
// See https://github.com/facebook/docusaurus/issues/4591#issuecomment-822372398
|
|
21
|
+
title: Joi.string().allow(''),
|
|
22
|
+
// See https://github.com/facebook/docusaurus/issues/4591#issuecomment-822372398
|
|
23
|
+
description: Joi.string().allow(''),
|
|
24
|
+
keywords: Joi.array().items(Joi.string().required()),
|
|
25
|
+
image: URISchema,
|
|
26
|
+
slug: Joi.string(),
|
|
27
|
+
wrapperClassName: Joi.string(),
|
|
28
|
+
hide_table_of_contents: Joi.boolean(),
|
|
29
|
+
...FrontMatterTOCHeadingLevels,
|
|
30
|
+
last_update: FrontMatterLastUpdateSchema,
|
|
31
|
+
}).concat(ContentVisibilitySchema);
|
|
32
|
+
|
|
33
|
+
export function validatePageFrontMatter(frontMatter: {
|
|
34
|
+
[key: string]: unknown;
|
|
35
|
+
}): PageFrontMatter {
|
|
36
|
+
return validateFrontMatter(frontMatter, PageFrontMatterSchema);
|
|
37
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
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 path from 'node:path';
|
|
9
|
+
import {
|
|
10
|
+
aliasedSitePath,
|
|
11
|
+
docuHash,
|
|
12
|
+
addTrailingPathSeparator,
|
|
13
|
+
getContentPathList,
|
|
14
|
+
resolveMarkdownLinkPathname,
|
|
15
|
+
} from '@docusaurus/utils';
|
|
16
|
+
import {createAbsoluteFilePathMatcher} from '@docusaurus/glob';
|
|
17
|
+
import {createMDXLoaderRule} from '@docusaurus/mdx-loader';
|
|
18
|
+
import {pathExists} from '@docusaurus/fs';
|
|
19
|
+
import {createAllRoutes} from './routes';
|
|
20
|
+
import {createPagesContentPaths, loadPagesContent} from './content';
|
|
21
|
+
import {createContentHelpers} from './contentHelpers';
|
|
22
|
+
import type {LoadContext, Plugin} from '@docusaurus/types';
|
|
23
|
+
import type {
|
|
24
|
+
PluginOptions,
|
|
25
|
+
LoadedContent,
|
|
26
|
+
PageFrontMatter,
|
|
27
|
+
} from '@docusaurus/plugin-content-pages';
|
|
28
|
+
import type {RuleSetRule} from 'webpack';
|
|
29
|
+
|
|
30
|
+
export default function pluginContentPages(
|
|
31
|
+
context: LoadContext,
|
|
32
|
+
options: PluginOptions,
|
|
33
|
+
): Plugin<LoadedContent | null> {
|
|
34
|
+
const {siteConfig, siteDir, generatedFilesDir} = context;
|
|
35
|
+
|
|
36
|
+
const contentPaths = createPagesContentPaths({context, options});
|
|
37
|
+
const contentHelpers = createContentHelpers();
|
|
38
|
+
|
|
39
|
+
const pluginDataDirRoot = path.join(
|
|
40
|
+
generatedFilesDir,
|
|
41
|
+
'docusaurus-plugin-content-pages',
|
|
42
|
+
);
|
|
43
|
+
const dataDir = path.join(pluginDataDirRoot, options.id);
|
|
44
|
+
|
|
45
|
+
function createPagesMDXLoaderRule(): RuleSetRule {
|
|
46
|
+
const {
|
|
47
|
+
admonitions,
|
|
48
|
+
rehypePlugins,
|
|
49
|
+
remarkPlugins,
|
|
50
|
+
recmaPlugins,
|
|
51
|
+
beforeDefaultRehypePlugins,
|
|
52
|
+
beforeDefaultRemarkPlugins,
|
|
53
|
+
} = options;
|
|
54
|
+
const contentDirs = getContentPathList(contentPaths);
|
|
55
|
+
|
|
56
|
+
return createMDXLoaderRule({
|
|
57
|
+
include: contentDirs
|
|
58
|
+
// Trailing slash is important, see https://github.com/facebook/docusaurus/pull/3970
|
|
59
|
+
.map(addTrailingPathSeparator),
|
|
60
|
+
options: {
|
|
61
|
+
admonitions,
|
|
62
|
+
remarkPlugins,
|
|
63
|
+
rehypePlugins,
|
|
64
|
+
recmaPlugins,
|
|
65
|
+
beforeDefaultRehypePlugins,
|
|
66
|
+
beforeDefaultRemarkPlugins,
|
|
67
|
+
staticDirs: siteConfig.staticDirectories.map((dir) =>
|
|
68
|
+
path.resolve(siteDir, dir),
|
|
69
|
+
),
|
|
70
|
+
siteDir,
|
|
71
|
+
isMDXPartial: createAbsoluteFilePathMatcher(
|
|
72
|
+
options.exclude,
|
|
73
|
+
contentDirs,
|
|
74
|
+
),
|
|
75
|
+
metadataPath: (mdxPath: string) => {
|
|
76
|
+
// Note that metadataPath must be the same/in-sync as
|
|
77
|
+
// the path from createData for each MDX.
|
|
78
|
+
const aliasedSource = aliasedSitePath(mdxPath, siteDir);
|
|
79
|
+
return path.join(dataDir, `${docuHash(aliasedSource)}.json`);
|
|
80
|
+
},
|
|
81
|
+
// createAssets converts relative paths to require() calls
|
|
82
|
+
createAssets: ({frontMatter}: {frontMatter: PageFrontMatter}) => ({
|
|
83
|
+
image: frontMatter.image,
|
|
84
|
+
}),
|
|
85
|
+
markdownConfig: siteConfig.markdown,
|
|
86
|
+
resolveMarkdownLink: ({linkPathname, sourceFilePath}) => {
|
|
87
|
+
return resolveMarkdownLinkPathname(linkPathname, {
|
|
88
|
+
sourceFilePath,
|
|
89
|
+
sourceToPermalink: contentHelpers.sourceToPermalink,
|
|
90
|
+
siteDir,
|
|
91
|
+
contentPaths,
|
|
92
|
+
});
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const pagesMDXLoaderRule = createPagesMDXLoaderRule();
|
|
99
|
+
|
|
100
|
+
return {
|
|
101
|
+
name: 'docusaurus-plugin-content-pages',
|
|
102
|
+
|
|
103
|
+
getPathsToWatch() {
|
|
104
|
+
const {include} = options;
|
|
105
|
+
return getContentPathList(contentPaths).flatMap((contentPath) =>
|
|
106
|
+
include.map((pattern) => `${contentPath}/${pattern}`),
|
|
107
|
+
);
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
async loadContent() {
|
|
111
|
+
if (!(await pathExists(contentPaths.contentPath))) {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
return loadPagesContent({context, options, contentPaths});
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
async contentLoaded({content, actions}) {
|
|
118
|
+
if (!content) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
contentHelpers.updateContent(content);
|
|
122
|
+
await createAllRoutes({content, options, actions});
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
configureWebpack() {
|
|
126
|
+
return {
|
|
127
|
+
module: {
|
|
128
|
+
rules: [pagesMDXLoaderRule],
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export {validateOptions} from './options';
|
package/src/options.ts
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
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
|
+
Joi,
|
|
10
|
+
RemarkPluginsSchema,
|
|
11
|
+
RehypePluginsSchema,
|
|
12
|
+
RecmaPluginsSchema,
|
|
13
|
+
AdmonitionsSchema,
|
|
14
|
+
RouteBasePathSchema,
|
|
15
|
+
URISchema,
|
|
16
|
+
} from '@docusaurus/utils-validation';
|
|
17
|
+
import {DEFAULT_PLUGIN_ID} from '@docusaurus/utils';
|
|
18
|
+
import {GlobExcludeDefault} from '@docusaurus/glob';
|
|
19
|
+
import type {OptionValidationContext} from '@docusaurus/types';
|
|
20
|
+
import type {PluginOptions, Options} from '@docusaurus/plugin-content-pages';
|
|
21
|
+
|
|
22
|
+
export const DEFAULT_OPTIONS: PluginOptions = {
|
|
23
|
+
id: DEFAULT_PLUGIN_ID,
|
|
24
|
+
path: 'src/pages', // Path to data on filesystem, relative to site dir.
|
|
25
|
+
routeBasePath: '/', // URL Route.
|
|
26
|
+
include: ['**/*.{js,jsx,ts,tsx,md,mdx}'], // Extensions to include.
|
|
27
|
+
exclude: GlobExcludeDefault,
|
|
28
|
+
mdxPageComponent: '@theme/MDXPage',
|
|
29
|
+
remarkPlugins: [],
|
|
30
|
+
rehypePlugins: [],
|
|
31
|
+
recmaPlugins: [],
|
|
32
|
+
beforeDefaultRehypePlugins: [],
|
|
33
|
+
beforeDefaultRemarkPlugins: [],
|
|
34
|
+
admonitions: true,
|
|
35
|
+
showLastUpdateTime: false,
|
|
36
|
+
showLastUpdateAuthor: false,
|
|
37
|
+
editLocalizedFiles: false,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const PluginOptionSchema = Joi.object<PluginOptions>({
|
|
41
|
+
path: Joi.string().default(DEFAULT_OPTIONS.path),
|
|
42
|
+
routeBasePath: RouteBasePathSchema.default(DEFAULT_OPTIONS.routeBasePath),
|
|
43
|
+
include: Joi.array().items(Joi.string()).default(DEFAULT_OPTIONS.include),
|
|
44
|
+
exclude: Joi.array().items(Joi.string()).default(DEFAULT_OPTIONS.exclude),
|
|
45
|
+
mdxPageComponent: Joi.string().default(DEFAULT_OPTIONS.mdxPageComponent),
|
|
46
|
+
remarkPlugins: RemarkPluginsSchema.default(DEFAULT_OPTIONS.remarkPlugins),
|
|
47
|
+
rehypePlugins: RehypePluginsSchema.default(DEFAULT_OPTIONS.rehypePlugins),
|
|
48
|
+
recmaPlugins: RecmaPluginsSchema.default(DEFAULT_OPTIONS.recmaPlugins),
|
|
49
|
+
beforeDefaultRehypePlugins: RehypePluginsSchema.default(
|
|
50
|
+
DEFAULT_OPTIONS.beforeDefaultRehypePlugins,
|
|
51
|
+
),
|
|
52
|
+
beforeDefaultRemarkPlugins: RemarkPluginsSchema.default(
|
|
53
|
+
DEFAULT_OPTIONS.beforeDefaultRemarkPlugins,
|
|
54
|
+
),
|
|
55
|
+
admonitions: AdmonitionsSchema.default(DEFAULT_OPTIONS.admonitions),
|
|
56
|
+
showLastUpdateTime: Joi.bool().default(DEFAULT_OPTIONS.showLastUpdateTime),
|
|
57
|
+
showLastUpdateAuthor: Joi.bool().default(
|
|
58
|
+
DEFAULT_OPTIONS.showLastUpdateAuthor,
|
|
59
|
+
),
|
|
60
|
+
editUrl: Joi.alternatives().try(URISchema, Joi.function()),
|
|
61
|
+
editLocalizedFiles: Joi.boolean().default(DEFAULT_OPTIONS.editLocalizedFiles),
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
export function validateOptions({
|
|
65
|
+
validate,
|
|
66
|
+
options,
|
|
67
|
+
}: OptionValidationContext<Options, PluginOptions>): PluginOptions {
|
|
68
|
+
const validatedOptions = validate(PluginOptionSchema, options);
|
|
69
|
+
return validatedOptions;
|
|
70
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
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
|
+
declare module '@docusaurus/plugin-content-pages' {
|
|
9
|
+
import type {MDXOptions} from '@docusaurus/mdx-loader';
|
|
10
|
+
import type {
|
|
11
|
+
LoadContext,
|
|
12
|
+
Plugin,
|
|
13
|
+
OptionValidationContext,
|
|
14
|
+
} from '@docusaurus/types';
|
|
15
|
+
import type {FrontMatterLastUpdate, LastUpdateData} from '@docusaurus/utils';
|
|
16
|
+
|
|
17
|
+
export type Assets = {
|
|
18
|
+
image?: string;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export type PluginOptions = MDXOptions & {
|
|
22
|
+
id: string;
|
|
23
|
+
path: string;
|
|
24
|
+
routeBasePath: string;
|
|
25
|
+
include: string[];
|
|
26
|
+
exclude: string[];
|
|
27
|
+
mdxPageComponent: string;
|
|
28
|
+
showLastUpdateTime: boolean;
|
|
29
|
+
showLastUpdateAuthor: boolean;
|
|
30
|
+
editUrl?: string | EditUrlFunction;
|
|
31
|
+
editLocalizedFiles?: boolean;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export type Options = Partial<PluginOptions>;
|
|
35
|
+
|
|
36
|
+
export type PageFrontMatter = {
|
|
37
|
+
readonly title?: string;
|
|
38
|
+
readonly description?: string;
|
|
39
|
+
readonly image?: string;
|
|
40
|
+
readonly slug?: string;
|
|
41
|
+
readonly keywords?: string[];
|
|
42
|
+
readonly wrapperClassName?: string;
|
|
43
|
+
readonly hide_table_of_contents?: string;
|
|
44
|
+
readonly toc_min_heading_level?: number;
|
|
45
|
+
readonly toc_max_heading_level?: number;
|
|
46
|
+
readonly draft?: boolean;
|
|
47
|
+
readonly unlisted?: boolean;
|
|
48
|
+
readonly last_update?: FrontMatterLastUpdate;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export type JSXPageMetadata = {
|
|
52
|
+
type: 'jsx';
|
|
53
|
+
permalink: string;
|
|
54
|
+
source: string;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export type MDXPageMetadata = LastUpdateData & {
|
|
58
|
+
type: 'mdx';
|
|
59
|
+
permalink: string;
|
|
60
|
+
source: string;
|
|
61
|
+
frontMatter: PageFrontMatter & {[key: string]: unknown};
|
|
62
|
+
editUrl?: string;
|
|
63
|
+
title?: string;
|
|
64
|
+
description?: string;
|
|
65
|
+
unlisted: boolean;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export type EditUrlFunction = (editUrlParams: {
|
|
69
|
+
/**
|
|
70
|
+
* The root content directory containing this post file, relative to the
|
|
71
|
+
* site path. Usually the same as `options.path` but can be localized
|
|
72
|
+
*/
|
|
73
|
+
pagesDirPath: string;
|
|
74
|
+
/** Path to this pages file, relative to `pagesDirPath`. */
|
|
75
|
+
pagesPath: string;
|
|
76
|
+
/** @see {@link PagesPostMetadata.permalink} */
|
|
77
|
+
permalink: string;
|
|
78
|
+
/** Locale name. */
|
|
79
|
+
locale: string;
|
|
80
|
+
}) => string | undefined;
|
|
81
|
+
|
|
82
|
+
export type Metadata = JSXPageMetadata | MDXPageMetadata;
|
|
83
|
+
|
|
84
|
+
export type LoadedContent = Metadata[];
|
|
85
|
+
|
|
86
|
+
export default function pluginContentPages(
|
|
87
|
+
context: LoadContext,
|
|
88
|
+
options: PluginOptions,
|
|
89
|
+
): Plugin<LoadedContent | null>;
|
|
90
|
+
|
|
91
|
+
export function validateOptions(
|
|
92
|
+
args: OptionValidationContext<Options | undefined, PluginOptions>,
|
|
93
|
+
): PluginOptions;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
declare module '@theme/MDXPage' {
|
|
97
|
+
import type {ReactNode} from 'react';
|
|
98
|
+
import type {LoadedMDXContent} from '@docusaurus/mdx-loader';
|
|
99
|
+
import type {
|
|
100
|
+
MDXPageMetadata,
|
|
101
|
+
PageFrontMatter,
|
|
102
|
+
Assets,
|
|
103
|
+
} from '@docusaurus/plugin-content-pages';
|
|
104
|
+
|
|
105
|
+
export interface Props {
|
|
106
|
+
readonly content: LoadedMDXContent<
|
|
107
|
+
PageFrontMatter,
|
|
108
|
+
MDXPageMetadata,
|
|
109
|
+
Assets
|
|
110
|
+
>;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export default function MDXPage(props: Props): ReactNode;
|
|
114
|
+
}
|
package/src/routes.ts
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
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 {aliasedSitePathToRelativePath, docuHash} from '@docusaurus/utils';
|
|
9
|
+
import type {
|
|
10
|
+
PluginContentLoadedActions,
|
|
11
|
+
RouteConfig,
|
|
12
|
+
RouteMetadata,
|
|
13
|
+
} from '@docusaurus/types';
|
|
14
|
+
import type {
|
|
15
|
+
PluginOptions,
|
|
16
|
+
Metadata,
|
|
17
|
+
LoadedContent,
|
|
18
|
+
MDXPageMetadata,
|
|
19
|
+
} from '@docusaurus/plugin-content-pages';
|
|
20
|
+
|
|
21
|
+
type CreateAllRoutesParam = {
|
|
22
|
+
content: LoadedContent;
|
|
23
|
+
options: PluginOptions;
|
|
24
|
+
actions: PluginContentLoadedActions;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
function createPageRouteMetadata(metadata: Metadata): RouteMetadata {
|
|
28
|
+
const lastUpdatedAt =
|
|
29
|
+
metadata.type === 'mdx' ? metadata.lastUpdatedAt : undefined;
|
|
30
|
+
return {
|
|
31
|
+
sourceFilePath: aliasedSitePathToRelativePath(metadata.source),
|
|
32
|
+
lastUpdatedAt,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export async function createAllRoutes(
|
|
37
|
+
param: CreateAllRoutesParam,
|
|
38
|
+
): Promise<void> {
|
|
39
|
+
const routes = await buildAllRoutes(param);
|
|
40
|
+
routes.forEach(param.actions.addRoute);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function buildAllRoutes({
|
|
44
|
+
content,
|
|
45
|
+
actions,
|
|
46
|
+
options,
|
|
47
|
+
}: CreateAllRoutesParam): Promise<RouteConfig[]> {
|
|
48
|
+
const {createData} = actions;
|
|
49
|
+
|
|
50
|
+
async function buildMDXPageRoute(
|
|
51
|
+
metadata: MDXPageMetadata,
|
|
52
|
+
): Promise<RouteConfig> {
|
|
53
|
+
await createData(
|
|
54
|
+
// Note that this created data path must be in sync with
|
|
55
|
+
// metadataPath provided to mdx-loader.
|
|
56
|
+
`${docuHash(metadata.source)}.json`,
|
|
57
|
+
metadata,
|
|
58
|
+
);
|
|
59
|
+
return {
|
|
60
|
+
path: metadata.permalink,
|
|
61
|
+
component: options.mdxPageComponent,
|
|
62
|
+
exact: true,
|
|
63
|
+
metadata: createPageRouteMetadata(metadata),
|
|
64
|
+
modules: {
|
|
65
|
+
content: metadata.source,
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async function buildJSXRoute(metadata: Metadata): Promise<RouteConfig> {
|
|
71
|
+
return {
|
|
72
|
+
path: metadata.permalink,
|
|
73
|
+
component: metadata.source,
|
|
74
|
+
exact: true,
|
|
75
|
+
metadata: createPageRouteMetadata(metadata),
|
|
76
|
+
modules: {
|
|
77
|
+
config: `@generated/docusaurus.config`,
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async function buildPageRoute(metadata: Metadata): Promise<RouteConfig> {
|
|
83
|
+
return metadata.type === 'mdx'
|
|
84
|
+
? buildMDXPageRoute(metadata)
|
|
85
|
+
: buildJSXRoute(metadata);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return Promise.all(content.map(buildPageRoute));
|
|
89
|
+
}
|