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"
|
"test": "mocha --exit --timeout 20000"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@astrojs/micromark-extension-mdx-jsx": "^1.0.3",
|
||||||
"@astrojs/prism": "^0.4.1",
|
"@astrojs/prism": "^0.4.1",
|
||||||
|
"acorn": "^8.7.1",
|
||||||
|
"acorn-jsx": "^5.3.2",
|
||||||
"assert": "^2.0.0",
|
"assert": "^2.0.0",
|
||||||
"github-slugger": "^1.4.0",
|
"github-slugger": "^1.4.0",
|
||||||
"mdast-util-mdx-expression": "^1.2.0",
|
"mdast-util-mdx-expression": "^1.2.0",
|
||||||
"mdast-util-mdx-jsx": "^1.2.0",
|
"mdast-util-mdx-jsx": "^1.2.0",
|
||||||
"mdast-util-to-string": "^3.1.0",
|
"mdast-util-to-string": "^3.1.0",
|
||||||
"micromark-extension-mdx-jsx": "^1.0.3",
|
"micromark-extension-mdx-expression": "^1.0.3",
|
||||||
"micromark-extension-mdxjs": "^1.0.0",
|
"micromark-extension-mdx-md": "^1.0.0",
|
||||||
|
"micromark-util-combine-extensions": "^1.0.0",
|
||||||
"prismjs": "^1.28.0",
|
"prismjs": "^1.28.0",
|
||||||
"rehype-raw": "^6.1.1",
|
"rehype-raw": "^6.1.1",
|
||||||
"rehype-stringify": "^9.0.3",
|
"rehype-stringify": "^9.0.3",
|
||||||
|
@ -55,6 +59,7 @@
|
||||||
"@types/unist": "^2.0.6",
|
"@types/unist": "^2.0.6",
|
||||||
"astro-scripts": "workspace:*",
|
"astro-scripts": "workspace:*",
|
||||||
"chai": "^4.3.6",
|
"chai": "^4.3.6",
|
||||||
|
"micromark-util-types": "^1.0.2",
|
||||||
"mocha": "^9.2.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 * as fromMarkdown from 'mdast-util-from-markdown';
|
||||||
import type { Tag } from 'mdast-util-mdx-jsx';
|
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';
|
import { mdxFromMarkdown, mdxToMarkdown } from './mdast-util-mdxish.js';
|
||||||
|
|
||||||
export default function remarkMdxish(this: any, options = {}) {
|
export default function remarkMdxish(this: any, options = {}) {
|
||||||
|
|
|
@ -15,4 +15,126 @@ describe('strictness', () => {
|
||||||
`<img src="hi.jpg" /></p>`
|
`<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