diff options
author | 2023-01-03 17:12:47 -0500 | |
---|---|---|
committer | 2023-01-03 17:12:47 -0500 | |
commit | a9c2920264e36cc5dc05f4adc1912187979edb0d (patch) | |
tree | 0a1987beb45f2c9a3670ee6122483bea81839139 /packages/integrations/mdx/src | |
parent | 163a9a9d0ef8b08a71033e719ba06ff63cd2df60 (diff) | |
download | astro-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.ts | 68 | ||||
-rw-r--r-- | packages/integrations/mdx/src/plugins.ts | 57 |
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; |