diff --git a/app/composables/useMarkdown.ts b/app/composables/useMarkdown.ts index c0ab0e6aa..4f3cfe730 100644 --- a/app/composables/useMarkdown.ts +++ b/app/composables/useMarkdown.ts @@ -37,6 +37,9 @@ function stripAndEscapeHtml(text: string, packageName?: string): string { // Only match tags that start with a letter or / (to avoid matching things like "a < b > c") stripped = stripped.replace(/<\/?[a-z][^>]*>/gi, '') + // Strip HTML comments: (including unclosed comments from truncation) + stripped = stripped.replace(/|$)/g, '') + if (packageName) { // Trim first to handle leading/trailing whitespace from stripped HTML stripped = stripped.trim() diff --git a/test/nuxt/composables/use-markdown.spec.ts b/test/nuxt/composables/use-markdown.spec.ts index 77a805552..b8ac88f3b 100644 --- a/test/nuxt/composables/use-markdown.spec.ts +++ b/test/nuxt/composables/use-markdown.spec.ts @@ -318,4 +318,36 @@ describe('useMarkdown', () => { expect(processed.value).toBe('bold and also bold') }) }) + + describe('HTML comment stripping', () => { + it('strips HTML comments', () => { + const processed = useMarkdown({ text: 'A library' }) + expect(processed.value).toBe('A library') + }) + + it('strips HTML comments from the middle of text', () => { + const processed = useMarkdown({ text: 'Before after' }) + expect(processed.value).toBe('Before after') + }) + + it('strips multiple HTML comments', () => { + const processed = useMarkdown({ text: 'Text here' }) + expect(processed.value).toBe('Text here') + }) + + it('strips multiline HTML comments', () => { + const processed = useMarkdown({ text: 'Text' }) + expect(processed.value).toBe('Text') + }) + + it('returns empty string when description is only a comment', () => { + const processed = useMarkdown({ text: '' }) + expect(processed.value).toBe('') + }) + + it('strips unclosed HTML comments (truncated)', () => { + const processed = useMarkdown({ text: 'A library