Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: handle all admonitions via JSX component #7152

Merged
merged 27 commits into from Jun 3, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
d02485a
refactor: handle all admonitions via JSX component
lex111 Apr 11, 2022
3b74726
fixes
Josh-Cena Apr 12, 2022
d2f18d8
Merge branch 'main' into lex111/themed-admonitions
slorber May 5, 2022
d3a9711
ability to customize admonition keywords and tag
slorber May 5, 2022
4b8121f
move remark admonitions to mdx-loader
slorber May 5, 2022
3bbdbab
upgrade AdmonitionsSchema
slorber May 5, 2022
00a7e74
upgrade AdmonitionsSchema
slorber May 5, 2022
f6fb1b0
upgrade AdmonitionsSchema
slorber May 5, 2022
1f3fff4
wire admonition option to all content plugins
slorber May 5, 2022
25ae510
fix admonitions validation schema
slorber May 5, 2022
32dbb35
add license + readme
slorber May 5, 2022
eb94727
fix test
slorber May 5, 2022
e3d4a02
lint issue
slorber May 5, 2022
c3ecb56
update Admonition, make it fail-safe
slorber May 5, 2022
41d614f
lint
slorber May 5, 2022
c101ae1
fixes
Josh-Cena May 6, 2022
63afa4e
fix?
Josh-Cena May 6, 2022
048d8d4
refactor: migrate to CSS modules, fix a11y issue
lex111 May 6, 2022
0e9e357
Merge branch 'main' into lex111/themed-admonitions
Josh-Cena May 14, 2022
cc0719f
Merge branch 'main' into lex111/themed-admonitions
Josh-Cena May 22, 2022
0e4663c
Merge branch 'main' into lex111/themed-admonitions
Josh-Cena May 24, 2022
233ca61
Merge branch 'main' into lex111/themed-admonitions
Josh-Cena May 24, 2022
a18f60b
Merge branch 'main' into lex111/themed-admonitions
Josh-Cena May 25, 2022
2e82db9
Merge branch 'main' into lex111/themed-admonitions
slorber Jun 2, 2022
01f669c
Implement workaround to support interpolation in MDX admonition titles
slorber Jun 3, 2022
287e2f0
add link to relevant issue comment https://github.com/facebook/docusa…
slorber Jun 3, 2022
63e9e02
Little refactors
Josh-Cena Jun 3, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 0 additions & 1 deletion packages/docusaurus-plugin-content-blog/package.json
Expand Up @@ -29,7 +29,6 @@
"fs-extra": "^10.0.1",
"lodash": "^4.17.21",
"reading-time": "^1.5.0",
"remark-admonitions": "^1.2.1",
"tslib": "^2.3.1",
"utility-types": "^3.10.0",
"webpack": "^5.72.0"
Expand Down
13 changes: 0 additions & 13 deletions packages/docusaurus-plugin-content-blog/src/deps.d.ts

This file was deleted.

7 changes: 0 additions & 7 deletions packages/docusaurus-plugin-content-blog/src/index.ts
Expand Up @@ -6,7 +6,6 @@
*/

