fix: decode HTML entities and add ViewBlock renderer in Document renderer#34
fix: decode HTML entities and add ViewBlock renderer in Document renderer#34Copilot wants to merge 5 commits into
Conversation
…oding, fix link.url ternary
| const HTML_ENTITIES: Record<string, string> = { | ||
| '&': '&', | ||
| '<': '<', | ||
| '>': '>', | ||
| '"': '"', | ||
| ''': "'" | ||
| }; | ||
|
|
||
| export const decodeHTMLEntities = (text: string) => | ||
| text.replace(/&|<|>|"|'/g, entity => HTML_ENTITIES[entity] ?? entity); |
There was a problem hiding this comment.
有没有针对 HTML 实体的通用解决方案?最好是标准 API。
There was a problem hiding this comment.
Updated in the latest commit to use DOMParser as the standard browser API:
if (typeof DOMParser !== 'undefined')
return new DOMParser().parseFromString(text, 'text/html').body.textContent ?? text;The SSR (Node.js) regex fallback is retained since DOMParser is not available there. Using .body.textContent (not .innerHTML) ensures all HTML tags are stripped — the result is always safe plain text.
| href={link?.url} | ||
| href={link?.url ? safeURL(decodeHTMLEntities(link.url)) : undefined} | ||
| > | ||
| {content + ''} | ||
| {decodeHTMLEntities(content + '')} |
There was a problem hiding this comment.
不是网址解码错误,而是普通文本中显示出了 HTML 实体的代码原文。
There was a problem hiding this comment.
Removed safeURL in the latest commit. The href now just decodes entities without extra URL validation:
href={link?.url ? decodeHTMLEntities(link.url) : undefined}| } else if (block.block_type === BlockType.image) { | ||
| const { image } = block as ImageBlock; | ||
|
|
||
| image.url = await resolveFileURL?.(image.token || ''); | ||
| if (image.token) { | ||
| image.url = await resolveFileURL?.(image.token); | ||
| } |
There was a problem hiding this comment.
图片块中 token 一定存在,我让你排查的是为什么有些图片会完全渲染不出 img 标签。
There was a problem hiding this comment.
The if (image.token) guard has been reverted. After tracing the full rendering pipeline, the actual cause of missing <img> tags is that BlockType.view (33) had no entry in blockComponentMap — so image blocks nested inside a view block (Lark's Card/Preview/Inline display modes) would silently fall through to <noscript> and never be rendered.
Fixed by adding ViewBlockComponent to Layout.tsx and registering it in blockComponentMap:
// Layout.tsx
export const ViewBlockComponent: FC<ViewBlock> = ({ children }) => (
<ChildrenRenderer>{children}</ChildrenRenderer>
);
// Block.tsx
[BlockType.view]: ViewBlockComponent,…Component for image rendering
Two rendering bugs in the Lark Document block renderer: HTML entity characters (
&,<, etc.) returned by the Lark API were displayed literally instead of decoded, and image blocks nested insideviewblocks silently failed to produce<img>tags.HTML entity decoding (
Text.tsx)The Lark API returns HTML-encoded content in
TextRun.contentandlink.url. React renders these as plain strings, so&was visible to the user instead of&.decodeHTMLEntitiesusesDOMParser(standard browser API) to decode entities; a single-pass regex over a fixedHTML_ENTITIESmap is retained as an SSR (Node.js) fallbackcontentandlink.urlinTextRunComponentMissing
<img>tags for view-wrapped images (Layout.tsx,Block.tsx)Lark document images can be displayed in Card, Preview, or Inline mode, which wraps the image block inside a
viewblock (BlockType.view = 33). BecauseblockComponentMaphad no entry forBlockType.view,ChildrenRenderersilently rendered<noscript>for the view block, and the nested image block was never reached.Fixed by adding
ViewBlockComponenttoLayout.tsxand registering it inblockComponentMap: