[MD] extendDefaultPlugins to preserve default remark plugins (#4474)

* feat: add { extends } to markdown config

* test: remark plugins with extends

* deps: pnpm lock

* chore: changeset

* fix: remarkPlugins -> rehypePlugins

* docs: update markdown config reference

* Revert "feat: add { extends } to markdown config"

This reverts commit 5d050bbcf9a2c0d470cae79c4d0a954d489f4e8c.

* feat: new "extendDefaultPlugins" flag

* docs: update config

* nit: We -> Astro applies

* fix: backticks on `false`

* nit: Note -> REAL note

Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>

* docs: note -> caution

Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>
This commit is contained in:
Ben Holmes 2022-08-25 17:21:56 -04:00 committed by GitHub
parent d4cd7a59fd
commit ac03218247
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 100 additions and 31 deletions

View file

@ -0,0 +1,6 @@
---
'astro': minor
'@astrojs/markdown-remark': minor
---
Add "extends" to markdown plugin config to preserve Astro defaults

View file

@ -648,17 +648,19 @@ export interface AstroUserConfig {
* @name markdown.remarkPlugins
* @type {RemarkPlugins}
* @description
* Pass a custom [Remark](https://github.com/remarkjs/remark) plugin to customize how your Markdown is built.
* Pass [remark plugins](https://github.com/remarkjs/remark) to customize how your Markdown is built. You can import and apply the plugin function (recommended), or pass the plugin name as a string.
*
* **Note:** Enabling custom `remarkPlugins` or `rehypePlugins` removes Astro's built-in support for [GitHub-flavored Markdown](https://github.github.com/gfm/) support and [Smartypants](https://github.com/silvenon/remark-smartypants). You must explicitly add these plugins to your `astro.config.mjs` file, if desired.
* :::caution
* Providing a list of plugins will **remove** our default plugins. To preserve these defaults, see the `extendDefaultPlugins` flag.
* :::
*
* ```js
* import remarkToc from 'remark-toc';
* {
* markdown: {
* // Example: The default set of remark plugins used by Astro
* remarkPlugins: ['remark-gfm', 'remark-smartypants'],
* },
* };
* remarkPlugins: [remarkToc]
* }
* }
* ```
*/
remarkPlugins?: RemarkPlugins;
@ -667,26 +669,47 @@ export interface AstroUserConfig {
* @name markdown.rehypePlugins
* @type {RehypePlugins}
* @description
* Pass a custom [Rehype](https://github.com/remarkjs/remark-rehype) plugin to customize how your Markdown is built.
* Pass [rehype plugins](https://github.com/remarkjs/remark-rehype) to customize how your Markdown's output HTML is processed. You can import and apply the plugin function (recommended), or pass the plugin name as a string.
*
* **Note:** Enabling custom `remarkPlugins` or `rehypePlugins` removes Astro's built-in support for [GitHub-flavored Markdown](https://github.github.com/gfm/) support and [Smartypants](https://github.com/silvenon/remark-smartypants). You must explicitly add these plugins to your `astro.config.mjs` file, if desired.
* :::caution
* Providing a list of plugins will **remove** our default plugins. To preserve these defaults, see the `extendDefaultPlugins` flag.
* :::
*
* ```js
* import rehypeMinifyHtml from 'rehype-minify';
* {
* markdown: {
* // Example: The default set of rehype plugins used by Astro
* rehypePlugins: [],
* },
* };
* rehypePlugins: [rehypeMinifyHtml]
* }
* }
* ```
*/
rehypePlugins?: RehypePlugins;
/**
* @docs
* @name markdown.extendDefaultPlugins
* @type {boolean}
* @default `false`
* @description
* Astro applies the [GitHub-flavored Markdown](https://github.com/remarkjs/remark-gfm) and [Smartypants](https://github.com/silvenon/remark-smartypants) plugins by default. When adding your own remark or rehype plugins, you can preserve these defaults by setting the `extendDefaultPlugins` flag to `true`:
*
* ```js
* {
* markdown: {
* extendDefaultPlugins: true,
* remarkPlugins: [exampleRemarkPlugin],
* rehypePlugins: [exampleRehypePlugin],
* }
* }
* ```
*/
extendDefaultPlugins?: boolean;
/**
* @docs
* @name markdown.remarkRehype
* @type {RemarkRehype}
* @description
* Pass options to [remark-rehype](https://github.com/remarkjs/remark-rehype#api) .
* Pass options to [remark-rehype](https://github.com/remarkjs/remark-rehype#api).
*
* ```js
* {

View file

@ -219,6 +219,7 @@ export const AstroConfigSchema = z.object({
.custom<RemarkRehype>((data) => data instanceof Object && !Array.isArray(data))
.optional()
.default(ASTRO_CONFIG_DEFAULTS.markdown.remarkRehype),
extendDefaultPlugins: z.boolean().default(false),
})
.default({}),
vite: z

View file

@ -3,12 +3,24 @@ import * as cheerio from 'cheerio';
import { loadFixture } from './test-utils.js';
import addClasses from './fixtures/astro-markdown-plugins/add-classes.mjs';
describe('Astro Markdown plugins', () => {
let fixture;
async function buildFixture(config) {
const fixture = await loadFixture({
root: './fixtures/astro-markdown-plugins/',
...config,
});
await fixture.build();
return fixture;
}
before(async () => {
fixture = await loadFixture({
root: './fixtures/astro-markdown-plugins/',
function remarkExamplePlugin() {
return (tree) => {
tree.children.push({ type: 'paragraph', children: [{ type: 'text', value: 'Remark plugin applied!' }] })
}
}
describe('Astro Markdown plugins', () => {
it('Can render markdown with plugins', async () => {
const fixture = await buildFixture({
markdown: {
remarkPlugins: [
'remark-code-titles',
@ -21,17 +33,43 @@ describe('Astro Markdown plugins', () => {
],
},
});
await fixture.build();
});
it('Can render markdown with plugins', async () => {
const html = await fixture.readFile('/index.html');
const $ = cheerio.load(html);
// test 1: Added a TOC
expect($('.toc')).to.have.lengthOf(1);
// teste 2: Added .title to h1
// test 2: Added .title to h1
expect($('#hello-world').hasClass('title')).to.equal(true);
});
for (const extendDefaultPlugins of [true, false]) {
it(`Handles default plugins when extendDefaultPlugins = ${extendDefaultPlugins}`, async () => {
const fixture = await buildFixture({
markdown: {
remarkPlugins: [remarkExamplePlugin],
rehypePlugins: [
[addClasses, { 'h1,h2,h3': 'title' }],
],
extendDefaultPlugins,
},
});
const html = await fixture.readFile('/with-gfm/index.html');
const $ = cheerio.load(html);
// test 1: GFM autolink applied correctly
if (extendDefaultPlugins === true) {
expect($('a[href="https://example.com"]')).to.have.lengthOf(1);
} else {
expect($('a[href="https://example.com"]')).to.have.lengthOf(0);
}
// test 2: (sanity check) remark plugins still applied
expect(html).to.include('Remark plugin applied!');
// test 3: (sanity check) rehype plugins still applied
expect($('#github-flavored-markdown-test')).to.have.lengthOf(1);
expect($('#github-flavored-markdown-test').hasClass('title')).to.equal(true);
})
}
});

View file

@ -1,7 +1,6 @@
import { defineConfig } from 'astro/config';
import preact from '@astrojs/preact';
// https://astro.build/config
export default defineConfig({
integrations: [preact()],
integrations: [],
});

View file

@ -3,7 +3,6 @@
"version": "0.0.0",
"private": true,
"dependencies": {
"@astrojs/preact": "workspace:*",
"astro": "workspace:*",
"hast-util-select": "^5.0.2",
"rehype-slug": "^5.0.1"

View file

@ -0,0 +1,3 @@
# GitHub-flavored Markdown test
This should auto-gen a link: https://example.com

View file

@ -39,6 +39,7 @@ export async function renderMarkdown(
remarkPlugins = [],
rehypePlugins = [],
remarkRehype = {},
extendDefaultPlugins = false,
isAstroFlavoredMd = false,
} = opts;
const input = new VFile({ value: content, path: fileURL });
@ -50,9 +51,9 @@ export async function renderMarkdown(
.use(remarkInitializeAstroData)
.use(isAstroFlavoredMd ? [remarkMdxish, remarkMarkAndUnravel, remarkUnwrap, remarkEscape] : []);
if (remarkPlugins.length === 0 && rehypePlugins.length === 0) {
remarkPlugins = [...DEFAULT_REMARK_PLUGINS];
rehypePlugins = [...DEFAULT_REHYPE_PLUGINS];
if (extendDefaultPlugins || (remarkPlugins.length === 0 && rehypePlugins.length === 0)) {
remarkPlugins = [...DEFAULT_REMARK_PLUGINS, ...remarkPlugins];
rehypePlugins = [...DEFAULT_REHYPE_PLUGINS, ...rehypePlugins];
}
const loadedRemarkPlugins = await Promise.all(loadPlugins(remarkPlugins));

View file

@ -43,6 +43,7 @@ export interface AstroMarkdownOptions {
remarkPlugins?: RemarkPlugins;
rehypePlugins?: RehypePlugins;
remarkRehype?: RemarkRehype;
extendDefaultPlugins?: boolean;
}
export interface MarkdownRenderingOptions extends AstroMarkdownOptions {

View file

@ -1286,12 +1286,10 @@ importers:
packages/astro/test/fixtures/astro-markdown-plugins:
specifiers:
'@astrojs/preact': workspace:*
astro: workspace:*
hast-util-select: ^5.0.2
rehype-slug: ^5.0.1
dependencies:
'@astrojs/preact': link:../../../../integrations/preact
astro: link:../../..
hast-util-select: 5.0.2
rehype-slug: 5.0.1