astro/packages/integrations/mdx/test/mdx-plugins.test.js
Ben Holmes a9c2920264
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>
2023-01-03 17:12:47 -05:00

215 lines
5.1 KiB
JavaScript

import mdx from '@astrojs/mdx';
import { expect } from 'chai';
import { parseHTML } from 'linkedom';
import { loadFixture } from '../../../astro/test/test-utils.js';
import remarkToc from 'remark-toc';
import { visit as estreeVisit } from 'estree-util-visit';
const FIXTURE_ROOT = new URL('./fixtures/mdx-plugins/', import.meta.url);
const FILE = '/with-plugins/index.html';
describe('MDX plugins', () => {
it('supports custom remark plugins - TOC', async () => {
const fixture = await buildFixture({
integrations: [
mdx({
remarkPlugins: [remarkToc],
}),
],
});
const html = await fixture.readFile(FILE);
const { document } = parseHTML(html);
expect(selectTocLink(document)).to.not.be.null;
});
it('Applies GFM by default', async () => {
const fixture = await buildFixture({
integrations: [mdx()],
});
const html = await fixture.readFile(FILE);
const { document } = parseHTML(html);
expect(selectGfmLink(document)).to.not.be.null;
});
it('supports custom rehype plugins', async () => {
const fixture = await buildFixture({
integrations: [
mdx({
rehypePlugins: [rehypeExamplePlugin],
}),
],
});
const html = await fixture.readFile(FILE);
const { document } = parseHTML(html);
expect(selectRehypeExample(document)).to.not.be.null;
});
it('extends markdown config by default', async () => {
const fixture = await buildFixture({
markdown: {
remarkPlugins: [remarkExamplePlugin],
rehypePlugins: [rehypeExamplePlugin],
},
integrations: [mdx()],
});
const html = await fixture.readFile(FILE);
const { document } = parseHTML(html);
expect(selectRemarkExample(document)).to.not.be.null;
expect(selectRehypeExample(document)).to.not.be.null;
});
it('ignores string-based plugins in markdown config', async () => {
const fixture = await buildFixture({
markdown: {
remarkPlugins: [['remark-toc']],
},
integrations: [mdx()],
});
const html = await fixture.readFile(FILE);
const { document } = parseHTML(html);
expect(selectTocLink(document)).to.be.null;
});
for (const extendMarkdownConfig of [true, false]) {
describe(`extendMarkdownConfig = ${extendMarkdownConfig}`, () => {
let fixture;
before(async () => {
fixture = await buildFixture({
markdown: {
remarkPlugins: [remarkToc],
gfm: false,
},
integrations: [
mdx({
extendMarkdownConfig,
remarkPlugins: [remarkExamplePlugin],
rehypePlugins: [rehypeExamplePlugin],
}),
],
});
});
it('Handles MDX plugins', async () => {
const html = await fixture.readFile(FILE);
const { document } = parseHTML(html);
expect(selectRemarkExample(document, 'MDX remark plugins not applied.')).to.not.be.null;
expect(selectRehypeExample(document, 'MDX rehype plugins not applied.')).to.not.be.null;
});
it('Handles Markdown plugins', async () => {
const html = await fixture.readFile(FILE);
const { document } = parseHTML(html);
expect(
selectTocLink(
document,
'`remarkToc` plugin applied unexpectedly. Should override Markdown config.'
)
).to.be.null;
});
it('Handles gfm', async () => {
const html = await fixture.readFile(FILE);
const { document } = parseHTML(html);
if (extendMarkdownConfig === true) {
expect(selectGfmLink(document), 'Does not respect `markdown.gfm` option.').to.be.null;
} else {
expect(selectGfmLink(document), 'Respects `markdown.gfm` unexpectedly.').to.not.be.null;
}
});
});
}
it('supports custom recma plugins', async () => {
const fixture = await buildFixture({
integrations: [
mdx({
recmaPlugins: [recmaExamplePlugin],
}),
],
});
const html = await fixture.readFile(FILE);
const { document } = parseHTML(html);
expect(selectRecmaExample(document)).to.not.be.null;
});
});
async function buildFixture(config) {
const fixture = await loadFixture({
root: FIXTURE_ROOT,
...config,
});
await fixture.build();
return fixture;
}
function remarkExamplePlugin() {
return (tree) => {
tree.children.push({
type: 'html',
value: '<div data-remark-plugin-works="true"></div>',
});
};
}
function rehypeExamplePlugin() {
return (tree) => {
tree.children.push({
type: 'element',
tagName: 'div',
properties: { 'data-rehype-plugin-works': 'true' },
});
};
}
function recmaExamplePlugin() {
return (tree) => {
estreeVisit(tree, (node) => {
if (
node.type === 'VariableDeclarator' &&
node.id.name === 'recmaPluginWorking' &&
node.init?.type === 'Literal'
) {
node.init = {
...(node.init ?? {}),
value: true,
raw: 'true',
};
}
});
};
}
function selectTocLink(document) {
return document.querySelector('ul a[href="#section-1"]');
}
function selectGfmLink(document) {
return document.querySelector('a[href="https://handle-me-gfm.com"]');
}
function selectRemarkExample(document) {
return document.querySelector('div[data-remark-plugin-works]');
}
function selectRehypeExample(document) {
return document.querySelector('div[data-rehype-plugin-works]');
}
function selectRecmaExample(document) {
return document.querySelector('div[data-recma-plugin-works]');
}