feat(markdown): add MarkdownRenderer with code/Mermaid/CSV/Survey/HtmlPreview blocks#233
feat(markdown): add MarkdownRenderer with code/Mermaid/CSV/Survey/HtmlPreview blocks#233rajkumargaramie wants to merge 8 commits into
Conversation
…lPreview blocks
Adds a self-contained Markdown rendering component with:
- marked + DOMPurify pipeline
- highlight.js syntax highlighting (eager: js/ts/py/json/xml/css/bash/sql/yaml/md;
lazy: java/cpp/c/csharp/php/ruby/go/rust/perl/r/makefile/dockerfile)
- Copy-to-clipboard button on fenced code blocks
- React-portal blocks for mermaid diagrams, CSV tables, survey previews, and
sandboxed HTML previews
- atom-one-light / atom-one-dark theme bundled and scoped via [data-theme]
Exports:
- '@mieweb/ui' — { MarkdownRenderer, FenceBlock, MermaidBlock, CsvBlock,
SurveyBlock, HtmlPreviewBlock, useMarkdown }
- '@mieweb/ui/components/Markdown' — same, as tree-shakeable subpath
- '@mieweb/ui/markdown.css' — bundled hljs themes + fence block styles
mermaid, papaparse, and js-yaml are optional peer dependencies so consumers
that don't use those block types don't pay the bundle cost.
Deploying ui with
|
| Latest commit: |
c0bc576
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://5bcf2a5b.ui-6d0.pages.dev |
| Branch Preview URL: | https://markdown-components.ui-6d0.pages.dev |
There was a problem hiding this comment.
Pull request overview
Adds a new Markdown rendering subsystem to @mieweb/ui that converts markdown to sanitized HTML, highlights code blocks, and mounts React-powered “special fence blocks” (Mermaid/CSV/Survey/HTML preview) via portals—plus a separate exported stylesheet (@mieweb/ui/markdown.css) for highlight.js + fence styling.
Changes:
- Introduces
MarkdownRenderer+useMarkdownpipeline using marked + DOMPurify + highlight.js, including placeholder emission for special fenced blocks. - Adds block components (
FenceBlock,MermaidBlock,CsvBlock,SurveyBlock,HtmlPreviewBlock) and bundled highlight/fence CSS. - Updates build/package exports and dependency config to ship a tree-shakeable Markdown subpath and a dedicated
markdown.cssexport.
Reviewed changes
Copilot reviewed 12 out of 13 changed files in this pull request and generated 13 comments.
Show a summary per file
| File | Description |
|---|---|
| tsup.config.ts | Adds a tree-shakeable Markdown entry point and marks optional block deps as externals. |
| src/index.ts | Re-exports Markdown components from the package root. |
| src/components/Markdown/useMarkdown.ts | Implements marked→sanitized HTML rendering, highlight.js integration, caching, placeholder emission, and delegated copy handler. |
| src/components/Markdown/MarkdownRenderer.tsx | Renders sanitized HTML and mounts block components into placeholders via portals. |
| src/components/Markdown/FenceBlock.tsx | Provides a reusable UI wrapper for fenced blocks (copy + raw/rendered toggle + error state). |
| src/components/Markdown/MermaidBlock.tsx | Adds Mermaid diagram rendering (dynamic import) into FenceBlock. |
| src/components/Markdown/CsvBlock.tsx | Adds CSV parsing + sortable/exportable table block. |
| src/components/Markdown/SurveyBlock.tsx | Adds JSON/YAML survey preview block. |
| src/components/Markdown/HtmlPreviewBlock.tsx | Adds sandboxed iframe HTML preview with expand-to-modal behavior. |
| src/components/Markdown/styles.css | Bundles/scopes highlight.js themes and fence-block styles; exported as @mieweb/ui/markdown.css. |
| src/components/Markdown/index.ts | Exposes the Markdown module’s public exports. |
| package.json | Adds markdown.css export + build copy step; adds hard deps (marked/dompurify/highlight.js) and optional peer deps metadata. |
| pnpm-lock.yaml | Locks new dependencies introduced by the Markdown feature. |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
Comments suppressed due to low confidence (1)
src/components/Markdown/MermaidBlock.tsx:76
dangerouslySetInnerHTMLis used to inject Mermaid’s generated SVG. Even with a safersecurityLevel, it’s worth sanitizing/validating the SVG string (or rendering via a DOM API) before injection to reduce XSS risk from malformed output or upstream changes.
<div
ref={containerRef}
className="flex justify-center p-4"
dangerouslySetInnerHTML={{ __html: svg }}
/>
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Render plain code fences via React portal + FenceBlock (new CodeBlock component) instead of injecting raw HTML + a global click listener. Removes COPY_BTN_HTML, the document-level click handler, and the .fence-block / .fence-copy-btn CSS — code blocks now use the same copy/raw-toggle UX as Mermaid/CSV/Survey/HTML blocks. - useMarkdown: bound the render cache (LRU, 200 entries), reset the block-id counter per render, use marked's RendererThis instead of unsafe `unknown` casts, register js/ts/sh hljs aliases. - MermaidBlock: drop unused containerRef. - HtmlPreviewBlock: drop unused iframeRef and unreachable Escape branch in handleCloseExpanded. - Export CodeBlock and highlightCode helper.
7ff2d4f to
ffb15f2
Compare
…act 19 portal fix, stories
…s, Mermaid dark mode, clipboard fallback
…header), fix prettier formatting
…TML preview toggle, links, streaming story
…d theme reactivity, sentinel injection guard, cache cap, safe URL revoke, unmount-safe copy timer, README
garrity-miepub
left a comment
There was a problem hiding this comment.
Rebase needed
10 PRs have landed on main since this branch was cut (May 14). Merging as-is will silently revert #240, #241, #242, #245, and 6bfe832. Please rebase on origin/main and force-push.
Post-rebase nits
- HTML Preview — consider dropping
allow-scriptsfrom the iframe sandbox if interactive JS isn't needed - SSR — guard
DOMPurify.addHook()inuseMarkdown.tswithtypeof document !== 'undefined' - A11y — add
aria-sorton CsvBlock<th>androle="img" aria-label="..."on Mermaid SVG container
Otherwise the markdown work looks solid — sanitization, lazy loading, and caching are all well done.
Adds a self-contained Markdown rendering component so consumer apps (e.g. ozwell-workspace) don't have to re-implement the marked + DOMPurify + highlight.js pipeline themselves.
What's included
MarkdownRenderer— full pipeline (marked GFM + DOMPurify sanitisation + hljs highlighting + React portals for special blocks)FenceBlock— base wrapper (copy button, raw/rendered toggle, error state)MermaidBlock— sandboxed Mermaid diagram renderingCsvBlock— sortable / exportable CSV tableSurveyBlock— JSON/YAML survey previewHtmlPreviewBlock— sandboxed iframe HTML preview with expanduseMarkdown— hook (render/renderAsync/clearCache)[data-theme]Exports
@mieweb/ui— all of the above (named exports)@mieweb/ui/components/Markdown— tree-shakeable subpath@mieweb/ui/markdown.css— bundled hljs themes + fence-block stylesDependencies
marked,dompurify,highlight.js— small, always-needed for the markdown pipelinemermaid,papaparse,js-yaml— only loaded when the matching block type is used. Apps that never render Mermaid/CSV/Survey blocks don't pay the bundle cost.Why
Originally landed in ozwell-workspace; centralising here so other products consuming
@mieweb/ui'sAIChat(viarenderTextContent) can get full Markdown + code-block rendering for free.Usage