diff --git a/packages/docusaurus-mdx-loader/src/index.js b/packages/docusaurus-mdx-loader/src/index.js index 3081306ef1..3f93c0f8c9 100644 --- a/packages/docusaurus-mdx-loader/src/index.js +++ b/packages/docusaurus-mdx-loader/src/index.js @@ -72,6 +72,17 @@ module.exports = async function (fileString) { } } + if ( + options.forbidFrontMatter && + typeof options.forbidFrontMatter === 'function' + ) { + if ( + options.forbidFrontMatter(this.resourcePath) && + Object.keys(data).length > 0 + ) { + return callback(new Error(`Front matter is forbidden in this file`)); + } + } const code = ` import React from 'react'; import { mdx } from '@mdx-js/react'; diff --git a/packages/docusaurus-plugin-content-pages/package.json b/packages/docusaurus-plugin-content-pages/package.json index ba7958b5d4..7868fa42bd 100644 --- a/packages/docusaurus-plugin-content-pages/package.json +++ b/packages/docusaurus-plugin-content-pages/package.json @@ -23,7 +23,9 @@ "@hapi/joi": "17.1.1", "globby": "^10.0.1", "loader-utils": "^1.2.3", - "remark-admonitions": "^1.2.1" + "minimatch": "^3.0.4", + "remark-admonitions": "^1.2.1", + "slash": "^3.0.0" }, "peerDependencies": { "@docusaurus/core": "^2.0.0", diff --git a/packages/docusaurus-plugin-content-pages/src/__tests__/__fixtures__/website/src/pages/hello/_ignore.js b/packages/docusaurus-plugin-content-pages/src/__tests__/__fixtures__/website/src/pages/hello/_ignore.js new file mode 100644 index 0000000000..27672446b8 --- /dev/null +++ b/packages/docusaurus-plugin-content-pages/src/__tests__/__fixtures__/website/src/pages/hello/_ignore.js @@ -0,0 +1 @@ +export default (a,b)=>a+b \ No newline at end of file diff --git a/packages/docusaurus-plugin-content-pages/src/__tests__/__fixtures__/website/src/pages/hello/_ignore.md b/packages/docusaurus-plugin-content-pages/src/__tests__/__fixtures__/website/src/pages/hello/_ignore.md new file mode 100644 index 0000000000..a42f8b6e8c --- /dev/null +++ b/packages/docusaurus-plugin-content-pages/src/__tests__/__fixtures__/website/src/pages/hello/_ignore.md @@ -0,0 +1 @@ +# ignored \ No newline at end of file diff --git a/packages/docusaurus-plugin-content-pages/src/__tests__/__fixtures__/website/src/pages/hello/_ignore.mdx b/packages/docusaurus-plugin-content-pages/src/__tests__/__fixtures__/website/src/pages/hello/_ignore.mdx new file mode 100644 index 0000000000..a42f8b6e8c --- /dev/null +++ b/packages/docusaurus-plugin-content-pages/src/__tests__/__fixtures__/website/src/pages/hello/_ignore.mdx @@ -0,0 +1 @@ +# ignored \ No newline at end of file diff --git a/packages/docusaurus-plugin-content-pages/src/__tests__/__fixtures__/website/src/pages/hello/_ignore.tsx b/packages/docusaurus-plugin-content-pages/src/__tests__/__fixtures__/website/src/pages/hello/_ignore.tsx new file mode 100644 index 0000000000..53a73c1e90 --- /dev/null +++ b/packages/docusaurus-plugin-content-pages/src/__tests__/__fixtures__/website/src/pages/hello/_ignore.tsx @@ -0,0 +1 @@ +export default (a:number,b:number)=>a+b; \ No newline at end of file diff --git a/packages/docusaurus-plugin-content-pages/src/__tests__/pluginOptionSchema.test.ts b/packages/docusaurus-plugin-content-pages/src/__tests__/pluginOptionSchema.test.ts index dd93ec0a00..5ed170d1f1 100644 --- a/packages/docusaurus-plugin-content-pages/src/__tests__/pluginOptionSchema.test.ts +++ b/packages/docusaurus-plugin-content-pages/src/__tests__/pluginOptionSchema.test.ts @@ -10,7 +10,7 @@ import {PluginOptions} from '../types'; export default function normalizePluginOptions( options: Partial, -) { +): PluginOptions { const {value, error} = PluginOptionSchema.validate(options, { convert: false, }); @@ -37,6 +37,7 @@ describe('normalizePagesPluginOptions', () => { path: 'src/my-pages', routeBasePath: 'my-pages', include: ['**/*.{js,jsx,ts,tsx}'], + exclude: ['**/$*/'], }; const value = normalizePluginOptions(userOptions); expect(value).toEqual({...DEFAULT_OPTIONS, ...userOptions}); diff --git a/packages/docusaurus-plugin-content-pages/src/index.ts b/packages/docusaurus-plugin-content-pages/src/index.ts index 8a29d781c6..de51bcbb93 100644 --- a/packages/docusaurus-plugin-content-pages/src/index.ts +++ b/packages/docusaurus-plugin-content-pages/src/index.ts @@ -8,6 +8,8 @@ import globby from 'globby'; import fs from 'fs'; import path from 'path'; +import minimatch from 'minimatch'; +import slash from 'slash'; import { encodePath, fileToPath, @@ -51,6 +53,11 @@ export default function pluginContentPages( ); const dataDir = path.join(pluginDataDirRoot, options.id ?? DEFAULT_PLUGIN_ID); + const excludeRegex = new RegExp( + options.exclude + .map((pattern) => minimatch.makeRe(pattern).source) + .join('|'), + ); return { name: 'docusaurus-plugin-content-pages', @@ -81,6 +88,7 @@ export default function pluginContentPages( const {baseUrl} = siteConfig; const pagesFiles = await globby(include, { cwd: pagesDir, + ignore: options.exclude, }); function toMetadata(relativeSource: string): Metadata { @@ -173,12 +181,17 @@ export default function pluginContentPages( // Note that metadataPath must be the same/in-sync as // the path from createData for each MDX. metadataPath: (mdxPath: string) => { - const aliasedPath = aliasedSitePath(mdxPath, siteDir); + if (excludeRegex.test(slash(mdxPath))) { + return null; + } + const aliasedSource = aliasedSitePath(mdxPath, siteDir); return path.join( dataDir, - `${docuHash(aliasedPath)}.json`, + `${docuHash(aliasedSource)}.json`, ); }, + forbidFrontMatter: (mdxPath: string) => + excludeRegex.test(slash(mdxPath)), }, }, { diff --git a/packages/docusaurus-plugin-content-pages/src/pluginOptionSchema.ts b/packages/docusaurus-plugin-content-pages/src/pluginOptionSchema.ts index b5d3dd29ef..9719ed90a6 100644 --- a/packages/docusaurus-plugin-content-pages/src/pluginOptionSchema.ts +++ b/packages/docusaurus-plugin-content-pages/src/pluginOptionSchema.ts @@ -20,12 +20,18 @@ export const DEFAULT_OPTIONS: PluginOptions = { remarkPlugins: [], rehypePlugins: [], admonitions: {}, + exclude: [ + '**/_*.{js,jsx,ts,tsx,md,mdx}', + '**/*.test.{js,ts}', + '**/__tests__/**', + ], }; export const PluginOptionSchema = Joi.object({ path: Joi.string().default(DEFAULT_OPTIONS.path), routeBasePath: Joi.string().default(DEFAULT_OPTIONS.routeBasePath), include: Joi.array().items(Joi.string()).default(DEFAULT_OPTIONS.include), + exclude: Joi.array().items(Joi.string()).default(DEFAULT_OPTIONS.exclude), mdxPageComponent: Joi.string().default(DEFAULT_OPTIONS.mdxPageComponent), remarkPlugins: RemarkPluginsSchema.default(DEFAULT_OPTIONS.remarkPlugins), rehypePlugins: RehypePluginsSchema.default(DEFAULT_OPTIONS.rehypePlugins), diff --git a/packages/docusaurus-plugin-content-pages/src/types.ts b/packages/docusaurus-plugin-content-pages/src/types.ts index 99f3f00d34..32b820715c 100644 --- a/packages/docusaurus-plugin-content-pages/src/types.ts +++ b/packages/docusaurus-plugin-content-pages/src/types.ts @@ -10,6 +10,7 @@ export interface PluginOptions { path: string; routeBasePath: string; include: string[]; + exclude: string[]; mdxPageComponent: string; remarkPlugins: ([Function, object] | Function)[]; rehypePlugins: string[]; diff --git a/website/docs/guides/creating-pages.md b/website/docs/guides/creating-pages.md index 5bb125d30e..7eb77ab5b9 100644 --- a/website/docs/guides/creating-pages.md +++ b/website/docs/guides/creating-pages.md @@ -91,7 +91,7 @@ In this component-based development era, it is encouraged to co-locate your styl - Add a `/src/pages/support.js` file - Create a `/src/pages/support/` directory and a `/src/pages/support/index.js` file. -The latter is preferred as it has the benefits of letting you put files related to the page within that directory. For example, a CSS module file (`styles.module.css`) with styles meant to only be used on the "Support" page. **Note:** this is merely a recommended directory structure and you will still need to manually import the CSS module file within your component module (`support/index.js`). +The latter is preferred as it has the benefits of letting you put files related to the page within that directory. For example, a CSS module file (`styles.module.css`) with styles meant to only be used on the "Support" page. **Note:** this is merely a recommended directory structure and you will still need to manually import the CSS module file within your component module (`support/index.js`). By default, any Markdown or Javascript file starting with `_` will be ignored, and no routes will be created for that file (see the `exclude` option). ```sh my-website @@ -99,6 +99,7 @@ my-website │ └── pages │ ├── styles.module.css │ ├── index.js +| ├──_ignored.js │ └── support │ ├── index.js │ └── styles.module.css @@ -107,7 +108,7 @@ my-website :::caution -All JavaScript/TypeScript files within the `src/pages/` directory will have corresponding website paths generated for them. Do not put reusable components or test files (ending with `.test.js`) into that directory otherwise they will be turned into pages, which might not be intended. +All JavaScript/TypeScript files within the `src/pages/` directory will have corresponding website paths generated for them. If you want to create reusable components into that directory, use the `exclude` option (by default, files prefixed with `_`, test files(`.test.js`) and files in `__tests__` directory are not turned into pages). ::: diff --git a/website/docs/using-plugins.md b/website/docs/using-plugins.md index 2acc349b02..13a1185c2f 100644 --- a/website/docs/using-plugins.md +++ b/website/docs/using-plugins.md @@ -375,7 +375,15 @@ module.exports = { * do not include trailing slash */ routeBasePath: '', - include: ['**/*.{js,jsx}'], + include: ['**/*.{js,jsx,ts,tsx,md,mdx}'], + /** + * No Route will be created for matching files + */ + exclude: [ + '**/_*.{js,jsx,ts,tsx,md,mdx}', + '**/*.test.{js,ts}', + '**/__tests__/**', + ], /** * Theme component used by markdown pages. */ diff --git a/website/src/pages/examples/_chapter1.md b/website/src/pages/examples/_chapter1.md new file mode 100644 index 0000000000..b7cac1eae7 --- /dev/null +++ b/website/src/pages/examples/_chapter1.md @@ -0,0 +1,3 @@ +# Chapter 1 + +Lorem ipsum chapter 1 diff --git a/website/src/pages/examples/_chapter2.mdx b/website/src/pages/examples/_chapter2.mdx new file mode 100644 index 0000000000..45dbbc0388 --- /dev/null +++ b/website/src/pages/examples/_chapter2.mdx @@ -0,0 +1,3 @@ +# Chapter 2 + +Lorem ipsum chapter 2 diff --git a/website/src/pages/examples/markdownPageExample.md b/website/src/pages/examples/markdownPageExample.md index 9cbb1bf1aa..c30f43508d 100644 --- a/website/src/pages/examples/markdownPageExample.md +++ b/website/src/pages/examples/markdownPageExample.md @@ -32,3 +32,25 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; This is an apple 🍎This is an orange 🍊This is a banana 🍌 + +## Import Mdx and Md files + +```js +// *.md file +import Chapter1 from './_chapter1.md'; + + + +// *.mdx file +import Chapter2 from './_chapter2.mdx'; + + +``` + +import Chapter1 from './\_chapter2.mdx'; + + + +import Chapter2 from './\_chapter2.mdx'; + +