Skip to content

fix(changelog): preserve HTML blocks in custom changelog entry sections#786

Merged
BYK merged 1 commit intomasterfrom
byk/fix/changelog-html-blocks
Mar 27, 2026
Merged

fix(changelog): preserve HTML blocks in custom changelog entry sections#786
BYK merged 1 commit intomasterfrom
byk/fix/changelog-html-blocks

Conversation

@BYK
Copy link
Copy Markdown
Member

@BYK BYK commented Mar 27, 2026

Changelog Entry

Preserve HTML blocks (e.g., <img> tags from GitHub image uploads) in custom ## Changelog Entry PR sections instead of silently dropping them.

Summary

GitHub stores uploaded images as standalone <img> HTML tags in PR bodies. When marked.lexer() parses these, it produces tokens of type html. However, parseTokensToEntries() only handled list, paragraph, and code token types — silently dropping everything else.

This adds an html token handler that preserves HTML blocks as nested content on the previous changelog entry, following the same pattern already used for fenced code blocks. Orphaned HTML blocks (with no preceding entry) are skipped, consistent with code block behavior.

Discovered via getsentry/cli#555 where the screenshot was dropped from the 0.21.0 release notes.

@BYK BYK marked this pull request as ready for review March 27, 2026 13:04
@BYK BYK force-pushed the byk/fix/changelog-html-blocks branch from 2cbb378 to c552c2d Compare March 27, 2026 13:06
Copy link
Copy Markdown
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Multi-line HTML blocks only indent first line
    • Created renderIndentedHtml() helper function that properly indents every line of multi-line HTML blocks, consistent with code block handling.

Create PR

Or push these changes by commenting:

@cursor push 4e8671910b
Preview (4e8671910b)
diff --git a/src/utils/__tests__/changelog-extract.test.ts b/src/utils/__tests__/changelog-extract.test.ts
--- a/src/utils/__tests__/changelog-extract.test.ts
+++ b/src/utils/__tests__/changelog-extract.test.ts
@@ -399,4 +399,42 @@
       'src="https://github.com/user-attachments/assets/abc123"',
     );
   });
+
+  it('indents every line of multi-line HTML blocks', () => {
+    const prBody = `### Changelog Entry
+
+Add collapsible details section.
+
+<details>
+<summary>Click to expand</summary>
+This is the content.
+</details>`;
+
+    const result = extractChangelogEntry(prBody);
+    expect(result).toHaveLength(1);
+    expect(result![0].text).toBe('Add collapsible details section.');
+    expect(result![0].nestedContent).toBe(
+      '  <details>\n  <summary>Click to expand</summary>\n  This is the content.\n  </details>',
+    );
+  });
+
+  it('indents every line of multi-line <table> HTML', () => {
+    const prBody = `### Changelog Entry
+
+Add comparison table.
+
+<table>
+<tr><th>Feature</th><th>Status</th></tr>
+<tr><td>A</td><td>Done</td></tr>
+</table>`;
+
+    const result = extractChangelogEntry(prBody);
+    expect(result).toHaveLength(1);
+    expect(result![0].text).toBe('Add comparison table.');
+    const lines = result![0].nestedContent!.split('\n');
+    expect(lines).toHaveLength(4);
+    for (const line of lines) {
+      expect(line).toMatch(/^ {2}/);
+    }
+  });
 });

diff --git a/src/utils/changelog.ts b/src/utils/changelog.ts
--- a/src/utils/changelog.ts
+++ b/src/utils/changelog.ts
@@ -330,6 +330,17 @@
 }
 
 /**
+ * Renders HTML content with proper indentation on every line.
+ * Each line is prefixed with `indent` to ensure proper nesting under list items.
+ */
+function renderIndentedHtml(htmlContent: string, indent = '  '): string {
+  return htmlContent
+    .split('\n')
+    .map(line => `${indent}${line}`)
+    .join('\n');
+}
+
+/**
  * Recursively extracts nested content from a list item's tokens.
  */
 function extractNestedContent(tokens: Token[]): string {
@@ -434,9 +445,10 @@
       const htmlContent = (token as Tokens.HTML).raw.trim();
       if (htmlContent && entries.length > 0) {
         const prev = entries[entries.length - 1];
+        const indentedHtml = renderIndentedHtml(htmlContent);
         prev.nestedContent = prev.nestedContent
-          ? `${prev.nestedContent}\n  ${htmlContent}`
-          : `  ${htmlContent}`;
+          ? `${prev.nestedContent}\n${indentedHtml}`
+          : indentedHtml;
       }
       // If no previous entry exists, skip — an orphaned HTML block
       // without descriptive text isn't a meaningful changelog entry.

This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.

GitHub stores uploaded images as standalone <img> HTML tags in PR bodies.
The marked lexer tokenizes these as `html` type tokens, which
`parseTokensToEntries()` did not handle — silently dropping them.

Add an `html` token handler that preserves HTML blocks as nested content
on the previous entry, following the same pattern used for code blocks.
@BYK BYK force-pushed the byk/fix/changelog-html-blocks branch from c552c2d to 1e63943 Compare March 27, 2026 13:22
@BYK
Copy link
Copy Markdown
Member Author

BYK commented Mar 27, 2026

Addressed the Cursor Bugbot feedback about multi-line HTML block indentation — now every line is indented with 2 spaces (matching the code block behavior), not just the first line. Added a dedicated test with a <details> block to verify.

@BYK BYK merged commit a3ad8d3 into master Mar 27, 2026
18 checks passed
@BYK BYK deleted the byk/fix/changelog-html-blocks branch March 27, 2026 13:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant