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:
parent
073bab5ec1
commit
c549f161ca
6 changed files with 572 additions and 416 deletions
5
.changeset/swift-rocks-refuse.md
Normal file
5
.changeset/swift-rocks-refuse.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@astrojs/markdown-remark': patch
|
||||
---
|
||||
|
||||
Allow AlpineJS syntax extensions in Markdown
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
31
packages/markdown/remark/src/mdxjs.ts
Normal file
31
packages/markdown/remark/src/mdxjs.ts
Normal 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
|
||||
]);
|
||||
}
|
|
@ -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 = {}) {
|
||||
|
|
|
@ -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" />`);
|
||||
});
|
||||
|
||||
});
|
||||
|
|
819
pnpm-lock.yaml
819
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue