diff --git a/CHANGELOG.md b/CHANGELOG.md index d21ff2bfea..480902659a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1309,7 +1309,7 @@ Starting with this release for a proper work of i18n functionality, you need to #### :rocket: New Feature - `docusaurus` - - [#3932](https://github.com/facebook/docusaurus/pull/3932) feat(v2): Add theme element ([@slorber](https://github.com/slorber)) + - [#3932](https://github.com/facebook/docusaurus/pull/3932) feat(v2): Add Root theme element ([@slorber](https://github.com/slorber)) - `docusaurus-module-type-aliases`, `docusaurus-theme-classic`, `docusaurus-types`, `docusaurus` - [#3916](https://github.com/facebook/docusaurus/pull/3916) feat(v2): Add localeDropdown navbar item type + i18n localeConfigs field ([@slorber](https://github.com/slorber)) - `docusaurus-mdx-loader`, `docusaurus-plugin-content-blog`, `docusaurus-plugin-content-docs`, `docusaurus-plugin-content-pages`, `docusaurus-theme-bootstrap`, `docusaurus-theme-classic`, `docusaurus-types` diff --git a/packages/docusaurus-mdx-loader/src/index.js b/packages/docusaurus-mdx-loader/src/index.js index 19890d9b64..82cb639524 100644 --- a/packages/docusaurus-mdx-loader/src/index.js +++ b/packages/docusaurus-mdx-loader/src/index.js @@ -98,11 +98,16 @@ File at ${filePath} contains FrontMatter that will be ignored: \n${JSON.stringif null, 2, )}`; - const shouldError = process.env.NODE_ENV === 'test' || process.env.CI; - if (shouldError) { - return callback(new Error(errorMessage)); + + if (options.isMDXPartialFrontMatterWarningDisabled === true) { + // no warning } else { - console.warn(chalk.yellow(errorMessage)); + const shouldError = process.env.NODE_ENV === 'test' || process.env.CI; + if (shouldError) { + return callback(new Error(errorMessage)); + } else { + console.warn(chalk.yellow(errorMessage)); + } } } diff --git a/packages/docusaurus/src/server/index.ts b/packages/docusaurus/src/server/index.ts index edbb0791ec..6dbb993d32 100644 --- a/packages/docusaurus/src/server/index.ts +++ b/packages/docusaurus/src/server/index.ts @@ -13,6 +13,7 @@ import { DEFAULT_BUILD_DIR_NAME, DEFAULT_CONFIG_FILE_NAME, GENERATED_FILES_DIR_NAME, + STATIC_DIR_NAME, } from '../constants'; import loadClientModules from './client-modules'; import loadConfig from './config'; @@ -24,6 +25,7 @@ import { DocusaurusSiteMetadata, HtmlTagObject, LoadContext, + LoadedPlugin, PluginConfig, Props, } from '@docusaurus/types'; @@ -36,6 +38,7 @@ import { getPluginsDefaultCodeTranslationMessages, } from './translations/translations'; import {mapValues} from 'lodash'; +import {RuleSetRule} from 'webpack'; export type LoadContextOptions = { customOutDir?: string; @@ -135,6 +138,104 @@ export function loadPluginConfigs(context: LoadContext): PluginConfig[] { ]; } +// Make a fake plugin to: +// - Resolve aliased theme components +// - Inject scripts/stylesheets +function createBootstrapPlugin({ + siteConfig, +}: { + siteConfig: DocusaurusConfig; +}): LoadedPlugin { + const { + stylesheets = [], + scripts = [], + clientModules: siteConfigClientModules = [], + } = siteConfig; + return { + name: 'docusaurus-bootstrap-plugin', + content: null, + options: {}, + version: {type: 'synthetic'}, + getClientModules() { + return siteConfigClientModules; + }, + injectHtmlTags: () => { + const stylesheetsTags = stylesheets.map((source) => + typeof source === 'string' + ? `` + : ({ + tagName: 'link', + attributes: { + rel: 'stylesheet', + ...source, + }, + } as HtmlTagObject), + ); + const scriptsTags = scripts.map((source) => + typeof source === 'string' + ? `` + : ({ + tagName: 'script', + attributes: { + ...source, + }, + } as HtmlTagObject), + ); + return { + headTags: [...stylesheetsTags, ...scriptsTags], + }; + }, + }; +} + +// Configurer Webpack fallback mdx loader for md/mdx files out of content-plugin folders +// Adds a "fallback" mdx loader for mdx files that are not processed by content plugins +// This allows to do things such as importing repo/README.md as a partial from another doc +// Not ideal solution though, but good enough for now +function createMDXFallbackPlugin({siteDir}: {siteDir: string}): LoadedPlugin { + return { + name: 'docusaurus-mdx-fallback-plugin', + content: null, + options: {}, + version: {type: 'synthetic'}, + configureWebpack(config, isServer, {getJSLoader}) { + // We need the mdx fallback loader to exclude files that were already processed by content plugins mdx loaders + // This works, but a bit hacky... + // Not sure there's a way to handle that differently in webpack :s + function getMDXFallbackExcludedPaths(): string[] { + const rules: RuleSetRule[] = config?.module?.rules as RuleSetRule[]; + return rules.flatMap((rule) => { + const isMDXRule = + rule.test instanceof RegExp && rule.test.test('x.mdx'); + return isMDXRule ? (rule.include as string[]) : []; + }); + } + + return { + module: { + rules: [ + { + test: /(\.mdx?)$/, + exclude: getMDXFallbackExcludedPaths(), + use: [ + getJSLoader({isServer}), + { + loader: require.resolve('@docusaurus/mdx-loader'), + options: { + staticDir: path.join(siteDir, STATIC_DIR_NAME), + isMDXPartial: (_filename) => true, // External mdx files are always meant to be imported as partials + isMDXPartialFrontMatterWarningDisabled: true, // External mdx files might have frontmatter, let's just disable the warning + }, + }, + ], + }, + ], + }, + }; + }, + }; +} + export async function load( siteDir: string, options: LoadContextOptions = {}, @@ -176,49 +277,8 @@ export async function load( `export default ${JSON.stringify(siteConfig, null, 2)};`, ); - // Make a fake plugin to: - // - Resolve aliased theme components - // - Inject scripts/stylesheets - const { - stylesheets = [], - scripts = [], - clientModules: siteConfigClientModules = [], - } = siteConfig; - plugins.push({ - name: 'docusaurus-bootstrap-plugin', - content: null, - options: {}, - version: {type: 'synthetic'}, - getClientModules() { - return siteConfigClientModules; - }, - injectHtmlTags: () => { - const stylesheetsTags = stylesheets.map((source) => - typeof source === 'string' - ? `` - : ({ - tagName: 'link', - attributes: { - rel: 'stylesheet', - ...source, - }, - } as HtmlTagObject), - ); - const scriptsTags = scripts.map((source) => - typeof source === 'string' - ? `` - : ({ - tagName: 'script', - attributes: { - ...source, - }, - } as HtmlTagObject), - ); - return { - headTags: [...stylesheetsTags, ...scriptsTags], - }; - }, - }); + plugins.push(createBootstrapPlugin({siteConfig})); + plugins.push(createMDXFallbackPlugin({siteDir})); // Load client modules. const clientModules = loadClientModules(plugins); diff --git a/website/_dogfooding/README.md b/website/_dogfooding/README.md index e49cae3ade..170fe3d799 100644 --- a/website/_dogfooding/README.md +++ b/website/_dogfooding/README.md @@ -1,3 +1,7 @@ +--- +test: 'some test frontmatter' +--- + # Docusaurus website dogfooding This is where we test edge cases of Docusaurus by using fancy configs, ensuring they all don't fail during a real site build. @@ -12,3 +16,4 @@ Fancy things we can test for here: - \_ prefix convention - Huge sidebars impact - Using folders with spaces on purpose +- Importing md docs that are out of content plugin folders as partials (such as this README file!) diff --git a/website/src/pages/deep-file-path-test/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/test-file.md b/website/_dogfooding/_pages tests/deep-file-path-test/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/test-file.md similarity index 100% rename from website/src/pages/deep-file-path-test/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/test-file.md rename to website/_dogfooding/_pages tests/deep-file-path-test/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/test-file.md diff --git a/website/_dogfooding/_pages tests/index.md b/website/_dogfooding/_pages tests/index.md index 9be91f24d9..1924033718 100644 --- a/website/_dogfooding/_pages tests/index.md +++ b/website/_dogfooding/_pages tests/index.md @@ -1,9 +1,19 @@ ## Page -Let's import some MDX partial: +Let's import a MDX partial at `./_pagePartial.md`: ```mdx-code-block import PagePartial from "./_pagePartial.md" ``` + +--- + +Now let's import `../README.md`: + +```mdx-code-block +import Readme from "../README.md" + + +``` diff --git a/website/src/pages/markdown-tests.md b/website/_dogfooding/_pages tests/markdown-tests.md similarity index 100% rename from website/src/pages/markdown-tests.md rename to website/_dogfooding/_pages tests/markdown-tests.md diff --git a/website/_dogfooding/_pages tests/markdownPageTests.md b/website/_dogfooding/_pages tests/markdownPageTests.md new file mode 100644 index 0000000000..79059cfeca --- /dev/null +++ b/website/_dogfooding/_pages tests/markdownPageTests.md @@ -0,0 +1,210 @@ +--- +title: Markdown Page tests title +description: Markdown Page tests description +wrapperClassName: docusaurus-markdown-example +--- + +# Markdown page tests + +This is a page generated from markdown to illustrate the Markdown page feature and test some edge cases. + +:::info + +Useful information. + +::: + +```jsx live +function Button() { + return ( + + ); +} +``` + +### Using absolute path + +![](/img/docusaurus.png) + +### Tab + +import Tabs from '@theme/Tabs'; + +import TabItem from '@theme/TabItem'; + +This is an apple 🍎This is an orange 🍊This is a banana 🍌 + +## Comments + +MDX comments can be used with + +```mdx + +``` + +See, nothing is displayed: + + + +## Import code block from source code file + +import MyComponent from "@site/src/pages/examples/\_myComponent" + +import BrowserWindow from '@site/src/components/BrowserWindow'; + +Let's say you have a React component. + +You can import and use it in MDX: + +```jsx title="myMarkdownFile.mdx" +import MyComponent from './myComponent'; + +; +``` + + + + + + + +But you can also display its source code directly in MDX, thanks to [Webpack raw-loader](https://webpack.js.org/loaders/raw-loader/) + +```jsx title="myMarkdownFile.mdx" +import CodeBlock from '@theme/CodeBlock'; + +import MyComponentSource from '!!raw-loader!./myComponent'; + +{MyComponentSource}; +``` + +import CodeBlock from "@theme/CodeBlock" + +import MyComponentSource from '!!raw-loader!@site/src/pages/examples/\_myComponent'; + + + +{MyComponentSource} + + + +## Test + +```jsx live +function Demo() { + React.useEffect(() => console.log('mount'), []); + return null; +} +``` + +## Code block test + +```js title="Title" +function Clock(props) { + const [date, setDate] = useState(new Date()); + useEffect(() => { + var timerID = setInterval(() => tick(), 1000); + + return function cleanup() { + clearInterval(timerID); + }; + }); + + function tick() { + setDate(new Date()); + } + + return ( +
+

