summaryrefslogtreecommitdiff
path: root/packages/integrations/mdx/src
diff options
context:
space:
mode:
authorGravatar Ben Holmes <hey@bholmes.dev> 2023-01-03 17:12:47 -0500
committerGravatar GitHub <noreply@github.com> 2023-01-03 17:12:47 -0500
commita9c2920264e36cc5dc05f4adc1912187979edb0d (patch)
tree0a1987beb45f2c9a3670ee6122483bea81839139 /packages/integrations/mdx/src
parent163a9a9d0ef8b08a71033e719ba06ff63cd2df60 (diff)
downloadastro-a9c2920264e36cc5dc05f4adc1912187979edb0d.tar.gz
astro-a9c2920264e36cc5dc05f4adc1912187979edb0d.tar.zst
astro-a9c2920264e36cc5dc05f4adc1912187979edb0d.zip
Markdown and MDX configuration rework (#5684)
* feat: change extendDefaults -> gfm * deps: remove smartypants from md/remark * tests: update markdown plugin tests * fix: borked lockfile * feat: allow all Markdown options in MDX config, with extend * deps: remove smartypants from MDX * chore: remove unused `mode` property * chore: remark rehype types * chore: dead code * fix: order of default config properties * refactor: move md defaults to remark * fix: RemarkRehype type * fix: apply defaults based on MD defaults * chore: update plugin tests * chore: add syntaxHighlight test * refactor: remove drafts from config defaults * docs: new MDX config options * chore: add changeset * edit: test both extends for syntax highlight * refactor: remove MDX config deep merge * docs: update README and changeset * edit: avoid -> disable Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca> * edit: `drafts` clarification Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca> * edit: remove "scare quotes" Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca> * docs: MDX config options redraft * docs: add migration * chore: changeset heading levels * refactor: githubFlavoredMarkdown -> gfm * chore: remove unused imports Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>
Diffstat (limited to 'packages/integrations/mdx/src')
-rw-r--r--packages/integrations/mdx/src/index.ts68
-rw-r--r--packages/integrations/mdx/src/plugins.ts57
2 files changed, 56 insertions, 69 deletions
diff --git a/packages/integrations/mdx/src/index.ts b/packages/integrations/mdx/src/index.ts
index e9d81ca1f..2fcc89731 100644
--- a/packages/integrations/mdx/src/index.ts
+++ b/packages/integrations/mdx/src/index.ts
@@ -1,4 +1,5 @@
import { toRemarkInitializeAstroData } from '@astrojs/markdown-remark/dist/internal.js';
+import { markdownConfigDefaults } from '@astrojs/markdown-remark';
import { compile as mdxCompile } from '@mdx-js/mdx';
import { PluggableList } from '@mdx-js/mdx/lib/core.js';
import mdxPlugin, { Options as MdxRollupPluginOptions } from '@mdx-js/rollup';
@@ -17,44 +18,41 @@ const RAW_CONTENT_ERROR =
const COMPILED_CONTENT_ERROR =
'MDX does not support compiledContent()! If you need to read the HTML contents to calculate values (ex. reading time), we suggest injecting frontmatter via rehype plugins. Learn more on our docs: https://docs.astro.build/en/guides/integrations-guide/mdx/#inject-frontmatter-via-remark-or-rehype-plugins';
-export type MdxOptions = {
- remarkPlugins?: PluggableList;
- rehypePlugins?: PluggableList;
- recmaPlugins?: PluggableList;
- /**
- * Choose which remark and rehype plugins to inherit, if any.
- *
- * - "markdown" (default) - inherit your project’s markdown plugin config ([see Markdown docs](https://docs.astro.build/en/guides/markdown-content/#configuring-markdown))
- * - "astroDefaults" - inherit Astro’s default plugins only ([see defaults](https://docs.astro.build/en/reference/configuration-reference/#markdownextenddefaultplugins))
- * - false - do not inherit any plugins
- */
- extendPlugins?: 'markdown' | 'astroDefaults' | false;
- remarkRehype?: RemarkRehypeOptions;
+export type MdxOptions = Omit<typeof markdownConfigDefaults, 'remarkPlugins' | 'rehypePlugins'> & {
+ extendMarkdownConfig: boolean;
+ recmaPlugins: PluggableList;
+ // Markdown allows strings as remark and rehype plugins.
+ // This is not supported by the MDX compiler, so override types here.
+ remarkPlugins: PluggableList;
+ rehypePlugins: PluggableList;
+ remarkRehype: RemarkRehypeOptions;
};
-export default function mdx(mdxOptions: MdxOptions = {}): AstroIntegration {
+export default function mdx(partialMdxOptions: Partial<MdxOptions> = {}): AstroIntegration {
return {
name: '@astrojs/mdx',
hooks: {
'astro:config:setup': async ({ updateConfig, config, addPageExtension, command }: any) => {
addPageExtension('.mdx');
- mdxOptions.extendPlugins ??= 'markdown';
- const remarkRehypeOptions = {
- ...(mdxOptions.extendPlugins === 'markdown' ? config.markdown.remarkRehype : {}),
- ...mdxOptions.remarkRehype,
- };
+ const extendMarkdownConfig =
+ partialMdxOptions.extendMarkdownConfig ?? defaultOptions.extendMarkdownConfig;
+
+ const mdxOptions = applyDefaultOptions({
+ options: partialMdxOptions,
+ defaults: extendMarkdownConfig ? config.markdown : defaultOptions,
+ });
const mdxPluginOpts: MdxRollupPluginOptions = {
remarkPlugins: await getRemarkPlugins(mdxOptions, config),
- rehypePlugins: getRehypePlugins(mdxOptions, config),
+ rehypePlugins: getRehypePlugins(mdxOptions),
recmaPlugins: mdxOptions.recmaPlugins,
+ remarkRehypeOptions: mdxOptions.remarkRehype,
jsx: true,
jsxImportSource: 'astro',
// Note: disable `.md` (and other alternative extensions for markdown files like `.markdown`) support
format: 'mdx',
mdExtensions: [],
- remarkRehypeOptions,
};
let importMetaEnv: Record<string, any> = {
@@ -166,6 +164,34 @@ export default function mdx(mdxOptions: MdxOptions = {}): AstroIntegration {
};
}
+const defaultOptions: MdxOptions = {
+ ...markdownConfigDefaults,
+ extendMarkdownConfig: true,
+ recmaPlugins: [],
+ remarkPlugins: [],
+ rehypePlugins: [],
+ remarkRehype: {},
+};
+
+function applyDefaultOptions({
+ options,
+ defaults,
+}: {
+ options: Partial<MdxOptions>;
+ defaults: MdxOptions;
+}): MdxOptions {
+ return {
+ syntaxHighlight: options.syntaxHighlight ?? defaults.syntaxHighlight,
+ extendMarkdownConfig: options.extendMarkdownConfig ?? defaults.extendMarkdownConfig,
+ recmaPlugins: options.recmaPlugins ?? defaults.recmaPlugins,
+ remarkRehype: options.remarkRehype ?? defaults.remarkRehype,
+ gfm: options.gfm ?? defaults.gfm,
+ remarkPlugins: options.remarkPlugins ?? defaults.remarkPlugins,
+ rehypePlugins: options.rehypePlugins ?? defaults.rehypePlugins,
+ shikiConfig: options.shikiConfig ?? defaults.shikiConfig,
+ };
+}
+
// Converts the first dot in `import.meta.env` to its Unicode escape sequence,
// which prevents Vite from replacing strings like `import.meta.env.SITE`
// in our JS representation of loaded Markdown files
diff --git a/packages/integrations/mdx/src/plugins.ts b/packages/integrations/mdx/src/plugins.ts
index 675a8a645..f5557b8a3 100644
--- a/packages/integrations/mdx/src/plugins.ts
+++ b/packages/integrations/mdx/src/plugins.ts
@@ -14,7 +14,6 @@ import type { Image } from 'mdast';
import { pathToFileURL } from 'node:url';
import rehypeRaw from 'rehype-raw';
import remarkGfm from 'remark-gfm';
-import remarkSmartypants from 'remark-smartypants';
import { visit } from 'unist-util-visit';
import type { VFile } from 'vfile';
import { MdxOptions } from './index.js';
@@ -140,36 +139,22 @@ function toRemarkContentRelImageError({ srcDir }: { srcDir: URL }) {
};
}
-const DEFAULT_REMARK_PLUGINS: PluggableList = [remarkGfm, remarkSmartypants];
-const DEFAULT_REHYPE_PLUGINS: PluggableList = [];
-
export async function getRemarkPlugins(
mdxOptions: MdxOptions,
config: AstroConfig
): Promise<MdxRollupPluginOptions['remarkPlugins']> {
let remarkPlugins: PluggableList = [];
- switch (mdxOptions.extendPlugins) {
- case false:
- break;
- case 'astroDefaults':
- remarkPlugins = [...remarkPlugins, ...DEFAULT_REMARK_PLUGINS];
- break;
- default:
- remarkPlugins = [
- ...remarkPlugins,
- ...(markdownShouldExtendDefaultPlugins(config) ? DEFAULT_REMARK_PLUGINS : []),
- ...ignoreStringPlugins(config.markdown.remarkPlugins ?? []),
- ];
- break;
- }
- if (config.markdown.syntaxHighlight === 'shiki') {
- remarkPlugins.push([await remarkShiki(config.markdown.shikiConfig)]);
+ if (mdxOptions.syntaxHighlight === 'shiki') {
+ remarkPlugins.push([await remarkShiki(mdxOptions.shikiConfig)]);
}
- if (config.markdown.syntaxHighlight === 'prism') {
+ if (mdxOptions.syntaxHighlight === 'prism') {
remarkPlugins.push(remarkPrism);
}
+ if (mdxOptions.gfm) {
+ remarkPlugins.push(remarkGfm);
+ }
- remarkPlugins = [...remarkPlugins, ...(mdxOptions.remarkPlugins ?? [])];
+ remarkPlugins = [...remarkPlugins, ...ignoreStringPlugins(mdxOptions.remarkPlugins)];
// Apply last in case user plugins resolve relative image paths
if (config.experimental.contentCollections) {
@@ -178,34 +163,17 @@ export async function getRemarkPlugins(
return remarkPlugins;
}
-export function getRehypePlugins(
- mdxOptions: MdxOptions,
- config: AstroConfig
-): MdxRollupPluginOptions['rehypePlugins'] {
+export function getRehypePlugins(mdxOptions: MdxOptions): MdxRollupPluginOptions['rehypePlugins'] {
let rehypePlugins: PluggableList = [
// ensure `data.meta` is preserved in `properties.metastring` for rehype syntax highlighters
rehypeMetaString,
// rehypeRaw allows custom syntax highlighters to work without added config
[rehypeRaw, { passThrough: nodeTypes }] as any,
];
- switch (mdxOptions.extendPlugins) {
- case false:
- break;
- case 'astroDefaults':
- rehypePlugins = [...rehypePlugins, ...DEFAULT_REHYPE_PLUGINS];
- break;
- default:
- rehypePlugins = [
- ...rehypePlugins,
- ...(markdownShouldExtendDefaultPlugins(config) ? DEFAULT_REHYPE_PLUGINS : []),
- ...ignoreStringPlugins(config.markdown.rehypePlugins ?? []),
- ];
- break;
- }
rehypePlugins = [
...rehypePlugins,
- ...(mdxOptions.rehypePlugins ?? []),
+ ...ignoreStringPlugins(mdxOptions.rehypePlugins),
// getHeadings() is guaranteed by TS, so this must be included.
// We run `rehypeHeadingIds` _last_ to respect any custom IDs set by user plugins.
rehypeHeadingIds,
@@ -216,13 +184,6 @@ export function getRehypePlugins(
return rehypePlugins;
}
-function markdownShouldExtendDefaultPlugins(config: AstroConfig): boolean {
- return (
- config.markdown.extendDefaultPlugins ||
- (config.markdown.remarkPlugins.length === 0 && config.markdown.rehypePlugins.length === 0)
- );
-}
-
function ignoreStringPlugins(plugins: any[]) {
let validPlugins: PluggableList = [];
let hasInvalidPlugin = false;