streamdown 1.0.12 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -18,6 +18,7 @@ Streamdown powers the [AI Elements Response](https://ai-sdk.dev/elements/compone
18
18
  - 📊 **GitHub Flavored Markdown** - Tables, task lists, and strikethrough support
19
19
  - 🔢 **Math rendering** - LaTeX equations via KaTeX
20
20
  - 🎯 **Code syntax highlighting** - Beautiful code blocks with Shiki
21
+ - 📈 **Mermaid diagrams** - Render flowcharts, sequence diagrams, and more
21
22
  - 🛡️ **Security-first** - Built on harden-react-markdown for safe rendering
22
23
  - ⚡ **Performance optimized** - Memoized rendering for efficient updates
23
24
 
@@ -49,6 +50,44 @@ export default function Page() {
49
50
  }
50
51
  ```
51
52
 
53
+ ### Mermaid Diagrams
54
+
55
+ Streamdown supports Mermaid diagrams using the `mermaid` language identifier:
56
+
57
+ ```tsx
58
+ import { Streamdown } from 'streamdown';
59
+
60
+ export default function Page() {
61
+ const markdown = `
62
+ # Flowchart Example
63
+
64
+ \`\`\`mermaid
65
+ graph TD
66
+ A[Start] --> B{Is it working?}
67
+ B -->|Yes| C[Great!]
68
+ B -->|No| D[Debug]
69
+ D --> B
70
+ \`\`\`
71
+
72
+ # Sequence Diagram
73
+
74
+ \`\`\`mermaid
75
+ sequenceDiagram
76
+ participant User
77
+ participant API
78
+ participant Database
79
+
80
+ User->>API: Request data
81
+ API->>Database: Query
82
+ Database-->>API: Results
83
+ API-->>User: Response
84
+ \`\`\`
85
+ `;
86
+
87
+ return <Streamdown>{markdown}</Streamdown>;
88
+ }
89
+ ```
90
+
52
91
  ### With AI SDK
53
92
 
54
93
  ```tsx
package/dist/index.cjs CHANGED
@@ -1,3 +1,3 @@
1
- "use strict";"use client";var z=Object.create;var b=Object.defineProperty;var G=Object.getOwnPropertyDescriptor;var F=Object.getOwnPropertyNames;var J=Object.getPrototypeOf,Q=Object.prototype.hasOwnProperty;var X=(e,t)=>{for(var n in t)b(e,n,{get:t[n],enumerable:!0})},N=(e,t,n,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of F(t))!Q.call(e,r)&&r!==n&&b(e,r,{get:()=>t[r],enumerable:!(o=G(t,r))||o.enumerable});return e};var g=(e,t,n)=>(n=e!=null?z(J(e)):{},N(t||!e||!e.__esModule?b(n,"default",{value:e,enumerable:!0}):n,e)),Y=e=>N(b({},"__esModule",{value:!0}),e);var ve={};X(ve,{ShikiThemeContext:()=>C,Streamdown:()=>$,default:()=>Te});module.exports=Y(ve);var l=require("react"),R=g(require("react-markdown"),1),U=g(require("rehype-katex"),1),D=g(require("remark-gfm"),1),q=g(require("remark-math"),1),Ue=require("katex/dist/katex.min.css"),I=g(require("harden-react-markdown"),1);var A=require("react");var y=require("lucide-react"),c=require("react"),w=require("shiki");var T=require("clsx"),v=require("tailwind-merge"),s=(...e)=>(0,v.twMerge)((0,T.clsx)(e));var p=require("react/jsx-runtime"),P=(0,c.createContext)({code:""});async function Z(e,t,n){return await(0,w.codeToHtml)(e,{lang:t,theme:n})}var S=({code:e,language:t,className:n,children:o,...r})=>{let[a,m]=(0,c.useState)(""),d=(0,c.useContext)(C);return(0,c.useEffect)(()=>{let u=!0;return Z(e,t,d).then(h=>{u&&m(h)}),()=>{u=!1}},[e,t,d]),(0,p.jsx)(P.Provider,{value:{code:e},children:(0,p.jsxs)("div",{className:"group relative",children:[(0,p.jsx)("div",{className:s("overflow-x-auto",n),dangerouslySetInnerHTML:{__html:a},...r}),o]})})},_=({onCopy:e,onError:t,timeout:n=2e3,children:o,className:r,...a})=>{let[m,d]=(0,c.useState)(!1),{code:u}=(0,c.useContext)(P),h=async()=>{var k;if(typeof window=="undefined"||!((k=navigator==null?void 0:navigator.clipboard)!=null&&k.writeText)){t==null||t(new Error("Clipboard API not available"));return}try{await navigator.clipboard.writeText(u),d(!0),e==null||e(),setTimeout(()=>d(!1),n)}catch(B){t==null||t(B)}},M=m?y.CheckIcon:y.CopyIcon;return(0,p.jsx)("button",{className:s("absolute top-2 right-2 shrink-0 rounded-md p-3 opacity-0 transition-all","hover:bg-secondary group-hover:opacity-100",r),onClick:h,type:"button",...a,children:o!=null?o:(0,p.jsx)(M,{size:14})})};var i=require("react/jsx-runtime"),H={ol:({node:e,children:t,className:n,...o})=>(0,i.jsx)("ol",{className:s("ml-4 list-outside list-decimal",n),...o,children:t}),li:({node:e,children:t,className:n,...o})=>(0,i.jsx)("li",{className:s("py-1",n),...o,children:t}),ul:({node:e,children:t,className:n,...o})=>(0,i.jsx)("ul",{className:s("ml-4 list-outside list-disc",n),...o,children:t}),hr:({node:e,className:t,...n})=>(0,i.jsx)("hr",{className:s("my-6 border-border",t),...n}),strong:({node:e,children:t,className:n,...o})=>(0,i.jsx)("span",{className:s("font-semibold",n),...o,children:t}),a:({node:e,children:t,className:n,href:o,...r})=>(0,i.jsx)("a",{className:s("font-medium text-primary underline",n),href:o,rel:"noreferrer",target:"_blank",...r,children:t}),h1:({node:e,children:t,className:n,...o})=>(0,i.jsx)("h1",{className:s("mt-6 mb-2 font-semibold text-3xl",n),...o,children:t}),h2:({node:e,children:t,className:n,...o})=>(0,i.jsx)("h2",{className:s("mt-6 mb-2 font-semibold text-2xl",n),...o,children:t}),h3:({node:e,children:t,className:n,...o})=>(0,i.jsx)("h3",{className:s("mt-6 mb-2 font-semibold text-xl",n),...o,children:t}),h4:({node:e,children:t,className:n,...o})=>(0,i.jsx)("h4",{className:s("mt-6 mb-2 font-semibold text-lg",n),...o,children:t}),h5:({node:e,children:t,className:n,...o})=>(0,i.jsx)("h5",{className:s("mt-6 mb-2 font-semibold text-base",n),...o,children:t}),h6:({node:e,children:t,className:n,...o})=>(0,i.jsx)("h6",{className:s("mt-6 mb-2 font-semibold text-sm",n),...o,children:t}),table:({node:e,children:t,className:n,...o})=>(0,i.jsx)("div",{className:"my-4 overflow-x-auto",children:(0,i.jsx)("table",{className:s("w-full border-collapse border border-border",n),...o,children:t})}),thead:({node:e,children:t,className:n,...o})=>(0,i.jsx)("thead",{className:s("bg-muted/50",n),...o,children:t}),tbody:({node:e,children:t,className:n,...o})=>(0,i.jsx)("tbody",{className:s("divide-y divide-border",n),...o,children:t}),tr:({node:e,children:t,className:n,...o})=>(0,i.jsx)("tr",{className:s("border-border border-b",n),...o,children:t}),th:({node:e,children:t,className:n,...o})=>(0,i.jsx)("th",{className:s("px-4 py-2 text-left font-semibold text-sm",n),...o,children:t}),td:({node:e,children:t,className:n,...o})=>(0,i.jsx)("td",{className:s("px-4 py-2 text-sm",n),...o,children:t}),blockquote:({node:e,children:t,className:n,...o})=>(0,i.jsx)("blockquote",{className:s("my-4 border-muted-foreground/30 border-l-4 pl-4 text-muted-foreground italic",n),...o,children:t}),code:({node:e,className:t,...n})=>{var r,a;return((r=e==null?void 0:e.position)==null?void 0:r.start.line)===((a=e==null?void 0:e.position)==null?void 0:a.end.line)?(0,i.jsx)("code",{className:s("rounded bg-muted px-1.5 py-0.5 font-mono text-sm",t),...n}):(0,i.jsx)("code",{className:t,...n})},pre:({node:e,className:t,children:n})=>{var a;let o="javascript";typeof((a=e==null?void 0:e.properties)==null?void 0:a.className)=="string"&&(o=e.properties.className.replace("language-",""));let r="";return(0,A.isValidElement)(n)&&n.props&&typeof n.props=="object"&&"children"in n.props&&typeof n.props.children=="string"?r=n.props.children:typeof n=="string"&&(r=n),(0,i.jsx)(S,{className:s("my-4 h-auto rounded-lg border p-4",t),code:r,language:o,children:(0,i.jsx)(_,{})})},sup:({node:e,children:t,className:n,...o})=>(0,i.jsx)("sup",{className:s("text-sm",n),...o,children:t}),sub:({node:e,children:t,className:n,...o})=>(0,i.jsx)("sub",{className:s("text-sm",n),...o,children:t})};var K=require("marked"),L=e=>K.marked.lexer(e).map(n=>n.raw);var j=/(!?\[)([^\]]*?)$/,E=/(\*\*)([^*]*?)$/,x=/(__)([^_]*?)$/,ee=/(\*\*\*)([^*]*?)$/,te=/(\*)([^*]*?)$/,ne=/(_)([^_]*?)$/,oe=/(`)([^`]*?)$/,re=/(~~)([^~]*?)$/,se=/(\$)([^$]*?)$/,ie=/(\$\$)([^$]*?)$/,ae=e=>{let t=e.match(j);if(t){let n=e.lastIndexOf(t[1]);return e.substring(0,n)}return e},ce=e=>e.match(E)&&(e.match(/\*\*/g)||[]).length%2===1?`${e}**`:e,le=e=>e.match(x)&&(e.match(/__/g)||[]).length%2===1?`${e}__`:e,de=e=>e.split("").reduce((t,n,o)=>{if(n==="*"){let r=e[o-1],a=e[o+1];if(r==="\\")return t;if(r!=="*"&&a!=="*")return t+1}return t},0),me=e=>e.match(te)&&de(e)%2===1?`${e}*`:e,pe=e=>e.split("").reduce((t,n,o)=>{if(n==="_"){let r=e[o-1],a=e[o+1];if(r==="\\")return t;if(r!=="_"&&a!=="_")return t+1}return t},0),ue=e=>e.match(ne)&&pe(e)%2===1?`${e}_`:e,he=(e,t)=>{let n=e.substring(t,t+3)==="```",o=t>0&&e.substring(t-1,t+2)==="```",r=t>1&&e.substring(t-2,t+1)==="```";return n||o||r},ge=e=>{let t=0;for(let n=0;n<e.length;n++)e[n]==="`"&&!he(e,n)&&t++;return t},fe=e=>{if(e.match(/^```[^`\n]*```?$/)&&!e.includes(`
2
- `))return e.endsWith("``")&&!e.endsWith("```")?`${e}\``:e;let n=(e.match(/```/g)||[]).length,o=n%2===1;return(e.endsWith("```\n")||e.endsWith("```"))&&n%2===0||n>0&&n%2===0&&e.includes(`
3
- `)?e:e.match(oe)&&!o&&ge(e)%2===1?`${e}\``:e},ke=e=>e.match(re)&&(e.match(/~~/g)||[]).length%2===1?`${e}~~`:e,be=e=>e.split("").reduce((t,n,o)=>{if(n==="$"){let r=e[o-1],a=e[o+1];if(r==="\\")return t;if(r!=="$"&&a!=="$")return t+1}return t},0),ye=e=>e.match(ie)&&(e.match(/\$\$/g)||[]).length%2===1?`${e}$$`:e,Ce=e=>e.match(se)&&be(e)%2===1?`${e}$`:e,Me=e=>{let t=0,n=e.match(/\*+/g)||[];for(let o of n){let r=o.length;r>=3&&(t+=Math.floor(r/3))}return t},Be=e=>/^\*{4,}$/.test(e)?e:e.match(ee)&&Me(e)%2===1?`${e}***`:e,O=e=>{if(!e||typeof e!="string")return e;let t=e;return t=ae(t),t=Be(t),t=ce(t),t=le(t),t=me(t),t=ue(t),t=fe(t),t=ke(t),t=ye(t),t=Ce(t),t};var f=require("react/jsx-runtime"),Ie=I.default.default||I.default,$e=Ie(R.default),C=(0,l.createContext)("github-light"),Ne=(0,l.memo)(({content:e,shouldParseIncompleteMarkdown:t,...n})=>{let o=(0,l.useMemo)(()=>typeof e=="string"&&t?O(e.trim()):e,[e,t]);return(0,f.jsx)($e,{...n,children:o})},(e,t)=>e.content===t.content),$=(0,l.memo)(({children:e,allowedImagePrefixes:t,allowedLinkPrefixes:n,defaultOrigin:o,parseIncompleteMarkdown:r=!0,components:a,rehypePlugins:m,remarkPlugins:d,className:u,shikiTheme:h="github-light",...M})=>{let k=(0,l.useId)(),B=(0,l.useMemo)(()=>L(typeof e=="string"?e:""),[e]);return(0,f.jsx)(C.Provider,{value:h,children:(0,f.jsx)("div",{className:s("space-y-4",u),...M,children:B.map((W,V)=>(0,f.jsx)(Ne,{allowedImagePrefixes:t!=null?t:["*"],allowedLinkPrefixes:n!=null?n:["*"],components:{...H,...a},content:W,defaultOrigin:o,rehypePlugins:[U.default,...m!=null?m:[]],remarkPlugins:[D.default,q.default,...d!=null?d:[]],shouldParseIncompleteMarkdown:r},`${k}-block_${V}`))})})},(e,t)=>e.children===t.children&&e.shikiTheme===t.shikiTheme);$.displayName="Streamdown";var Te=$;0&&(module.exports={ShikiThemeContext,Streamdown});
1
+ "use strict";"use client";var Z=Object.create;var T=Object.defineProperty;var j=Object.getOwnPropertyDescriptor;var ee=Object.getOwnPropertyNames;var te=Object.getPrototypeOf,re=Object.prototype.hasOwnProperty;var oe=(e,t)=>{for(var r in t)T(e,r,{get:t[r],enumerable:!0})},x=(e,t,r,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of ee(t))!re.call(e,s)&&s!==r&&T(e,s,{get:()=>t[s],enumerable:!(o=j(t,s))||o.enumerable});return e};var M=(e,t,r)=>(r=e!=null?Z(te(e)):{},x(t||!e||!e.__esModule?T(r,"default",{value:e,enumerable:!0}):r,e)),ne=e=>x(T({},"__esModule",{value:!0}),e);var Ee={};oe(Ee,{CodeBlock:()=>w,CodeBlockCopyButton:()=>I,CodeBlockRenderButton:()=>K,Mermaid:()=>P,ShikiThemeContext:()=>N,Streamdown:()=>H,default:()=>De});module.exports=ne(Ee);var g=require("react"),F=M(require("react-markdown"),1),G=M(require("rehype-katex"),1),J=M(require("remark-gfm"),1),Q=M(require("remark-math"),1),Ze=require("katex/dist/katex.min.css"),L=M(require("harden-react-markdown"),1);var U=require("react");var B=require("lucide-react"),p=require("react"),E=require("shiki");var R=require("clsx"),D=require("tailwind-merge"),n=(...e)=>(0,D.twMerge)((0,R.clsx)(e));var h=require("react/jsx-runtime"),S=(0,p.createContext)({code:""});async function se(e,t,r){return await(0,E.codeToHtml)(e,{lang:t,theme:r})}var w=({code:e,language:t,className:r,children:o,...s})=>{let[a,l]=(0,p.useState)(""),c=(0,p.useContext)(N);return(0,p.useEffect)(()=>{let d=!0;return se(e,t,c).then(m=>{d&&l(m)}).catch(m=>{console.error("Failed to highlight code:",m),d&&l(`<pre><code>${e}</code></pre>`)}),()=>{d=!1}},[e,t,c]),(0,h.jsx)(S.Provider,{value:{code:e},children:(0,h.jsxs)("div",{className:"group relative",children:[(0,h.jsx)("div",{className:n("overflow-x-auto",r),dangerouslySetInnerHTML:{__html:a},...s}),o]})})},I=({onCopy:e,onError:t,timeout:r=2e3,children:o,className:s,code:a,...l})=>{let[c,d]=(0,p.useState)(!1),m=(0,p.useContext)(S).code,f=a!=null?a:m,y=async()=>{var k;if(typeof window=="undefined"||!((k=navigator==null?void 0:navigator.clipboard)!=null&&k.writeText)){t==null||t(new Error("Clipboard API not available"));return}try{await navigator.clipboard.writeText(f),d(!0),e==null||e(),setTimeout(()=>d(!1),r)}catch(v){t==null||t(v)}},b=c?B.CheckIcon:B.CopyIcon;return(0,h.jsx)("button",{className:n("absolute top-2 right-2 shrink-0 rounded-md p-3 opacity-0 transition-all","hover:bg-secondary group-hover:opacity-100",s),onClick:y,type:"button",...l,children:o!=null?o:(0,h.jsx)(b,{size:14})})},K=({onRender:e,children:t,className:r,...o})=>{let{code:s}=(0,p.useContext)(S),a=()=>{e==null||e(s)};return(0,h.jsx)("button",{className:n("absolute top-2 right-12 shrink-0 rounded-md p-3 opacity-0 transition-all hover:bg-secondary group-hover:opacity-100",r),onClick:a,type:"button",...o,children:t||(0,h.jsx)(B.RouteIcon,{size:14})})};var C=require("react");var u=require("react/jsx-runtime"),O=!1,ie=async()=>{if(!O){let r=(await import("mermaid")).default;return r.initialize({startOnLoad:!1,theme:"default",securityLevel:"strict",fontFamily:"monospace",suppressErrorRendering:!0}),O=!0,r}return(await import("mermaid")).default},P=({chart:e,className:t})=>{let[r,o]=(0,C.useState)(null),[s,a]=(0,C.useState)(!0),[l,c]=(0,C.useState)(""),[d,m]=(0,C.useState)("");if((0,C.useEffect)(()=>{(async()=>{try{o(null),a(!0);let b=await ie(),k=e.split("").reduce((_,Y)=>(_<<5)-_+Y.charCodeAt(0)|0,0),v=`mermaid-${Math.abs(k)}`,{svg:A}=await b.render(v,e);c(A),m(A)}catch(b){if(!(d||l)){let k=b instanceof Error?b.message:"Failed to render Mermaid chart";o(k)}}finally{a(!1)}})()},[e]),s&&!l&&!d)return(0,u.jsx)("div",{className:n("my-4 flex justify-center p-4",t),children:(0,u.jsxs)("div",{className:"flex items-center space-x-2 text-muted-foreground",children:[(0,u.jsx)("div",{className:"h-4 w-4 animate-spin rounded-full border-current border-b-2"}),(0,u.jsx)("span",{className:"text-sm",children:"Loading diagram..."})]})});if(r&&!l&&!d)return(0,u.jsxs)("div",{className:n("rounded-lg border border-red-200 bg-red-50 p-4",t),children:[(0,u.jsxs)("p",{className:"font-mono text-red-700 text-sm",children:["Mermaid Error: ",r]}),(0,u.jsxs)("details",{className:"mt-2",children:[(0,u.jsx)("summary",{className:"cursor-pointer text-red-600 text-xs",children:"Show Code"}),(0,u.jsx)("pre",{className:"mt-2 overflow-x-auto rounded bg-red-100 p-2 text-red-800 text-xs",children:e})]})]});let f=l||d;return(0,u.jsx)("div",{"aria-label":"Mermaid chart",className:n("my-4 flex justify-center",t),dangerouslySetInnerHTML:{__html:f},role:"img"})};var i=require("react/jsx-runtime"),ae=/language-([^\s]+)/,ce=({node:e,className:t,children:r,...o})=>{var m,f,y;if(((m=e==null?void 0:e.position)==null?void 0:m.start.line)===((f=e==null?void 0:e.position)==null?void 0:f.end.line))return(0,i.jsx)("code",{className:n("rounded bg-muted px-1.5 py-0.5 font-mono text-sm",t),...o,children:r});let a=t==null?void 0:t.match(ae),l=(y=a==null?void 0:a.at(1))!=null?y:"plaintext",c="";return(0,U.isValidElement)(r)&&r.props&&typeof r.props=="object"&&"children"in r.props&&typeof r.props.children=="string"?c=r.props.children:typeof r=="string"&&(c=r),l==="mermaid"||c.includes("graph")||c.includes("flowchart")||c.includes("sequenceDiagram")||c.includes("classDiagram")||c.includes("gantt")?(0,i.jsxs)("div",{className:n("group relative my-4 h-auto rounded-lg border p-4",t),children:[(0,i.jsx)(P,{chart:c}),(0,i.jsx)(I,{code:c})]}):(0,i.jsx)(w,{className:n("my-4 h-auto rounded-lg border p-4",t),code:c,language:l,children:(0,i.jsx)(I,{})})},q={ol:({node:e,children:t,className:r,...o})=>(0,i.jsx)("ol",{className:n("ml-4 list-outside list-decimal",r),...o,children:t}),li:({node:e,children:t,className:r,...o})=>(0,i.jsx)("li",{className:n("py-1",r),...o,children:t}),ul:({node:e,children:t,className:r,...o})=>(0,i.jsx)("ul",{className:n("ml-4 list-outside list-disc",r),...o,children:t}),hr:({node:e,className:t,...r})=>(0,i.jsx)("hr",{className:n("my-6 border-border",t),...r}),strong:({node:e,children:t,className:r,...o})=>(0,i.jsx)("span",{className:n("font-semibold",r),...o,children:t}),a:({node:e,children:t,className:r,href:o,...s})=>(0,i.jsx)("a",{className:n("font-medium text-primary underline",r),href:o,rel:"noreferrer",target:"_blank",...s,children:t}),h1:({node:e,children:t,className:r,...o})=>(0,i.jsx)("h1",{className:n("mt-6 mb-2 font-semibold text-3xl",r),...o,children:t}),h2:({node:e,children:t,className:r,...o})=>(0,i.jsx)("h2",{className:n("mt-6 mb-2 font-semibold text-2xl",r),...o,children:t}),h3:({node:e,children:t,className:r,...o})=>(0,i.jsx)("h3",{className:n("mt-6 mb-2 font-semibold text-xl",r),...o,children:t}),h4:({node:e,children:t,className:r,...o})=>(0,i.jsx)("h4",{className:n("mt-6 mb-2 font-semibold text-lg",r),...o,children:t}),h5:({node:e,children:t,className:r,...o})=>(0,i.jsx)("h5",{className:n("mt-6 mb-2 font-semibold text-base",r),...o,children:t}),h6:({node:e,children:t,className:r,...o})=>(0,i.jsx)("h6",{className:n("mt-6 mb-2 font-semibold text-sm",r),...o,children:t}),table:({node:e,children:t,className:r,...o})=>(0,i.jsx)("div",{className:"my-4 overflow-x-auto",children:(0,i.jsx)("table",{className:n("w-full border-collapse border border-border",r),...o,children:t})}),thead:({node:e,children:t,className:r,...o})=>(0,i.jsx)("thead",{className:n("bg-muted/50",r),...o,children:t}),tbody:({node:e,children:t,className:r,...o})=>(0,i.jsx)("tbody",{className:n("divide-y divide-border",r),...o,children:t}),tr:({node:e,children:t,className:r,...o})=>(0,i.jsx)("tr",{className:n("border-border border-b",r),...o,children:t}),th:({node:e,children:t,className:r,...o})=>(0,i.jsx)("th",{className:n("px-4 py-2 text-left font-semibold text-sm",r),...o,children:t}),td:({node:e,children:t,className:r,...o})=>(0,i.jsx)("td",{className:n("px-4 py-2 text-sm",r),...o,children:t}),blockquote:({node:e,children:t,className:r,...o})=>(0,i.jsx)("blockquote",{className:n("my-4 border-muted-foreground/30 border-l-4 pl-4 text-muted-foreground italic",r),...o,children:t}),code:ce,pre:({children:e})=>e,sup:({node:e,children:t,className:r,...o})=>(0,i.jsx)("sup",{className:n("text-sm",r),...o,children:t}),sub:({node:e,children:t,className:r,...o})=>(0,i.jsx)("sub",{className:n("text-sm",r),...o,children:t})};var z=require("marked"),V=e=>z.marked.lexer(e).map(r=>r.raw);var le=/(!?\[)([^\]]*?)$/,de=/(\*\*)([^*]*?)$/,me=/(__)([^_]*?)$/,ue=/(\*\*\*)([^*]*?)$/,pe=/(\*)([^*]*?)$/,ge=/(_)([^_]*?)$/,he=/(`)([^`]*?)$/,fe=/(~~)([^~]*?)$/,be=/(\$)([^$]*?)$/,ke=/(\$\$)([^$]*?)$/,ye=e=>{let t=e.match(le);if(t){let r=e.lastIndexOf(t[1]);return e.substring(0,r)}return e},Me=e=>e.match(de)&&(e.match(/\*\*/g)||[]).length%2===1?`${e}**`:e,Ce=e=>e.match(me)&&(e.match(/__/g)||[]).length%2===1?`${e}__`:e,Be=e=>e.split("").reduce((t,r,o)=>{if(r==="*"){let s=e[o-1],a=e[o+1];if(s==="\\")return t;if(s!=="*"&&a!=="*")return t+1}return t},0),ve=e=>e.match(pe)&&Be(e)%2===1?`${e}*`:e,Ie=e=>e.split("").reduce((t,r,o)=>{if(r==="_"){let s=e[o-1],a=e[o+1];if(s==="\\")return t;if(s!=="_"&&a!=="_")return t+1}return t},0),$e=e=>e.match(ge)&&Ie(e)%2===1?`${e}_`:e,Te=(e,t)=>{let r=e.substring(t,t+3)==="```",o=t>0&&e.substring(t-1,t+2)==="```",s=t>1&&e.substring(t-2,t+1)==="```";return r||o||s},we=e=>{let t=0;for(let r=0;r<e.length;r++)e[r]==="`"&&!Te(e,r)&&t++;return t},Ne=e=>{if(e.match(/^```[^`\n]*```?$/)&&!e.includes(`
2
+ `))return e.endsWith("``")&&!e.endsWith("```")?`${e}\``:e;let r=(e.match(/```/g)||[]).length,o=r%2===1;return(e.endsWith("```\n")||e.endsWith("```"))&&r%2===0||r>0&&r%2===0&&e.includes(`
3
+ `)?e:e.match(he)&&!o&&we(e)%2===1?`${e}\``:e},Pe=e=>e.match(fe)&&(e.match(/~~/g)||[]).length%2===1?`${e}~~`:e,Se=e=>e.split("").reduce((t,r,o)=>{if(r==="$"){let s=e[o-1],a=e[o+1];if(s==="\\")return t;if(s!=="$"&&a!=="$")return t+1}return t},0),Le=e=>e.match(ke)&&(e.match(/\$\$/g)||[]).length%2===1?`${e}$$`:e,He=e=>e.match(be)&&Se(e)%2===1?`${e}$`:e,Ae=e=>{let t=0,r=e.match(/\*+/g)||[];for(let o of r){let s=o.length;s>=3&&(t+=Math.floor(s/3))}return t},_e=e=>/^\*{4,}$/.test(e)?e:e.match(ue)&&Ae(e)%2===1?`${e}***`:e,W=e=>{if(!e||typeof e!="string")return e;let t=e;return t=ye(t),t=_e(t),t=Me(t),t=Ce(t),t=ve(t),t=$e(t),t=Ne(t),t=Pe(t),t=Le(t),t=He(t),t};var $=require("react/jsx-runtime"),xe=L.default.default||L.default,Re=xe(F.default),N=(0,g.createContext)("github-light"),X=(0,g.memo)(({content:e,shouldParseIncompleteMarkdown:t,...r})=>{let o=(0,g.useMemo)(()=>typeof e=="string"&&t?W(e.trim()):e,[e,t]);return(0,$.jsx)(Re,{...r,children:o})},(e,t)=>e.content===t.content);X.displayName="Block";var H=(0,g.memo)(({children:e,allowedImagePrefixes:t,allowedLinkPrefixes:r,defaultOrigin:o,parseIncompleteMarkdown:s=!0,components:a,rehypePlugins:l,remarkPlugins:c,className:d,shikiTheme:m="github-light",...f})=>{let y=(0,g.useId)(),b=(0,g.useMemo)(()=>V(typeof e=="string"?e:""),[e]);return(0,$.jsx)(N.Provider,{value:m,children:(0,$.jsx)("div",{className:n("space-y-4",d),...f,children:b.map((k,v)=>(0,$.jsx)(X,{allowedImagePrefixes:t!=null?t:["*"],allowedLinkPrefixes:r!=null?r:["*"],components:{...q,...a},content:k,defaultOrigin:o,rehypePlugins:[G.default,...l!=null?l:[]],remarkPlugins:[J.default,Q.default,...c!=null?c:[]],shouldParseIncompleteMarkdown:s},`${y}-block_${v}`))})})},(e,t)=>e.children===t.children&&e.shikiTheme===t.shikiTheme);H.displayName="Streamdown";var De=H;0&&(module.exports={CodeBlock,CodeBlockCopyButton,CodeBlockRenderButton,Mermaid,ShikiThemeContext,Streamdown});
package/dist/index.d.cts CHANGED
@@ -1,7 +1,32 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as react from 'react';
3
+ import { HTMLAttributes, ComponentProps } from 'react';
3
4
  import { Options } from 'react-markdown';
4
- import { BundledTheme } from 'shiki';
5
+ import { BundledLanguage, BundledTheme } from 'shiki';
6
+
7
+ type MermaidProps = {
8
+ chart: string;
9
+ className?: string;
10
+ };
11
+ declare const Mermaid: ({ chart, className }: MermaidProps) => react_jsx_runtime.JSX.Element;
12
+
13
+ type CodeBlockProps = HTMLAttributes<HTMLDivElement> & {
14
+ code: string;
15
+ language: BundledLanguage;
16
+ };
17
+ declare const CodeBlock: ({ code, language, className, children, ...props }: CodeBlockProps) => react_jsx_runtime.JSX.Element;
18
+ type CodeBlockCopyButtonProps = ComponentProps<'button'> & {
19
+ onCopy?: () => void;
20
+ onError?: (error: Error) => void;
21
+ timeout?: number;
22
+ };
23
+ declare const CodeBlockCopyButton: ({ onCopy, onError, timeout, children, className, code: propCode, ...props }: CodeBlockCopyButtonProps & {
24
+ code?: string;
25
+ }) => react_jsx_runtime.JSX.Element;
26
+ type CodeBlockRenderButtonProps = ComponentProps<'button'> & {
27
+ onRender?: (code: string) => void;
28
+ };
29
+ declare const CodeBlockRenderButton: ({ onRender, children, className, ...props }: CodeBlockRenderButtonProps) => react_jsx_runtime.JSX.Element;
5
30
 
6
31
  type HardenReactMarkdownProps = Options & {
7
32
  defaultOrigin?: string;
@@ -16,4 +41,4 @@ type StreamdownProps = HardenReactMarkdownProps & {
16
41
  declare const ShikiThemeContext: react.Context<BundledTheme>;
17
42
  declare const Streamdown: react.MemoExoticComponent<({ children, allowedImagePrefixes, allowedLinkPrefixes, defaultOrigin, parseIncompleteMarkdown: shouldParseIncompleteMarkdown, components, rehypePlugins, remarkPlugins, className, shikiTheme, ...props }: StreamdownProps) => react_jsx_runtime.JSX.Element>;
18
43
 
19
- export { ShikiThemeContext, Streamdown, type StreamdownProps, Streamdown as default };
44
+ export { CodeBlock, CodeBlockCopyButton, CodeBlockRenderButton, Mermaid, ShikiThemeContext, Streamdown, type StreamdownProps, Streamdown as default };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,32 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as react from 'react';
3
+ import { HTMLAttributes, ComponentProps } from 'react';
3
4
  import { Options } from 'react-markdown';
4
- import { BundledTheme } from 'shiki';
5
+ import { BundledLanguage, BundledTheme } from 'shiki';
6
+
7
+ type MermaidProps = {
8
+ chart: string;
9
+ className?: string;
10
+ };
11
+ declare const Mermaid: ({ chart, className }: MermaidProps) => react_jsx_runtime.JSX.Element;
12
+
13
+ type CodeBlockProps = HTMLAttributes<HTMLDivElement> & {
14
+ code: string;
15
+ language: BundledLanguage;
16
+ };
17
+ declare const CodeBlock: ({ code, language, className, children, ...props }: CodeBlockProps) => react_jsx_runtime.JSX.Element;
18
+ type CodeBlockCopyButtonProps = ComponentProps<'button'> & {
19
+ onCopy?: () => void;
20
+ onError?: (error: Error) => void;
21
+ timeout?: number;
22
+ };
23
+ declare const CodeBlockCopyButton: ({ onCopy, onError, timeout, children, className, code: propCode, ...props }: CodeBlockCopyButtonProps & {
24
+ code?: string;
25
+ }) => react_jsx_runtime.JSX.Element;
26
+ type CodeBlockRenderButtonProps = ComponentProps<'button'> & {
27
+ onRender?: (code: string) => void;
28
+ };
29
+ declare const CodeBlockRenderButton: ({ onRender, children, className, ...props }: CodeBlockRenderButtonProps) => react_jsx_runtime.JSX.Element;
5
30
 
6
31
  type HardenReactMarkdownProps = Options & {
7
32
  defaultOrigin?: string;
@@ -16,4 +41,4 @@ type StreamdownProps = HardenReactMarkdownProps & {
16
41
  declare const ShikiThemeContext: react.Context<BundledTheme>;
17
42
  declare const Streamdown: react.MemoExoticComponent<({ children, allowedImagePrefixes, allowedLinkPrefixes, defaultOrigin, parseIncompleteMarkdown: shouldParseIncompleteMarkdown, components, rehypePlugins, remarkPlugins, className, shikiTheme, ...props }: StreamdownProps) => react_jsx_runtime.JSX.Element>;
18
43
 
19
- export { ShikiThemeContext, Streamdown, type StreamdownProps, Streamdown as default };
44
+ export { CodeBlock, CodeBlockCopyButton, CodeBlockRenderButton, Mermaid, ShikiThemeContext, Streamdown, type StreamdownProps, Streamdown as default };
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- "use client";import{createContext as ge,memo as v,useId as fe,useMemo as w}from"react";import ke from"react-markdown";import be from"rehype-katex";import ye from"remark-gfm";import Ce from"remark-math";import"katex/dist/katex.min.css";import T from"harden-react-markdown";import{isValidElement as W}from"react";import{CheckIcon as K,CopyIcon as L}from"lucide-react";import{createContext as O,useContext as b,useEffect as R,useState as y}from"react";import{codeToHtml as U}from"shiki";import{clsx as A}from"clsx";import{twMerge as H}from"tailwind-merge";var s=(...e)=>H(A(e));import{jsx as u,jsxs as q}from"react/jsx-runtime";var C=O({code:""});async function D(e,t,n){return await U(e,{lang:t,theme:n})}var M=({code:e,language:t,className:n,children:o,...r})=>{let[a,l]=y(""),c=b(k);return R(()=>{let d=!0;return D(e,t,c).then(m=>{d&&l(m)}),()=>{d=!1}},[e,t,c]),u(C.Provider,{value:{code:e},children:q("div",{className:"group relative",children:[u("div",{className:s("overflow-x-auto",n),dangerouslySetInnerHTML:{__html:a},...r}),o]})})},B=({onCopy:e,onError:t,timeout:n=2e3,children:o,className:r,...a})=>{let[l,c]=y(!1),{code:d}=b(C),m=async()=>{var p;if(typeof window=="undefined"||!((p=navigator==null?void 0:navigator.clipboard)!=null&&p.writeText)){t==null||t(new Error("Clipboard API not available"));return}try{await navigator.clipboard.writeText(d),c(!0),e==null||e(),setTimeout(()=>c(!1),n)}catch(f){t==null||t(f)}},g=l?K:L;return u("button",{className:s("absolute top-2 right-2 shrink-0 rounded-md p-3 opacity-0 transition-all","hover:bg-secondary group-hover:opacity-100",r),onClick:m,type:"button",...a,children:o!=null?o:u(g,{size:14})})};import{jsx as i}from"react/jsx-runtime";var I={ol:({node:e,children:t,className:n,...o})=>i("ol",{className:s("ml-4 list-outside list-decimal",n),...o,children:t}),li:({node:e,children:t,className:n,...o})=>i("li",{className:s("py-1",n),...o,children:t}),ul:({node:e,children:t,className:n,...o})=>i("ul",{className:s("ml-4 list-outside list-disc",n),...o,children:t}),hr:({node:e,className:t,...n})=>i("hr",{className:s("my-6 border-border",t),...n}),strong:({node:e,children:t,className:n,...o})=>i("span",{className:s("font-semibold",n),...o,children:t}),a:({node:e,children:t,className:n,href:o,...r})=>i("a",{className:s("font-medium text-primary underline",n),href:o,rel:"noreferrer",target:"_blank",...r,children:t}),h1:({node:e,children:t,className:n,...o})=>i("h1",{className:s("mt-6 mb-2 font-semibold text-3xl",n),...o,children:t}),h2:({node:e,children:t,className:n,...o})=>i("h2",{className:s("mt-6 mb-2 font-semibold text-2xl",n),...o,children:t}),h3:({node:e,children:t,className:n,...o})=>i("h3",{className:s("mt-6 mb-2 font-semibold text-xl",n),...o,children:t}),h4:({node:e,children:t,className:n,...o})=>i("h4",{className:s("mt-6 mb-2 font-semibold text-lg",n),...o,children:t}),h5:({node:e,children:t,className:n,...o})=>i("h5",{className:s("mt-6 mb-2 font-semibold text-base",n),...o,children:t}),h6:({node:e,children:t,className:n,...o})=>i("h6",{className:s("mt-6 mb-2 font-semibold text-sm",n),...o,children:t}),table:({node:e,children:t,className:n,...o})=>i("div",{className:"my-4 overflow-x-auto",children:i("table",{className:s("w-full border-collapse border border-border",n),...o,children:t})}),thead:({node:e,children:t,className:n,...o})=>i("thead",{className:s("bg-muted/50",n),...o,children:t}),tbody:({node:e,children:t,className:n,...o})=>i("tbody",{className:s("divide-y divide-border",n),...o,children:t}),tr:({node:e,children:t,className:n,...o})=>i("tr",{className:s("border-border border-b",n),...o,children:t}),th:({node:e,children:t,className:n,...o})=>i("th",{className:s("px-4 py-2 text-left font-semibold text-sm",n),...o,children:t}),td:({node:e,children:t,className:n,...o})=>i("td",{className:s("px-4 py-2 text-sm",n),...o,children:t}),blockquote:({node:e,children:t,className:n,...o})=>i("blockquote",{className:s("my-4 border-muted-foreground/30 border-l-4 pl-4 text-muted-foreground italic",n),...o,children:t}),code:({node:e,className:t,...n})=>{var r,a;return((r=e==null?void 0:e.position)==null?void 0:r.start.line)===((a=e==null?void 0:e.position)==null?void 0:a.end.line)?i("code",{className:s("rounded bg-muted px-1.5 py-0.5 font-mono text-sm",t),...n}):i("code",{className:t,...n})},pre:({node:e,className:t,children:n})=>{var a;let o="javascript";typeof((a=e==null?void 0:e.properties)==null?void 0:a.className)=="string"&&(o=e.properties.className.replace("language-",""));let r="";return W(n)&&n.props&&typeof n.props=="object"&&"children"in n.props&&typeof n.props.children=="string"?r=n.props.children:typeof n=="string"&&(r=n),i(M,{className:s("my-4 h-auto rounded-lg border p-4",t),code:r,language:o,children:i(B,{})})},sup:({node:e,children:t,className:n,...o})=>i("sup",{className:s("text-sm",n),...o,children:t}),sub:({node:e,children:t,className:n,...o})=>i("sub",{className:s("text-sm",n),...o,children:t})};import{marked as V}from"marked";var $=e=>V.lexer(e).map(n=>n.raw);var z=/(!?\[)([^\]]*?)$/,G=/(\*\*)([^*]*?)$/,F=/(__)([^_]*?)$/,J=/(\*\*\*)([^*]*?)$/,Q=/(\*)([^*]*?)$/,X=/(_)([^_]*?)$/,Y=/(`)([^`]*?)$/,Z=/(~~)([^~]*?)$/,j=/(\$)([^$]*?)$/,E=/(\$\$)([^$]*?)$/,x=e=>{let t=e.match(z);if(t){let n=e.lastIndexOf(t[1]);return e.substring(0,n)}return e},ee=e=>e.match(G)&&(e.match(/\*\*/g)||[]).length%2===1?`${e}**`:e,te=e=>e.match(F)&&(e.match(/__/g)||[]).length%2===1?`${e}__`:e,ne=e=>e.split("").reduce((t,n,o)=>{if(n==="*"){let r=e[o-1],a=e[o+1];if(r==="\\")return t;if(r!=="*"&&a!=="*")return t+1}return t},0),oe=e=>e.match(Q)&&ne(e)%2===1?`${e}*`:e,re=e=>e.split("").reduce((t,n,o)=>{if(n==="_"){let r=e[o-1],a=e[o+1];if(r==="\\")return t;if(r!=="_"&&a!=="_")return t+1}return t},0),se=e=>e.match(X)&&re(e)%2===1?`${e}_`:e,ie=(e,t)=>{let n=e.substring(t,t+3)==="```",o=t>0&&e.substring(t-1,t+2)==="```",r=t>1&&e.substring(t-2,t+1)==="```";return n||o||r},ae=e=>{let t=0;for(let n=0;n<e.length;n++)e[n]==="`"&&!ie(e,n)&&t++;return t},ce=e=>{if(e.match(/^```[^`\n]*```?$/)&&!e.includes(`
2
- `))return e.endsWith("``")&&!e.endsWith("```")?`${e}\``:e;let n=(e.match(/```/g)||[]).length,o=n%2===1;return(e.endsWith("```\n")||e.endsWith("```"))&&n%2===0||n>0&&n%2===0&&e.includes(`
3
- `)?e:e.match(Y)&&!o&&ae(e)%2===1?`${e}\``:e},le=e=>e.match(Z)&&(e.match(/~~/g)||[]).length%2===1?`${e}~~`:e,de=e=>e.split("").reduce((t,n,o)=>{if(n==="$"){let r=e[o-1],a=e[o+1];if(r==="\\")return t;if(r!=="$"&&a!=="$")return t+1}return t},0),me=e=>e.match(E)&&(e.match(/\$\$/g)||[]).length%2===1?`${e}$$`:e,pe=e=>e.match(j)&&de(e)%2===1?`${e}$`:e,ue=e=>{let t=0,n=e.match(/\*+/g)||[];for(let o of n){let r=o.length;r>=3&&(t+=Math.floor(r/3))}return t},he=e=>/^\*{4,}$/.test(e)?e:e.match(J)&&ue(e)%2===1?`${e}***`:e,N=e=>{if(!e||typeof e!="string")return e;let t=e;return t=x(t),t=he(t),t=ee(t),t=te(t),t=oe(t),t=se(t),t=ce(t),t=le(t),t=me(t),t=pe(t),t};import{jsx as h}from"react/jsx-runtime";var Me=T.default||T,Be=Me(ke),k=ge("github-light"),Ie=v(({content:e,shouldParseIncompleteMarkdown:t,...n})=>{let o=w(()=>typeof e=="string"&&t?N(e.trim()):e,[e,t]);return h(Be,{...n,children:o})},(e,t)=>e.content===t.content),P=v(({children:e,allowedImagePrefixes:t,allowedLinkPrefixes:n,defaultOrigin:o,parseIncompleteMarkdown:r=!0,components:a,rehypePlugins:l,remarkPlugins:c,className:d,shikiTheme:m="github-light",...g})=>{let p=fe(),f=w(()=>$(typeof e=="string"?e:""),[e]);return h(k.Provider,{value:m,children:h("div",{className:s("space-y-4",d),...g,children:f.map((S,_)=>h(Ie,{allowedImagePrefixes:t!=null?t:["*"],allowedLinkPrefixes:n!=null?n:["*"],components:{...I,...a},content:S,defaultOrigin:o,rehypePlugins:[be,...l!=null?l:[]],remarkPlugins:[ye,Ce,...c!=null?c:[]],shouldParseIncompleteMarkdown:r},`${p}-block_${_}`))})})},(e,t)=>e.children===t.children&&e.shikiTheme===t.shikiTheme);P.displayName="Streamdown";var xe=P;export{k as ShikiThemeContext,P as Streamdown,xe as default};
1
+ "use client";import{createContext as Le,memo as R,useId as He,useMemo as D}from"react";import Ae from"react-markdown";import _e from"rehype-katex";import xe from"remark-gfm";import Re from"remark-math";import"katex/dist/katex.min.css";import x from"harden-react-markdown";import{isValidElement as ee}from"react";import{CheckIcon as z,CopyIcon as V,RouteIcon as W}from"lucide-react";import{createContext as F,useContext as v,useEffect as G,useState as S}from"react";import{codeToHtml as J}from"shiki";import{clsx as U}from"clsx";import{twMerge as q}from"tailwind-merge";var n=(...e)=>q(U(e));import{jsx as f,jsxs as Y}from"react/jsx-runtime";var I=F({code:""});async function Q(e,t,r){return await J(e,{lang:t,theme:r})}var $=({code:e,language:t,className:r,children:o,...s})=>{let[a,l]=S(""),c=v(T);return G(()=>{let d=!0;return Q(e,t,c).then(m=>{d&&l(m)}).catch(m=>{console.error("Failed to highlight code:",m),d&&l(`<pre><code>${e}</code></pre>`)}),()=>{d=!1}},[e,t,c]),f(I.Provider,{value:{code:e},children:Y("div",{className:"group relative",children:[f("div",{className:n("overflow-x-auto",r),dangerouslySetInnerHTML:{__html:a},...s}),o]})})},y=({onCopy:e,onError:t,timeout:r=2e3,children:o,className:s,code:a,...l})=>{let[c,d]=S(!1),m=v(I).code,u=a!=null?a:m,h=async()=>{var g;if(typeof window=="undefined"||!((g=navigator==null?void 0:navigator.clipboard)!=null&&g.writeText)){t==null||t(new Error("Clipboard API not available"));return}try{await navigator.clipboard.writeText(u),d(!0),e==null||e(),setTimeout(()=>d(!1),r)}catch(k){t==null||t(k)}},p=c?z:V;return f("button",{className:n("absolute top-2 right-2 shrink-0 rounded-md p-3 opacity-0 transition-all","hover:bg-secondary group-hover:opacity-100",s),onClick:h,type:"button",...l,children:o!=null?o:f(p,{size:14})})},X=({onRender:e,children:t,className:r,...o})=>{let{code:s}=v(I),a=()=>{e==null||e(s)};return f("button",{className:n("absolute top-2 right-12 shrink-0 rounded-md p-3 opacity-0 transition-all hover:bg-secondary group-hover:opacity-100",r),onClick:a,type:"button",...o,children:t||f(W,{size:14})})};import{useEffect as Z,useState as M}from"react";import{jsx as b,jsxs as C}from"react/jsx-runtime";var L=!1,j=async()=>{if(!L){let r=(await import("mermaid")).default;return r.initialize({startOnLoad:!1,theme:"default",securityLevel:"strict",fontFamily:"monospace",suppressErrorRendering:!0}),L=!0,r}return(await import("mermaid")).default},w=({chart:e,className:t})=>{let[r,o]=M(null),[s,a]=M(!0),[l,c]=M(""),[d,m]=M("");if(Z(()=>{(async()=>{try{o(null),a(!0);let p=await j(),g=e.split("").reduce((P,O)=>(P<<5)-P+O.charCodeAt(0)|0,0),k=`mermaid-${Math.abs(g)}`,{svg:N}=await p.render(k,e);c(N),m(N)}catch(p){if(!(d||l)){let g=p instanceof Error?p.message:"Failed to render Mermaid chart";o(g)}}finally{a(!1)}})()},[e]),s&&!l&&!d)return b("div",{className:n("my-4 flex justify-center p-4",t),children:C("div",{className:"flex items-center space-x-2 text-muted-foreground",children:[b("div",{className:"h-4 w-4 animate-spin rounded-full border-current border-b-2"}),b("span",{className:"text-sm",children:"Loading diagram..."})]})});if(r&&!l&&!d)return C("div",{className:n("rounded-lg border border-red-200 bg-red-50 p-4",t),children:[C("p",{className:"font-mono text-red-700 text-sm",children:["Mermaid Error: ",r]}),C("details",{className:"mt-2",children:[b("summary",{className:"cursor-pointer text-red-600 text-xs",children:"Show Code"}),b("pre",{className:"mt-2 overflow-x-auto rounded bg-red-100 p-2 text-red-800 text-xs",children:e})]})]});let u=l||d;return b("div",{"aria-label":"Mermaid chart",className:n("my-4 flex justify-center",t),dangerouslySetInnerHTML:{__html:u},role:"img"})};import{jsx as i,jsxs as oe}from"react/jsx-runtime";var te=/language-([^\s]+)/,re=({node:e,className:t,children:r,...o})=>{var m,u,h;if(((m=e==null?void 0:e.position)==null?void 0:m.start.line)===((u=e==null?void 0:e.position)==null?void 0:u.end.line))return i("code",{className:n("rounded bg-muted px-1.5 py-0.5 font-mono text-sm",t),...o,children:r});let a=t==null?void 0:t.match(te),l=(h=a==null?void 0:a.at(1))!=null?h:"plaintext",c="";return ee(r)&&r.props&&typeof r.props=="object"&&"children"in r.props&&typeof r.props.children=="string"?c=r.props.children:typeof r=="string"&&(c=r),l==="mermaid"||c.includes("graph")||c.includes("flowchart")||c.includes("sequenceDiagram")||c.includes("classDiagram")||c.includes("gantt")?oe("div",{className:n("group relative my-4 h-auto rounded-lg border p-4",t),children:[i(w,{chart:c}),i(y,{code:c})]}):i($,{className:n("my-4 h-auto rounded-lg border p-4",t),code:c,language:l,children:i(y,{})})},H={ol:({node:e,children:t,className:r,...o})=>i("ol",{className:n("ml-4 list-outside list-decimal",r),...o,children:t}),li:({node:e,children:t,className:r,...o})=>i("li",{className:n("py-1",r),...o,children:t}),ul:({node:e,children:t,className:r,...o})=>i("ul",{className:n("ml-4 list-outside list-disc",r),...o,children:t}),hr:({node:e,className:t,...r})=>i("hr",{className:n("my-6 border-border",t),...r}),strong:({node:e,children:t,className:r,...o})=>i("span",{className:n("font-semibold",r),...o,children:t}),a:({node:e,children:t,className:r,href:o,...s})=>i("a",{className:n("font-medium text-primary underline",r),href:o,rel:"noreferrer",target:"_blank",...s,children:t}),h1:({node:e,children:t,className:r,...o})=>i("h1",{className:n("mt-6 mb-2 font-semibold text-3xl",r),...o,children:t}),h2:({node:e,children:t,className:r,...o})=>i("h2",{className:n("mt-6 mb-2 font-semibold text-2xl",r),...o,children:t}),h3:({node:e,children:t,className:r,...o})=>i("h3",{className:n("mt-6 mb-2 font-semibold text-xl",r),...o,children:t}),h4:({node:e,children:t,className:r,...o})=>i("h4",{className:n("mt-6 mb-2 font-semibold text-lg",r),...o,children:t}),h5:({node:e,children:t,className:r,...o})=>i("h5",{className:n("mt-6 mb-2 font-semibold text-base",r),...o,children:t}),h6:({node:e,children:t,className:r,...o})=>i("h6",{className:n("mt-6 mb-2 font-semibold text-sm",r),...o,children:t}),table:({node:e,children:t,className:r,...o})=>i("div",{className:"my-4 overflow-x-auto",children:i("table",{className:n("w-full border-collapse border border-border",r),...o,children:t})}),thead:({node:e,children:t,className:r,...o})=>i("thead",{className:n("bg-muted/50",r),...o,children:t}),tbody:({node:e,children:t,className:r,...o})=>i("tbody",{className:n("divide-y divide-border",r),...o,children:t}),tr:({node:e,children:t,className:r,...o})=>i("tr",{className:n("border-border border-b",r),...o,children:t}),th:({node:e,children:t,className:r,...o})=>i("th",{className:n("px-4 py-2 text-left font-semibold text-sm",r),...o,children:t}),td:({node:e,children:t,className:r,...o})=>i("td",{className:n("px-4 py-2 text-sm",r),...o,children:t}),blockquote:({node:e,children:t,className:r,...o})=>i("blockquote",{className:n("my-4 border-muted-foreground/30 border-l-4 pl-4 text-muted-foreground italic",r),...o,children:t}),code:re,pre:({children:e})=>e,sup:({node:e,children:t,className:r,...o})=>i("sup",{className:n("text-sm",r),...o,children:t}),sub:({node:e,children:t,className:r,...o})=>i("sub",{className:n("text-sm",r),...o,children:t})};import{marked as ne}from"marked";var A=e=>ne.lexer(e).map(r=>r.raw);var se=/(!?\[)([^\]]*?)$/,ie=/(\*\*)([^*]*?)$/,ae=/(__)([^_]*?)$/,ce=/(\*\*\*)([^*]*?)$/,le=/(\*)([^*]*?)$/,de=/(_)([^_]*?)$/,me=/(`)([^`]*?)$/,ue=/(~~)([^~]*?)$/,pe=/(\$)([^$]*?)$/,ge=/(\$\$)([^$]*?)$/,he=e=>{let t=e.match(se);if(t){let r=e.lastIndexOf(t[1]);return e.substring(0,r)}return e},fe=e=>e.match(ie)&&(e.match(/\*\*/g)||[]).length%2===1?`${e}**`:e,be=e=>e.match(ae)&&(e.match(/__/g)||[]).length%2===1?`${e}__`:e,ke=e=>e.split("").reduce((t,r,o)=>{if(r==="*"){let s=e[o-1],a=e[o+1];if(s==="\\")return t;if(s!=="*"&&a!=="*")return t+1}return t},0),ye=e=>e.match(le)&&ke(e)%2===1?`${e}*`:e,Me=e=>e.split("").reduce((t,r,o)=>{if(r==="_"){let s=e[o-1],a=e[o+1];if(s==="\\")return t;if(s!=="_"&&a!=="_")return t+1}return t},0),Ce=e=>e.match(de)&&Me(e)%2===1?`${e}_`:e,Be=(e,t)=>{let r=e.substring(t,t+3)==="```",o=t>0&&e.substring(t-1,t+2)==="```",s=t>1&&e.substring(t-2,t+1)==="```";return r||o||s},ve=e=>{let t=0;for(let r=0;r<e.length;r++)e[r]==="`"&&!Be(e,r)&&t++;return t},Ie=e=>{if(e.match(/^```[^`\n]*```?$/)&&!e.includes(`
2
+ `))return e.endsWith("``")&&!e.endsWith("```")?`${e}\``:e;let r=(e.match(/```/g)||[]).length,o=r%2===1;return(e.endsWith("```\n")||e.endsWith("```"))&&r%2===0||r>0&&r%2===0&&e.includes(`
3
+ `)?e:e.match(me)&&!o&&ve(e)%2===1?`${e}\``:e},$e=e=>e.match(ue)&&(e.match(/~~/g)||[]).length%2===1?`${e}~~`:e,Te=e=>e.split("").reduce((t,r,o)=>{if(r==="$"){let s=e[o-1],a=e[o+1];if(s==="\\")return t;if(s!=="$"&&a!=="$")return t+1}return t},0),we=e=>e.match(ge)&&(e.match(/\$\$/g)||[]).length%2===1?`${e}$$`:e,Ne=e=>e.match(pe)&&Te(e)%2===1?`${e}$`:e,Pe=e=>{let t=0,r=e.match(/\*+/g)||[];for(let o of r){let s=o.length;s>=3&&(t+=Math.floor(s/3))}return t},Se=e=>/^\*{4,}$/.test(e)?e:e.match(ce)&&Pe(e)%2===1?`${e}***`:e,_=e=>{if(!e||typeof e!="string")return e;let t=e;return t=he(t),t=Se(t),t=fe(t),t=be(t),t=ye(t),t=Ce(t),t=Ie(t),t=$e(t),t=we(t),t=Ne(t),t};import{jsx as B}from"react/jsx-runtime";var De=x.default||x,Ee=De(Ae),T=Le("github-light"),E=R(({content:e,shouldParseIncompleteMarkdown:t,...r})=>{let o=D(()=>typeof e=="string"&&t?_(e.trim()):e,[e,t]);return B(Ee,{...r,children:o})},(e,t)=>e.content===t.content);E.displayName="Block";var K=R(({children:e,allowedImagePrefixes:t,allowedLinkPrefixes:r,defaultOrigin:o,parseIncompleteMarkdown:s=!0,components:a,rehypePlugins:l,remarkPlugins:c,className:d,shikiTheme:m="github-light",...u})=>{let h=He(),p=D(()=>A(typeof e=="string"?e:""),[e]);return B(T.Provider,{value:m,children:B("div",{className:n("space-y-4",d),...u,children:p.map((g,k)=>B(E,{allowedImagePrefixes:t!=null?t:["*"],allowedLinkPrefixes:r!=null?r:["*"],components:{...H,...a},content:g,defaultOrigin:o,rehypePlugins:[_e,...l!=null?l:[]],remarkPlugins:[xe,Re,...c!=null?c:[]],shouldParseIncompleteMarkdown:s},`${h}-block_${k}`))})})},(e,t)=>e.children===t.children&&e.shikiTheme===t.shikiTheme);K.displayName="Streamdown";var Mt=K;export{$ as CodeBlock,y as CodeBlockCopyButton,X as CodeBlockRenderButton,w as Mermaid,T as ShikiThemeContext,K as Streamdown,Mt as default};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "streamdown",
3
- "version": "1.0.12",
3
+ "version": "1.1.1",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -16,6 +16,12 @@
16
16
  "dist",
17
17
  "README.md"
18
18
  ],
19
+ "homepage": "https://streamdown.ai",
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "https://github.com/vercel/streamdown.git",
23
+ "directory": "packages/streamdown"
24
+ },
19
25
  "scripts": {
20
26
  "build": "tsup",
21
27
  "test": "vitest run",
@@ -45,8 +51,9 @@
45
51
  "clsx": "^2.1.1",
46
52
  "harden-react-markdown": "^1.0.4",
47
53
  "katex": "^0.16.22",
48
- "lucide-react": "^0.539.0",
54
+ "lucide-react": "^0.541.0",
49
55
  "marked": "^16.1.2",
56
+ "mermaid": "^11.0.0",
50
57
  "react-markdown": "^10.1.0",
51
58
  "rehype-katex": "^7.0.1",
52
59
  "remark-gfm": "^4.0.1",