Skip to content

Commit d2f06d3

Browse files
devartifexCopilot
andcommitted
fix: prevent incomplete HTML tag sanitization in TTS strip
Apply iterative tag removal to handle nested/split tags like <scr<script>ipt> that survive a single-pass replace. Fixes code-scanning alert #21 (js/incomplete-multi-character-sanitization). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent d0dde09 commit d2f06d3

1 file changed

Lines changed: 34 additions & 22 deletions

File tree

‎src/lib/stores/tts.svelte.ts‎

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,41 @@
11
const SUPPORTED = typeof window !== 'undefined' && 'speechSynthesis' in window;
22

3+
/** Remove all HTML tags, repeating until no tags remain (prevents incomplete sanitization). */
4+
function stripHtmlTags(text: string): string {
5+
const tagPattern = /<[^>]*>/g;
6+
let previous = text;
7+
let result = text.replace(tagPattern, '');
8+
while (result !== previous) {
9+
previous = result;
10+
result = result.replace(tagPattern, '');
11+
}
12+
return result;
13+
}
14+
315
/** Strip markdown/HTML to plain text suitable for speech synthesis. */
416
function stripToPlainText(markdown: string): string {
5-
return markdown
6-
// Remove code blocks (``` ... ```)
7-
.replace(/```[\s\S]*?```/g, ' code block omitted ')
8-
// Remove inline code
9-
.replace(/`([^`]+)`/g, '$1')
10-
// Remove images
11-
.replace(/!\[([^\]]*)\]\([^)]+\)/g, '$1')
12-
// Remove links — keep text
13-
.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1')
14-
// Remove headings markers
15-
.replace(/^#{1,6}\s+/gm, '')
16-
// Remove bold/italic markers
17-
.replace(/\*{1,3}([^*]+)\*{1,3}/g, '$1')
18-
.replace(/_{1,3}([^_]+)_{1,3}/g, '$1')
19-
// Remove strikethrough
20-
.replace(/~~([^~]+)~~/g, '$1')
21-
// Remove blockquotes
22-
.replace(/^>\s+/gm, '')
23-
// Remove horizontal rules
24-
.replace(/^[-*_]{3,}\s*$/gm, '')
25-
// Remove HTML tags
26-
.replace(/<[^>]+>/g, '')
17+
return stripHtmlTags(
18+
markdown
19+
// Remove code blocks (``` ... ```)
20+
.replace(/```[\s\S]*?```/g, ' code block omitted ')
21+
// Remove inline code
22+
.replace(/`([^`]+)`/g, '$1')
23+
// Remove images
24+
.replace(/!\[([^\]]*)\]\([^)]+\)/g, '$1')
25+
// Remove links — keep text
26+
.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1')
27+
// Remove headings markers
28+
.replace(/^#{1,6}\s+/gm, '')
29+
// Remove bold/italic markers
30+
.replace(/\*{1,3}([^*]+)\*{1,3}/g, '$1')
31+
.replace(/_{1,3}([^_]+)_{1,3}/g, '$1')
32+
// Remove strikethrough
33+
.replace(/~~([^~]+)~~/g, '$1')
34+
// Remove blockquotes
35+
.replace(/^>\s+/gm, '')
36+
// Remove horizontal rules
37+
.replace(/^[-*_]{3,}\s*$/gm, '')
38+
)
2739
// Collapse multiple newlines/spaces
2840
.replace(/\n{2,}/g, '. ')
2941
.replace(/\n/g, ' ')

0 commit comments

Comments
 (0)