summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.changeset/late-swans-impress.md5
-rw-r--r--packages/markdown/remark/src/remark-mdxish.ts37
-rw-r--r--packages/markdown/remark/test/strictness.test.js16
3 files changed, 57 insertions, 1 deletions
diff --git a/.changeset/late-swans-impress.md b/.changeset/late-swans-impress.md
new file mode 100644
index 000000000..ace91bef8
--- /dev/null
+++ b/.changeset/late-swans-impress.md
@@ -0,0 +1,5 @@
+---
+'@astrojs/markdown-remark': patch
+---
+
+Fix: Allow self-closing tags in Markdown
diff --git a/packages/markdown/remark/src/remark-mdxish.ts b/packages/markdown/remark/src/remark-mdxish.ts
index 0ad8cbf4f..e94a1146f 100644
--- a/packages/markdown/remark/src/remark-mdxish.ts
+++ b/packages/markdown/remark/src/remark-mdxish.ts
@@ -1,11 +1,13 @@
import { mdxjs } from 'micromark-extension-mdxjs';
import { mdxFromMarkdown, mdxToMarkdown } from './mdast-util-mdxish.js';
+import type * as fromMarkdown from 'mdast-util-from-markdown';
+import type { Tag } from 'mdast-util-mdx-jsx';
export default function remarkMdxish(this: any, options = {}) {
const data = this.data();
add('micromarkExtensions', mdxjs(options));
- add('fromMarkdownExtensions', mdxFromMarkdown());
+ add('fromMarkdownExtensions', makeFromMarkdownLessStrict(mdxFromMarkdown()));
add('toMarkdownExtensions', mdxToMarkdown());
function add(field: string, value: unknown) {
@@ -13,3 +15,36 @@ export default function remarkMdxish(this: any, options = {}) {
list.push(value);
}
}
+
+function makeFromMarkdownLessStrict(extensions: fromMarkdown.Extension[]) {
+ extensions.forEach(extension => {
+ // Fix exit handlers that are too strict
+ ['mdxJsxFlowTag', 'mdxJsxTextTag'].forEach(exitHandler => {
+ if (!extension.exit || !extension.exit[exitHandler])
+ return;
+ extension.exit[exitHandler] = chainHandlers(
+ fixSelfClosing,
+ extension.exit[exitHandler]
+ );
+ });
+ });
+
+ return extensions;
+}
+
+const selfClosingTags = new Set([
+ 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'source',
+ 'track', 'wbr'
+]);
+
+function fixSelfClosing(this: fromMarkdown.CompileContext) {
+ const tag = this.getData('mdxJsxTag') as Tag;
+ if (tag.name && selfClosingTags.has(tag.name))
+ tag.selfClosing = true;
+}
+
+function chainHandlers(...handlers: fromMarkdown.Handle[]) {
+ return function handlerChain (this: fromMarkdown.CompileContext, token: fromMarkdown.Token) {
+ handlers.forEach(handler => handler.call(this, token));
+ };
+}
diff --git a/packages/markdown/remark/test/strictness.test.js b/packages/markdown/remark/test/strictness.test.js
new file mode 100644
index 000000000..c18cc41dd
--- /dev/null
+++ b/packages/markdown/remark/test/strictness.test.js
@@ -0,0 +1,16 @@
+import { renderMarkdown } from '../dist/index.js';
+import chai from 'chai';
+
+describe('strictness', () => {
+ it('should allow self-closing HTML tags (void elements)', async () => {
+ const { code } = await renderMarkdown(
+ `Use self-closing void elements<br>like word<wbr>break and images: <img src="hi.jpg">`,
+ {}
+ );
+
+ chai.expect(code).to.equal(
+ `<p>Use self-closing void elements<br />like word<wbr />break and images: ` +
+ `<img src="hi.jpg" /></p>`
+ );
+ });
+});