feat: add literalTagContent prop for plain-text custom tag children#423
feat: add literalTagContent prop for plain-text custom tag children#423sleitor wants to merge 2 commits intovercel:mainfrom
Conversation
|
Someone is attempting to deploy a commit to the Vercel Team on Vercel. A member of the Team first needs to authorize it. |
7ea3dab to
ad9dcaf
Compare
…revent HTML comment corruption When a tag appears in both allowedTags and literalTagContent and its content contains blank lines, the '<!---->' HTML comment inserted by preprocessCustomTags was subsequently corrupted to '<\!\-\-\-\->' by preprocessLiteralTagContent (which escapes '!' and '-' as markdown metacharacters). Fix: swap the execution order so preprocessLiteralTagContent runs first, then preprocessCustomTags inserts its markers. The HTML comments are never seen by the markdown escaper.
|
Thanks for the automated review! The HTML comment corruption issue is fixed in the latest commit (465de11). Root cause: Fix: Swapped the execution order — |
Summary
Adds an opt-in
literalTagContentprop that renders children of specified custom tags as plain text (no markdown parsing). This is useful for mention/entity tags in AI UIs where child content is a data label (e.g. a username or handle) rather than prose.Motivation
When using
allowedTagswith custom components, markdown inside tag children is still parsed. For example:renders with emphasis on
_some_username_, which is unintended for entity tags.Requiring model-side escaping (
\_) everywhere is fragile and adds prompt/runtime complexity.Solution
A new
literalTagContent?: string[]prop. For tags in that list, markdown metacharacters inside the tag content are escaped before the markdown parser runs, so the parser treats the children as plain text.Output: renders
@_some_username_as literal text — no emphasis.Why preprocessing, not a rehype plugin
The earlier approach (a rehype plugin that flattens children to text post-parse) loses the original characters — by the time rehype runs,
_some_username_has already been parsed into<em>some_username</em>so the underscores are gone. Escaping before parsing preserves the original content.Changes
packages/streamdown/lib/preprocess-literal-tag-content.ts— escapes markdown metacharacters inside matching tag content before parsingpackages/streamdown/index.tsx— addsliteralTagContent?: string[]toStreamdownPropsand wires the preprocessor intoprocessedChildrenpackages/streamdown/__tests__/allowed-tags.test.tsx— 5 new tests for theliteralTagContentproppackages/streamdown/__tests__/preprocess-literal-tag-content.test.ts— 10 unit tests for the preprocessorAll 807 existing tests continue to pass.
Closes #419