diff --git a/packages/svelte-markdown-preprocess/src/index.spec.ts b/packages/svelte-markdown-preprocess/src/index.spec.ts
index bb9ca7f4..df049a92 100644
--- a/packages/svelte-markdown-preprocess/src/index.spec.ts
+++ b/packages/svelte-markdown-preprocess/src/index.spec.ts
@@ -98,6 +98,49 @@ describe(svelteMarkdownPreprocess.name, () => {
});
});
+ describe('svelte components', () => {
+ const render = async (content: string) => {
+ const result = await svelteMarkdownPreprocess().markup({ filename: 'test.md', content });
+ return result?.code ?? '';
+ };
+
+ it('should render a component that owns its line', async () => {
+ await expect(render('')).resolves.toContain('');
+ });
+
+ it('should render sibling components sharing a line', async () => {
+ const code = await render(' ');
+
+ expect(code).toContain('');
+ expect(code).toContain('');
+ expect(code).not.toContain('<');
+ });
+
+ it('should render a component followed by prose on the same line', async () => {
+ const code = await render('In order to use this');
+
+ expect(code).toContain('');
+ expect(code).toContain('In order to use this');
+ });
+
+ it('should render a component preceded by prose on the same line', async () => {
+ await expect(render('Look at this ')).resolves.toContain(
+ 'Look at this ',
+ );
+ });
+
+ it('should import a relative source from a component sharing a line', async () => {
+ const code = await render('Look at this ');
+
+ expect(code).toContain(`import __image_0 from './img/example.webp';`);
+ expect(code).toContain('');
+ });
+
+ it('should leave a component inside a code fence as code', async () => {
+ await expect(render('```svelte\n\n```')).resolves.toContain(' {
it('should import relative images so vite can optimize them', async () => {
const result = await svelteMarkdownPreprocess().markup({
diff --git a/packages/svelte-markdown-preprocess/src/markdown.ts b/packages/svelte-markdown-preprocess/src/markdown.ts
index 1ed1791f..2c1b7072 100644
--- a/packages/svelte-markdown-preprocess/src/markdown.ts
+++ b/packages/svelte-markdown-preprocess/src/markdown.ts
@@ -27,7 +27,8 @@ const renderAlert = (
) => `${parser.parse(tokens)}\n`;
// Marked reads a dotted tag as text, so a component like `` needs its own rule.
-const SVELTE_COMPONENT_REGEX = /^<[A-Z]\w*\.\w+\b[^>]*\/>[ \t]*(?:\n+|$)/;
+const SVELTE_COMPONENT_REGEX = /^<[A-Z]\w*\.\w+\b[^>]*\/>/;
+const SVELTE_COMPONENT_BLOCK_REGEX = new RegExp(String.raw`${SVELTE_COMPONENT_REGEX.source}[ \t]*\n?`);
const normalizeText = (text: string) => escapeHtml(emojify(text));
@@ -75,9 +76,16 @@ export const markedSvelte = (): MarkedExtension => ({
},
html(src) {
- const match = SVELTE_COMPONENT_REGEX.exec(src);
+ const match = SVELTE_COMPONENT_BLOCK_REGEX.exec(src);
return match ? { type: 'html', raw: match[0], text: `${match[0].trim()}\n`, pre: false, block: true } : false;
},
+
+ tag(src) {
+ const match = SVELTE_COMPONENT_REGEX.exec(src);
+ return match
+ ? { type: 'html', raw: match[0], text: match[0], inLink: false, inRawBlock: false, block: false }
+ : false;
+ },
},
extensions: [