Skip to content

Commit

Permalink
[MD] extendDefaultPlugins to preserve default remark plugins (#4474)
Browse files Browse the repository at this point in the history
* 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 5d050bb.

* 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>
  • Loading branch information
bholmesdev and sarah11918 authored Aug 25, 2022
1 parent d4cd7a5 commit ac03218
Show file tree
Hide file tree
Showing 10 changed files with 100 additions and 31 deletions.
6 changes: 6 additions & 0 deletions .changeset/cool-turtles-lay.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'astro': minor
'@astrojs/markdown-remark': minor
---

Add "extends" to markdown plugin config to preserve Astro defaults
49 changes: 36 additions & 13 deletions packages/astro/src/@types/astro.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
* {
Expand Down
1 change: 1 addition & 0 deletions packages/astro/src/core/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
58 changes: 48 additions & 10 deletions packages/astro/test/astro-markdown-plugins.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

function remarkExamplePlugin() {
return (tree) => {
tree.children.push({ type: 'paragraph', children: [{ type: 'text', value: 'Remark plugin applied!' }] })
}
}

before(async () => {
fixture = await loadFixture({
root: './fixtures/astro-markdown-plugins/',
describe('Astro Markdown plugins', () => {
it('Can render markdown with plugins', async () => {
const fixture = await buildFixture({
markdown: {
remarkPlugins: [
'remark-code-titles',
Expand All @@ -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);
})
}
});
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { defineConfig } from 'astro/config';
import preact from '@astrojs/preact';

// https://astro.build/config
export default defineConfig({
integrations: [preact()],
integrations: [],
});
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# GitHub-flavored Markdown test

This should auto-gen a link: https://example.com
7 changes: 4 additions & 3 deletions packages/markdown/remark/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export async function renderMarkdown(
remarkPlugins = [],
rehypePlugins = [],
remarkRehype = {},
extendDefaultPlugins = false,
isAstroFlavoredMd = false,
} = opts;
const input = new VFile({ value: content, path: fileURL });
Expand All @@ -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));
Expand Down
1 change: 1 addition & 0 deletions packages/markdown/remark/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export interface AstroMarkdownOptions {
remarkPlugins?: RemarkPlugins;
rehypePlugins?: RehypePlugins;
remarkRehype?: RemarkRehype;
extendDefaultPlugins?: boolean;
}

export interface MarkdownRenderingOptions extends AstroMarkdownOptions {
Expand Down
2 changes: 0 additions & 2 deletions pnpm-lock.yaml

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

0 comments on commit ac03218

Please sign in to comment.