Allow AlpineJS syntax extensions in Markdown (#3554)

* Allow AlpineJS syntax extensions in Markdown

* Remove unwanted MDX ESM import/export support
This commit is contained in:
hippotastic 2022-06-08 19:41:36 +02:00 committed by GitHub
parent 073bab5ec1
commit c549f161ca
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 572 additions and 416 deletions

View file

@ -0,0 +1,5 @@
---
'@astrojs/markdown-remark': patch
---
Allow AlpineJS syntax extensions in Markdown

View file

@ -24,14 +24,18 @@
"test": "mocha --exit --timeout 20000"
},
"dependencies": {
"@astrojs/micromark-extension-mdx-jsx": "^1.0.3",
"@astrojs/prism": "^0.4.1",
"acorn": "^8.7.1",
"acorn-jsx": "^5.3.2",
"assert": "^2.0.0",
"github-slugger": "^1.4.0",
"mdast-util-mdx-expression": "^1.2.0",
"mdast-util-mdx-jsx": "^1.2.0",
"mdast-util-to-string": "^3.1.0",
"micromark-extension-mdx-jsx": "^1.0.3",
"micromark-extension-mdxjs": "^1.0.0",
"micromark-extension-mdx-expression": "^1.0.3",
"micromark-extension-mdx-md": "^1.0.0",
"micromark-util-combine-extensions": "^1.0.0",
"prismjs": "^1.28.0",
"rehype-raw": "^6.1.1",
"rehype-stringify": "^9.0.3",
@ -55,6 +59,7 @@
"@types/unist": "^2.0.6",
"astro-scripts": "workspace:*",
"chai": "^4.3.6",
"micromark-util-types": "^1.0.2",
"mocha": "^9.2.2"
}
}

View file

@ -0,0 +1,31 @@
// Note: The code in this file is based on `micromark-extension-mdxjs`
// and was adapted to use our fork `@astrojs/micromark-extension-mdx-jsx`
// instead of `micromark-extension-mdx-jsx` to allow some extended syntax.
// See `@astrojs/micromark-extension-mdx-jsx` on NPM for more details.
// Also, support for ESM imports & exports in Markdown content was removed.
import { Parser } from 'acorn';
import acornJsx from 'acorn-jsx';
import { combineExtensions } from 'micromark-util-combine-extensions';
import { mdxExpression } from 'micromark-extension-mdx-expression';
import { mdxJsx } from '@astrojs/micromark-extension-mdx-jsx';
import { mdxMd } from 'micromark-extension-mdx-md';
import type { Options } from 'micromark-extension-mdx-expression';
import type { Extension } from 'micromark-util-types';
export function mdxjs(options: Options): Extension {
const settings: any = Object.assign(
{
acorn: Parser.extend(acornJsx()),
acornOptions: { ecmaVersion: 2020, sourceType: 'module' },
addResult: true
},
options
);
return combineExtensions([
mdxExpression(settings),
mdxJsx(settings),
mdxMd
]);
}

View file

@ -1,6 +1,6 @@
import type * as fromMarkdown from 'mdast-util-from-markdown';
import type { Tag } from 'mdast-util-mdx-jsx';
import { mdxjs } from 'micromark-extension-mdxjs';
import { mdxjs } from './mdxjs.js';
import { mdxFromMarkdown, mdxToMarkdown } from './mdast-util-mdxish.js';
export default function remarkMdxish(this: any, options = {}) {

View file

@ -15,4 +15,126 @@ describe('strictness', () => {
`<img src="hi.jpg" /></p>`
);
});
it('should allow attribute names starting with ":" after element names', async () => {
const { code } = await renderMarkdown(
`<div :class="open ? '' : 'hidden'">Test</div>`,
{}
);
chai
.expect(code.trim())
.to.equal(`<div :class="open ? '' : 'hidden'">Test</div>`);
});
it('should allow attribute names starting with ":" after local element names', async () => {
const { code } = await renderMarkdown(
`<div.abc :class="open ? '' : 'hidden'">x</div.abc>`,
{}
);
chai
.expect(code.trim())
.to.equal(`<div.abc :class="open ? '' : 'hidden'">x</div.abc>`);
});
it('should allow attribute names starting with ":" after attribute names', async () => {
const { code } = await renderMarkdown(
`<input type="text" disabled :placeholder="hi">`,
{}
);
chai
.expect(code.trim())
.to.equal(`<input type="text" disabled :placeholder="hi" />`);
});
it('should allow attribute names starting with ":" after local attribute names', async () => {
const { code } = await renderMarkdown(
`<input type="text" x-test:disabled :placeholder="hi">`,
{}
);
chai
.expect(code.trim())
.to.equal(`<input type="text" x-test:disabled :placeholder="hi" />`);
});
it('should allow attribute names starting with ":" after attribute values', async () => {
const { code } = await renderMarkdown(
`<input type="text" :placeholder="placeholder">`,
{}
);
chai
.expect(code.trim())
.to.equal(`<input type="text" :placeholder="placeholder" />`);
});
it('should allow attribute names starting with "@" after element names', async () => {
const { code } = await renderMarkdown(
`<button @click="handleClick">Test</button>`,
{}
);
chai
.expect(code.trim())
.to.equal(`<button @click="handleClick">Test</button>`);
});
it('should allow attribute names starting with "@" after local element names', async () => {
const { code } = await renderMarkdown(
`<button.local @click="handleClick">Test</button.local>`,
{}
);
chai
.expect(code.trim())
.to.equal(`<button.local @click="handleClick">Test</button.local>`);
});
it('should allow attribute names starting with "@" after attribute names', async () => {
const { code } = await renderMarkdown(
`<button disabled @click="handleClick">Test</button>`,
{}
);
chai
.expect(code.trim())
.to.equal(`<button disabled @click="handleClick">Test</button>`);
});
it('should allow attribute names starting with "@" after local attribute names', async () => {
const { code } = await renderMarkdown(
`<button x-test:disabled @click="handleClick">Test</button>`,
{}
);
chai
.expect(code.trim())
.to.equal(`<button x-test:disabled @click="handleClick">Test</button>`);
});
it('should allow attribute names starting with "@" after attribute values', async () => {
const { code } = await renderMarkdown(
`<button type="submit" @click="handleClick">Test</button>`,
{}
);
chai
.expect(code.trim())
.to.equal(`<button type="submit" @click="handleClick">Test</button>`);
});
it('should allow attribute names containing dots', async () => {
const { code } = await renderMarkdown(
`<input x-on:input.debounce.500ms="fetchResults">`,
{}
);
chai
.expect(code.trim())
.to.equal(`<input x-on:input.debounce.500ms="fetchResults" />`);
});
});

File diff suppressed because it is too large Load diff