From 294d300a83ea3ed8e48fdf8366e9c8a8745a928c Mon Sep 17 00:00:00 2001 From: Igor Klepacki Date: Fri, 27 Jun 2025 02:08:52 +0200 Subject: [PATCH] fix: resolve svg being invalidly set as raw nodes --- src/index.ts | 26 +++++++++++++------------- test/index.test.ts | 35 +++++++++++++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/src/index.ts b/src/index.ts index 2aafe87..daf9db4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -246,17 +246,20 @@ function detectRenderMode(file?: VFile): RenderMode { // Removed: Using mdast-util-to-string instead of custom extractTextContent function -function parseIconHtml(iconHtml: string): Array<{ type: 'html'; value: string }> { +function parseIconHtml(iconHtml: string): ElementContent[] { if (!iconHtml || !iconHtml.trim()) { return [] } try { - // Validate HTML structure but return as raw HTML node for component mode compatibility + // Parse HTML string into proper HAST nodes const hastTree = fromHtml(iconHtml, { fragment: true }) if (hastTree.type === 'root' && hastTree.children && hastTree.children.length > 0) { - return [{ type: 'html', value: iconHtml }] + // Return the actual HAST elements, not raw HTML nodes + return hastTree.children.filter( + (child): child is ElementContent => child.type === 'element' || child.type === 'text' + ) } return [] @@ -308,18 +311,15 @@ function createAlertComponent( }, }, [ - u( - config.tags.icon, - { - data: { - hName: config.tags.icon, - hProperties: { - className: config.classNames.icon, - }, + u(config.tags.icon, { + data: { + hName: config.tags.icon, + hProperties: { + className: config.classNames.icon, }, + hChildren: iconChildren, // Place HAST nodes in data.hChildren }, - iconChildren - ), + }), u('text', title), ] ), diff --git a/test/index.test.ts b/test/index.test.ts index 0a380af..99cb983 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -570,7 +570,7 @@ describe('remarkGitHubAlerts', () => { expect(result).toContain('viewBox="0 0 16 16"') expect(result).toContain('data-alert-type="tip"') expect(result).toContain( - '' + '') }) @@ -1220,7 +1220,8 @@ More regular text. // Verify special characters are properly handled expect(result).toContain('') expect(result).toContain('') - expect(result).toContain('Test & "quotes" <tags>') + // HTML entities can be rendered as named or numeric entities + expect(result).toMatch(/Test (?:&|&) "quotes" (?:<|<)tags(?:>|>)/) expect(result).toContain('') expect(result).toContain('') expect(result).toContain('data-alert-type="warning"') @@ -1407,5 +1408,35 @@ More regular text. expect(result).not.toContain('') } }) + + it('should properly render SVG icons as DOM elements not text in component mode', async () => { + // This test specifically addresses the user's issue where SVG was being rendered as text + const userProvidedSvg = + '' + const markdown = `> [!NOTE] +> User test case for SVG rendering.` + + const result = await processMarkdownComponent(markdown, { + alerts: { + note: { + iconElementHtml: userProvidedSvg, + }, + }, + }) + + // Verify the SVG is properly included as DOM elements + expect(result).toContain('') + expect(result).toContain('') + }) }) })