From 53d3670c7ffcf7da7a12b2546ee86e427dc6e1d0 Mon Sep 17 00:00:00 2001 From: Jared Vititoe Date: Wed, 15 Jul 2026 14:42:10 -0400 Subject: [PATCH] Fix markdown comments breaking on reload (template whitespace parsed as code) Stored markdown comments rendered fine in the live preview (parses the raw textarea value) but broke after refresh: the server template emitted the comment text on an indented line, so the on-load renderer parsed element.textContent with ~20 spaces of leading indentation. Markdown treats 4+ leading spaces as a code block, so the first line (e.g. a heading or table row) was mis-parsed and blocks got wrapped in

, producing invalid HTML that broke the page layout. - markdown.js: trim the text before parseMarkdown in both on-load renderers so template indentation can't be parsed as a leading code block. - TicketView.php: emit the comment text inline (no surrounding whitespace) so the element's textContent is exactly the stored markdown. Co-Authored-By: Claude Opus 4.8 --- assets/js/markdown.js | 9 +++++++-- views/TicketView.php | 11 +++++++---- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/assets/js/markdown.js b/assets/js/markdown.js index 42efc19..7bba4ee 100644 --- a/assets/js/markdown.js +++ b/assets/js/markdown.js @@ -334,7 +334,10 @@ function buildTable(rows) { // Apply markdown rendering to all elements with data-markdown attribute function renderMarkdownElements() { document.querySelectorAll('[data-markdown]:not([data-rendered])').forEach(element => { - const markdownText = element.getAttribute('data-markdown') || element.textContent; + // Trim so template indentation/whitespace in the element's text content + // doesn't get parsed as a leading code block (which breaks headings, + // tables, etc. and diverges from the live preview). + const markdownText = (element.getAttribute('data-markdown') || element.textContent).trim(); element.innerHTML = parseMarkdown(markdownText); element.dataset.rendered = '1'; }); @@ -587,7 +590,9 @@ function processPlainTextComments() { function renderMarkdownComments() { document.querySelectorAll('.comment-text[data-markdown]:not([data-rendered])').forEach(el => { el.classList.add('lt-markdown'); - el.innerHTML = parseMarkdown(el.textContent); + // Trim template whitespace so the first line isn't parsed as an + // indented code block (matches the live-preview rendering). + el.innerHTML = parseMarkdown(el.textContent.trim()); el.dataset.rendered = '1'; }); } diff --git a/views/TicketView.php b/views/TicketView.php index 767ffc0..4b49a38 100644 --- a/views/TicketView.php +++ b/views/TicketView.php @@ -621,11 +621,14 @@ include __DIR__ . '/layout_header.php';

> - > -
+ : nl2br(htmlspecialchars($comment['comment_text'])) + ?>