* Parse a single line of markdown * @param {string} line - Raw markdown line * @returns {string} Parsed HTML line
(line, isPreviewMode = false)
| 449 | * @returns {string} Parsed HTML line |
| 450 | */ |
| 451 | static parseLine(line, isPreviewMode = false) { |
| 452 | let html = this.escapeHtml(line); |
| 453 | |
| 454 | // Preserve indentation |
| 455 | html = this.preserveIndentation(html, line); |
| 456 | |
| 457 | // Check for block elements first |
| 458 | const horizontalRule = this.parseHorizontalRule(html); |
| 459 | if (horizontalRule) return horizontalRule; |
| 460 | |
| 461 | const codeBlock = this.parseCodeBlock(html); |
| 462 | if (codeBlock) return codeBlock; |
| 463 | |
| 464 | // Parse block elements |
| 465 | html = this.parseHeader(html); |
| 466 | html = this.parseBlockquote(html); |
| 467 | html = this.parseTaskList(html, isPreviewMode); // Check task lists before regular bullet lists |
| 468 | html = this.parseBulletList(html); |
| 469 | html = this.parseNumberedList(html); |
| 470 | |
| 471 | // Parse inline elements (skip for headers and list items — already parsed inside those functions) |
| 472 | if (!html.includes('<li') && !html.includes('<h')) { |
| 473 | html = this.parseInlineElements(html); |
| 474 | } |
| 475 | |
| 476 | // Wrap in div to maintain line structure |
| 477 | if (html.trim() === '') { |
| 478 | // Intentionally use for empty lines to maintain vertical spacing |
| 479 | // This causes a 0->1 character count difference but preserves visual alignment |
| 480 | return '<div> </div>'; |
| 481 | } |
| 482 | |
| 483 | return `<div>${html}</div>`; |
| 484 | } |
| 485 | |
| 486 | /** |
| 487 | * Parse full markdown text |
no test coverage detected