| 1 | // REFACTORING NOTES: |
| 2 | // 1. Improved inline formatting parsing to handle both * and ** for italics/bold |
| 3 | // 2. Fixed regex patterns to be non-greedy and handle multiple elements correctly |
| 4 | // 3. Better separation of concerns and clearer function names |
| 5 | // 4. Added comprehensive comments for maintainability |
| 6 | |
| 7 | /** |
| 8 | * Wraps text in HTML tags |
| 9 | * @param {string} text - The text to wrap |
| 10 | * @param {string} tag - The HTML tag name |
| 11 | * @returns {string} The wrapped text |
| 12 | */ |
| 1 | 13 | function wrap(text, tag) { |
| 2 | 14 | return `<${tag}>${text}</${tag}>`; |
| 3 | 15 | } |
| 4 | 16 | |
| 17 | /** |
| 18 | * Checks if text starts with a specific HTML tag |
| 19 | * @param {string} text - The text to check |
| 20 | * @param {string} tag - The tag to look for |
| 21 | * @returns {boolean} True if text starts with the tag |
| 22 | */ |
| 5 | 23 | function isTag(text, tag) { |
| 6 | 24 | return text.startsWith(`<${tag}>`); |
| 7 | 25 | } |
| 8 | 26 | |
| 9 | | function parser(markdown, delimiter, tag) { |
| 10 | | const pattern = new RegExp(`${delimiter}(.+)${delimiter}`); |
| 27 | /** |
| 28 | * Parses inline formatting (bold/italic) using regex |
| 29 | * @param {string} markdown - The markdown text |
| 30 | * @param {string} delimiter - The delimiter to search for |
| 31 | * @param {string} tag - The HTML tag to replace with |
| 32 | * @returns {string} The parsed text |
| 33 | */ |
| 34 | function parseInlineFormatting(markdown, delimiter, tag) { |
| 35 | // Escape special regex characters in delimiter |
| 36 | const escapedDelimiter = delimiter.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); |
| 37 | // Use non-greedy matching to handle multiple elements correctly |
| 38 | const pattern = new RegExp(`${escapedDelimiter}([^${delimiter}]+?)${escapedDelimiter}`, 'g'); |
| 11 | 39 | const replacement = `<${tag}>$1</${tag}>`; |
| 12 | 40 | return markdown.replace(pattern, replacement); |
| 13 | 41 | } |
| 14 | 42 | |
| 15 | | function parse__(markdown) { |
| 16 | | return parser(markdown, '__', 'strong'); |
| 43 | /** |
| 44 | * Parses bold text (both ** and __) |
| 45 | * @param {string} markdown - The markdown text |
| 46 | * @returns {string} The text with bold formatting applied |
| 47 | */ |
| 48 | function parseBold(markdown) { |
| 49 | // Handle **bold** first, then __bold__ |
| 50 | let result = parseInlineFormatting(markdown, '**', 'strong'); |
| 51 | result = parseInlineFormatting(result, '__', 'strong'); |
| 52 | return result; |
| 17 | 53 | } |
| 18 | 54 | |
| 19 | | function parse_(markdown) { |
| 20 | | return parser(markdown, '_', 'em'); |
| 55 | /** |
| 56 | * Parses italic text (both * and _) |
| 57 | * @param {string} markdown - The markdown text |
| 58 | * @returns {string} The text with italic formatting applied |
| 59 | */ |
| 60 | function parseItalic(markdown) { |
| 61 | // Handle *italic* first, then _italic_ |
| 62 | let result = parseInlineFormatting(markdown, '*', 'em'); |
| 63 | result = parseInlineFormatting(result, '_', 'em'); |
| 64 | return result; |
| 65 | } |
| 66 | |
| 67 | /** |
| 68 | * Parses all inline formatting (bold and italic) |
| 69 | * @param {string} markdown - The markdown text |
| 70 | * @returns {string} The text with all inline formatting applied |
| 71 | */ |
| 72 | function parseInlineFormattingAll(markdown) { |
| 73 | // Parse bold first, then italic to avoid conflicts |
| 74 | let result = parseBold(markdown); |
| 75 | result = parseItalic(result); |
| 76 | return result; |
| 21 | 77 | } |
| 22 | 78 | |
| 79 | /** |
| 80 | * Parses text content with inline formatting |
| 81 | * @param {string} markdown - The markdown text |
| 82 | * @param {boolean} list - Whether this is part of a list |
| 83 | * @returns {string} The parsed text |
| 84 | */ |
| 23 | 85 | function parseText(markdown, list) { |
| 24 | | const parsedText = parse_(parse__(markdown)); |
| 86 | const parsedText = parseInlineFormattingAll(markdown); |
| 25 | 87 | if (list) { |
| 26 | 88 | return parsedText; |
| 27 | 89 | } else { |