@docusaurus/plugin-content-pages 2.0.0-beta.15d451942 → 2.0.0-beta.18

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.
Files changed (35) hide show
  1. package/{src/__tests__/__fixtures__/website/i18n/fr/docusaurus-plugin-content-pages/hello/translatedJs.js → lib/frontMatter.d.ts} +4 -8
  2. package/lib/frontMatter.js +21 -0
  3. package/lib/index.d.ts +5 -4
  4. package/lib/index.js +43 -59
  5. package/lib/markdownLoader.d.ts +2 -6
  6. package/lib/markdownLoader.js +4 -4
  7. package/lib/options.d.ts +10 -0
  8. package/lib/{pluginOptionSchema.js → options.js} +15 -7
  9. package/lib/types.d.ts +1 -21
  10. package/package.json +13 -14
  11. package/{types.d.ts → src/deps.d.ts} +1 -1
  12. package/src/frontMatter.ts +27 -0
  13. package/src/index.ts +54 -81
  14. package/src/markdownLoader.ts +8 -11
  15. package/src/{pluginOptionSchema.ts → options.ts} +14 -7
  16. package/src/plugin-content-pages.d.ts +51 -12
  17. package/src/types.ts +1 -25
  18. package/lib/.tsbuildinfo +0 -4393
  19. package/lib/pluginOptionSchema.d.ts +0 -10
  20. package/src/__tests__/__fixtures__/website/docusaurus.config.js +0 -14
  21. package/src/__tests__/__fixtures__/website/i18n/fr/docusaurus-plugin-content-pages/hello/translatedMd.md +0 -1
  22. package/src/__tests__/__fixtures__/website/src/pages/hello/_ignore.js +0 -1
  23. package/src/__tests__/__fixtures__/website/src/pages/hello/_ignore.md +0 -1
  24. package/src/__tests__/__fixtures__/website/src/pages/hello/_ignore.mdx +0 -1
  25. package/src/__tests__/__fixtures__/website/src/pages/hello/_ignore.tsx +0 -1
  26. package/src/__tests__/__fixtures__/website/src/pages/hello/index.md +0 -2
  27. package/src/__tests__/__fixtures__/website/src/pages/hello/mdxPage.mdx +0 -5
  28. package/src/__tests__/__fixtures__/website/src/pages/hello/translatedJs.js +0 -14
  29. package/src/__tests__/__fixtures__/website/src/pages/hello/translatedMd.md +0 -1
  30. package/src/__tests__/__fixtures__/website/src/pages/hello/world.js +0 -22
  31. package/src/__tests__/__fixtures__/website/src/pages/index.js +0 -23
  32. package/src/__tests__/__fixtures__/website/src/pages/typescript.tsx +0 -22
  33. package/src/__tests__/index.test.ts +0 -139
  34. package/src/__tests__/pluginOptionSchema.test.ts +0 -54
  35. package/tsconfig.json +0 -9
package/src/index.ts CHANGED
@@ -5,11 +5,8 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- import globby from 'globby';
9
- import fs from 'fs';
8
+ import fs from 'fs-extra';
10
9
  import path from 'path';
