feat(quick-260329-ton): implement renderInlineMarkdown utility
- Escapes HTML special chars first (XSS safe) - Converts **bold** to <strong>, *italic* to <em> - Standalone asterisks with spaces are left unchanged - Pure function, no DOM dependency
This commit is contained in:
@@ -0,0 +1,30 @@
|
|||||||
|
/**
|
||||||
|
* Renders inline Markdown (bold, italic) to HTML safely.
|
||||||
|
*
|
||||||
|
* - Escapes HTML special characters first to prevent XSS
|
||||||
|
* - Converts **bold** to <strong>bold</strong>
|
||||||
|
* - Converts *italic* to <em>italic</em>
|
||||||
|
* - Standalone asterisks surrounded by spaces are left unchanged
|
||||||
|
*
|
||||||
|
* Pure function — no DOM required.
|
||||||
|
*/
|
||||||
|
export function renderInlineMarkdown(text: string): string {
|
||||||
|
if (text === "") return "";
|
||||||
|
|
||||||
|
// Step 1: Escape HTML special characters to prevent XSS
|
||||||
|
let result = text
|
||||||
|
.replace(/&/g, "&")
|
||||||
|
.replace(/</g, "<")
|
||||||
|
.replace(/>/g, ">")
|
||||||
|
.replace(/"/g, """)
|
||||||
|
.replace(/'/g, "'");
|
||||||
|
|
||||||
|
// Step 2: Convert **bold** (must come before *italic* so ** is not consumed as two *)
|
||||||
|
result = result.replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>");
|
||||||
|
|
||||||
|
// Step 3: Convert *italic* — only matches when content is non-empty and
|
||||||
|
// asterisks are not surrounded by spaces (avoids "2 * 3 * 4" false positives)
|
||||||
|
result = result.replace(/\*(\S[^*]*?\S|\S)\*/g, "<em>$1</em>");
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user