Add normalizeHtmlIndentation prop to prevent indented HTML tags fro…#264
Add normalizeHtmlIndentation prop to prevent indented HTML tags fro…#264zhdzb wants to merge 1 commit intovercel:mainfrom
normalizeHtmlIndentation prop to prevent indented HTML tags fro…#264Conversation
|
@zhdzb is attempting to deploy a commit to the Vercel Team on Vercel. A member of the Team first needs to authorize it. |
16abcfe to
b14e9e2
Compare
There was a problem hiding this comment.
Additional Suggestion:
The normalizeHtmlIndentation prop is missing from the Streamdown component's memo comparison function, which means changes to this prop won't trigger a re-render.
View Details
📝 Patch Details
diff --git a/packages/streamdown/index.tsx b/packages/streamdown/index.tsx
index 617da5e..8750c84 100644
--- a/packages/streamdown/index.tsx
+++ b/packages/streamdown/index.tsx
@@ -395,6 +395,7 @@ export const Streamdown = memo(
prevProps.children === nextProps.children &&
prevProps.shikiTheme === nextProps.shikiTheme &&
prevProps.isAnimating === nextProps.isAnimating &&
- prevProps.mode === nextProps.mode
+ prevProps.mode === nextProps.mode &&
+ prevProps.normalizeHtmlIndentation === nextProps.normalizeHtmlIndentation
);
Streamdown.displayName = "Streamdown";
Analysis
Streamdown memo comparison missing normalizeHtmlIndentation prop check
What fails: The Streamdown component's memo comparison function only checks 4 props (children, shikiTheme, isAnimating, mode) but ignores the normalizeHtmlIndentation prop. When this prop changes while others remain the same, the component doesn't re-render, preventing Block components from receiving the updated shouldNormalizeHtmlIndentation value.
How to reproduce:
const [normalize, setNormalize] = useState(false);
return (
<>
<button onClick={() => setNormalize(true)}>Toggle normalization</button>
<Streamdown normalizeHtmlIndentation={normalize}>
{contentWithIndentedHtml}
</Streamdown>
</>
);After clicking the button, the prop changes but the component won't re-render because the memo comparison returns true (skip re-render) when only normalizeHtmlIndentation changes.
Result: The HTML content is not re-normalized according to the new prop value since Block components never receive the updated shouldNormalizeHtmlIndentation prop.
Expected: When normalizeHtmlIndentation prop changes, the Streamdown component should re-render and pass the new value to Block components.
Fix applied: Added normalizeHtmlIndentation to the memo comparison function in the Streamdown component (line 399 of packages/streamdown/index.tsx). The comparison now checks:
prevProps.normalizeHtmlIndentation === nextProps.normalizeHtmlIndentation
This ensures that changes to this prop trigger a re-render, allowing Block components to receive and apply the updated normalization setting.
…m being treated as code blocks
b14e9e2 to
683b9b4
Compare
The second
Description
Description
When rendering AI-generated HTML content with nested tags (e.g., from streaming socket data), indented HTML tags with 4+ leading spaces are incorrectly parsed as code blocks by the Markdown parser.
This occurs because the Markdown specification treats lines starting with 4+ spaces as indented code blocks. While this behavior is correct for Markdown syntax, it causes issues when rendering HTML content that uses indentation for readability.
Problem Scenario
In streaming scenarios where HTML content is generated incrementally, nested tags are often indented with 4+ spaces for better readability. However, when such content is parsed by Streamdown, the indented HTML tags after blank lines are mistakenly treated as code blocks instead of HTML elements.
Example
HTML content like this:
Title One
Type of Change
Related Issues
Fixes #
Closes #
Related to #
Changes Made
normalizeHtmlIndentationprop - When enabled, removes excessive indentation (4+ spaces) before HTML tagsnormalizeHtmlIndentation()utility function - Exported for manual preprocessingTesting
Test Coverage
-Added 20 new unit tests in normalize-html-indentation.test.tsx covering:
Utility function edge cases (empty strings, non-HTML content, various HTML structures)
Streamdown component behavior with the new prop enabled/disabled
HTML block merging scenarios with nested tags, void elements, and self-closing tags
-All 541 existing tests continue to pass
-No breaking changes to existing functionality
Screenshots/Demos
Before (without normalizeHtmlIndentation):
Indented HTML tags after blank lines are rendered as code blocks.
After (with normalizeHtmlIndentation={true}):
All HTML tags are correctly rendered as HTML elements.
Checklist
pnpm changeset)Changeset
Additional Notes