It is {date.toLocaleTimeString()}.

+ // highlight-start + {/* prettier-ignore */} + long long long long long long long long long long long long line + {/* prettier-ignore */} + // highlight-end +
+ ); +} +``` + +```jsx live +function Clock(props) { + const [date, setDate] = useState(new Date()); + useEffect(() => { + var timerID = setInterval(() => tick(), 1000); + + return function cleanup() { + clearInterval(timerID); + }; + }); + + function tick() { + setDate(new Date()); + } + + return ( +
+

It is {date.toLocaleTimeString()}.

+
+ ); +} +``` + + + test + + +test + +## direct using of `pre` + +
test
+ + +
+1
+2
+3
+
+ +## Custom heading id {#custom} + +## Children elements inside pre/code elements + +See https://github.com/facebook/docusaurus/pull/1584 + +

+  
+    Lol bro
+  
+
+ + + + Lol bro + + + +## Pipe + +Code tag + double pipe: || + +Code tag + double pipe: || + +## Images edge cases + +![](/dogfooding/新控制器空间/图片.png) + +![](/dogfooding/4/图片.png) + +![](/dogfooding/4/docu.png) diff --git a/website/community/5-changelog.md b/website/community/5-changelog.md new file mode 100644 index 0000000000..8380049786 --- /dev/null +++ b/website/community/5-changelog.md @@ -0,0 +1,11 @@ +--- +title: Docusaurus 2 Changelog +hide_title: true +sidebar_label: Changelog +--- + +```mdx-code-block +import Changelog from "../../CHANGELOG.md" + + +``` diff --git a/website/src/pages/examples/_chapter1.md b/website/src/pages/examples/_chapter1.md deleted file mode 100644 index b7cac1eae7..0000000000 --- a/website/src/pages/examples/_chapter1.md +++ /dev/null @@ -1,3 +0,0 @@ -# Chapter 1 - -Lorem ipsum chapter 1 diff --git a/website/src/pages/examples/_chapter2.mdx b/website/src/pages/examples/_chapter2.mdx deleted file mode 100644 index 45dbbc0388..0000000000 --- a/website/src/pages/examples/_chapter2.mdx +++ /dev/null @@ -1,3 +0,0 @@ -# Chapter 2 - -Lorem ipsum chapter 2 diff --git a/website/src/pages/examples/markdownPageExample.md b/website/src/pages/examples/markdownPageExample.md index 07658ffa75..71bac44acf 100644 --- a/website/src/pages/examples/markdownPageExample.md +++ b/website/src/pages/examples/markdownPageExample.md @@ -1,6 +1,6 @@ --- -title: Markdown Page example title -description: Markdown Page example description +title: Markdown Page example +description: Markdown Page example wrapperClassName: docusaurus-markdown-example --- @@ -8,225 +8,8 @@ wrapperClassName: docusaurus-markdown-example This is a page generated from markdown to illustrate the Markdown page feature. -It supports all the regular MDX features, as you can see: +:::tip -:::info - -Useful information. +Use Markdown pages when you just want to focus on content and the default layout is good enough ::: - -```jsx live -function Button() { - return ( - - ); -} -``` - -### Using absolute path - -![](/img/docusaurus.png) - -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 './\_chapter1.md'; - - - -import Chapter2 from './\_chapter2.mdx'; - - - -## Comments - -MDX comments can be used with - -```mdx - -``` - -See, nothing is displayed: - - - -## Import code block from source code file - -import MyComponent from "@site/src/pages/examples/\_myComponent" - -import BrowserWindow from '@site/src/components/BrowserWindow'; - -Let's say you have a React component. - -You can import and use it in MDX: - -```jsx title="myMarkdownFile.mdx" -import MyComponent from './myComponent'; - -; -``` - - - - - - - -But you can also display its source code directly in MDX, thanks to [Webpack raw-loader](https://webpack.js.org/loaders/raw-loader/) - -```jsx title="myMarkdownFile.mdx" -import CodeBlock from '@theme/CodeBlock'; - -import MyComponentSource from '!!raw-loader!./myComponent'; - -{MyComponentSource}; -``` - -import CodeBlock from "@theme/CodeBlock" - -import MyComponentSource from '!!raw-loader!@site/src/pages/examples/\_myComponent'; - - - -{MyComponentSource} - - - -## Test - -```jsx live -function Demo() { - React.useEffect(() => console.log('mount'), []); - return null; -} -``` - -## Code block test - -```js title="Title" -function Clock(props) { - const [date, setDate] = useState(new Date()); - useEffect(() => { - var timerID = setInterval(() => tick(), 1000); - - return function cleanup() { - clearInterval(timerID); - }; - }); - - function tick() { - setDate(new Date()); - } - - return ( -
-

It is {date.toLocaleTimeString()}.

- // highlight-start - {/* prettier-ignore */} - long long long long long long long long long long long long line - {/* prettier-ignore */} - // highlight-end -
- ); -} -``` - -```jsx live -function Clock(props) { - const [date, setDate] = useState(new Date()); - useEffect(() => { - var timerID = setInterval(() => tick(), 1000); - - return function cleanup() { - clearInterval(timerID); - }; - }); - - function tick() { - setDate(new Date()); - } - - return ( -
-

It is {date.toLocaleTimeString()}.

-
- ); -} -``` - - - test - - -test - -## direct using of `pre` - -
test
- - -
-1
-2
-3
-
- -## Custom heading id {#custom} - -## Children elements inside pre/code elements - -See https://github.com/facebook/docusaurus/pull/1584 - -

-  
-    Lol bro
-  
-
- - - - Lol bro - - - -## Pipe - -Code tag + double pipe: || - -Code tag + double pipe: || - -## Images edge cases - -![](/dogfooding/新控制器空间/图片.png) - -![](/dogfooding/4/图片.png) - -![](/dogfooding/4/docu.png)