import path from 'path';
import admonitions from 'remark-admonitions';
import {
normalizeUrl,
docuHash,
Expand Down Expand Up @@ -55,12 +54,6 @@ export default async function pluginContentBlog(
context: LoadContext,
options: PluginOptions,
): Promise<Plugin<BlogContent>> {
if (options.admonitions) {
options.remarkPlugins = options.remarkPlugins.concat([
[admonitions, options.admonitions],
]);
}

const {
siteDir,
siteConfig,
Expand Down
1 change: 0 additions & 1 deletion packages/docusaurus-plugin-content-docs/package.json
Expand Up @@ -34,7 +34,6 @@
"import-fresh": "^3.3.0",
"js-yaml": "^4.1.0",
"lodash": "^4.17.21",
"remark-admonitions": "^1.2.1",
"tslib": "^2.3.1",
"utility-types": "^3.10.0",
"webpack": "^5.72.0"
Expand Down
Expand Up @@ -79,7 +79,6 @@ describe('normalizeDocsPluginOptions', () => {
expect(testValidate(userOptions)).toEqual({
...defaultOptions,
...userOptions,
remarkPlugins: [...userOptions.remarkPlugins, expect.any(Array)],
});
});

Expand All @@ -96,7 +95,6 @@ describe('normalizeDocsPluginOptions', () => {
expect(testValidate(userOptions)).toEqual({
...defaultOptions,
...userOptions,
remarkPlugins: [...userOptions.remarkPlugins, expect.any(Array)],
});
});

Expand Down
13 changes: 0 additions & 13 deletions packages/docusaurus-plugin-content-docs/src/deps.d.ts

This file was deleted.

7 changes: 0 additions & 7 deletions packages/docusaurus-plugin-content-docs/src/options.ts
Expand Up @@ -17,7 +17,6 @@ import {GlobExcludeDefault} from '@docusaurus/utils';

import type {OptionValidationContext} from '@docusaurus/types';
import logger from '@docusaurus/logger';
import admonitions from 'remark-admonitions';
import {DefaultSidebarItemsGenerator} from './sidebars/generator';
import {
DefaultNumberPrefixParser,
Expand Down Expand Up @@ -168,11 +167,5 @@ export function validateOptions({

const normalizedOptions = validate(OptionsSchema, options) as PluginOptions;

if (normalizedOptions.admonitions) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is removed, but admonitions remains in schema + default value

We want to still allow custom admonitions? Are custom admonitions configured globally or per plugin?

Do we want to do a breaking change and add a custom error message, or try to keep retro-compatibility?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should keep this here for the time being, but when we eventually have a centralized markdown.remarkPlugins config (#5999) I'd like to move it there. Note that I also want to have admonitions as part of the default MDX loader preset, so it can be configured as part of the docusaurus-remark-preset.

Copy link
Collaborator

@slorber slorber Apr 20, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Josh-Cena I agree we should keep the options there, at least for now

The problem is that the provided options do not make sense anymore

https://github.com/lorikrell/gamerchic/blob/ec6e1595a51b7e65538262dd9308fb7517e42f9f/docusaurus.config.js#L359

{
        admonitions: {
          customTypes: {
            homebrew: {
              keyword: `homebrew`,
              infima: true,
              svg: '<svg /></svg>'
            },
            gamerchic: {
              keyword: `gamerchic`,
              infima: true,
              svg: '<svg /></svg>'
            },
          },
        },
}  

Now the options should look like:

{
        admonitions: {
          customKeywords: ["homebrew","gamerchic"]
        },
}  

And custom styling/svg should be applied by swizzling the admonition component.

@lex111 it's worth supporting that to ensure that the above site config have a way to upgrade Docusaurus without losing its custom admonitions

We also need to add option schema changes so that it prints a clear error message when user is trying to use the "old" customizations format

normalizedOptions.remarkPlugins = normalizedOptions.remarkPlugins.concat([
[admonitions, normalizedOptions.admonitions],
]);
}

return normalizedOptions;
}
1 change: 0 additions & 1 deletion packages/docusaurus-plugin-content-pages/package.json
Expand Up @@ -23,7 +23,6 @@
"@docusaurus/utils": "2.0.0-beta.18",
"@docusaurus/utils-validation": "2.0.0-beta.18",
"fs-extra": "^10.0.1",
"remark-admonitions": "^1.2.1",
"tslib": "^2.3.1",
"webpack": "^5.72.0"
},
Expand Down
13 changes: 0 additions & 13 deletions packages/docusaurus-plugin-content-pages/src/deps.d.ts

This file was deleted.

6 changes: 0 additions & 6 deletions packages/docusaurus-plugin-content-pages/src/index.ts
Expand Up @@ -22,7 +22,6 @@ import {
parseMarkdownString,
} from '@docusaurus/utils';
import type {LoadContext, Plugin} from '@docusaurus/types';
import admonitions from 'remark-admonitions';
import {validatePageFrontMatter} from './frontMatter';

import type {LoadedContent, PagesContentPaths} from './types';
Expand All @@ -39,11 +38,6 @@ export default async function pluginContentPages(
context: LoadContext,
options: PluginOptions,
): Promise<Plugin<LoadedContent | null>> {
if (options.admonitions) {
options.remarkPlugins = options.remarkPlugins.concat([
[admonitions, options.admonitions],
]);
}
const {
siteConfig,
siteDir,
Expand Down
5 changes: 4 additions & 1 deletion packages/docusaurus-theme-classic/package.json
Expand Up @@ -39,7 +39,8 @@
"prism-react-renderer": "^1.3.1",
"prismjs": "^1.27.0",
"react-router-dom": "^5.2.0",
"rtlcss": "^3.5.0"
"rtlcss": "^3.5.0",
"unist-util-visit": "^2.0.3"
},
"devDependencies": {
"@babel/cli": "^7.17.6",
Expand All @@ -53,6 +54,8 @@
"cross-env": "^7.0.3",
"fs-extra": "^10.0.1",
"react-test-renderer": "^17.0.2",
"rehype-stringify": "^8.0.0",
"remark-rehype": "^8.1.0",
"utility-types": "^3.10.0"
},
"peerDependencies": {
Expand Down
43 changes: 31 additions & 12 deletions packages/docusaurus-theme-classic/src/index.ts
Expand Up @@ -15,6 +15,9 @@ import {readDefaultCodeTranslationMessages} from '@docusaurus/theme-translations
import type {Options} from '@docusaurus/theme-classic';
import type webpack from 'webpack';

import admonitions from './remark/admonitions';
import type {MDXOptions} from '@docusaurus/mdx-loader';

const requireFromDocusaurusCore = createRequire(
require.resolve('@docusaurus/core/package.json'),
);
Expand Down Expand Up @@ -151,22 +154,38 @@ export default function docusaurusThemeClassic(
return modules;
},

configureWebpack() {
configureWebpack(config) {
const prismLanguages = additionalLanguages
.map((lang) => `prism-${lang}`)
.join('|');

return {
plugins: [
// This allows better optimization by only bundling those components
// that the user actually needs, because the modules are dynamically
// required and can't be known during compile time.
new ContextReplacementPlugin(
/prismjs[\\/]components$/,
new RegExp(`^./(${prismLanguages})$`),
),
],
};
// This allows better optimization by only bundling those components
// that the user actually needs, because the modules are dynamically
// required and can't be known during compile time.
config.plugins?.push(
new ContextReplacementPlugin(
/prismjs[\\/]components$/,
new RegExp(`^./(${prismLanguages})$`),
),
);

config.module?.rules?.forEach((rule) => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤪 not a fan of this

Maybe we could just add an mdx-loader "admonitions" option on which we'd just forward the plugin options (if we keep them?)

I know it's not ideal to add everything to mdx-loader but it's probably a good-enough temporary solution until we figure out something better

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I explained above, the idea was for the theme to provide admonitions functionality, so the remark plugin should add from the theme. That's why I suggested to implement a simplified lifecycle hook to solve only this issue for now.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can make the loader provide an optional "admonitions" feature that the theme would enable

it's less flexible but would definitively work without needing any extra lifecycle, giving us time to figure out a good API for that lifecycle. If we can avoid introducing temporary experimental public apis that's better

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can make the loader provide an optional "admonitions" feature that the theme would enable

Do you mean move the admonitions plugin to the mdx-loader or something else?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, for now, you can move the admonition plugin to mdx loader and pass an admonition: {customKeywords: []} option. We'll likely move it outside later but for now it's the simplest solution.

if (typeof rule !== 'string' && Array.isArray(rule.use)) {
rule.use.forEach((useItem) => {
if (
typeof useItem !== 'string' &&
'loader' in useItem &&
useItem.loader?.includes('docusaurus-mdx-loader')
) {
useItem.options ??= {};
(useItem.options as MDXOptions).remarkPlugins ??= [];
(useItem.options as MDXOptions).remarkPlugins.push(admonitions);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to support custom admonitions as we previously did. We have users heavily using them.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree 👍

can you show example sites using custom admonitions and the configs used?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Josh-Cena I think we should also study how changes in this PR will look like after MDX 2 and https://github.com/remarkjs/remark-directive

I don't think the current API for admonition customization will stay as is, and instead we'll do customizations through swizzle?

So maybe we can already do the breaking change today if it's already planned anyway 🤷‍♂️

}
});
}
});

return {mergeStrategy: {'*': 'replace'}, ...config};
},

configurePostCss(postCssOptions) {
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

@@ -0,0 +1,9 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`admonitions remark plugin base 1`] = `
"<p>The blog feature enables you to deploy in no time a full-featured blog.</p>
<admonition title="Sample Title" type="info"><p>Check the <a href="./api/plugins/plugin-content-blog.md">Blog Plugin API Reference documentation</a> for an exhaustive list of options.</p></admonition>
<h2>Initial setup {#initial-setup}</h2>
<p>To set up your site's blog, start by creating a <code>blog</code> directory.</p>
<admonition type="tip"><p>Use the <strong><a href="introduction.md#fast-track">Fast Track</a></strong> to understand Docusaurus in <strong>5 minutes ⏱</strong>!</p><p>Use <strong><a href="https://docusaurus.new">docusaurus.new</a></strong> to test Docusaurus immediately in your browser!</p></admonition>"
`;
@@ -0,0 +1,33 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import path from 'path';
import remark from 'remark';
import vfile from 'to-vfile';
import plugin from '../index';
import remark2rehype from 'remark-rehype';
import stringify from 'rehype-stringify';

const processFixture = async (name) => {
const filePath = path.join(__dirname, '__fixtures__', `${name}.md`);
const file = await vfile.read(filePath);

const result = await remark()
.use(plugin)
.use(remark2rehype)
.use(stringify)
.process(file);

return result.toString();
};

describe('admonitions remark plugin', () => {
it('base', async () => {
const result = await processFixture('base');
expect(result).toMatchSnapshot();
});
});