diff --git a/.changeset/curly-wasps-sin.md b/.changeset/curly-wasps-sin.md new file mode 100644 index 000000000..274738d66 --- /dev/null +++ b/.changeset/curly-wasps-sin.md @@ -0,0 +1,5 @@ +--- +'@astrojs/markdown-remark': patch +--- + +Now you can use local plugins by passing a function instead of an `import` diff --git a/docs/src/pages/en/guides/markdown-content.md b/docs/src/pages/en/guides/markdown-content.md index b5e33d5b2..6eb80d5e1 100644 --- a/docs/src/pages/en/guides/markdown-content.md +++ b/docs/src/pages/en/guides/markdown-content.md @@ -69,6 +69,8 @@ export default { You can provide names of the plugins as well as import them: ```js +import autolinkHeadings from 'remark-autolink-headings' + // astro.config.mjs export default { markdownOptions: { @@ -76,7 +78,7 @@ export default { '@astrojs/markdown-remark', { remarkPlugins: [ - [import('remark-autolink-headings'), { behavior: 'prepend' }], + [autolinkHeadings, { behavior: 'prepend' }], ], }, ], diff --git a/examples/with-markdown-plugins/astro.config.mjs b/examples/with-markdown-plugins/astro.config.mjs index 0fbb40de6..908b64cb0 100644 --- a/examples/with-markdown-plugins/astro.config.mjs +++ b/examples/with-markdown-plugins/astro.config.mjs @@ -6,6 +6,7 @@ // helpful tooltips, and warnings if your exported object is invalid. // You can disable this by removing "@ts-check" and `@type` comments below. import astroRemark from '@astrojs/markdown-remark'; +import addClasses from './add-classes.mjs'; // @ts-check export default /** @type {import('astro').AstroUserConfig} */ ({ @@ -15,12 +16,7 @@ export default /** @type {import('astro').AstroUserConfig} */ ({ astroRemark, { remarkPlugins: ['remark-code-titles'], - rehypePlugins: [ - ['rehype-autolink-headings', { behavior: 'prepend' }], - ['rehype-toc', { headings: ['h2', 'h3'] }], - [new URL('./add-classes.mjs', import.meta.url).pathname, { 'h1,h2,h3': 'title' }], - 'rehype-slug', - ], + rehypePlugins: [['rehype-autolink-headings', { behavior: 'prepend' }], ['rehype-toc', { headings: ['h2', 'h3'] }], [addClasses, { 'h1,h2,h3': 'title' }], 'rehype-slug'], }, ], }, diff --git a/packages/astro/package.json b/packages/astro/package.json index 09df48cbe..ceac177e8 100644 --- a/packages/astro/package.json +++ b/packages/astro/package.json @@ -125,6 +125,7 @@ "@types/yargs-parser": "^20.2.1", "chai": "^4.3.4", "cheerio": "^1.0.0-rc.10", + "hast-util-select": "^5.0.1", "mocha": "^9.1.3", "vite": "~2.6.10" }, diff --git a/packages/astro/test/astro-markdown-plugins.test.js b/packages/astro/test/astro-markdown-plugins.test.js index aca9fcf7b..ee780a738 100644 --- a/packages/astro/test/astro-markdown-plugins.test.js +++ b/packages/astro/test/astro-markdown-plugins.test.js @@ -2,6 +2,7 @@ import { expect } from 'chai'; import cheerio from 'cheerio'; import { loadFixture } from './test-utils.js'; import markdownRemark from '@astrojs/markdown-remark'; +import addClasses from './fixtures/astro-markdown-plugins/add-classes.mjs'; describe('Astro Markdown plugins', () => { let fixture; @@ -15,11 +16,7 @@ describe('Astro Markdown plugins', () => { markdownRemark, { remarkPlugins: ['remark-code-titles', ['rehype-autolink-headings', { behavior: 'prepend' }]], - rehypePlugins: [ - [import('rehype-toc'), { headings: ['h2', 'h3'] }], - [import('../../../examples/with-markdown-plugins/add-classes.mjs'), { 'h1,h2,h3': 'title' }], - 'rehype-slug', - ], + rehypePlugins: [['rehype-toc', { headings: ['h2', 'h3'] }], [addClasses, { 'h1,h2,h3': 'title' }], 'rehype-slug'], }, ], }, diff --git a/packages/astro/test/fixtures/astro-markdown-plugins/add-classes.mjs b/packages/astro/test/fixtures/astro-markdown-plugins/add-classes.mjs new file mode 100644 index 000000000..39acabd52 --- /dev/null +++ b/packages/astro/test/fixtures/astro-markdown-plugins/add-classes.mjs @@ -0,0 +1,18 @@ +import { selectAll } from 'hast-util-select'; + +export default (additions) => { + const adders = Object.entries(additions).map(adder); + return (node) => adders.forEach((a) => a(node)); +}; + +const adder = ([selector, className]) => { + const writer = write(className); + return (node) => selectAll(selector, node).forEach(writer); +}; + +const write = + (className) => + ({ properties }) => { + if (!properties.className) properties.className = className; + else properties.className += ` ${className}`; + }; diff --git a/packages/markdown/remark/src/load-plugins.ts b/packages/markdown/remark/src/load-plugins.ts index b1e72ae36..139eeaf19 100644 --- a/packages/markdown/remark/src/load-plugins.ts +++ b/packages/markdown/remark/src/load-plugins.ts @@ -1,26 +1,27 @@ import * as unified from 'unified'; -import type { Plugin, UnifiedPluginImport } from './types'; +import type { Plugin } from './types'; -async function importPlugin(p: string | UnifiedPluginImport): UnifiedPluginImport { +async function importPlugin(p: string | unified.Plugin): Promise { if (typeof p === 'string') { - return await import(p); + const importResult = await import(p); + return importResult.default; } - return await p; + return p; } -export function loadPlugins(items: Plugin[]): Promise<[unified.Plugin] | [unified.Plugin, any]>[] { +export function loadPlugins(items: Plugin[]): Promise<[unified.Plugin, any?]>[] { return items.map((p) => { return new Promise((resolve, reject) => { if (Array.isArray(p)) { const [plugin, opts] = p; return importPlugin(plugin) - .then((m) => resolve([m.default, opts])) + .then((m) => resolve([m, opts])) .catch((e) => reject(e)); } return importPlugin(p) - .then((m) => resolve([m.default])) + .then((m) => resolve([m])) .catch((e) => reject(e)); }); }); diff --git a/packages/markdown/remark/src/types.ts b/packages/markdown/remark/src/types.ts index 043594c9c..94c3e78a3 100644 --- a/packages/markdown/remark/src/types.ts +++ b/packages/markdown/remark/src/types.ts @@ -1,8 +1,7 @@ import type * as unified from 'unified'; import type * as shiki from 'shiki'; -export type UnifiedPluginImport = Promise<{ default: unified.Plugin }>; -export type Plugin = string | [string, any] | UnifiedPluginImport | [UnifiedPluginImport, any]; +export type Plugin = string | [string, any] | unified.Plugin | [unified.Plugin, any]; export interface AstroMarkdownOptions { mode?: 'md' | 'mdx'; diff --git a/yarn.lock b/yarn.lock index fce23a986..57fa86926 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4978,7 +4978,7 @@ hast-util-raw@^7.2.0: web-namespaces "^2.0.0" zwitch "^2.0.0" -hast-util-select@5.0.1: +hast-util-select@5.0.1, hast-util-select@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/hast-util-select/-/hast-util-select-5.0.1.tgz#ed3788ad1a8d2d7f16a6bf8153ce9378edbe9d6d" integrity sha512-cxnImmR/tN/ipvbwGrKtEErmy83K1xWx8Bu7nImiwTOJ7X/fW1X6L1241ux+MYUXDwx8GxrE4LVmXRlEnbQsQA==