11
- import minimatch from 'minimatch';
12
- import slash from 'slash';
13
10
  import {
14
11
  encodePath,
15
12
  fileToPath,
@@ -18,29 +15,18 @@ import {
18
15
  getPluginI18nPath,
19
16
  getFolderContainingFile,
20
17
  addTrailingPathSeparator,
18
+ Globby,
19
+ createAbsoluteFilePathMatcher,
20
+ normalizeUrl,
21
+ DEFAULT_PLUGIN_ID,
22
+ parseMarkdownString,
21
23
  } from '@docusaurus/utils';
22
- import {
23
- LoadContext,
24
- Plugin,
25
- OptionValidationContext,
26
- ValidationResult,
27
- ConfigureWebpackUtils,
28
- } from '@docusaurus/types';
29
- import {Configuration} from 'webpack';
24
+ import type {LoadContext, Plugin} from '@docusaurus/types';
30
25
  import admonitions from 'remark-admonitions';
31
- import {PluginOptionSchema} from './pluginOptionSchema';
32
- import {
33
- DEFAULT_PLUGIN_ID,
34
- STATIC_DIR_NAME,
35
- } from '@docusaurus/core/lib/constants';
26
+ import {validatePageFrontMatter} from './frontMatter';
36
27
 
37
- import {
38
- PluginOptions,
39
- LoadedContent,
40
- Metadata,
41
- PagesContentPaths,
42
- } from './types';
43
- import {flatten} from 'lodash';
28
+ import type {LoadedContent, PagesContentPaths} from './types';
29
+ import type {PluginOptions, Metadata} from '@docusaurus/plugin-content-pages';
44
30
 
45
31
  export function getContentPathList(contentPaths: PagesContentPaths): string[] {
46
32
  return [contentPaths.contentPathLocalized, contentPaths.contentPath];
@@ -49,13 +35,13 @@ export function getContentPathList(contentPaths: PagesContentPaths): string[] {
49
35
  const isMarkdownSource = (source: string) =>
50
36
  source.endsWith('.md') || source.endsWith('.mdx');
51
37
 
52
- export default function pluginContentPages(
38
+ export default async function pluginContentPages(
53
39
  context: LoadContext,
54
40
  options: PluginOptions,
55
- ): Plugin<LoadedContent | null> {
41
+ ): Promise<Plugin<LoadedContent | null>> {
56
42
  if (options.admonitions) {
57
43
  options.remarkPlugins = options.remarkPlugins.concat([
58
- [admonitions, options.admonitions || {}],
44
+ [admonitions, options.admonitions],
59
45
  ]);
60
46
  }
61
47
  const {
@@ -81,42 +67,25 @@ export default function pluginContentPages(
81
67
  );
82
68
  const dataDir = path.join(pluginDataDirRoot, options.id ?? DEFAULT_PLUGIN_ID);
83
69
 
84
- const excludeRegex = new RegExp(
85
- options.exclude
86
- .map((pattern) => minimatch.makeRe(pattern).source)
87
- .join('|'),
88
- );
89
70
  return {
90
71
  name: 'docusaurus-plugin-content-pages',
91
72
 
92
73
  getPathsToWatch() {
93
- const {include = []} = options;
94
- return flatten(
95
- getContentPathList(contentPaths).map((contentPath) => {
96
- return include.map((pattern) => `${contentPath}/${pattern}`);
97
- }),
74
+ const {include} = options;
75
+ return getContentPathList(contentPaths).flatMap((contentPath) =>
76
+ include.map((pattern) => `${contentPath}/${pattern}`),
98
77
  );
99
78
  },
100
79
 
101
- getClientModules() {
102
- const modules = [];
103
-
104
- if (options.admonitions) {
105
- modules.push(require.resolve('remark-admonitions/styles/infima.css'));
106
- }
107
-
108
- return modules;
109
- },
110
-
111
80
  async loadContent() {
112
81
  const {include} = options;
113
82
 
114
- if (!fs.existsSync(contentPaths.contentPath)) {
83
+ if (!(await fs.pathExists(contentPaths.contentPath))) {
115
84
  return null;
116
85
  }
117
86
 
118
87
  const {baseUrl} = siteConfig;
119
- const pagesFiles = await globby(include, {
88
+ const pagesFiles = await Globby(include, {
120
89
  cwd: contentPaths.contentPath,
121
90
  ignore: options.exclude,
122
91
  });
@@ -130,21 +99,33 @@ export default function pluginContentPages(
130
99
 
131
100
  const source = path.join(contentPath, relativeSource);
132
101
  const aliasedSourcePath = aliasedSitePath(source, siteDir);
133
- const pathName = encodePath(fileToPath(relativeSource));
134
- const permalink = pathName.replace(/^\//, baseUrl || '');
135
- if (isMarkdownSource(relativeSource)) {
136
- return {
137
- type: 'mdx',
138
- permalink,
139
- source: aliasedSourcePath,
140
- };
141
- } else {
102
+ const permalink = normalizeUrl([
103
+ baseUrl,
104
+ options.routeBasePath,
105
+ encodePath(fileToPath(relativeSource)),
106
+ ]);
107
+ if (!isMarkdownSource(relativeSource)) {
142
108
  return {
143
109
  type: 'jsx',
144
110
  permalink,
145
111
  source: aliasedSourcePath,
146
112
  };
147
113
  }
114
+ const content = await fs.readFile(source, 'utf-8');
115
+ const {
116
+ frontMatter: unsafeFrontMatter,
117
+ contentTitle,
118
+ excerpt,
119
+ } = parseMarkdownString(content);
120
+ const frontMatter = validatePageFrontMatter(unsafeFrontMatter);
121
+ return {
122
+ type: 'mdx',
123
+ permalink,
124
+ source: aliasedSourcePath,
125
+ title: frontMatter.title ?? contentTitle,
126
+ description: frontMatter.description ?? excerpt,
127
+ frontMatter,
128
+ };
148
129
  }
149
130
 
150
131
  return Promise.all(pagesFiles.map(toMetadata));
@@ -189,17 +170,14 @@ export default function pluginContentPages(
189
170
  );
190
171
  },
191
172
 
192
- configureWebpack(
193
- _config: Configuration,
194
- isServer: boolean,
195
- {getJSLoader}: ConfigureWebpackUtils,
196
- ) {
173
+ configureWebpack(config, isServer, {getJSLoader}) {
197
174
  const {
198
175
  rehypePlugins,
199
176
  remarkPlugins,
200
177
  beforeDefaultRehypePlugins,
201
178
  beforeDefaultRemarkPlugins,
202
179
  } = options;
180
+ const contentDirs = getContentPathList(contentPaths);
203
181
  return {
204
182
  resolve: {
205
183
  alias: {
@@ -209,8 +187,8 @@ export default function pluginContentPages(
209
187
  module: {
210
188
  rules: [
211
189
  {
212
- test: /(\.mdx?)$/,
213
- include: getContentPathList(contentPaths)
190
+ test: /\.mdx?$/i,
191
+ include: contentDirs
214
192
  // Trailing slash is important, see https://github.com/facebook/docusaurus/pull/3970
215
193
  .map(addTrailingPathSeparator),
216
194
  use: [
@@ -222,22 +200,23 @@ export default function pluginContentPages(
222
200
  rehypePlugins,
223
201
  beforeDefaultRehypePlugins,
224
202
  beforeDefaultRemarkPlugins,
225
- keepContentTitle: true,
226
- staticDir: path.join(siteDir, STATIC_DIR_NAME),
227
- // Note that metadataPath must be the same/in-sync as
228
- // the path from createData for each MDX.
203
+ staticDirs: siteConfig.staticDirectories.map((dir) =>
204
+ path.resolve(siteDir, dir),
205
+ ),
206
+ siteDir,
207
+ isMDXPartial: createAbsoluteFilePathMatcher(
208
+ options.exclude,
209
+ contentDirs,
210
+ ),
229
211
  metadataPath: (mdxPath: string) => {
230
- if (excludeRegex.test(slash(mdxPath))) {
231
- return null;
232
- }
212
+ // Note that metadataPath must be the same/in-sync as
213
+ // the path from createData for each MDX.
233
214
  const aliasedSource = aliasedSitePath(mdxPath, siteDir);
234
215
  return path.join(
235
216
  dataDir,
236
217
  `${docuHash(aliasedSource)}.json`,
237
218
  );
238
219
  },
239
- forbidFrontMatter: (mdxPath: string) =>
240
- excludeRegex.test(slash(mdxPath)),
241
220
  },
242
221
  },
243
222
  {
@@ -256,10 +235,4 @@ export default function pluginContentPages(
256
235
  };
257
236
  }
258
237
 
259
- export function validateOptions({
260
- validate,
261
- options,
262
- }: OptionValidationContext<PluginOptions>): ValidationResult<PluginOptions> {
263
- const validatedOptions = validate(PluginOptionSchema, options);
264
- return validatedOptions;
265
- }
238
+ export {validateOptions} from './options';
@@ -5,21 +5,18 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- // TODO temporary until Webpack5 export this type
9
- // see https://github.com/webpack/webpack/issues/11630
10
- interface Loader extends Function {
11
- (this: any, source: string): string | Buffer | void | undefined;
12
- }
8
+ import type {LoaderContext} from 'webpack';
13
9
 
14
- const markdownLoader: Loader = function (fileString) {
10
+ export default function markdownLoader(
11
+ this: LoaderContext<undefined>,
12
+ fileString: string,
13
+ ): void {
15
14
  const callback = this.async();
16
15
 
17
16
  // const options = this.getOptions();
18
17
 
19
- // TODO provide additinal md processing here? like interlinking pages?
18
+ // TODO provide additional md processing here? like interlinking pages?
20
19
  // fileString = linkify(fileString)
21
20
 
22
- return callback && callback(null, fileString);
23
- };
24
-
25
- export default markdownLoader;
21
+ return callback?.(null, fileString);
22
+ }
@@ -4,32 +4,31 @@
4
4
  * This source code is licensed under the MIT license found in the
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
- import {PluginOptions} from './types';
7
+
8
+ import type {PluginOptions, Options} from '@docusaurus/plugin-content-pages';
8
9
  import {
9
10
  Joi,
10
11
  RemarkPluginsSchema,
11
12
  RehypePluginsSchema,
12
13
  AdmonitionsSchema,
13
14
  } from '@docusaurus/utils-validation';
15
+ import {GlobExcludeDefault} from '@docusaurus/utils';
16
+ import type {OptionValidationContext} from '@docusaurus/types';
14
17
 
15
18
  export const DEFAULT_OPTIONS: PluginOptions = {
16
19
  path: 'src/pages', // Path to data on filesystem, relative to site dir.
17
20
  routeBasePath: '/', // URL Route.
18
21
  include: ['**/*.{js,jsx,ts,tsx,md,mdx}'], // Extensions to include.
22
+ exclude: GlobExcludeDefault,
19
23
  mdxPageComponent: '@theme/MDXPage',
20
24
  remarkPlugins: [],
21
25
  rehypePlugins: [],
22
26
  beforeDefaultRehypePlugins: [],
23
27
  beforeDefaultRemarkPlugins: [],
24
28
  admonitions: {},
25
- exclude: [
26
- '**/_*.{js,jsx,ts,tsx,md,mdx}',
27
- '**/*.test.{js,ts}',
28
- '**/__tests__/**',
29
- ],
30
29
  };
31
30
 
32
- export const PluginOptionSchema = Joi.object({
31
+ const PluginOptionSchema = Joi.object({
33
32
  path: Joi.string().default(DEFAULT_OPTIONS.path),
34
33
  routeBasePath: Joi.string().default(DEFAULT_OPTIONS.routeBasePath),
35
34
  include: Joi.array().items(Joi.string()).default(DEFAULT_OPTIONS.include),
@@ -45,3 +44,11 @@ export const PluginOptionSchema = Joi.object({
45
44
  ),
46
45
  admonitions: AdmonitionsSchema.default(DEFAULT_OPTIONS.admonitions),
47
46
  });
47
+
48
+ export function validateOptions({
49
+ validate,
50
+ options,
51
+ }: OptionValidationContext<Options, PluginOptions>): PluginOptions {
52
+ const validatedOptions = validate(PluginOptionSchema, options);
53
+ return validatedOptions;
54
+ }
@@ -5,24 +5,63 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
+ declare module '@docusaurus/plugin-content-pages' {
9
+ import type {RemarkAndRehypePluginOptions} from '@docusaurus/mdx-loader';
10
+
11
+ export type PluginOptions = RemarkAndRehypePluginOptions & {
12
+ id?: string;
13
+ path: string;
14
+ routeBasePath: string;
15
+ include: string[];
16
+ exclude: string[];
17
+ mdxPageComponent: string;
18
+ admonitions: {[key: string]: unknown};
19
+ };
20
+
21
+ export type Options = Partial<PluginOptions>;
22
+
23
+ export type FrontMatter = {
24
+ readonly title?: string;
25
+ readonly description?: string;
26
+ readonly wrapperClassName?: string;
27
+ readonly hide_table_of_contents?: string;
28
+ readonly toc_min_heading_level?: number;
29
+ readonly toc_max_heading_level?: number;
30
+ };
31
+
32
+ export type JSXPageMetadata = {
33
+ type: 'jsx';
34
+ permalink: string;
35
+ source: string;
36
+ };
37
+
38
+ export type MDXPageMetadata = {
39
+ type: 'mdx';
40
+ permalink: string;
41
+ source: string;
42
+ frontMatter: FrontMatter & {[key: string]: unknown};
43
+ title?: string;
44
+ description?: string;
45
+ };
46
+
47
+ export type Metadata = JSXPageMetadata | MDXPageMetadata;
48
+ }
49
+
8
50
  declare module '@theme/MDXPage' {
9
51
  import type {TOCItem} from '@docusaurus/types';
52
+ import type {
53
+ MDXPageMetadata,
54
+ FrontMatter,
55
+ } from '@docusaurus/plugin-content-pages';
10
56
 
11
- export type Props = {
57
+ export interface Props {
12
58
  readonly content: {
13
- readonly frontMatter: {
14
- readonly title: string;
15
- readonly description: string;
16
- readonly wrapperClassName?: string;
17
- // eslint-disable-next-line camelcase
18
- readonly hide_table_of_contents?: string;
19
- };
20
- readonly metadata: {readonly permalink: string};
59
+ readonly frontMatter: FrontMatter;
60
+ readonly metadata: MDXPageMetadata;
21
61
  readonly toc: readonly TOCItem[];
22
62
  (): JSX.Element;
23
63
  };
24
- };
64
+ }
25
65
 
26
- const MDXPage: (props: Props) => JSX.Element;
27
- export default MDXPage;
66
+ export default function MDXPage(props: Props): JSX.Element;
28
67
  }
package/src/types.ts CHANGED
@@ -5,31 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- import type {RemarkAndRehypePluginOptions} from '@docusaurus/mdx-loader';
9
-
10
- export interface PluginOptions extends RemarkAndRehypePluginOptions {
11
- id?: string;
12
- path: string;
13
- routeBasePath: string;
14
- include: string[];
15
- exclude: string[];
16
- mdxPageComponent: string;
17
- admonitions: Record<string, unknown>;
18
- }
19
-
20
- export type JSXPageMetadata = {
21
- type: 'jsx';
22
- permalink: string;
23
- source: string;
24
- };
25
-
26
- export type MDXPageMetadata = {
27
- type: 'mdx';
28
- permalink: string;
29
- source: string;
30
- };
31
-
32
- export type Metadata = JSXPageMetadata | MDXPageMetadata;
8
+ import type {Metadata} from '@docusaurus/plugin-content-pages';
33
9
 
34
10
  export type LoadedContent = Metadata[];
35
11