{"_id":"flux-md","_rev":"33-c983f5fb3c2a2e2b816df6e745eaecad","name":"flux-md","dist-tags":{"latest":"0.21.0"},"versions":{"0.3.1":{"name":"flux-md","version":"0.3.1","keywords":["markdown","streaming","wasm","rust","react","incremental","llm","ai","math","katex","latex","bidi","rtl"],"license":"MIT","_id":"flux-md@0.3.1","maintainers":[{"name":"siinghd","email":"szinghh@gmail.com"}],"homepage":"https://md.hsingh.app","bugs":{"url":"https://github.com/siinghd/flux-md/issues"},"dist":{"shasum":"a61d15717bc1e339217b1bb2656803da73fe6b78","tarball":"https://registry.npmjs.org/flux-md/-/flux-md-0.3.1.tgz","fileCount":19,"integrity":"sha512-K9gGXlRDFQGH3dnYqqlBcsRn1L6XaS6vYWaTztmIg2GyPnQ8YdXb4pwcUsBzT7RH2yeEc+Eb8nKA8Uu1UL4FfQ==","signatures":[{"sig":"MEYCIQC9UMwO7+CQdP6buXmZRysK3hqLOl9MlSOa7xOCa1nbbAIhAIBXBIbUPKJ5g1XvVh5/zIjHeC2Mk7IfV2+lIzZGVWXA","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":260189},"main":"./src/index.ts","type":"module","types":"./src/index.ts","exports":{".":"./src/index.ts","./react":"./src/react.tsx","./types":"./src/types.ts","./client":"./src/client.ts","./highlight":"./src/hi.ts"},"gitHead":"0ebc19d67ee834cc3a7ecf3f7061a174ea71f6d9","scripts":{"test":"bun test","prepublishOnly":"cd ../.. && bun run build:wasm"},"_npmUser":{"name":"siinghd","email":"szinghh@gmail.com"},"repository":{"url":"git+https://github.com/siinghd/flux-md.git","type":"git"},"_npmVersion":"11.11.0","description":"Zero-dep streaming markdown for the browser. Rust→WASM core, Web Worker per stream, incremental parse with speculative closure.","directories":{},"_nodeVersion":"25.8.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"react":"^18.3.1","react-dom":"^18.3.1","typescript":"^5.6.3","@types/react":"^18.3.12","@types/react-dom":"^18.3.1"},"peerDependencies":{"react":">=18"},"peerDependenciesMeta":{"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/flux-md_0.3.1_1779889046572_0.408999346262648","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package has been renamed to brookmd — same project, same API surface with Flux*→Brook* names. Install brookmd instead: https://github.com/siinghd/brookmd"},"0.3.2":{"name":"flux-md","version":"0.3.2","keywords":["markdown","streaming","wasm","rust","react","incremental","llm","ai","math","katex","latex","bidi","rtl"],"license":"MIT","_id":"flux-md@0.3.2","maintainers":[{"name":"siinghd","email":"szinghh@gmail.com"}],"homepage":"https://md.hsingh.app","bugs":{"url":"https://github.com/siinghd/flux-md/issues"},"dist":{"shasum":"a056519fc03cb73235a02eae70de541928fcaff6","tarball":"https://registry.npmjs.org/flux-md/-/flux-md-0.3.2.tgz","fileCount":19,"integrity":"sha512-SFQgM3f27gSuinyTRPCUzxOFk31SF0SJ7X6G2plgUXxDNgXCuKdquggZmSxZUHPKfxRnc1DPNnh4cQsYS1xF4g==","signatures":[{"sig":"MEYCIQD0oGaM4M4BEZoiwW9/6PmE2lPAZba4qVqhpDOX85FTDwIhAM/nStNzNTlqBXGovMVxyaU8dShZNCQG7IDuBO50eV/O","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":260727},"main":"./src/index.ts","type":"module","types":"./src/index.ts","exports":{".":"./src/index.ts","./react":"./src/react.tsx","./types":"./src/types.ts","./client":"./src/client.ts","./highlight":"./src/hi.ts"},"gitHead":"962e55b346abd2153dd73cce4a35d9297b73d94e","scripts":{"test":"bun test","prepublishOnly":"cd ../.. && bun run build:wasm"},"_npmUser":{"name":"siinghd","email":"szinghh@gmail.com"},"repository":{"url":"git+https://github.com/siinghd/flux-md.git","type":"git"},"_npmVersion":"11.11.0","description":"Zero-dep streaming markdown for the browser. Rust→WASM core, Web Worker per stream, incremental parse with speculative closure.","directories":{},"_nodeVersion":"25.8.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"react":"^18.3.1","react-dom":"^18.3.1","typescript":"^5.6.3","@types/react":"^18.3.12","@types/react-dom":"^18.3.1"},"peerDependencies":{"react":">=18"},"peerDependenciesMeta":{"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/flux-md_0.3.2_1779890566206_0.41462962536704406","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package has been renamed to brookmd — same project, same API surface with Flux*→Brook* names. Install brookmd instead: https://github.com/siinghd/brookmd"},"0.4.0":{"name":"flux-md","version":"0.4.0","keywords":["markdown","streaming","wasm","rust","react","incremental","llm","ai","math","katex","latex","bidi","rtl"],"license":"MIT","_id":"flux-md@0.4.0","maintainers":[{"name":"siinghd","email":"szinghh@gmail.com"}],"homepage":"https://md.hsingh.app","bugs":{"url":"https://github.com/siinghd/flux-md/issues"},"dist":{"shasum":"4ee098af8d853ac303d9bd30e0caa97fb9a38a23","tarball":"https://registry.npmjs.org/flux-md/-/flux-md-0.4.0.tgz","fileCount":19,"integrity":"sha512-oqjAYHFqb+M+HhUgFksG8QC+9FWEdM6INwFkJWqdACgVsOWAxKvfHlTAKEkcG1SoaFEMLYglEPqPGoMTj3qsBw==","signatures":[{"sig":"MEYCIQCW79YA9TFfvnOWEplr35St81Je7rqJTHSXValUaQGzTQIhAKJtcIqJiLvaNMjhk0457+06zdN7InIDPqJNmNkXhPCE","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":279619},"main":"./src/index.ts","type":"module","types":"./src/index.ts","exports":{".":"./src/index.ts","./react":"./src/react.tsx","./types":"./src/types.ts","./client":"./src/client.ts","./highlight":"./src/hi.ts"},"gitHead":"dd52368a3de0c74b1cee246c6a5decee1c0a9685","scripts":{"test":"bun test","prepublishOnly":"cd ../.. && bun run build:wasm"},"_npmUser":{"name":"siinghd","email":"szinghh@gmail.com"},"repository":{"url":"git+https://github.com/siinghd/flux-md.git","type":"git"},"_npmVersion":"11.11.0","description":"Zero-dep streaming markdown for the browser. Rust→WASM core, Web Worker per stream, incremental parse with speculative closure.","directories":{},"_nodeVersion":"25.8.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"react":"^18.3.1","react-dom":"^18.3.1","typescript":"^5.6.3","@types/react":"^18.3.12","@types/react-dom":"^18.3.1"},"peerDependencies":{"react":">=18"},"peerDependenciesMeta":{"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/flux-md_0.4.0_1779907227383_0.0092393394798429","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package has been renamed to brookmd — same project, same API surface with Flux*→Brook* names. Install brookmd instead: https://github.com/siinghd/brookmd"},"0.5.0":{"name":"flux-md","version":"0.5.0","keywords":["markdown","streaming","wasm","rust","react","incremental","llm","ai","math","katex","latex","bidi","rtl"],"license":"MIT","_id":"flux-md@0.5.0","maintainers":[{"name":"siinghd","email":"szinghh@gmail.com"}],"homepage":"https://md.hsingh.app","bugs":{"url":"https://github.com/siinghd/flux-md/issues"},"dist":{"shasum":"6b412efe28c44df47144f919a04745de36545e06","tarball":"https://registry.npmjs.org/flux-md/-/flux-md-0.5.0.tgz","fileCount":19,"integrity":"sha512-SOBSgN+XH2ExnrTMXCPRDTAJLBMG1qa9WVYPGbzC3/eGgzLCKAbR2ZoW7jxDJ4fg2M9DULMGpC9M+4bQV0xkHQ==","signatures":[{"sig":"MEUCIENkMft8ztlEmlaVxqllCLeCm12fHLCQQt0MbrZJvDNHAiEA7rzgbxyATFn8Xgqli2ywWG91tBXAf03QNqvPDVOLFNE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":283009},"main":"./src/index.ts","type":"module","types":"./src/index.ts","exports":{".":"./src/index.ts","./react":"./src/react.tsx","./types":"./src/types.ts","./client":"./src/client.ts","./highlight":"./src/hi.ts"},"gitHead":"6391081c60cd4b18fe734b0be5be04b0656a2022","scripts":{"test":"bun test","prepublishOnly":"cd ../.. && bun run build:wasm"},"_npmUser":{"name":"siinghd","email":"szinghh@gmail.com"},"repository":{"url":"git+https://github.com/siinghd/flux-md.git","type":"git"},"_npmVersion":"11.11.0","description":"Zero-dep streaming markdown for the browser. Rust→WASM core, Web Worker per stream, incremental parse with speculative closure.","directories":{},"_nodeVersion":"25.8.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"react":"^18.3.1","react-dom":"^18.3.1","typescript":"^5.6.3","@types/react":"^18.3.12","@types/react-dom":"^18.3.1"},"peerDependencies":{"react":">=18"},"peerDependenciesMeta":{"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/flux-md_0.5.0_1779914198291_0.3080246410687566","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package has been renamed to brookmd — same project, same API surface with Flux*→Brook* names. Install brookmd instead: https://github.com/siinghd/brookmd"},"0.5.1":{"name":"flux-md","version":"0.5.1","keywords":["markdown","streaming","wasm","rust","react","incremental","llm","ai","math","katex","latex","bidi","rtl"],"license":"MIT","_id":"flux-md@0.5.1","maintainers":[{"name":"siinghd","email":"szinghh@gmail.com"}],"homepage":"https://md.hsingh.app","bugs":{"url":"https://github.com/siinghd/flux-md/issues"},"dist":{"shasum":"264d006f8d67a20b55aafba7d93be1ddfa076efc","tarball":"https://registry.npmjs.org/flux-md/-/flux-md-0.5.1.tgz","fileCount":19,"integrity":"sha512-rnTXPuBMqBgWls7aRFdCF1xX3gK6DfPF3ObvN1ajX7w0MgEOTtLXLZrv8QVzTkCIWAzSLQtAo0lyyIHY6fN9wg==","signatures":[{"sig":"MEUCIAMrr+iZfBMBBK3L2D4srw5Q/UEVG4fIRfGA0QWj+E8HAiEA9XWMAONxkFTHWdchwn8Y4hcl+8kpzuk/QIF3zq5j9LY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":284958},"main":"./src/index.ts","type":"module","types":"./src/index.ts","exports":{".":"./src/index.ts","./react":"./src/react.tsx","./types":"./src/types.ts","./client":"./src/client.ts","./highlight":"./src/hi.ts"},"gitHead":"0896693597dbb83a0573c008e1932744a723750d","scripts":{"test":"bun test","prepublishOnly":"cd ../.. && bun run build:wasm"},"_npmUser":{"name":"siinghd","email":"szinghh@gmail.com"},"repository":{"url":"git+https://github.com/siinghd/flux-md.git","type":"git"},"_npmVersion":"11.11.0","description":"Zero-dep streaming markdown for the browser. Rust→WASM core, Web Worker per stream, incremental parse with speculative closure.","directories":{},"_nodeVersion":"25.8.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"react":"^18.3.1","react-dom":"^18.3.1","typescript":"^5.6.3","@types/react":"^18.3.12","@types/react-dom":"^18.3.1"},"peerDependencies":{"react":">=18"},"peerDependenciesMeta":{"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/flux-md_0.5.1_1779915174056_0.6621548974706437","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package has been renamed to brookmd — same project, same API surface with Flux*→Brook* names. Install brookmd instead: https://github.com/siinghd/brookmd"},"0.5.5":{"name":"flux-md","version":"0.5.5","keywords":["markdown","streaming","wasm","rust","react","incremental","llm","ai","math","katex","latex","bidi","rtl"],"license":"MIT","_id":"flux-md@0.5.5","maintainers":[{"name":"siinghd","email":"szinghh@gmail.com"}],"homepage":"https://md.hsingh.app","bugs":{"url":"https://github.com/siinghd/flux-md/issues"},"dist":{"shasum":"6733da5d245c671f1fdb83f17c22b1e0084bb2f6","tarball":"https://registry.npmjs.org/flux-md/-/flux-md-0.5.5.tgz","fileCount":19,"integrity":"sha512-dqTkehTF2H+fmMheu5apEc3LNNl+Fc12sdAMiaOE3GkpY9wWQBS8F6ICYjf0Ayy4FwgiilgDcBIwjpbSPRxpgg==","signatures":[{"sig":"MEYCIQCaPwOUGk+GEtGfrNfxepATL2xtMNixHvPQsGgO0e+NfAIhAOIODpvxtWiky4gSc2FZdbbL3A1bFQV4AnSO/U2Iep9v","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":301733},"main":"./src/index.ts","type":"module","types":"./src/index.ts","exports":{".":"./src/index.ts","./react":"./src/react.tsx","./types":"./src/types.ts","./client":"./src/client.ts","./highlight":"./src/hi.ts"},"gitHead":"a7aa0f00e54b3c64b3ffb4b865f5a64d92cf61cf","scripts":{"test":"bun test","prepublishOnly":"cd ../.. && bun run build:wasm"},"_npmUser":{"name":"siinghd","email":"szinghh@gmail.com"},"repository":{"url":"git+https://github.com/siinghd/flux-md.git","type":"git"},"_npmVersion":"11.11.0","description":"Zero-dep streaming markdown for the browser. Rust→WASM core, Web Worker per stream, incremental parse with speculative closure.","directories":{},"_nodeVersion":"25.8.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"react":"^18.3.1","react-dom":"^18.3.1","typescript":"^5.6.3","@types/react":"^18.3.12","@types/react-dom":"^18.3.1"},"peerDependencies":{"react":">=18"},"peerDependenciesMeta":{"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/flux-md_0.5.5_1779985172782_0.5735894292455037","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package has been renamed to brookmd — same project, same API surface with Flux*→Brook* names. Install brookmd instead: https://github.com/siinghd/brookmd"},"0.6.0":{"name":"flux-md","version":"0.6.0","keywords":["markdown","streaming","wasm","rust","react","vue","svelte","solid","web-component","custom-element","incremental","llm","ai","math","katex","latex","bidi","rtl"],"license":"MIT","_id":"flux-md@0.6.0","maintainers":[{"name":"siinghd","email":"szinghh@gmail.com"}],"homepage":"https://md.hsingh.app","bugs":{"url":"https://github.com/siinghd/flux-md/issues"},"dist":{"shasum":"cd83bac82631646da11abe9b60268cf446c860ca","tarball":"https://registry.npmjs.org/flux-md/-/flux-md-0.6.0.tgz","fileCount":27,"integrity":"sha512-C002lp/bqxKvucPsHykuZ7N7ehkTO1oUqu3KEjor+IPLSXLPe0UDueYK6UU+H01i9W2uUt7g+FOFTsdDCMpoFA==","signatures":[{"sig":"MEUCIGR7VVcf9e0NxbOTbh51esqnTiDg84jrFyRwA4xTDkW1AiEA8HuKYzlryHp6r0S6jSxEf+2lQdnsmR4IOpvqsC2RX4A=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":362438},"main":"./src/index.ts","type":"module","types":"./src/index.ts","exports":{".":"./src/index.ts","./dom":"./src/dom.ts","./vue":"./src/vue.ts","./react":"./src/react.tsx","./solid":"./src/solid.tsx","./types":"./src/types.ts","./client":"./src/client.ts","./svelte":"./src/svelte.ts","./element":"./src/element.ts","./highlight":"./src/hi.ts"},"gitHead":"950647f6b85f4d112e7297fdaeaef5eadce2b59e","scripts":{"test":"bun test","prepublishOnly":"cd ../.. && bun run build:wasm"},"_npmUser":{"name":"siinghd","email":"szinghh@gmail.com"},"repository":{"url":"git+https://github.com/siinghd/flux-md.git","type":"git"},"_npmVersion":"11.11.0","description":"Zero-dep streaming markdown for the browser. Rust→WASM core, Web Worker per stream, incremental parse with speculative closure.","directories":{},"_nodeVersion":"25.8.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","react":"^18.3.1","svelte":"^4.2.0","solid-js":"^1.8.0","happy-dom":"^15.11.6","react-dom":"^18.3.1","typescript":"^5.6.3","@types/react":"^18.3.12","@types/react-dom":"^18.3.1"},"peerDependencies":{"vue":">=3","react":">=18","svelte":">=4","solid-js":"^1.8.0"},"peerDependenciesMeta":{"vue":{"optional":true},"react":{"optional":true},"svelte":{"optional":true},"solid-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/flux-md_0.6.0_1779995468939_0.12993495378581987","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package has been renamed to brookmd — same project, same API surface with Flux*→Brook* names. Install brookmd instead: https://github.com/siinghd/brookmd"},"0.7.0":{"name":"flux-md","version":"0.7.0","keywords":["markdown","streaming","wasm","rust","react","vue","svelte","solid","web-component","custom-element","incremental","llm","ai","math","katex","latex","bidi","rtl"],"license":"MIT","_id":"flux-md@0.7.0","maintainers":[{"name":"siinghd","email":"szinghh@gmail.com"}],"homepage":"https://md.hsingh.app","bugs":{"url":"https://github.com/siinghd/flux-md/issues"},"dist":{"shasum":"59c8134e5dd54819f695eec854595e516e9dc62e","tarball":"https://registry.npmjs.org/flux-md/-/flux-md-0.7.0.tgz","fileCount":27,"integrity":"sha512-nFciR6LPVR8ryVe3GyrAdE2xcS560k0MkC+uIhr23hDQ17u+EXy9q3q7HpE8MQAVjFYnaT+8xoOulMKu2PwA8w==","signatures":[{"sig":"MEYCIQDbn4avoCsJlsdk1jVuK+N7K4J5pIBbVbNal2TKgNNoXAIhAJiOcx5R8/BZJUQWhG2KfMrDQrF4mEzcz/hmy4K9MX4E","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":374076},"main":"./src/index.ts","type":"module","types":"./src/index.ts","exports":{".":"./src/index.ts","./dom":"./src/dom.ts","./vue":"./src/vue.ts","./react":"./src/react.tsx","./solid":"./src/solid.tsx","./types":"./src/types.ts","./client":"./src/client.ts","./svelte":"./src/svelte.ts","./element":"./src/element.ts","./highlight":"./src/hi.ts"},"gitHead":"56a7b2e9f05bd6e7ec1f2b331887b4b07eb841a2","scripts":{"test":"bun test","prepublishOnly":"cd ../.. && bun run build:wasm"},"_npmUser":{"name":"siinghd","email":"szinghh@gmail.com"},"repository":{"url":"git+https://github.com/siinghd/flux-md.git","type":"git"},"_npmVersion":"11.11.0","description":"Zero-dep streaming markdown for the browser. Rust→WASM core, Web Worker per stream, incremental parse with speculative closure.","directories":{},"sideEffects":["./src/worker.ts"],"_nodeVersion":"25.8.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","react":"^18.3.1","svelte":"^4.2.0","solid-js":"^1.8.0","happy-dom":"^15.11.6","react-dom":"^18.3.1","typescript":"^5.6.3","@types/react":"^18.3.12","@types/react-dom":"^18.3.1"},"peerDependencies":{"vue":">=3","react":">=18","svelte":">=4","solid-js":"^1.8.0"},"peerDependenciesMeta":{"vue":{"optional":true},"react":{"optional":true},"svelte":{"optional":true},"solid-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/flux-md_0.7.0_1780079766189_0.3050339163687146","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package has been renamed to brookmd — same project, same API surface with Flux*→Brook* names. Install brookmd instead: https://github.com/siinghd/brookmd"},"0.8.0":{"name":"flux-md","version":"0.8.0","keywords":["markdown","streaming","wasm","rust","react","vue","svelte","solid","web-component","custom-element","incremental","llm","ai","math","katex","latex","bidi","rtl"],"license":"MIT","_id":"flux-md@0.8.0","maintainers":[{"name":"siinghd","email":"szinghh@gmail.com"}],"homepage":"https://md.hsingh.app","bugs":{"url":"https://github.com/siinghd/flux-md/issues"},"dist":{"shasum":"08435438f0027fa1775257a265240ce082879eef","tarball":"https://registry.npmjs.org/flux-md/-/flux-md-0.8.0.tgz","fileCount":27,"integrity":"sha512-iq0/we2iLsC9aKV8hlygQFbYsjprsBN2BDP8zzTfimXv3QA+qzzh4GAEM/FTkH5j3SMsB24nb9CIoJcXyRFfog==","signatures":[{"sig":"MEYCIQCAy9mZbDqt8pwWeWpohxh21DxgPnoJ7XvqQQt3u+nYywIhAN20NtsxR6+FGwY5l8WdoY8LGPlDIw2Gc3aMcYrGnZYK","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":379384},"main":"./src/index.ts","type":"module","types":"./src/index.ts","exports":{".":"./src/index.ts","./dom":"./src/dom.ts","./vue":"./src/vue.ts","./react":"./src/react.tsx","./solid":"./src/solid.tsx","./types":"./src/types.ts","./client":"./src/client.ts","./svelte":"./src/svelte.ts","./element":"./src/element.ts","./highlight":"./src/hi.ts"},"gitHead":"c57997acb43dc7ef0a884ea85abb92858d25e0fc","scripts":{"test":"bun test","prepublishOnly":"cd ../.. && bun run build:wasm"},"_npmUser":{"name":"siinghd","email":"szinghh@gmail.com"},"repository":{"url":"git+https://github.com/siinghd/flux-md.git","type":"git"},"_npmVersion":"11.11.0","description":"Zero-dep streaming markdown for the browser. Rust→WASM core, Web Worker per stream, incremental parse with speculative closure.","directories":{},"sideEffects":["./src/worker.ts"],"_nodeVersion":"25.8.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","react":"^18.3.1","svelte":"^4.2.0","solid-js":"^1.8.0","happy-dom":"^15.11.6","react-dom":"^18.3.1","typescript":"^5.6.3","@types/react":"^18.3.12","@types/react-dom":"^18.3.1"},"peerDependencies":{"vue":">=3","react":">=18","svelte":">=4","solid-js":"^1.8.0"},"peerDependenciesMeta":{"vue":{"optional":true},"react":{"optional":true},"svelte":{"optional":true},"solid-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/flux-md_0.8.0_1780083539444_0.7531571857012112","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package has been renamed to brookmd — same project, same API surface with Flux*→Brook* names. Install brookmd instead: https://github.com/siinghd/brookmd"},"0.9.0":{"name":"flux-md","version":"0.9.0","keywords":["markdown","streaming","wasm","rust","react","vue","svelte","solid","web-component","custom-element","incremental","llm","ai","math","katex","latex","bidi","rtl"],"license":"MIT","_id":"flux-md@0.9.0","maintainers":[{"name":"siinghd","email":"szinghh@gmail.com"}],"homepage":"https://md.hsingh.app","bugs":{"url":"https://github.com/siinghd/flux-md/issues"},"dist":{"shasum":"43c9f67eb0e0a0438dc3b3e71b736cfe47bf50d5","tarball":"https://registry.npmjs.org/flux-md/-/flux-md-0.9.0.tgz","fileCount":27,"integrity":"sha512-qiu/Q5FI2iQtgArkdinvx432zHImsZZgJvinXaZKa8glTJJchBJMWy1shnPCSa15kguIX97+Uo1XuqUNKxVDKw==","signatures":[{"sig":"MEQCIC+JnSuL3vnJLxU6N5T2+/jDrmu5YL0gEO9ySonaEExRAiBwmyE6h7UkqRS828/KdGHS92/1ib2HxDnYbn7BxOPlcA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":390288},"main":"./src/index.ts","type":"module","types":"./src/index.ts","exports":{".":"./src/index.ts","./dom":"./src/dom.ts","./vue":"./src/vue.ts","./react":"./src/react.tsx","./solid":"./src/solid.tsx","./types":"./src/types.ts","./client":"./src/client.ts","./svelte":"./src/svelte.ts","./element":"./src/element.ts","./highlight":"./src/hi.ts"},"gitHead":"d0c09b792ae3633d9cdb55320129f6e9aa0a2248","scripts":{"test":"bun test","prepublishOnly":"cd ../.. && bun run build:wasm"},"_npmUser":{"name":"siinghd","email":"szinghh@gmail.com"},"repository":{"url":"git+https://github.com/siinghd/flux-md.git","type":"git"},"_npmVersion":"11.11.0","description":"Zero-dep streaming markdown for the browser. Rust→WASM core, Web Worker per stream, incremental parse with speculative closure.","directories":{},"sideEffects":["./src/worker.ts"],"_nodeVersion":"25.8.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","react":"^18.3.1","svelte":"^4.2.0","solid-js":"^1.8.0","happy-dom":"^15.11.6","react-dom":"^18.3.1","typescript":"^5.6.3","@types/react":"^18.3.12","@types/react-dom":"^18.3.1"},"peerDependencies":{"vue":">=3","react":">=18","svelte":">=4","solid-js":"^1.8.0"},"peerDependenciesMeta":{"vue":{"optional":true},"react":{"optional":true},"svelte":{"optional":true},"solid-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/flux-md_0.9.0_1780088774049_0.6682595767617228","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package has been renamed to brookmd — same project, same API surface with Flux*→Brook* names. Install brookmd instead: https://github.com/siinghd/brookmd"},"0.10.0":{"name":"flux-md","version":"0.10.0","keywords":["markdown","streaming","wasm","rust","react","vue","svelte","solid","web-component","custom-element","incremental","llm","ai","math","katex","latex","bidi","rtl"],"license":"MIT","_id":"flux-md@0.10.0","maintainers":[{"name":"siinghd","email":"szinghh@gmail.com"}],"homepage":"https://md.hsingh.app","bugs":{"url":"https://github.com/siinghd/flux-md/issues"},"dist":{"shasum":"bed0be02c1fcad1c49eb6fd1120391baca51101a","tarball":"https://registry.npmjs.org/flux-md/-/flux-md-0.10.0.tgz","fileCount":27,"integrity":"sha512-Kdv1EciH7EVvT66xUlh8o19HHUyMod0+u0GRMOcvKHTjlr8zMazaftEFxJTeaHO1oLNhJ9L6QC/Kl1vJBPJHfQ==","signatures":[{"sig":"MEQCIAJSP9tZk3/Rk2dWc3r0HNQc95lLpuN/5UdN8HECgL62AiBQ4glyfqB+n3+KOhjPD5rn6AGs3mJIg4UZ0gQwSADqKQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":416945},"main":"./src/index.ts","type":"module","types":"./src/index.ts","exports":{".":"./src/index.ts","./dom":"./src/dom.ts","./vue":"./src/vue.ts","./react":"./src/react.tsx","./solid":"./src/solid.tsx","./types":"./src/types.ts","./client":"./src/client.ts","./svelte":"./src/svelte.ts","./element":"./src/element.ts","./highlight":"./src/hi.ts"},"gitHead":"f312a690971a1e13994a2529f2f9adac2b6e21d7","scripts":{"test":"bun test","test:ssr-cold":"bun test/ssr-cold.mjs","prepublishOnly":"cd ../.. && bun run build:wasm"},"_npmUser":{"name":"siinghd","email":"szinghh@gmail.com"},"repository":{"url":"git+https://github.com/siinghd/flux-md.git","type":"git"},"_npmVersion":"11.11.0","description":"Zero-dep streaming markdown for the browser. Rust→WASM core, Web Worker per stream, incremental parse with speculative closure.","directories":{},"sideEffects":["./src/worker.ts"],"_nodeVersion":"25.8.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","react":"^18.3.1","svelte":"^4.2.0","solid-js":"^1.8.0","happy-dom":"^15.11.6","react-dom":"^18.3.1","typescript":"^5.6.3","@types/react":"^18.3.12","@types/react-dom":"^18.3.1"},"peerDependencies":{"vue":">=3","react":">=18","svelte":">=4","solid-js":"^1.8.0"},"peerDependenciesMeta":{"vue":{"optional":true},"react":{"optional":true},"svelte":{"optional":true},"solid-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/flux-md_0.10.0_1780160871984_0.8786243967831193","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package has been renamed to brookmd — same project, same API surface with Flux*→Brook* names. Install brookmd instead: https://github.com/siinghd/brookmd"},"0.11.0":{"name":"flux-md","version":"0.11.0","keywords":["markdown","streaming","wasm","rust","react","vue","svelte","solid","web-component","custom-element","incremental","llm","ai","math","katex","latex","bidi","rtl"],"license":"MIT","_id":"flux-md@0.11.0","maintainers":[{"name":"siinghd","email":"szinghh@gmail.com"}],"homepage":"https://md.hsingh.app","bugs":{"url":"https://github.com/siinghd/flux-md/issues"},"dist":{"shasum":"c694d14bef8af490d7711fe0cd39fda496aef765","tarball":"https://registry.npmjs.org/flux-md/-/flux-md-0.11.0.tgz","fileCount":27,"integrity":"sha512-oDkXLroBRrMjhq/nbZSR5vfd+pd5+LmPLBXp6bChtUaeSG6w6VhKr5javiJSn1tnvWNd7tqROcbjiTsrDdMcOw==","signatures":[{"sig":"MEQCIFjZg+QGh5OnZLa6jDuWSlp9wCJ2S/LMTggJtYwpPXhKAiBDhWgNPoql7gLy+kLN8ECCwLssMLDezkvlC2EFFfdt5A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":419937},"main":"./src/index.ts","type":"module","types":"./src/index.ts","exports":{".":"./src/index.ts","./dom":"./src/dom.ts","./vue":"./src/vue.ts","./react":"./src/react.tsx","./solid":"./src/solid.tsx","./types":"./src/types.ts","./client":"./src/client.ts","./svelte":"./src/svelte.ts","./element":"./src/element.ts","./highlight":"./src/hi.ts"},"gitHead":"ac2a784af70cfd4cc601f5872e53178699cb0104","scripts":{"test":"bun test","test:ssr-cold":"bun test/ssr-cold.mjs","prepublishOnly":"cd ../.. && bun run build:wasm","typecheck:test":"tsc --noEmit -p tsconfig.test.json"},"_npmUser":{"name":"siinghd","email":"szinghh@gmail.com"},"repository":{"url":"git+https://github.com/siinghd/flux-md.git","type":"git"},"_npmVersion":"11.11.0","description":"Zero-dep streaming markdown for the browser. Rust→WASM core, Web Worker per stream, incremental parse with speculative closure.","directories":{},"sideEffects":["./src/worker.ts"],"_nodeVersion":"25.8.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","react":"^18.3.1","svelte":"^4.2.0","solid-js":"^1.8.0","happy-dom":"^15.11.6","react-dom":"^18.3.1","@types/bun":"^1.3.14","typescript":"^5.6.3","@types/react":"^18.3.12","@types/react-dom":"^18.3.1"},"peerDependencies":{"vue":">=3","react":">=18","svelte":">=4","solid-js":"^1.8.0"},"peerDependenciesMeta":{"vue":{"optional":true},"react":{"optional":true},"svelte":{"optional":true},"solid-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/flux-md_0.11.0_1780169932318_0.7764727919097039","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package has been renamed to brookmd — same project, same API surface with Flux*→Brook* names. Install brookmd instead: https://github.com/siinghd/brookmd"},"0.12.0":{"name":"flux-md","version":"0.12.0","keywords":["markdown","streaming","wasm","rust","react","vue","svelte","solid","web-component","custom-element","incremental","llm","ai","math","katex","latex","bidi","rtl"],"license":"MIT","_id":"flux-md@0.12.0","maintainers":[{"name":"siinghd","email":"szinghh@gmail.com"}],"homepage":"https://md.hsingh.app","bugs":{"url":"https://github.com/siinghd/flux-md/issues"},"dist":{"shasum":"ffbf9968c68431e1bed14b45a845fb72052bb440","tarball":"https://registry.npmjs.org/flux-md/-/flux-md-0.12.0.tgz","fileCount":28,"integrity":"sha512-nEiPlj27rnmSxH5m2DFx5RHuEAkcGKcrEIxJ53U/TALslKYR8Ca5ebrd0SQ9qpwJaZfj99p4k+p9c9Dto9tPNw==","signatures":[{"sig":"MEUCIC1Xcm2xUUyBNEXGpIDwOz3SXt0H/RpFrtetyC8w+Ll0AiEA+gSQqtvOnwav6xxOOeK2aYBipivNXx76u6/KG9GNIvI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":427929},"main":"./src/index.ts","type":"module","types":"./src/index.ts","exports":{".":"./src/index.ts","./dom":"./src/dom.ts","./vue":"./src/vue.ts","./react":"./src/react.tsx","./solid":"./src/solid.tsx","./types":"./src/types.ts","./client":"./src/client.ts","./svelte":"./src/svelte.ts","./element":"./src/element.ts","./highlight":"./src/hi.ts","./styles.css":"./src/styles.css"},"gitHead":"8b029a859af09768e238ac015666235d71422447","scripts":{"test":"bun test","test:ssr-cold":"bun test/ssr-cold.mjs","prepublishOnly":"cd ../.. && bun run build:wasm","typecheck:test":"tsc --noEmit -p tsconfig.test.json"},"_npmUser":{"name":"siinghd","email":"szinghh@gmail.com"},"repository":{"url":"git+https://github.com/siinghd/flux-md.git","type":"git"},"_npmVersion":"11.11.0","description":"Zero-dep streaming markdown for the browser. Rust→WASM core, Web Worker per stream, incremental parse with speculative closure.","directories":{},"sideEffects":["./src/worker.ts","./src/styles.css"],"_nodeVersion":"25.8.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","react":"^18.3.1","svelte":"^4.2.0","solid-js":"^1.8.0","happy-dom":"^15.11.6","react-dom":"^18.3.1","@types/bun":"^1.3.14","typescript":"^5.6.3","@types/react":"^18.3.12","@types/react-dom":"^18.3.1"},"peerDependencies":{"vue":">=3","react":">=18","svelte":">=4","solid-js":"^1.8.0"},"peerDependenciesMeta":{"vue":{"optional":true},"react":{"optional":true},"svelte":{"optional":true},"solid-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/flux-md_0.12.0_1780176734515_0.3142340403214572","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package has been renamed to brookmd — same project, same API surface with Flux*→Brook* names. Install brookmd instead: https://github.com/siinghd/brookmd"},"0.13.0":{"name":"flux-md","version":"0.13.0","keywords":["markdown","streaming","wasm","rust","react","vue","svelte","solid","web-component","custom-element","incremental","llm","ai","math","katex","latex","bidi","rtl"],"license":"MIT","_id":"flux-md@0.13.0","maintainers":[{"name":"siinghd","email":"szinghh@gmail.com"}],"homepage":"https://md.hsingh.app","bugs":{"url":"https://github.com/siinghd/flux-md/issues"},"dist":{"shasum":"b8158e2b8542aeb10f444f1190f8a447e9dbfa88","tarball":"https://registry.npmjs.org/flux-md/-/flux-md-0.13.0.tgz","fileCount":29,"integrity":"sha512-h5WgeDXEtR1ldEHwU4Lar8xIAVYt7WIGjwLvREb0Vs5MTctwpStYHZazRy8b7cU2N7aAEvoHTP8s6gW/0M2+Og==","signatures":[{"sig":"MEUCIQDctXVUMgsYaNHPi07IvEDu3lf6HPvRkZpskFF+pB1vMQIgRnsqkaWjCyD/gVT5GEc3UgBJj4u/4EqW/JK523rkKDk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":461611},"main":"./src/index.ts","type":"module","types":"./src/index.ts","exports":{".":"./src/index.ts","./dom":"./src/dom.ts","./vue":"./src/vue.ts","./react":"./src/react.tsx","./solid":"./src/solid.tsx","./types":"./src/types.ts","./client":"./src/client.ts","./svelte":"./src/svelte.ts","./element":"./src/element.ts","./highlight":"./src/hi.ts","./styles.css":"./src/styles.css"},"gitHead":"e056a4eb5947332feaded394dcf9ee15adbd7d76","scripts":{"test":"bun test","test:ssr-cold":"bun test/ssr-cold.mjs","prepublishOnly":"cd ../.. && bun run build:wasm","typecheck:test":"tsc --noEmit -p tsconfig.test.json"},"_npmUser":{"name":"siinghd","email":"szinghh@gmail.com"},"repository":{"url":"git+https://github.com/siinghd/flux-md.git","type":"git"},"_npmVersion":"11.11.0","description":"Zero-dep streaming markdown for the browser. Rust→WASM core, Web Worker per stream, incremental parse with speculative closure.","directories":{},"sideEffects":["./src/worker.ts","./src/styles.css"],"_nodeVersion":"25.8.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","react":"^18.3.1","svelte":"^4.2.0","solid-js":"^1.8.0","happy-dom":"^15.11.6","react-dom":"^18.3.1","@types/bun":"^1.3.14","typescript":"^5.6.3","@types/react":"^18.3.12","@types/react-dom":"^18.3.1"},"peerDependencies":{"vue":">=3","react":">=18","svelte":">=4","solid-js":"^1.8.0"},"peerDependenciesMeta":{"vue":{"optional":true},"react":{"optional":true},"svelte":{"optional":true},"solid-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/flux-md_0.13.0_1780590705223_0.31785431605214964","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package has been renamed to brookmd — same project, same API surface with Flux*→Brook* names. Install brookmd instead: https://github.com/siinghd/brookmd"},"0.14.0":{"name":"flux-md","version":"0.14.0","keywords":["markdown","streaming","wasm","rust","react","vue","svelte","solid","web-component","custom-element","incremental","llm","ai","math","katex","latex","bidi","rtl"],"license":"MIT","_id":"flux-md@0.14.0","maintainers":[{"name":"siinghd","email":"szinghh@gmail.com"}],"homepage":"https://md.hsingh.app","bugs":{"url":"https://github.com/siinghd/flux-md/issues"},"dist":{"shasum":"e5bde1ece26afab2a9883d14085a5b6d2200d1a3","tarball":"https://registry.npmjs.org/flux-md/-/flux-md-0.14.0.tgz","fileCount":30,"integrity":"sha512-BTaG28rL5K04z9XXlkh/HcmYGHs/r2/8CZwuM1Xgp7DCwaWr7B0NXGMQnpHbXPYpaIxbkrw2agd51vcff1DOYQ==","signatures":[{"sig":"MEUCIQCMZlqA3XVcl/xtMXinN+Cu5db472cINazLMEAQV2XadQIgAI00lAnYK5/u+jeZjn0lcbbFRxLyMNRBJDUH8XyoUyg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":488542},"main":"./src/index.ts","type":"module","types":"./src/index.ts","exports":{".":"./src/index.ts","./dom":"./src/dom.ts","./vue":"./src/vue.ts","./react":"./src/react.tsx","./solid":"./src/solid.tsx","./types":"./src/types.ts","./client":"./src/client.ts","./server":"./src/server.tsx","./svelte":"./src/svelte.ts","./element":"./src/element.ts","./highlight":"./src/hi.ts","./styles.css":"./src/styles.css"},"gitHead":"780cde663f0d8f4bdd3b9784f65b2df38f4d8037","scripts":{"test":"bun test","test:ssr-cold":"bun test/ssr-cold.mjs","prepublishOnly":"cd ../.. && bun run build:wasm","typecheck:test":"tsc --noEmit -p tsconfig.test.json"},"_npmUser":{"name":"siinghd","email":"szinghh@gmail.com"},"repository":{"url":"git+https://github.com/siinghd/flux-md.git","type":"git"},"_npmVersion":"11.11.0","description":"Zero-dep streaming markdown for the browser. Rust→WASM core, Web Worker per stream, incremental parse with speculative closure.","directories":{},"sideEffects":["./src/worker.ts","./src/styles.css"],"_nodeVersion":"25.8.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","react":"^18.3.1","svelte":"^4.2.0","solid-js":"^1.8.0","happy-dom":"^15.11.6","react-dom":"^18.3.1","@types/bun":"^1.3.14","typescript":"^5.6.3","@types/react":"^18.3.12","@types/react-dom":"^18.3.1"},"peerDependencies":{"vue":">=3","react":">=18","svelte":">=4","solid-js":"^1.8.0"},"peerDependenciesMeta":{"vue":{"optional":true},"react":{"optional":true},"svelte":{"optional":true},"solid-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/flux-md_0.14.0_1781710343918_0.7689638936745913","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package has been renamed to brookmd — same project, same API surface with Flux*→Brook* names. Install brookmd instead: https://github.com/siinghd/brookmd"},"0.15.0":{"name":"flux-md","version":"0.15.0","keywords":["markdown","streaming","wasm","rust","react","vue","svelte","solid","web-component","custom-element","incremental","llm","ai","math","katex","latex","bidi","rtl"],"license":"MIT","_id":"flux-md@0.15.0","maintainers":[{"name":"siinghd","email":"szinghh@gmail.com"}],"homepage":"https://md.hsingh.app","bugs":{"url":"https://github.com/siinghd/flux-md/issues"},"dist":{"shasum":"c5e7fa73d1bee9f5cccd2f9ee34ca4663f5de9bd","tarball":"https://registry.npmjs.org/flux-md/-/flux-md-0.15.0.tgz","fileCount":30,"integrity":"sha512-hbe1mWYPmZ59nLebOVgd/IItXPVN/PrbY6NlI6W6pZnEUnh2JEl3Ht6/iFdptdf7ELrMR2bmAUnDo6cOzEoBAw==","signatures":[{"sig":"MEQCIDotGQ2sdX5vAcBJIsStTQ4sHCoPF5hrWvFQNawXk2FkAiB6OlQbRl9PwaLnWFJV2rQ9NN/FzAnGI7j4P9nFBirjCQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":499589},"main":"./src/index.ts","type":"module","types":"./src/index.ts","exports":{".":"./src/index.ts","./dom":"./src/dom.ts","./vue":"./src/vue.ts","./react":"./src/react.tsx","./solid":"./src/solid.tsx","./types":"./src/types.ts","./client":"./src/client.ts","./server":"./src/server.tsx","./svelte":"./src/svelte.ts","./element":"./src/element.ts","./highlight":"./src/hi.ts","./styles.css":"./src/styles.css"},"gitHead":"6c79c93d3cfa687147f0c9dfdcfd06ba8595e43a","scripts":{"test":"bun test","test:ssr-cold":"bun test/ssr-cold.mjs","prepublishOnly":"cd ../.. && bun run build:wasm","typecheck:test":"tsc --noEmit -p tsconfig.test.json"},"_npmUser":{"name":"siinghd","email":"szinghh@gmail.com"},"repository":{"url":"git+https://github.com/siinghd/flux-md.git","type":"git"},"_npmVersion":"11.11.0","description":"Zero-dep streaming markdown for the browser. Rust→WASM core, Web Worker per stream, incremental parse with speculative closure.","directories":{},"sideEffects":["./src/worker.ts","./src/styles.css"],"_nodeVersion":"25.8.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","react":"^18.3.1","svelte":"^4.2.0","solid-js":"^1.8.0","happy-dom":"^15.11.6","react-dom":"^18.3.1","@types/bun":"^1.3.14","typescript":"^5.6.3","@types/react":"^18.3.12","@types/react-dom":"^18.3.1"},"peerDependencies":{"vue":">=3","react":">=18","svelte":">=4","solid-js":"^1.8.0"},"peerDependenciesMeta":{"vue":{"optional":true},"react":{"optional":true},"svelte":{"optional":true},"solid-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/flux-md_0.15.0_1781720046762_0.4507169392492325","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package has been renamed to brookmd — same project, same API surface with Flux*→Brook* names. Install brookmd instead: https://github.com/siinghd/brookmd"},"0.15.1":{"name":"flux-md","version":"0.15.1","keywords":["markdown","streaming","wasm","rust","react","vue","svelte","solid","web-component","custom-element","incremental","llm","ai","math","katex","latex","bidi","rtl"],"license":"MIT","_id":"flux-md@0.15.1","maintainers":[{"name":"siinghd","email":"szinghh@gmail.com"}],"homepage":"https://md.hsingh.app","bugs":{"url":"https://github.com/siinghd/flux-md/issues"},"dist":{"shasum":"8d39ddbee3d34a6781d9b05095c2d16df5fd6a95","tarball":"https://registry.npmjs.org/flux-md/-/flux-md-0.15.1.tgz","fileCount":30,"integrity":"sha512-SGe/5t1qPYSavM4wrnBPG8sORx6n15OFVxl5YWg+eyS2FwvAb/DD/5k5uesDT+Y7dOqKPLaMt0Hpwu9LBTwcUg==","signatures":[{"sig":"MEUCIGOEgtOxk1CAkFoK5gCsHbpSaERjGnEez7Fy8Ka1E6MBAiEAlrGTtsZ/SDzrg748a63A9qlONe4P3CuM5rzNHgFqnyg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":510459},"main":"./src/index.ts","type":"module","types":"./src/index.ts","exports":{".":"./src/index.ts","./dom":"./src/dom.ts","./vue":"./src/vue.ts","./react":"./src/react.tsx","./solid":"./src/solid.tsx","./types":"./src/types.ts","./client":"./src/client.ts","./server":"./src/server.tsx","./svelte":"./src/svelte.ts","./element":"./src/element.ts","./highlight":"./src/hi.ts","./styles.css":"./src/styles.css"},"gitHead":"8bf4b6a5f8922137e95f1ff21eab82745944f85e","scripts":{"test":"bun test","test:ssr-cold":"bun test/ssr-cold.mjs","prepublishOnly":"cd ../.. && bun run build:wasm","typecheck:test":"tsc --noEmit -p tsconfig.test.json"},"_npmUser":{"name":"siinghd","email":"szinghh@gmail.com"},"repository":{"url":"git+https://github.com/siinghd/flux-md.git","type":"git"},"_npmVersion":"11.11.0","description":"Zero-dep streaming markdown for the browser. Rust→WASM core, Web Worker per stream, incremental parse with speculative closure.","directories":{},"sideEffects":["./src/worker.ts","./src/styles.css"],"_nodeVersion":"25.8.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","react":"^18.3.1","svelte":"^4.2.0","solid-js":"^1.8.0","happy-dom":"^15.11.6","react-dom":"^18.3.1","@types/bun":"^1.3.14","typescript":"^5.6.3","@types/react":"^18.3.12","@types/react-dom":"^18.3.1"},"peerDependencies":{"vue":">=3","react":">=18","svelte":">=4","solid-js":"^1.8.0"},"peerDependenciesMeta":{"vue":{"optional":true},"react":{"optional":true},"svelte":{"optional":true},"solid-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/flux-md_0.15.1_1782222528355_0.18006187442388333","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package has been renamed to brookmd — same project, same API surface with Flux*→Brook* names. Install brookmd instead: https://github.com/siinghd/brookmd"},"0.16.0":{"name":"flux-md","version":"0.16.0","keywords":["markdown","streaming","wasm","rust","react","vue","svelte","solid","web-component","custom-element","incremental","llm","ai","math","katex","latex","bidi","rtl"],"license":"MIT","_id":"flux-md@0.16.0","maintainers":[{"name":"siinghd","email":"szinghh@gmail.com"}],"homepage":"https://md.hsingh.app","bugs":{"url":"https://github.com/siinghd/flux-md/issues"},"dist":{"shasum":"9c129ba9c4595dfba12e6e326187dac19f14b31a","tarball":"https://registry.npmjs.org/flux-md/-/flux-md-0.16.0.tgz","fileCount":29,"integrity":"sha512-Ta5Q6jF2G7QKW3/TzEX9UPakKtvG9VHDVvfz3lG3eRiyha58Tu7AqPFwOSsQZEIlbV2M5vsrDqz2bEBOBbwkEg==","signatures":[{"sig":"MEUCIB1B8lSfu7ceTBSdMzgeIiywr6YWMIvIT5KiAJB32tZ7AiEA17wSJAstWiTUZ/jAxnu2LNNPh3bMyOyN+Bkh0onDKFY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":510682},"main":"./src/index.ts","type":"module","types":"./src/index.ts","exports":{".":"./src/index.ts","./dom":"./src/dom.ts","./vue":"./src/vue.ts","./react":"./src/react.tsx","./solid":"./src/solid.tsx","./types":"./src/types.ts","./client":"./src/client.ts","./server":"./src/server.tsx","./svelte":"./src/svelte.ts","./element":"./src/element.ts","./highlight":"./src/hi.ts","./styles.css":"./src/styles.css"},"gitHead":"150f90490270e3bb6a93a020d2d860c6c275f3e6","scripts":{"test":"bun test","test:ssr-cold":"bun test/ssr-cold.mjs","prepublishOnly":"cd ../.. && bun run build:wasm","typecheck:test":"tsc --noEmit -p tsconfig.test.json"},"_npmUser":{"name":"siinghd","email":"szinghh@gmail.com"},"repository":{"url":"git+https://github.com/siinghd/flux-md.git","type":"git"},"_npmVersion":"11.11.0","description":"Zero-dep streaming markdown for the browser. Rust→WASM core, Web Worker per stream, incremental parse with speculative closure.","directories":{},"sideEffects":["./src/worker.ts","./src/styles.css"],"_nodeVersion":"25.8.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","react":"^18.3.1","svelte":"^4.2.0","solid-js":"^1.8.0","happy-dom":"^15.11.6","react-dom":"^18.3.1","@types/bun":"^1.3.14","typescript":"^5.6.3","@types/react":"^18.3.12","@types/react-dom":"^18.3.1"},"peerDependencies":{"vue":">=3","react":">=18","svelte":">=4","solid-js":"^1.8.0"},"peerDependenciesMeta":{"vue":{"optional":true},"react":{"optional":true},"svelte":{"optional":true},"solid-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/flux-md_0.16.0_1782398202127_0.5790028980646253","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package has been renamed to brookmd — same project, same API surface with Flux*→Brook* names. Install brookmd instead: https://github.com/siinghd/brookmd"},"0.16.1":{"name":"flux-md","version":"0.16.1","keywords":["markdown","streaming","wasm","rust","react","vue","svelte","solid","web-component","custom-element","incremental","llm","ai","math","katex","latex","bidi","rtl"],"license":"MIT","_id":"flux-md@0.16.1","maintainers":[{"name":"siinghd","email":"szinghh@gmail.com"}],"homepage":"https://md.hsingh.app","bugs":{"url":"https://github.com/siinghd/flux-md/issues"},"dist":{"shasum":"7cec377c5357cd0b38162c2ad9bec401322d5404","tarball":"https://registry.npmjs.org/flux-md/-/flux-md-0.16.1.tgz","fileCount":29,"integrity":"sha512-kZhs2eePeD3hluH9khUjDcFkCNDuMoDlhkAtkqE55GgnDQMD/aBNUdVoWnRysVYw4AnVEaEHd2F1LtoAPZCdsQ==","signatures":[{"sig":"MEYCIQCgdeYFwjOxsUNFFxdqsehYfHi2LdrGDLC6W5byyb7W3gIhAK7kY2Zm5Xd+zGX0YgUdrtEBRg3du1cTJ2YcHoGXoT9W","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":512256},"main":"./src/index.ts","type":"module","types":"./src/index.ts","exports":{".":"./src/index.ts","./dom":"./src/dom.ts","./vue":"./src/vue.ts","./react":"./src/react.tsx","./solid":"./src/solid.tsx","./types":"./src/types.ts","./client":"./src/client.ts","./server":"./src/server.tsx","./svelte":"./src/svelte.ts","./element":"./src/element.ts","./highlight":"./src/hi.ts","./styles.css":"./src/styles.css"},"gitHead":"a912418a4f0335a8ea42b29ef6b582cbd9dd4877","scripts":{"test":"bun test","test:ssr-cold":"bun test/ssr-cold.mjs","prepublishOnly":"cd ../.. && bun run build:wasm","typecheck:test":"tsc --noEmit -p tsconfig.test.json"},"_npmUser":{"name":"siinghd","email":"szinghh@gmail.com"},"repository":{"url":"git+https://github.com/siinghd/flux-md.git","type":"git"},"_npmVersion":"11.11.0","description":"Zero-dep streaming markdown for the browser. Rust→WASM core, Web Worker per stream, incremental parse with speculative closure.","directories":{},"sideEffects":["./src/worker.ts","./src/styles.css"],"_nodeVersion":"25.8.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","react":"^18.3.1","svelte":"^4.2.0","solid-js":"^1.8.0","happy-dom":"^15.11.6","react-dom":"^18.3.1","@types/bun":"^1.3.14","typescript":"^5.6.3","@types/react":"^18.3.12","@types/react-dom":"^18.3.1"},"peerDependencies":{"vue":">=3","react":">=18","svelte":">=4","solid-js":"^1.8.0"},"peerDependenciesMeta":{"vue":{"optional":true},"react":{"optional":true},"svelte":{"optional":true},"solid-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/flux-md_0.16.1_1782423102533_0.38839985146069145","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package has been renamed to brookmd — same project, same API surface with Flux*→Brook* names. Install brookmd instead: https://github.com/siinghd/brookmd"},"0.16.2":{"name":"flux-md","version":"0.16.2","keywords":["markdown","streaming","wasm","rust","react","vue","svelte","solid","web-component","custom-element","incremental","llm","ai","math","katex","latex","bidi","rtl"],"license":"MIT","_id":"flux-md@0.16.2","maintainers":[{"name":"siinghd","email":"szinghh@gmail.com"}],"homepage":"https://md.hsingh.app","bugs":{"url":"https://github.com/siinghd/flux-md/issues"},"dist":{"shasum":"45205c9cd94fd32e35d01678e76e58fdabae592e","tarball":"https://registry.npmjs.org/flux-md/-/flux-md-0.16.2.tgz","fileCount":29,"integrity":"sha512-m20xVe4qFSIKvpTDXNVwYwWu9DI+ZePmcEsJtQz67kKzZGAWtTxcqRyZg7ImHUWvYt8UAoz+uqu8AUVfNCdDLg==","signatures":[{"sig":"MEYCIQDputG6hzR8B1Y8eUwuaO8oKwWeOfIk1t0HUpGpP3rB6wIhAI1jjb6MnCHrz68ZPS5WQ2XD++O2XakhIpzbhmzRWiu2","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":513857},"main":"./src/index.ts","type":"module","types":"./src/index.ts","exports":{".":"./src/index.ts","./dom":"./src/dom.ts","./vue":"./src/vue.ts","./react":"./src/react.tsx","./solid":"./src/solid.tsx","./types":"./src/types.ts","./client":"./src/client.ts","./server":"./src/server.tsx","./svelte":"./src/svelte.ts","./element":"./src/element.ts","./highlight":"./src/hi.ts","./styles.css":"./src/styles.css"},"gitHead":"f8997f92a9b07c9ed288827076dde4551ce67092","scripts":{"test":"bun test","test:ssr-cold":"bun test/ssr-cold.mjs","prepublishOnly":"cd ../.. && bun run build:wasm","typecheck:test":"tsc --noEmit -p tsconfig.test.json"},"_npmUser":{"name":"siinghd","email":"szinghh@gmail.com"},"repository":{"url":"git+https://github.com/siinghd/flux-md.git","type":"git"},"_npmVersion":"11.11.0","description":"Zero-dep streaming markdown for the browser. Rust→WASM core, Web Worker per stream, incremental parse with speculative closure.","directories":{},"sideEffects":["./src/worker.ts","./src/styles.css"],"_nodeVersion":"25.8.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","react":"^18.3.1","svelte":"^4.2.0","solid-js":"^1.8.0","happy-dom":"^15.11.6","react-dom":"^18.3.1","@types/bun":"^1.3.14","typescript":"^5.6.3","@types/react":"^18.3.12","@types/react-dom":"^18.3.1"},"peerDependencies":{"vue":">=3","react":">=18","svelte":">=4","solid-js":"^1.8.0"},"peerDependenciesMeta":{"vue":{"optional":true},"react":{"optional":true},"svelte":{"optional":true},"solid-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/flux-md_0.16.2_1782447506890_0.05328825468473708","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package has been renamed to brookmd — same project, same API surface with Flux*→Brook* names. Install brookmd instead: https://github.com/siinghd/brookmd"},"0.17.0":{"name":"flux-md","version":"0.17.0","keywords":["markdown","streaming","wasm","rust","react","vue","svelte","solid","web-component","custom-element","incremental","llm","ai","math","katex","latex","bidi","rtl"],"license":"MIT","_id":"flux-md@0.17.0","maintainers":[{"name":"siinghd","email":"szinghh@gmail.com"}],"homepage":"https://md.hsingh.app","bugs":{"url":"https://github.com/siinghd/flux-md/issues"},"dist":{"shasum":"7e9659cec482202f4070aab4703296bd8e60b599","tarball":"https://registry.npmjs.org/flux-md/-/flux-md-0.17.0.tgz","fileCount":50,"integrity":"sha512-bl+OjvquViMX9Bx0djJQ3eLpvnYc16/kJ8dLtWhQ1rPabLwgv+7V3VR5yh+GmhazB1xertaWCPbfHjbviBMwqg==","signatures":[{"sig":"MEUCIQDd5OdBR7M7AlyvNv+rnOD3B+nE5Lf56FkkTyEjHxSqtQIgVxUNQOgUW12/P8ut/t4ur72pehl14myB6I6yp4fX4WI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":460734},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./dom":{"types":"./dist/dom.d.ts","import":"./dist/dom.js"},"./vue":{"types":"./dist/vue.d.ts","import":"./dist/vue.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js"},"./solid":{"types":"./dist/solid.d.ts","import":"./dist/solid.js"},"./types":{"types":"./dist/types.d.ts","import":"./dist/types.js"},"./client":{"types":"./dist/client.d.ts","import":"./dist/client.js"},"./server":{"types":"./dist/server.d.ts","import":"./dist/server.js"},"./svelte":{"types":"./dist/svelte.d.ts","import":"./dist/svelte.js"},"./element":{"types":"./dist/element.d.ts","import":"./dist/element.js"},"./highlight":{"types":"./dist/hi.d.ts","import":"./dist/hi.js"},"./styles.css":"./dist/styles.css","./package.json":"./package.json"},"gitHead":"ac1a4266cab24c58cfc3485fd23f341a93dfab05","scripts":{"test":"bun test","build":"node scripts/build.mjs","test:ssr-cold":"bun test/ssr-cold.mjs","prepublishOnly":"cd ../.. && bun run build:wasm && cd packages/flux-md && node scripts/build.mjs","typecheck:test":"tsc --noEmit -p tsconfig.test.json","test:consumer-smoke":"bash test/consumer-smoke/run.sh"},"_npmUser":{"name":"siinghd","email":"szinghh@gmail.com"},"repository":{"url":"git+https://github.com/siinghd/flux-md.git","type":"git"},"_npmVersion":"11.11.0","description":"Zero-dep streaming markdown for the browser. Rust→WASM core, Web Worker per stream, incremental parse with speculative closure.","directories":{},"sideEffects":["./dist/worker.js","./dist/styles.css"],"_nodeVersion":"25.8.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","react":"^18.3.1","svelte":"^4.2.0","esbuild":"^0.28.1","solid-js":"^1.8.0","happy-dom":"^15.11.6","react-dom":"^18.3.1","@types/bun":"^1.3.14","typescript":"^5.6.3","@types/react":"^18.3.12","@types/react-dom":"^18.3.1"},"peerDependencies":{"vue":">=3","react":">=18","svelte":">=4","solid-js":"^1.8.0"},"peerDependenciesMeta":{"vue":{"optional":true},"react":{"optional":true},"svelte":{"optional":true},"solid-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/flux-md_0.17.0_1782584865376_0.0894770647919334","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package has been renamed to brookmd — same project, same API surface with Flux*→Brook* names. Install brookmd instead: https://github.com/siinghd/brookmd"},"0.18.0":{"name":"flux-md","version":"0.18.0","keywords":["markdown","streaming","wasm","rust","react","vue","svelte","solid","web-component","custom-element","incremental","llm","ai","math","katex","latex","bidi","rtl"],"license":"MIT","_id":"flux-md@0.18.0","maintainers":[{"name":"siinghd","email":"szinghh@gmail.com"}],"homepage":"https://md.hsingh.app","bugs":{"url":"https://github.com/siinghd/flux-md/issues"},"dist":{"shasum":"2d9d85f8a251e5fe8e61f8a1ea1c3a2f9ef72273","tarball":"https://registry.npmjs.org/flux-md/-/flux-md-0.18.0.tgz","fileCount":53,"integrity":"sha512-pBLg2yspVni111zmmrqzMvdF0PVP5hfZGFRAyNCErHbEzENef9qdkDJo6lII9LSJKnQQA0f2duK5WfZ+1pBIOA==","signatures":[{"sig":"MEUCIQCMagxdpbK4oBn0ZnFa3mCZpTXONawshkEkjqVLqLYFkgIgbJga5fJWQjOVZO1H3aFk89WvHJs3fjVY4fuTwer77DQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":515162},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./dom":{"types":"./dist/dom.d.ts","import":"./dist/dom.js"},"./vue":{"types":"./dist/vue.d.ts","import":"./dist/vue.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js"},"./solid":{"types":"./dist/solid.d.ts","import":"./dist/solid.js"},"./types":{"types":"./dist/types.d.ts","import":"./dist/types.js"},"./client":{"types":"./dist/client.d.ts","import":"./dist/client.js"},"./server":{"types":"./dist/server.d.ts","import":"./dist/server.js"},"./svelte":{"types":"./dist/svelte.d.ts","import":"./dist/svelte.js"},"./element":{"types":"./dist/element.d.ts","import":"./dist/element.js"},"./highlight":{"types":"./dist/hi.d.ts","import":"./dist/hi.js"},"./styles.css":"./dist/styles.css","./package.json":"./package.json","./server/react":{"types":"./dist/server-react.d.ts","import":"./dist/server-react.js"}},"gitHead":"deaf441113188b48ecc5208147f21b5f3363c307","scripts":{"test":"bun test","build":"node scripts/build.mjs","test:ssr-cold":"bun test/ssr-cold.mjs","prepublishOnly":"cd ../.. && bun run build:wasm && cd packages/flux-md && node scripts/build.mjs","typecheck:test":"tsc --noEmit -p tsconfig.test.json","test:consumer-smoke":"bash test/consumer-smoke/run.sh"},"_npmUser":{"name":"siinghd","email":"szinghh@gmail.com"},"repository":{"url":"git+https://github.com/siinghd/flux-md.git","type":"git"},"_npmVersion":"11.11.0","description":"Zero-dep streaming markdown for the browser. Rust→WASM core, Web Worker per stream, incremental parse with speculative closure.","directories":{},"sideEffects":["./dist/worker.js","./dist/styles.css"],"_nodeVersion":"25.8.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","react":"^18.3.1","svelte":"^4.2.0","esbuild":"^0.28.1","solid-js":"^1.8.0","happy-dom":"^15.11.6","react-dom":"^18.3.1","@types/bun":"^1.3.14","typescript":"^5.6.3","@types/react":"^18.3.12","@types/react-dom":"^18.3.1"},"peerDependencies":{"vue":">=3","react":">=18","svelte":">=4","solid-js":"^1.8.0"},"peerDependenciesMeta":{"vue":{"optional":true},"react":{"optional":true},"svelte":{"optional":true},"solid-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/flux-md_0.18.0_1782744831453_0.9321260882437621","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package has been renamed to brookmd — same project, same API surface with Flux*→Brook* names. Install brookmd instead: https://github.com/siinghd/brookmd"},"0.18.1":{"name":"flux-md","version":"0.18.1","keywords":["markdown","streaming","wasm","rust","react","vue","svelte","solid","web-component","custom-element","incremental","llm","ai","math","katex","latex","bidi","rtl"],"license":"MIT","_id":"flux-md@0.18.1","maintainers":[{"name":"siinghd","email":"szinghh@gmail.com"}],"homepage":"https://md.hsingh.app","bugs":{"url":"https://github.com/siinghd/flux-md/issues"},"dist":{"shasum":"f418b05b60e4f3f54050f3309f8821f9509bddce","tarball":"https://registry.npmjs.org/flux-md/-/flux-md-0.18.1.tgz","fileCount":53,"integrity":"sha512-b6CgS+9dGPnCtGfe33EQh76EriX+FVJVHGJ+ilBQsdqkAMDLnXvIPqAfpX+1D2Qjo/8m0riXcIYFWbzC+dbKCg==","signatures":[{"sig":"MEUCIQDXqZ2zazQfMf3t0ioBHCRnSAFCiqX2ucTHSj8a6qUhhgIgaINktL0EExw7LUlxQhHJpElv1PWEHWVFWz9veo7x98s=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":507293},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./dom":{"types":"./dist/dom.d.ts","import":"./dist/dom.js"},"./vue":{"types":"./dist/vue.d.ts","import":"./dist/vue.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js"},"./solid":{"types":"./dist/solid.d.ts","import":"./dist/solid.js"},"./types":{"types":"./dist/types.d.ts","import":"./dist/types.js"},"./client":{"types":"./dist/client.d.ts","import":"./dist/client.js"},"./server":{"types":"./dist/server.d.ts","import":"./dist/server.js"},"./svelte":{"types":"./dist/svelte.d.ts","import":"./dist/svelte.js"},"./element":{"types":"./dist/element.d.ts","import":"./dist/element.js"},"./highlight":{"types":"./dist/hi.d.ts","import":"./dist/hi.js"},"./styles.css":"./dist/styles.css","./package.json":"./package.json","./server/react":{"types":"./dist/server-react.d.ts","import":"./dist/server-react.js"}},"gitHead":"3d53c883e0c9c82f12b60f52b91d606974d69f21","scripts":{"test":"bun test","build":"node scripts/build.mjs","test:ssr-cold":"bun test/ssr-cold.mjs","prepublishOnly":"cd ../.. && bun run build:wasm && cd packages/flux-md && node scripts/build.mjs","typecheck:test":"tsc --noEmit -p tsconfig.test.json","test:consumer-smoke":"bash test/consumer-smoke/run.sh"},"_npmUser":{"name":"siinghd","email":"szinghh@gmail.com"},"repository":{"url":"git+https://github.com/siinghd/flux-md.git","type":"git"},"_npmVersion":"11.11.0","description":"Zero-dep streaming markdown for the browser. Rust→WASM core, Web Worker per stream, incremental parse with speculative closure.","directories":{},"sideEffects":["./dist/worker.js","./dist/styles.css"],"_nodeVersion":"25.8.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","react":"^18.3.1","svelte":"^4.2.0","esbuild":"^0.28.1","solid-js":"^1.8.0","happy-dom":"^15.11.6","react-dom":"^18.3.1","@types/bun":"^1.3.14","typescript":"^5.6.3","@types/react":"^18.3.12","@types/react-dom":"^18.3.1"},"peerDependencies":{"vue":">=3","react":">=18","svelte":">=4","solid-js":"^1.8.0"},"peerDependenciesMeta":{"vue":{"optional":true},"react":{"optional":true},"svelte":{"optional":true},"solid-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/flux-md_0.18.1_1782749157381_0.9647145041991461","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package has been renamed to brookmd — same project, same API surface with Flux*→Brook* names. Install brookmd instead: https://github.com/siinghd/brookmd"},"0.18.2":{"name":"flux-md","version":"0.18.2","keywords":["markdown","streaming","wasm","rust","react","vue","svelte","solid","web-component","custom-element","incremental","llm","ai","math","katex","latex","bidi","rtl"],"license":"MIT","_id":"flux-md@0.18.2","maintainers":[{"name":"siinghd","email":"szinghh@gmail.com"}],"homepage":"https://md.hsingh.app","bugs":{"url":"https://github.com/siinghd/flux-md/issues"},"dist":{"shasum":"221513d59955c79cdf452cd93af29192636714f3","tarball":"https://registry.npmjs.org/flux-md/-/flux-md-0.18.2.tgz","fileCount":53,"integrity":"sha512-4qpy7JlUDdwnkWYfUphIV+4SBkInI1xrQwJq9cCJOojCH5GlBxSdKTUSgidqN+gN7edjl52X2Sg5HQ3laEo8Ng==","signatures":[{"sig":"MEUCIF5q41oRkzZToU6SDyMvseGpnq0QE8dsmW4ArMPpX2jyAiEAsLUN80S6yc5UWyNDsxkpwPzozXjZi1V03QfZF3TVu90=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":508448},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./dom":{"types":"./dist/dom.d.ts","import":"./dist/dom.js"},"./vue":{"types":"./dist/vue.d.ts","import":"./dist/vue.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js"},"./solid":{"types":"./dist/solid.d.ts","import":"./dist/solid.js"},"./types":{"types":"./dist/types.d.ts","import":"./dist/types.js"},"./client":{"types":"./dist/client.d.ts","import":"./dist/client.js"},"./server":{"types":"./dist/server.d.ts","import":"./dist/server.js"},"./svelte":{"types":"./dist/svelte.d.ts","import":"./dist/svelte.js"},"./element":{"types":"./dist/element.d.ts","import":"./dist/element.js"},"./highlight":{"types":"./dist/hi.d.ts","import":"./dist/hi.js"},"./styles.css":"./dist/styles.css","./package.json":"./package.json","./server/react":{"types":"./dist/server-react.d.ts","import":"./dist/server-react.js"}},"gitHead":"4856bf10490810e399baf374a44aa2e71403d5f3","scripts":{"test":"bun test","build":"node scripts/build.mjs","test:ssr-cold":"bun test/ssr-cold.mjs","prepublishOnly":"cd ../.. && bun run build:wasm && cd packages/flux-md && node scripts/build.mjs","typecheck:test":"tsc --noEmit -p tsconfig.test.json","test:consumer-smoke":"bash test/consumer-smoke/run.sh"},"_npmUser":{"name":"siinghd","email":"szinghh@gmail.com"},"repository":{"url":"git+https://github.com/siinghd/flux-md.git","type":"git"},"_npmVersion":"11.11.0","description":"Zero-dep streaming markdown for the browser. Rust→WASM core, Web Worker per stream, incremental parse with speculative closure.","directories":{},"sideEffects":["./dist/worker.js","./dist/styles.css"],"_nodeVersion":"25.8.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","react":"^18.3.1","svelte":"^4.2.0","esbuild":"^0.28.1","solid-js":"^1.8.0","happy-dom":"^15.11.6","react-dom":"^18.3.1","@types/bun":"^1.3.14","typescript":"^5.6.3","@types/react":"^18.3.12","@types/react-dom":"^18.3.1"},"peerDependencies":{"vue":">=3","react":">=18","svelte":">=4","solid-js":"^1.8.0"},"peerDependenciesMeta":{"vue":{"optional":true},"react":{"optional":true},"svelte":{"optional":true},"solid-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/flux-md_0.18.2_1782750315697_0.854944641966173","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package has been renamed to brookmd — same project, same API surface with Flux*→Brook* names. Install brookmd instead: https://github.com/siinghd/brookmd"},"0.18.3":{"name":"flux-md","version":"0.18.3","keywords":["markdown","streaming","wasm","rust","react","vue","svelte","solid","web-component","custom-element","incremental","llm","ai","math","katex","latex","bidi","rtl"],"license":"MIT","_id":"flux-md@0.18.3","maintainers":[{"name":"siinghd","email":"szinghh@gmail.com"}],"homepage":"https://md.hsingh.app","bugs":{"url":"https://github.com/siinghd/flux-md/issues"},"dist":{"shasum":"0f7c07303cee6b1fa23d1d146df9b6e8306d3630","tarball":"https://registry.npmjs.org/flux-md/-/flux-md-0.18.3.tgz","fileCount":53,"integrity":"sha512-5Nzz6ihHQUG8wEuryiWK/fydg/KJ6A95gDoVDCbtrlw7+1vqRgxpqTFZXQ0mmR0tRi1lh6omA2KOSDxj80NqZg==","signatures":[{"sig":"MEUCIHe8iope6VQNuu7zP7/eyZlR2ZlBCbiIScZtoKyi/1rsAiEAhSlgferItw+4ez5m9f3T3UM66ShyCZYUilO6Qz3TdNU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":509437},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./dom":{"types":"./dist/dom.d.ts","import":"./dist/dom.js"},"./vue":{"types":"./dist/vue.d.ts","import":"./dist/vue.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js"},"./solid":{"types":"./dist/solid.d.ts","import":"./dist/solid.js"},"./types":{"types":"./dist/types.d.ts","import":"./dist/types.js"},"./client":{"types":"./dist/client.d.ts","import":"./dist/client.js"},"./server":{"types":"./dist/server.d.ts","import":"./dist/server.js"},"./svelte":{"types":"./dist/svelte.d.ts","import":"./dist/svelte.js"},"./element":{"types":"./dist/element.d.ts","import":"./dist/element.js"},"./highlight":{"types":"./dist/hi.d.ts","import":"./dist/hi.js"},"./styles.css":"./dist/styles.css","./package.json":"./package.json","./server/react":{"types":"./dist/server-react.d.ts","import":"./dist/server-react.js"}},"gitHead":"07621f86b81d17d58e6310614860d93203e77273","scripts":{"test":"bun test","build":"node scripts/build.mjs","test:ssr-cold":"bun test/ssr-cold.mjs","prepublishOnly":"cd ../.. && bun run build:wasm && cd packages/flux-md && node scripts/build.mjs","typecheck:test":"tsc --noEmit -p tsconfig.test.json","test:consumer-smoke":"bash test/consumer-smoke/run.sh"},"_npmUser":{"name":"siinghd","email":"szinghh@gmail.com"},"repository":{"url":"git+https://github.com/siinghd/flux-md.git","type":"git"},"_npmVersion":"11.11.0","description":"Zero-dep streaming markdown for the browser. Rust→WASM core, Web Worker per stream, incremental parse with speculative closure.","directories":{},"sideEffects":["./dist/worker.js","./dist/styles.css"],"_nodeVersion":"25.8.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","react":"^18.3.1","svelte":"^4.2.0","esbuild":"^0.28.1","solid-js":"^1.8.0","happy-dom":"^15.11.6","react-dom":"^18.3.1","@types/bun":"^1.3.14","typescript":"^5.6.3","@types/react":"^18.3.12","@types/react-dom":"^18.3.1"},"peerDependencies":{"vue":">=3","react":">=18","svelte":">=4","solid-js":"^1.8.0"},"peerDependenciesMeta":{"vue":{"optional":true},"react":{"optional":true},"svelte":{"optional":true},"solid-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/flux-md_0.18.3_1782759406728_0.4017017454198888","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package has been renamed to brookmd — same project, same API surface with Flux*→Brook* names. Install brookmd instead: https://github.com/siinghd/brookmd"},"0.18.4":{"name":"flux-md","version":"0.18.4","keywords":["markdown","streaming","wasm","rust","react","vue","svelte","solid","web-component","custom-element","incremental","llm","ai","math","katex","latex","bidi","rtl"],"license":"MIT","_id":"flux-md@0.18.4","maintainers":[{"name":"siinghd","email":"szinghh@gmail.com"}],"homepage":"https://md.hsingh.app","bugs":{"url":"https://github.com/siinghd/flux-md/issues"},"dist":{"shasum":"0247c25d4b3fa1cd04e19303acfd189ef9cc1acc","tarball":"https://registry.npmjs.org/flux-md/-/flux-md-0.18.4.tgz","fileCount":53,"integrity":"sha512-Xwr6YUlJoQ7qVg3RA1nc4dc8SazTLcZbpgewPXn4JPuVWLvQ15m+iYMJLS7Gr+oR0owarWf4ACvAQt8Ob+soCw==","signatures":[{"sig":"MEUCIQDrP+LFD/7rD3sXoEjF85fhU9VJg4ned3C1bgdBuRZxaQIgbXkuaPUFgL0pgoT81dWLoTSB88EIjitqNBldMMpkMd0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":511040},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./dom":{"types":"./dist/dom.d.ts","import":"./dist/dom.js"},"./vue":{"types":"./dist/vue.d.ts","import":"./dist/vue.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js"},"./solid":{"types":"./dist/solid.d.ts","import":"./dist/solid.js"},"./types":{"types":"./dist/types.d.ts","import":"./dist/types.js"},"./client":{"types":"./dist/client.d.ts","import":"./dist/client.js"},"./server":{"types":"./dist/server.d.ts","import":"./dist/server.js"},"./svelte":{"types":"./dist/svelte.d.ts","import":"./dist/svelte.js"},"./element":{"types":"./dist/element.d.ts","import":"./dist/element.js"},"./highlight":{"types":"./dist/hi.d.ts","import":"./dist/hi.js"},"./styles.css":"./dist/styles.css","./package.json":"./package.json","./server/react":{"types":"./dist/server-react.d.ts","import":"./dist/server-react.js"}},"gitHead":"878d39bb2f069475d8bb1e7f9feb6b1c7701184c","scripts":{"test":"bun test","build":"node scripts/build.mjs","test:ssr-cold":"bun test/ssr-cold.mjs","prepublishOnly":"cd ../.. && bun run build:wasm && cd packages/flux-md && node scripts/build.mjs","typecheck:test":"tsc --noEmit -p tsconfig.test.json","test:consumer-smoke":"bash test/consumer-smoke/run.sh"},"_npmUser":{"name":"siinghd","email":"szinghh@gmail.com"},"repository":{"url":"git+https://github.com/siinghd/flux-md.git","type":"git"},"_npmVersion":"11.11.0","description":"Zero-dep streaming markdown for the browser. Rust→WASM core, Web Worker per stream, incremental parse with speculative closure.","directories":{},"sideEffects":["./dist/worker.js","./dist/styles.css"],"_nodeVersion":"25.8.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","react":"^18.3.1","svelte":"^4.2.0","esbuild":"^0.28.1","solid-js":"^1.8.0","happy-dom":"^15.11.6","react-dom":"^18.3.1","@types/bun":"^1.3.14","typescript":"^5.6.3","@types/react":"^18.3.12","@types/react-dom":"^18.3.1"},"peerDependencies":{"vue":">=3","react":">=18","svelte":">=4","solid-js":"^1.8.0"},"peerDependenciesMeta":{"vue":{"optional":true},"react":{"optional":true},"svelte":{"optional":true},"solid-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/flux-md_0.18.4_1782761741696_0.8170897686058649","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package has been renamed to brookmd — same project, same API surface with Flux*→Brook* names. Install brookmd instead: https://github.com/siinghd/brookmd"},"0.19.0":{"name":"flux-md","version":"0.19.0","keywords":["markdown","streaming","wasm","rust","react","vue","svelte","solid","web-component","custom-element","incremental","llm","ai","math","katex","latex","bidi","rtl"],"license":"MIT","_id":"flux-md@0.19.0","maintainers":[{"name":"siinghd","email":"szinghh@gmail.com"}],"homepage":"https://md.hsingh.app","bugs":{"url":"https://github.com/siinghd/flux-md/issues"},"dist":{"shasum":"ac06510fb0b6bb48c08d3a026f74de1d25ad7291","tarball":"https://registry.npmjs.org/flux-md/-/flux-md-0.19.0.tgz","fileCount":57,"integrity":"sha512-g+BP2zKk+kbAwCRbtNv6UZecnM8FNRAfWHHr3rfHemccnGYQmbVQcREo3laTxiV/3lgBoztcxlugIcceEE9DLQ==","signatures":[{"sig":"MEQCIHw28w6UnpBHlsVEMs5hxlML8hSkDVCO2diXlZzb71avAiAdH9AqyNx+MABcQQbZwcnKP2bdnWfU51840mFOfR5MTw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":535279},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./dom":{"types":"./dist/dom.d.ts","import":"./dist/dom.js"},"./vue":{"types":"./dist/vue.d.ts","import":"./dist/vue.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js"},"./solid":{"types":"./dist/solid.d.ts","import":"./dist/solid.js"},"./types":{"types":"./dist/types.d.ts","import":"./dist/types.js"},"./client":{"types":"./dist/client.d.ts","import":"./dist/client.js"},"./server":{"types":"./dist/server.d.ts","import":"./dist/server.js"},"./svelte":{"types":"./dist/svelte.d.ts","import":"./dist/svelte.js"},"./element":{"types":"./dist/element.d.ts","import":"./dist/element.js"},"./highlight":{"types":"./dist/hi.d.ts","import":"./dist/hi.js"},"./styles.css":"./dist/styles.css","./package.json":"./package.json","./server/react":{"types":"./dist/server-react.d.ts","import":"./dist/server-react.js"}},"gitHead":"5ad7364451e7e3266e00e99fc7326905c1f6905a","scripts":{"test":"bun test","build":"node scripts/build.mjs","test:ssr-cold":"bun test/ssr-cold.mjs","prepublishOnly":"cd ../.. && bun run build:wasm && cd packages/flux-md && node scripts/build.mjs","typecheck:test":"tsc --noEmit -p tsconfig.test.json","test:consumer-smoke":"bash test/consumer-smoke/run.sh"},"_npmUser":{"name":"siinghd","email":"szinghh@gmail.com"},"repository":{"url":"git+https://github.com/siinghd/flux-md.git","type":"git"},"_npmVersion":"11.11.0","description":"Zero-dep streaming markdown for the browser. Rust→WASM core, Web Worker per stream, incremental parse with speculative closure.","directories":{},"sideEffects":["./dist/worker.js","./dist/styles.css"],"_nodeVersion":"25.8.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","react":"^18.3.1","svelte":"^4.2.0","esbuild":"^0.28.1","solid-js":"^1.8.0","happy-dom":"^15.11.6","react-dom":"^18.3.1","@types/bun":"^1.3.14","typescript":"^5.6.3","@types/react":"^18.3.12","@types/react-dom":"^18.3.1"},"peerDependencies":{"vue":">=3","react":">=18","svelte":">=4","solid-js":"^1.8.0"},"peerDependenciesMeta":{"vue":{"optional":true},"react":{"optional":true},"svelte":{"optional":true},"solid-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/flux-md_0.19.0_1782827733609_0.22431408405469688","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package has been renamed to brookmd — same project, same API surface with Flux*→Brook* names. Install brookmd instead: https://github.com/siinghd/brookmd"},"0.20.0":{"name":"flux-md","version":"0.20.0","keywords":["markdown","streaming","wasm","rust","react","vue","svelte","solid","web-component","custom-element","incremental","llm","ai","math","katex","latex","bidi","rtl"],"license":"MIT","_id":"flux-md@0.20.0","maintainers":[{"name":"siinghd","email":"szinghh@gmail.com"}],"homepage":"https://md.hsingh.app","bugs":{"url":"https://github.com/siinghd/flux-md/issues"},"dist":{"shasum":"3b58baf5dece5d7e07a502104a573c0fe2b87344","tarball":"https://registry.npmjs.org/flux-md/-/flux-md-0.20.0.tgz","fileCount":57,"integrity":"sha512-QwqLcQDT0il42PUSV/AcPZdPLPsjY9+crUrg6DdyDsDyensgLnefzDURz2VuOL2I8A1OdVNcD2wFW+ckppMBwQ==","signatures":[{"sig":"MEQCIBo+neifSwPW7GDR2lOnIEUXoWsufg/P1vKOgPIEsIbLAiA+g2CrXNPkTmGW7q8VkbFhXf0iSwrNLyYzOQER0MezGg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":571543},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./dom":{"types":"./dist/dom.d.ts","import":"./dist/dom.js"},"./vue":{"types":"./dist/vue.d.ts","import":"./dist/vue.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js"},"./solid":{"types":"./dist/solid.d.ts","import":"./dist/solid.js"},"./types":{"types":"./dist/types.d.ts","import":"./dist/types.js"},"./client":{"types":"./dist/client.d.ts","import":"./dist/client.js"},"./server":{"types":"./dist/server.d.ts","import":"./dist/server.js"},"./svelte":{"types":"./dist/svelte.d.ts","import":"./dist/svelte.js"},"./element":{"types":"./dist/element.d.ts","import":"./dist/element.js"},"./highlight":{"types":"./dist/hi.d.ts","import":"./dist/hi.js"},"./styles.css":"./dist/styles.css","./package.json":"./package.json","./server/react":{"types":"./dist/server-react.d.ts","import":"./dist/server-react.js"}},"gitHead":"b3ac231889f40fc103a48831c8949484c82195fe","scripts":{"test":"bun test","build":"node scripts/build.mjs","test:ssr-cold":"bun test/ssr-cold.mjs","prepublishOnly":"cd ../.. && bun run build:wasm && cd packages/flux-md && node scripts/build.mjs","typecheck:test":"tsc --noEmit -p tsconfig.test.json","test:consumer-smoke":"bash test/consumer-smoke/run.sh"},"_npmUser":{"name":"siinghd","email":"szinghh@gmail.com"},"repository":{"url":"git+https://github.com/siinghd/flux-md.git","type":"git"},"_npmVersion":"11.11.0","description":"Zero-dep streaming markdown for the browser. Rust→WASM core, Web Worker per stream, incremental parse with speculative closure.","directories":{},"sideEffects":["./dist/worker.js","./dist/styles.css"],"_nodeVersion":"25.8.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","react":"^18.3.1","svelte":"^4.2.0","esbuild":"^0.28.1","solid-js":"^1.8.0","happy-dom":"^15.11.6","react-dom":"^18.3.1","@types/bun":"^1.3.14","typescript":"^5.6.3","@types/react":"^18.3.12","@types/react-dom":"^18.3.1"},"peerDependencies":{"vue":">=3","react":">=18","svelte":">=4","solid-js":"^1.8.0"},"peerDependenciesMeta":{"vue":{"optional":true},"react":{"optional":true},"svelte":{"optional":true},"solid-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/flux-md_0.20.0_1783011284228_0.032707915314796","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package has been renamed to brookmd — same project, same API surface with Flux*→Brook* names. Install brookmd instead: https://github.com/siinghd/brookmd"},"0.20.1":{"name":"flux-md","version":"0.20.1","keywords":["markdown","streaming","wasm","rust","react","vue","svelte","solid","web-component","custom-element","incremental","llm","ai","math","katex","latex","bidi","rtl"],"license":"MIT","_id":"flux-md@0.20.1","maintainers":[{"name":"siinghd","email":"szinghh@gmail.com"}],"homepage":"https://md.hsingh.app","bugs":{"url":"https://github.com/siinghd/flux-md/issues"},"dist":{"shasum":"b8290eb95c5f85803c5aaf59add0c3dc2ae7b39f","tarball":"https://registry.npmjs.org/flux-md/-/flux-md-0.20.1.tgz","fileCount":57,"integrity":"sha512-93CNLtVylNmTXA0j5/e5dIU9IMCKWJsFj0RKZl325JgZQjKJ6YSOHo7CDqYLyOT2nEjzZSlHreFQgGx+uE+FtA==","signatures":[{"sig":"MEUCIDQ9Ggm2SYxICj5CaG4b8a+D98Uq5eUl0SSIBR8EcSDiAiEA5masUJuhPBDDR2BMoeSCpN4fewaQCwgLrMJpdJa3YsU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":582323},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./dom":{"types":"./dist/dom.d.ts","import":"./dist/dom.js"},"./vue":{"types":"./dist/vue.d.ts","import":"./dist/vue.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js"},"./solid":{"types":"./dist/solid.d.ts","import":"./dist/solid.js"},"./types":{"types":"./dist/types.d.ts","import":"./dist/types.js"},"./client":{"types":"./dist/client.d.ts","import":"./dist/client.js"},"./server":{"types":"./dist/server.d.ts","import":"./dist/server.js"},"./svelte":{"types":"./dist/svelte.d.ts","import":"./dist/svelte.js"},"./element":{"types":"./dist/element.d.ts","import":"./dist/element.js"},"./highlight":{"types":"./dist/hi.d.ts","import":"./dist/hi.js"},"./styles.css":"./dist/styles.css","./package.json":"./package.json","./server/react":{"types":"./dist/server-react.d.ts","import":"./dist/server-react.js"}},"gitHead":"f4ee3c8e51317d4fb149b3f89fd5239054669d03","scripts":{"test":"bun test","build":"node scripts/build.mjs","test:ssr-cold":"bun test/ssr-cold.mjs","prepublishOnly":"cd ../.. && bun run build:wasm && cd packages/flux-md && node scripts/build.mjs","typecheck:test":"tsc --noEmit -p tsconfig.test.json","test:consumer-smoke":"bash test/consumer-smoke/run.sh"},"_npmUser":{"name":"siinghd","email":"szinghh@gmail.com"},"repository":{"url":"git+https://github.com/siinghd/flux-md.git","type":"git"},"_npmVersion":"11.11.0","description":"Zero-dep streaming markdown for the browser. Rust→WASM core, Web Worker per stream, incremental parse with speculative closure.","directories":{},"sideEffects":["./dist/worker.js","./dist/styles.css"],"_nodeVersion":"25.8.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","react":"^18.3.1","svelte":"^4.2.0","esbuild":"^0.28.1","solid-js":"^1.8.0","happy-dom":"^15.11.6","react-dom":"^18.3.1","@types/bun":"^1.3.14","typescript":"^5.6.3","@types/react":"^18.3.12","@types/react-dom":"^18.3.1"},"peerDependencies":{"vue":">=3","react":">=18","svelte":">=4","solid-js":"^1.8.0"},"peerDependenciesMeta":{"vue":{"optional":true},"react":{"optional":true},"svelte":{"optional":true},"solid-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/flux-md_0.20.1_1784083912141_0.1735994171068489","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package has been renamed to brookmd — same project, same API surface with Flux*→Brook* names. Install brookmd instead: https://github.com/siinghd/brookmd"},"0.20.2":{"name":"flux-md","version":"0.20.2","keywords":["markdown","streaming","wasm","rust","react","vue","svelte","solid","web-component","custom-element","incremental","llm","ai","math","katex","latex","bidi","rtl"],"license":"MIT","_id":"flux-md@0.20.2","maintainers":[{"name":"siinghd","email":"szinghh@gmail.com"}],"homepage":"https://md.hsingh.app","bugs":{"url":"https://github.com/siinghd/flux-md/issues"},"dist":{"shasum":"04fdd5442a5936426255a26dba3dd2deed952250","tarball":"https://registry.npmjs.org/flux-md/-/flux-md-0.20.2.tgz","fileCount":57,"integrity":"sha512-1uXvdIOxUfb0QroYExNqrQl/Ix4pQwLtdKf4NMcNc8p86DpzdJmiVDXCyay7QfQ+ckOiJ4rJQ0MCUt7sVVgzYg==","signatures":[{"sig":"MEYCIQDdSiVxmFrGjoJ6rqQu0e3Yr9KwpmiindJDkjzZNPZdcgIhAILTbWDY00BA8Y9zawZzWa3BKGtw9GGEud5J4Ol7L9s+","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":583081},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./dom":{"types":"./dist/dom.d.ts","import":"./dist/dom.js"},"./vue":{"types":"./dist/vue.d.ts","import":"./dist/vue.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js"},"./solid":{"types":"./dist/solid.d.ts","import":"./dist/solid.js"},"./types":{"types":"./dist/types.d.ts","import":"./dist/types.js"},"./client":{"types":"./dist/client.d.ts","import":"./dist/client.js"},"./server":{"types":"./dist/server.d.ts","import":"./dist/server.js"},"./svelte":{"types":"./dist/svelte.d.ts","import":"./dist/svelte.js"},"./element":{"types":"./dist/element.d.ts","import":"./dist/element.js"},"./highlight":{"types":"./dist/hi.d.ts","import":"./dist/hi.js"},"./styles.css":"./dist/styles.css","./package.json":"./package.json","./server/react":{"types":"./dist/server-react.d.ts","import":"./dist/server-react.js"}},"gitHead":"c16d6637b2bfae9c4d5c1fcb04a156a1f330422f","scripts":{"test":"bun test","build":"node scripts/build.mjs","test:ssr-cold":"bun test/ssr-cold.mjs","prepublishOnly":"cd ../.. && bun run build:wasm && cd packages/flux-md && node scripts/build.mjs","typecheck:test":"tsc --noEmit -p tsconfig.test.json","test:consumer-smoke":"bash test/consumer-smoke/run.sh"},"_npmUser":{"name":"siinghd","email":"szinghh@gmail.com"},"repository":{"url":"git+https://github.com/siinghd/flux-md.git","type":"git"},"_npmVersion":"11.11.0","description":"Zero-dep streaming markdown for the browser. Rust→WASM core, Web Worker per stream, incremental parse with speculative closure.","directories":{},"sideEffects":["./dist/worker.js","./dist/styles.css"],"_nodeVersion":"25.8.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","react":"^18.3.1","svelte":"^4.2.0","esbuild":"^0.28.1","solid-js":"^1.8.0","happy-dom":"^15.11.6","react-dom":"^18.3.1","@types/bun":"^1.3.14","typescript":"^5.6.3","@types/react":"^18.3.12","@types/react-dom":"^18.3.1"},"peerDependencies":{"vue":">=3","react":">=18","svelte":">=4","solid-js":"^1.8.0"},"peerDependenciesMeta":{"vue":{"optional":true},"react":{"optional":true},"svelte":{"optional":true},"solid-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/flux-md_0.20.2_1784084742311_0.5521830505322982","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package has been renamed to brookmd — same project, same API surface with Flux*→Brook* names. Install brookmd instead: https://github.com/siinghd/brookmd"},"0.20.3":{"name":"flux-md","version":"0.20.3","keywords":["markdown","streaming","wasm","rust","react","vue","svelte","solid","web-component","custom-element","incremental","llm","ai","math","katex","latex","bidi","rtl"],"license":"MIT","_id":"flux-md@0.20.3","maintainers":[{"name":"siinghd","email":"szinghh@gmail.com"}],"homepage":"https://md.hsingh.app","bugs":{"url":"https://github.com/siinghd/flux-md/issues"},"dist":{"shasum":"697b1db3a952df956b2743f7ee7b9b7aa4b0cd64","tarball":"https://registry.npmjs.org/flux-md/-/flux-md-0.20.3.tgz","fileCount":57,"integrity":"sha512-2vEZ5hfMAdbTg+aP1zu8DkObbT7tIF0xabLiP+AJEpjEuO3GK12t2FAyEuht1NxPOURbFOdc4iDBSr/CNPaWZA==","signatures":[{"sig":"MEUCIELrpUZMwf2Mscye9wh2KrTVau0GBDCv5WY0xbgMuJtOAiEArHViqWjghz58GSsewhigfspOiT6mpns4Ac2HdSn52Gk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":585343},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./dom":{"types":"./dist/dom.d.ts","import":"./dist/dom.js"},"./vue":{"types":"./dist/vue.d.ts","import":"./dist/vue.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js"},"./solid":{"types":"./dist/solid.d.ts","import":"./dist/solid.js"},"./types":{"types":"./dist/types.d.ts","import":"./dist/types.js"},"./client":{"types":"./dist/client.d.ts","import":"./dist/client.js"},"./server":{"types":"./dist/server.d.ts","import":"./dist/server.js"},"./svelte":{"types":"./dist/svelte.d.ts","import":"./dist/svelte.js"},"./element":{"types":"./dist/element.d.ts","import":"./dist/element.js"},"./highlight":{"types":"./dist/hi.d.ts","import":"./dist/hi.js"},"./styles.css":"./dist/styles.css","./package.json":"./package.json","./server/react":{"types":"./dist/server-react.d.ts","import":"./dist/server-react.js"}},"gitHead":"bf308d338c7e2c55183bac856c7e2fd605047c02","scripts":{"test":"bun test","build":"node scripts/build.mjs","test:ssr-cold":"bun test/ssr-cold.mjs","prepublishOnly":"cd ../.. && bun run build:wasm && cd packages/flux-md && node scripts/build.mjs","typecheck:test":"tsc --noEmit -p tsconfig.test.json","test:consumer-smoke":"bash test/consumer-smoke/run.sh"},"_npmUser":{"name":"siinghd","email":"szinghh@gmail.com"},"repository":{"url":"git+https://github.com/siinghd/flux-md.git","type":"git"},"_npmVersion":"11.11.0","description":"Zero-dep streaming markdown for the browser. Rust→WASM core, Web Worker per stream, incremental parse with speculative closure.","directories":{},"sideEffects":["./dist/worker.js","./dist/styles.css"],"_nodeVersion":"25.8.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","react":"^18.3.1","svelte":"^4.2.0","esbuild":"^0.28.1","solid-js":"^1.8.0","happy-dom":"^15.11.6","react-dom":"^18.3.1","@types/bun":"^1.3.14","typescript":"^5.6.3","@types/react":"^18.3.12","@types/react-dom":"^18.3.1"},"peerDependencies":{"vue":">=3","react":">=18","svelte":">=4","solid-js":"^1.8.0"},"peerDependenciesMeta":{"vue":{"optional":true},"react":{"optional":true},"svelte":{"optional":true},"solid-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/flux-md_0.20.3_1784122790170_0.7694672150281892","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package has been renamed to brookmd — same project, same API surface with Flux*→Brook* names. Install brookmd instead: https://github.com/siinghd/brookmd"},"0.21.0":{"name":"flux-md","version":"0.21.0","keywords":["markdown","streaming","wasm","rust","react","vue","svelte","solid","web-component","custom-element","incremental","llm","ai","math","katex","latex","bidi","rtl"],"license":"MIT","_id":"flux-md@0.21.0","maintainers":[{"name":"siinghd","email":"szinghh@gmail.com"}],"homepage":"https://md.hsingh.app","bugs":{"url":"https://github.com/siinghd/flux-md/issues"},"dist":{"shasum":"bb33c1d28ef78f8c264f604710b1ca1392e9958b","tarball":"https://registry.npmjs.org/flux-md/-/flux-md-0.21.0.tgz","fileCount":59,"integrity":"sha512-sy92xw3LXj7/48Qq4T7BPvP/pBz3Z3I5obbHooerSYCuF4tvjPhoe4MZKlzPPzg98AMQvde/d3uUSHTKJbGRew==","signatures":[{"sig":"MEYCIQCl6ODWiOe1utTrF1ZsaUaDcQEiuLThbBjRflGKnXQsegIhAOyYiY5NqQ2ZWU1eS6W+QXvsDKWzo0TU4KITxSmp6f+p","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":599259},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./dom":{"types":"./dist/dom.d.ts","import":"./dist/dom.js"},"./vue":{"types":"./dist/vue.d.ts","import":"./dist/vue.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js"},"./solid":{"types":"./dist/solid.d.ts","import":"./dist/solid.js"},"./types":{"types":"./dist/types.d.ts","import":"./dist/types.js"},"./client":{"types":"./dist/client.d.ts","import":"./dist/client.js"},"./server":{"types":"./dist/server.d.ts","import":"./dist/server.js"},"./svelte":{"types":"./dist/svelte.d.ts","import":"./dist/svelte.js"},"./element":{"types":"./dist/element.d.ts","import":"./dist/element.js"},"./highlight":{"types":"./dist/hi.d.ts","import":"./dist/hi.js"},"./styles.css":"./dist/styles.css","./block-props":{"types":"./dist/block-props.d.ts","import":"./dist/block-props.js"},"./worker-core":{"types":"./dist/worker-core.d.ts","import":"./dist/worker-core.js"},"./package.json":"./package.json","./server/react":{"types":"./dist/server-react.d.ts","import":"./dist/server-react.js"},"./html-to-react":{"types":"./dist/html-to-react.d.ts","import":"./dist/html-to-react.js"}},"gitHead":"1a5fca43d8c3f4237f561ae781f55737ca0f2456","scripts":{"test":"bun test","build":"node scripts/build.mjs","test:ssr-cold":"bun test/ssr-cold.mjs","prepublishOnly":"cd ../.. && bun run build:wasm && cd packages/flux-md && node scripts/build.mjs","typecheck:test":"tsc --noEmit -p tsconfig.test.json","test:consumer-smoke":"bash test/consumer-smoke/run.sh"},"_npmUser":{"name":"siinghd","email":"szinghh@gmail.com"},"repository":{"url":"git+https://github.com/siinghd/flux-md.git","type":"git"},"_npmVersion":"11.11.0","description":"Zero-dep streaming markdown for the browser. Rust→WASM core, Web Worker per stream, incremental parse with speculative closure.","directories":{},"sideEffects":["./dist/worker.js","./dist/styles.css"],"_nodeVersion":"25.8.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","react":"^18.3.1","svelte":"^4.2.0","esbuild":"^0.28.1","solid-js":"^1.8.0","happy-dom":"^15.11.6","react-dom":"^18.3.1","@types/bun":"^1.3.14","typescript":"^5.6.3","@types/react":"^18.3.12","@types/react-dom":"^18.3.1"},"peerDependencies":{"vue":">=3","react":">=18","svelte":">=4","solid-js":"^1.8.0"},"peerDependenciesMeta":{"vue":{"optional":true},"react":{"optional":true},"svelte":{"optional":true},"solid-js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/flux-md_0.21.0_1784573009029_0.7696530703193618","host":"s3://npm-registry-packages-npm-production"},"deprecated":"This package has been renamed to brookmd — same project, same API surface with Flux*→Brook* names. Install brookmd instead: https://github.com/siinghd/brookmd"}},"time":{"created":"2026-05-27T13:37:26.430Z","modified":"2026-07-20T20:41:56.128Z","0.3.1":"2026-05-27T13:37:26.707Z","0.3.2":"2026-05-27T14:02:46.401Z","0.4.0":"2026-05-27T18:40:27.523Z","0.5.0":"2026-05-27T20:36:38.428Z","0.5.1":"2026-05-27T20:52:54.200Z","0.5.5":"2026-05-28T16:19:33.006Z","0.6.0":"2026-05-28T19:11:09.211Z","0.7.0":"2026-05-29T18:36:06.443Z","0.8.0":"2026-05-29T19:38:59.879Z","0.9.0":"2026-05-29T21:06:14.241Z","0.10.0":"2026-05-30T17:07:52.174Z","0.11.0":"2026-05-30T19:38:52.502Z","0.12.0":"2026-05-30T21:32:14.657Z","0.13.0":"2026-06-04T16:31:45.406Z","0.14.0":"2026-06-17T15:32:24.119Z","0.15.0":"2026-06-17T18:14:06.998Z","0.15.1":"2026-06-23T13:48:48.499Z","0.16.0":"2026-06-25T14:36:42.301Z","0.16.1":"2026-06-25T21:31:42.742Z","0.16.2":"2026-06-26T04:18:27.053Z","0.17.0":"2026-06-27T18:27:45.528Z","0.18.0":"2026-06-29T14:53:51.681Z","0.18.1":"2026-06-29T16:05:57.575Z","0.18.2":"2026-06-29T16:25:15.900Z","0.18.3":"2026-06-29T18:56:46.907Z","0.18.4":"2026-06-29T19:35:41.907Z","0.19.0":"2026-06-30T13:55:33.806Z","0.20.0":"2026-07-02T16:54:44.445Z","0.20.1":"2026-07-15T02:51:52.376Z","0.20.2":"2026-07-15T03:05:42.504Z","0.20.3":"2026-07-15T13:39:50.341Z","0.21.0":"2026-07-20T18:43:29.212Z"},"bugs":{"url":"https://github.com/siinghd/flux-md/issues"},"license":"MIT","homepage":"https://md.hsingh.app","keywords":["markdown","streaming","wasm","rust","react","vue","svelte","solid","web-component","custom-element","incremental","llm","ai","math","katex","latex","bidi","rtl"],"repository":{"url":"git+https://github.com/siinghd/flux-md.git","type":"git"},"description":"Zero-dep streaming markdown for the browser. Rust→WASM core, Web Worker per stream, incremental parse with speculative closure.","maintainers":[{"name":"siinghd","email":"szinghh@gmail.com"}],"readme":"# flux-md\n\nZero-dep streaming markdown for the browser. Rust→WASM core, one Web Worker per stream, incremental parse with speculative closure for mid-stream constructs.\n\nDrop in a streaming-aware renderer — **React, Vue, Svelte, Solid, a framework-agnostic `<flux-markdown>` Web Component, or the vanilla DOM mount** — wire each LLM stream to a `FluxClient`, and the markdown renders incrementally off the main thread, block by block, with stable identities so unchanged blocks never re-reconcile.\n\nParsing runs entirely **off the main thread** — each stream gets its own pooled Web Worker, so many concurrent LLM responses render without contending for the UI thread. On each token the parser re-parses only the **active tail**, not the whole document, and heavy renderers (syntax highlighting, math, mermaid) are **deferred until a block closes**. The result is low retained memory and a main thread that stays responsive while streaming. See [the live demo](https://md.hsingh.app/).\n\n## Install\n\n```bash\nbun add flux-md     # or: npm i flux-md / pnpm add flux-md\n```\n\nflux-md ships **compiled, non-minified ESM** (`dist/*.js` + `.d.ts` types) plus\nthe compiled WASM — no raw `.ts`/`.tsx` source. The worker and WASM asset are\nreferenced with the **web-standard `new URL(asset,\nimport.meta.url)`** pattern, so any bundler with asset-module support resolves\nthem: **Vite** (the reference setup), **webpack 5**, **Rollup** (with asset\nmodules), **Parcel**, and **Next.js** (App Router — Turbopack *and* webpack;\n**verified on Next.js 16**, see the [Next.js callout](#nextjs) below).\n\nThe streaming client (`<FluxMarkdown>` / `FluxClient`) is **browser-only** (it\nconstructs Web Workers). For **server-side / static rendering of finished\ncontent** — SSR, React Server Components, build steps — use the worker-free,\nsynchronous [`flux-md/server`](#server-side-rendering) entry. The framework packages — `react`,\n`vue`, `svelte`, `solid-js` — are all **optional** peer dependencies; you only\nneed the one whose binding you import. The framework-free entries\n(`flux-md/client`, `flux-md/dom`, `flux-md/element`, and `flux-md/server`) need\nnone. (The bare `flux-md` entry re-exports the React component surface, so it\npulls `react` — import from `flux-md/client` if you want a framework-free core.)\n\n> **Vite — one-line config.** Vite's dependency pre-bundling (esbuild) hoists\n> the wasm-bindgen glue into `.vite/deps/`, which breaks the relative\n> `new URL(\"…_bg.wasm\", import.meta.url)` lookup so the worker can't load WASM\n> (you'll see a 404 / \"magic word\" error). Exclude flux-md from pre-bundling:\n>\n> ```ts\n> // vite.config.ts\n> export default defineConfig({\n>   optimizeDeps: { exclude: [\"flux-md\"] },\n> });\n> ```\n>\n> No other bundler needs this — it's specific to Vite's optimizer.\n\n<a id=\"nextjs\"></a>\n\n> **Next.js (App Router) — one requirement.** Works on **Next.js** with\n> **Turbopack** (the default for both `next dev` and `next build`) or webpack.\n> Since 0.17.0 flux-md ships **compiled ESM**, so **no `transpilePackages` or\n> other build config is needed** — earlier versions required it only because the\n> package shipped raw TypeScript, which Next does not compile inside\n> `node_modules`. That no longer applies.\n>\n> **Use it from a Client Component.** `<FluxMarkdown>` uses React hooks (and\n> spawns a Web Worker on mount), so it must carry `\"use client\"` — it can't be\n> a Server Component. (It is still SSR-safe: on the server it renders an empty\n> shell and only starts streaming after hydration, so there's no SSR crash —\n> the constraint is hooks, not the worker.)\n>\n> ```tsx\n> \"use client\";\n> import { FluxMarkdown } from \"flux-md/react\";\n>\n> export default function Answer({ stream }: { stream: AsyncIterable<string> }) {\n>   return <FluxMarkdown stream={stream} />;\n> }\n> ```\n>\n> **Create the `stream` in Client Component code, not in a Server Component.**\n> A `Response` / `ReadableStream` / `AsyncIterable` isn't serializable, so it\n> can't be passed as a prop from a Server Component (e.g. `page.tsx`) — that\n> throws *\"Only plain objects can be passed to Client Components.\"* Pass a\n> serializable prop (a URL, the chat messages) from the server and open the\n> stream on the client — e.g. `stream={await fetch(\"/api/chat\")}` from a client\n> effect, or the `useFluxStream` hook (see [Quick start](#quick-start)).\n>\n> That's it — Turbopack bundles the worker and emits the `.wasm` to\n> `_next/static/media` itself, so no extra asset/loader config is needed (and the\n> Vite `optimizeDeps` workaround above does **not** apply). Both `next dev` and\n> `next build && next start` are verified to spawn the worker, load the WASM, and\n> stream markdown. _Dev tip:_ open the app on `localhost` — Next dev blocks\n> cross-origin dev resources (HMR, chunks) from other hosts (e.g. `127.0.0.1`)\n> unless you add them to `allowedDevOrigins` in `next.config`.\n\n## Quick start\n\n```ts\nimport { FluxClient, FluxMarkdown } from \"flux-md\";\n\n// One client per stream. Spawns a Web Worker that owns a Rust parser.\nconst client = new FluxClient();\n\n// Feed chunks as they arrive from your SSE / fetch reader.\nfor await (const delta of streamFromAi()) {\n  client.append(delta);\n}\nclient.finalize();\n```\n\nIn React — pass the stream straight to `<FluxMarkdown>`. It owns the client,\npipes the stream, supersedes it if it changes, and cleans up on unmount:\n\n```tsx\nimport { FluxMarkdown } from \"flux-md/react\";\n\nexport function ChatMessage({ stream }: { stream: AsyncIterable<string> }) {\n  return <FluxMarkdown stream={stream} />;\n}\n```\n\n`stream` accepts an `AsyncIterable<string>` (e.g. SSE deltas), a `Response`, or\na `ReadableStream<Uint8Array>` — so `<FluxMarkdown stream={await fetch(\"/api/chat\")} />`\nworks too.\n\nNeed the client handle (for `outline()` / `getMetrics()` / a shared client)? Use\nthe `useFluxStream` hook — same lifecycle, returns the owned client:\n\n```tsx\nimport { FluxMarkdown, useFluxStream } from \"flux-md/react\";\n\nexport function ChatMessage({ stream }: { stream: AsyncIterable<string> }) {\n  const client = useFluxStream(stream);\n  return <FluxMarkdown client={client} />;\n}\n```\n\n### Already holding a growing string? — `useFluxMarkdownString`\n\nMany apps keep the streaming message as a **single growing string prop** (it\nre-renders with the full text-so-far each token), not as a stream. Feed that\nstring straight in — `useFluxMarkdownString` diffs it for you and forwards only\nthe delta, so you don't hand-roll an append/reset bridge:\n\n```tsx\nimport { FluxMarkdown, useFluxMarkdownString } from \"flux-md/react\";\n\nexport function ChatMessage({ text, streaming }: { text: string; streaming: boolean }) {\n  const client = useFluxMarkdownString(text, { streaming });\n  return <FluxMarkdown client={client} />;\n}\n```\n\nIt handles the two shapes a controlled string takes: a **prefix-extension** (the\ncommon token-by-token growth) appends only the new suffix; a **divergence** (e.g.\nthe finished text swapped for a re-processed final string — bolded numbers,\nwrapped tickers) resets and reparses. Pass `streaming: false` once the content is\nfinal so the last block commits (a finished code fence then highlights). The\nframework-neutral primitive is **`client.setContent(fullString, { done })`** —\nuse it from any binding.\n\n> **Transforming streamed content?** If the enrichment runs **live per token**\n> (e.g. bold every number as it arrives), do it at **render time** via\n> [`components`](#custom-components--overrides) — keep the markdown source\n> append-only so parsing stays incremental. Re-transforming the *whole* string\n> each token (so earlier bytes change) forces `setContent` to reparse every tick\n> (O(n²)); that's what render-time overrides avoid. `setContent`'s reset path is\n> for the **once**-at-the-end reprocess swap, not per-token rewrites. That swap\n> is seamless: the current view stays on screen while the new string reparses —\n> the document never blanks, scroll never moves, and blocks whose rendered\n> content is unchanged keep their identity (and React keys), so only genuinely\n> changed blocks re-render. (`setContent(\"\")` is an explicit clear and resets\n> immediately.)\n\n<details>\n<summary>Full manual control (caller-owned client)</summary>\n\nWhen you want to drive the stream yourself, pass a `client` you own — the\ncomponent never destroys it:\n\n```tsx\nimport { useEffect, useState } from \"react\";\nimport { FluxClient, FluxMarkdown } from \"flux-md\";\n\nexport function ChatMessage({ stream }: { stream: AsyncIterable<string> }) {\n  const [client] = useState(() => new FluxClient());\n  useEffect(() => () => client.destroy(), [client]);\n  useEffect(() => {\n    const ac = new AbortController();\n    client.pipeFrom(stream, { signal: ac.signal }); // pipeFrom also accepts AsyncIterable\n    return () => ac.abort();\n  }, [client, stream]);\n  return <FluxMarkdown client={client} />;\n}\n```\n\n</details>\n\n> **StrictMode note:** a stream (SSE generator / `Response`) can be consumed only\n> once, so React StrictMode's dev-only double-mount may truncate it in\n> development. Production mounts once and is unaffected.\n\nMultiple concurrent streams just need multiple clients — each runs in its own worker, so they don't share main-thread budget.\n\n## Framework bindings\n\n`FluxClient` is framework-neutral — it owns the worker and exposes\n`subscribe`/`getSnapshot`. Pick a renderer to put its blocks on screen. Every\nbinding below is thin glue over the same incremental DOM renderer, so they\nshare one identity contract: a committed block's node is never recreated, only\nthe streaming tail re-renders.\n\n**One ownership rule across all bindings:** the renderer's teardown (React\nunmount, `handle.destroy()`, element disconnect, etc.) frees only the rendered\nDOM and the subscription — it **never** destroys the client. You call\n`client.destroy()` when you're done with the stream. (React's `<FluxMarkdown>`,\ndocumented [below](#fluxmarkdown-react), is the same.)\n\n### Vanilla / any framework — `flux-md/dom`\n\n```ts\nimport { FluxClient } from \"flux-md/client\";\nimport { mountFluxMarkdown } from \"flux-md/dom\";\n\nconst client = new FluxClient();\nconst handle = mountFluxMarkdown(client, document.getElementById(\"out\")!, {\n  stickToBottom: true,\n});\n\n// Feed it from a fetch/SSE reader:\nconst reader = (await fetch(\"/api/chat\")).body!.getReader();\nconst dec = new TextDecoder();\nfor (;;) {\n  const { value, done } = await reader.read();\n  if (done) break;\n  client.append(dec.decode(value, { stream: true })); // stream:true carries multibyte across chunks\n}\nclient.append(dec.decode());\nclient.finalize();\n\n// Teardown: destroy BOTH — the renderer and the client you created.\nhandle.destroy();\nclient.destroy();\n```\n\n**Already holding a growing string?** There's no framework reactivity to wrap,\nso just call **`client.setContent(fullString, { done })`** instead of the\n`append` loop — it diffs internally (prefix → delta; divergence → reparse) and\nfinalizes on `done`. That's the same primitive the React/Vue/Svelte/Solid\ncontrolled-string helpers wrap; in vanilla you call it directly.\n\n`mountFluxMarkdown(client, container, options?)` returns `{ destroy(), refresh() }`.\nOptions: `components`, `sanitize`, `virtualize`, `stickToBottom`, `highlightCode`\n(default true), `batch` (default true — one DOM write per `requestAnimationFrame`),\n`morphOpenBlocks` (default false — morph a growing generic open block's subtree in\nplace instead of rebuilding it via `innerHTML`, so only the changed parts repaint\nand focus/selection in the streaming tail survive; the rendered result is\nequivalent to the default rebuild path).\nBlock-kind overrides use `components` keyed by block-kind (`CodeBlock`, `Table`,\n`Alert`, `Component`, …) with values `(props) => HTMLElement | string`. Tag-level\n(lowercase `a`/`table`/`code`) overrides are **React-only** — there's no virtual\ntree on the fast `innerHTML` path; a block-kind override can rewrite the `html`\nit's handed instead.\n\n### Web Component `<flux-markdown>` — `flux-md/element`\n\nThe universal binding — plain HTML, Angular, or any framework that renders DOM.\nRegister once, then use the element:\n\n```ts\nimport { defineFluxMarkdown } from \"flux-md/element\";\ndefineFluxMarkdown(); // defines <flux-markdown>; pass a custom tag name if you like\n```\n\n```html\n<!-- zero-JS streaming straight from a URL -->\n<flux-markdown src=\"/api/post.md\" gfm-math stick-to-bottom></flux-markdown>\n\n<!-- one-shot from inline text -->\n<flux-markdown># Hello **world**</flux-markdown>\n```\n\n```js\n// or caller-owned streaming — drive your own client:\nconst el = document.querySelector(\"flux-markdown\");\nel.client = myFluxClient;             // element subscribes; never destroys it\nel.components = { Thinking: (p) => myNode(p) };\nmyFluxClient.append(delta);\n```\n\nConfig flags are **tri-state attributes**: absent = library default;\n`gfm-math` / `gfm-math=\"true\"` / `=\"1\"` = on; `gfm-math=\"false\"` / `=\"0\"` = off\n(the only way to turn off a default-on flag such as `gfm-alerts`). It renders in\nlight DOM so your markdown CSS applies, and `defineFluxMarkdown` is a no-op under\nSSR (no `customElements`). A self-owned element (`src` / `markdown` / inline\ntext / `append()`) is torn down on disconnect; a caller-supplied `client` is left\nalone.\n\n**Angular** consumes the same element — no separate package:\n\n```ts\nimport { Component, CUSTOM_ELEMENTS_SCHEMA } from \"@angular/core\";\nimport { defineFluxMarkdown } from \"flux-md/element\";\ndefineFluxMarkdown(); // once at bootstrap\n\n@Component({\n  standalone: true,\n  schemas: [CUSTOM_ELEMENTS_SCHEMA],\n  template: `<flux-markdown [attr.src]=\"url\" stick-to-bottom></flux-markdown>`,\n})\nexport class Answer { url = \"/api/post.md\"; }\n```\n\n**Controlled growing string?** Assign a caller-owned client and drive it with\n`setContent` — `el.client = myClient; myClient.setContent(fullString, { done })`\n— the element subscribes and renders, you own the diffing. (The self-owned\n`markdown` attribute is **one-shot** — it re-parses the whole document on each\nchange, so don't point it at a per-token-growing string; use a client +\n`setContent` for that.)\n\n### Vue 3 — `flux-md/vue`\n\n```vue\n<script setup lang=\"ts\">\nimport { onBeforeUnmount } from \"vue\";\nimport { FluxClient } from \"flux-md/client\";\nimport { FluxMarkdown } from \"flux-md/vue\";\n\nconst client = new FluxClient();\n// feed client.append(delta) from your stream, then client.finalize()\nonBeforeUnmount(() => client.destroy());\n</script>\n\n<template>\n  <FluxMarkdown :client=\"client\" stick-to-bottom />\n</template>\n```\n\nProps: `client` (required), `components`, `sanitize`, `virtualize`,\n`stickToBottom`. There's also a `useFluxMarkdown` composable returning a\n`container` ref if you'd rather mount into your own element.\n\n**Already holding a growing string?** `useFluxMarkdownString` owns a client and\ndiffs the string for you (the Vue analogue of the React hook — see\n[Controlled strings](#already-holding-a-growing-string--usefluxmarkdownstring)):\n\n```vue\n<script setup lang=\"ts\">\nimport { FluxMarkdown, useFluxMarkdownString } from \"flux-md/vue\";\nconst props = defineProps<{ text: string; streaming: boolean }>();\n// Pass getters so the composable tracks the live values; it owns + destroys the client.\nconst client = useFluxMarkdownString(() => props.text, () => ({ streaming: props.streaming }));\n</script>\n<template><FluxMarkdown :client=\"client\" /></template>\n```\n\n### Svelte (4 & 5) — `flux-md/svelte`\n\nA Svelte action — works in both v4 and v5, no `.svelte` build step:\n\n```svelte\n<script lang=\"ts\">\n  import { onDestroy } from \"svelte\";\n  import { FluxClient } from \"flux-md/client\";\n  import { fluxMarkdown } from \"flux-md/svelte\";\n\n  const client = new FluxClient();\n  // feed client.append(delta) then client.finalize()\n  onDestroy(() => client.destroy());\n</script>\n\n<div use:fluxMarkdown={{ client, stickToBottom: true }} />\n```\n\n**Growing string?** The `fluxMarkdownString` action owns a client and diffs the\nstring — `use:fluxMarkdownString={{ content, streaming }}` (it destroys its\nclient on `destroy`, so no manual cleanup):\n\n```svelte\n<script lang=\"ts\">\n  import { fluxMarkdownString } from \"flux-md/svelte\";\n  export let content: string;     // the growing message\n  export let streaming: boolean;  // false once complete → finalizes\n</script>\n\n<div use:fluxMarkdownString={{ content, streaming, stickToBottom: true }} />\n```\n\n### Solid — `flux-md/solid`\n\n```tsx\nimport { onCleanup } from \"solid-js\";\nimport { FluxClient } from \"flux-md/client\";\nimport { FluxMarkdown } from \"flux-md/solid\";\n\nconst client = new FluxClient();\n// feed client.append(delta) then client.finalize()\nonCleanup(() => client.destroy());\n\n<FluxMarkdown client={client} stickToBottom />;\n```\n\n**Growing string?** `createFluxMarkdownString` owns a client and diffs the string\n(the Solid analogue of the React hook), driving `setContent` from a\n`createEffect` and destroying the client on cleanup:\n\n```tsx\nimport { FluxMarkdown, createFluxMarkdownString } from \"flux-md/solid\";\n\nfunction Message(props: { text: string; streaming: boolean }) {\n  const client = createFluxMarkdownString(() => props.text, () => ({ streaming: props.streaming }));\n  return <FluxMarkdown client={client} />;\n}\n```\n\nThe Solid binding's mount/teardown logic is tested, but its JSX component shell\nhas so far only been exercised through a real Solid (`vite-plugin-solid`) build\nin development, not in CI — treat it as the newest of the bindings and file an\nissue if your Solid setup trips on it. The component is a thin `ref`'d `<div>`;\nif you hit a transform edge, `mountFluxMarkdown` from `flux-md/dom` inside\n`onMount`/`onCleanup` is the zero-surprise fallback.\n\n## Server-side rendering\n\n`<FluxMarkdown>` / `FluxClient` are browser-only (they spawn a Web Worker), but\nthe Rust→WASM core is a plain **synchronous** parser. So `flux-md/server` renders\n**finished** markdown on the server with no worker and no async ceremony — Node\nSSR, React Server Components, or a build step:\n\n```ts\nimport { initFlux, renderToString } from \"flux-md/server\";\n\nawait initFlux();                                       // once at startup (loads the WASM)\nconst html = renderToString(\"# Hello\\n\\n**world**\");   // sync HTML string, no worker\n```\n\nFor React server rendering (RSC, static generation, or SSR), use\n`<FluxMarkdownStatic>` from **`flux-md/server/react`** — a hookless, RSC-safe\ncomponent that renders finished content with the same `components` overrides\n(inline/block component tags dispatch on the server too). It lives in its own\nsubpath so the core `flux-md/server` above stays importable with no `react`\ninstalled:\n\n```tsx\nimport { initFlux } from \"flux-md/server\";\nimport { FluxMarkdownStatic } from \"flux-md/server/react\";\n\nawait initFlux();\nexport default function Doc({ md }: { md: string }) {\n  return (\n    <FluxMarkdownStatic\n      content={md}\n      config={{ inlineComponentTags: [\"tik\"] }}\n      components={{ tik: ({ symbol }) => <span className=\"ticker\">{symbol}</span> }}\n    />\n  );\n}\n```\n\n- **`initFlux()`** — async, idempotent. In Node it reads the package's `.wasm` off\n  disk (Node's `fetch` can't load `file://`); on the web it fetches the\n  bundler-resolved asset. On edge runtimes pass bytes yourself:\n  `initFluxSync(wasmBytes)`.\n- **`renderToString(md, { config })`** — synchronous HTML string, **zero React\n  dependency** (imports cleanly with no `react` installed).\n- **`parseToBlocks(md, { config })`** — the block array, for custom rendering.\n- **`<FluxMarkdownStatic content config components />`** (from\n  `flux-md/server/react`) — synchronous React tree for **render-once** contexts;\n  render it with your framework's server renderer\n  (`renderToStaticMarkup`, RSC, …). For live streaming, client-side code\n  highlighting, or Mermaid, render `<FluxMarkdown>` on the client instead — it's a\n  separate component. (If you SSR-then-hydrate, use the *same* component on both\n  sides; the dedicated client renderers in `<FluxMarkdown>` don't hydrate\n  `<FluxMarkdownStatic>`'s plainer markup.)\n\n## What it does\n\n| Concern | flux-md | conventional main-thread renderer |\n|---|---|---|\n| Re-parse on each token | No — only the active tail | Yes, full string |\n| Where parse runs | Web Worker (off main thread) | Main thread |\n| Block identity across chunks | Stable monotonic IDs | New keys on every render |\n| Mid-stream unclosed `` ``` `` / `*` / `**` | Speculatively closed in render, replaced cleanly | Often renders raw or breaks |\n| Half-streamed link `[label](https://…` | Label-only inert anchor (`data-flux-pending`), URL never leaks | Raw brackets + partial URL flash |\n| Heavy renderers (syntax, math, mermaid) | Deferred until block close | Re-run per chunk |\n| XSS sanitization | Allowlist in Rust + URL scheme check | Downstream sanitizer pass on the JS thread |\n\n### Streaming links\n\nA link's destination is the last thing a model emits — `[Earnings Call](https://…`\noften spans many tokens. While a link is still streaming, flux-md renders it as\nan **inert, label-only anchor**: the label text inside an `<a>` with no `href`\n(the half-typed URL never flashes on screen), marked so you can style it:\n\n```html\n<a data-flux-pending=\"\" target=\"_blank\" rel=\"noopener noreferrer nofollow\">Earnings Call</a>\n```\n\nAn anchor without an `href` gets **no default link styling** from the browser, so\nwithout a rule for the marker the link would \"pop\" blue only when the URL\ncompletes. The bundled theme (`import \"flux-md/styles.css\"`) already styles it;\nif you bring your own CSS, copy this:\n\n```css\n.flux-md a[data-flux-pending] {\n  color: var(--flux-accent, #0969da); /* match your settled link's resting style */\n  cursor: default;                    /* not clickable yet */\n}\n```\n\nThe moment the closing `)` arrives, the `href` appears and `data-flux-pending`\nis dropped — committed and finalized output never carry the marker, and the\nfinished block is byte-identical to a one-shot parse. Two composition notes:\n`urlTransform` runs only on a real `href`, so it never sees a half-streamed URL\nprefix — only the complete one (it may run again on re-renders while the\nsurrounding block is still open); `decorators` skip text\ninside `<a>` by default (`skipInside`), pending or not.\n\n## Styling\n\nflux-md emits semantic HTML under a `.flux-md` root and **ships no CSS by\ndefault** — bring your own design system, or opt into the bundled theme:\n\n```ts\nimport \"flux-md/styles.css\";\n```\n\nIt gives good-looking output out of the box, **including the built-in syntax\nhighlighter's colors** (without any CSS, `highlight()` renders uncolored). The\ntheme is scoped to `.flux-md`, zero-runtime, and **does not change the rendered\nHTML** — skip the import and nothing is styled.\n\n> **Next.js Pages Router:** `flux-md/styles.css` is global CSS, which the Pages\n> Router only allows importing from `pages/_app`. Import it there (App Router and\n> other bundlers can import it from any component). Or skip it and bring your own\n> `.flux-md` styles.\n\nRe-theme by overriding a few CSS variables; it's light by default and switches to\ndark automatically via `prefers-color-scheme` (force a mode with\n`class=\"flux-md flux-dark\"` or `flux-light`):\n\n```css\n.flux-md {\n  --flux-accent: #7c3aed;   /* links */\n  --flux-bg-code: #faf7ff;  /* code background */\n  --flux-t-kw: #c026d3;     /* syntax: keywords (also --flux-t-str/num/com/fn/ty/…) */\n}\n```\n\n## Public API\n\n### `FluxClient`\n\n```ts\nclass FluxClient {\n  constructor(options?: {\n    pool?: FluxPool;\n    config?: ParserConfig;\n    onError?: (err: { message: string; fatal?: boolean }) => void; // worker/parse + WASM-init errors\n    onBlock?: (block: Block) => void;                 // fires once per block as it commits\n  });\n  append(chunk: string): void;                      // queue text for parsing\n  pipeFrom(                                         // read → append → finalize\n    src: ReadableStream<Uint8Array> | Response | AsyncIterable<string>,\n    opts?: { signal?: AbortSignal },                // abort to supersede (no finalize)\n  ): Promise<void>;\n  finalize(): void;                                 // mark stream complete\n  setContent(                                       // drive from a controlled full string\n    full: string,                                   // diffs vs last: prefix → append delta; else seamless\n    opts?: { done?: boolean },                      //   reset+reparse (view held, unchanged blocks keep identity)\n  ): void;                                          // done:true → finalize\n  reset(): void;                                    // wipe and reuse\n  destroy(): void;                                  // free this stream's parser\n  whenReady(): Promise<void>;                       // resolves once WASM loaded; rejects on init failure\n  subscribe(listener: () => void): () => void;      // React-friendly store\n  getSnapshot(): Block[];                           // ordered current blocks\n  outline(): { level: number; text: string; id: number }[]; // heading table-of-contents (works mid-stream)\n  toPlaintext(): string;                            // rendered document as plain text (search / summaries)\n  getMetrics(): { bytes, patches, totalParseMs, throughputKBs,\n                   retainedBytes, wasmMemoryBytes, ... };\n}\n```\n\n`pipeFrom` is the LLM-native shortcut — hand it a `fetch` response and it\nreads, appends, and finalizes for you:\n\n```ts\nconst client = new FluxClient();\nawait client.pipeFrom(await fetch(\"/api/chat\")); // streams the body in, then finalizes\n```\n\nPass `onError` to be notified of worker/parse errors and a fatal WASM-init\nfailure (`{ fatal: true }`); without it, errors are only `console.error`'d and a\nload failure surfaces as a rejected `whenReady()`. Pass `onBlock` to run a side\neffect each time a block commits (e.g. lazy-highlight a finished code block).\n\n#### Per-stream config\n\n```ts\nconst client = new FluxClient({\n  config: {\n    gfmAutolinks: true,   // bare www./http(s):// URLs + emails → links (default true)\n    gfmAlerts: true,      // > [!NOTE] → callouts (default true)\n    gfmTagfilter: false,  // GFM disallowed raw HTML: escape <script>/<title>/… under unsafeHtml (default false)\n    gfmFootnotes: true,   // [^1] + [^1]: → footnote section (default false)\n    gfmMath: true,        // $…$ / \\(…\\) inline + $$…$$ / \\[…\\] display math (default false)\n    dirAuto: true,        // per-block dir=\"auto\" for RTL/bidi text (default false)\n    a11y: true,           // task-list <label> + <th scope=\"col\"> a11y markup (default false)\n    unsafeHtml: false,    // pass raw HTML through (default false — keep it false for untrusted input)\n    componentTags: [\"Thinking\", \"Callout\"], // BLOCK custom tags w/ markdown inside (default none)\n    inlineComponentTags: [\"tik\", \"cite\"],   // INLINE custom tags (chips/citations) w/ markdown inside (default none)\n    htmlAllowlist: [\"br\", \"sub\", \"sup\"],    // safe raw-HTML sanitizer: [] = allow all but dangerous; list = only those (default off)\n    dropHtmlTags: [],                        // tags removed entirely (comments always dropped when sanitizing; default off)\n    blockData: true,      // opt-in structured kind.data per block (default false — see \"Structured block data\")\n  },\n});\n```\n\nOmitted fields use the defaults above, so `new FluxClient()` is unchanged.\nConfig is applied when the stream's parser is created and is **immutable** for\nthat stream (`reset()` keeps it; use a new client for different flags).\n\nWhen to enable each flag:\n\n- `gfmAutolinks` — on by default. Leave it on unless you want strict CommonMark.\n- `gfmAlerts` — on by default. Leave it on unless you want strict CommonMark.\n- `gfmMath: true` — when your LLM emits `$…$` or `$$…$$` (or LaTeX `\\(…\\)` /\n  `\\[…\\]`). flux-md emits KaTeX-ready markup; you bring the KaTeX pass (or\n  `components.MathBlock`).\n- `gfmFootnotes: true` — when your input uses `[^1]` references and `[^1]:`\n  definitions. Off by default; see the footnote streaming caveat above.\n- `dirAuto: true` — when content can be RTL / mixed-direction. Emits per-block\n  `dir=\"auto\"` so the browser detects direction independently per block.\n- `a11y: true` — opt-in accessibility markup that deviates from strict GFM\n  byte-output: wraps task-list checkboxes in a `<label>` (screen-reader\n  association) and adds `scope=\"col\"` to table headers. Off by default so\n  conformance output stays exact.\n- `unsafeHtml: true` — only when rendering trusted HTML. For untrusted /\n  LLM-produced HTML, pair this with `<FluxMarkdown sanitize={…} />` (DOMPurify or\n  similar — see [Security](#security)).\n- `gfmTagfilter: true` — the GFM \"Disallowed Raw HTML\" extension, for use with\n  `unsafeHtml`: the nine disallowed tags (`<title>`, `<textarea>`, `<style>`,\n  `<xmp>`, `<iframe>`, `<noembed>`, `<noframes>`, `<script>`, `<plaintext>`) get\n  their leading `<` escaped so they display as text instead of taking effect —\n  opening and closing forms, any case, in blocks and inline. Off by default\n  (strict CommonMark passes them through under `unsafeHtml`); it's a tag\n  denylist, **not** a sanitizer — untrusted input still wants `sanitize`.\n- `componentTags: [\"Thinking\", …]` — when your LLM emits **block** custom tags\n  like `<Thinking>…</Thinking>` (on their own line) and you want their inner\n  content parsed as markdown and dispatched to a React component. Safe without\n  `unsafeHtml` (attributes are sanitized; allowlisted tags only).\n- `inlineComponentTags: [\"tik\", …]` — same idea for **inline** custom elements\n  that sit inside a paragraph, heading, list item, or **table cell** (ticker\n  chips, citations, `@mentions`). See [Inline component tags](#inline-component-tags).\n- `htmlAllowlist` / `dropHtmlTags` — render a **safe subset of raw HTML** (e.g.\n  `<br>`, `<sub>`, `<sup>`) natively without `unsafeHtml`, drop specific tags, and\n  drop HTML comments. See [Safe raw HTML](#safe-raw-html).\n\n**Footnotes** (`gfmFootnotes`) work in streaming with one honest caveat: a\n`[^1]` reference renders speculatively the moment it's seen (committed blocks\ncan't re-render), and the footnote **section is emitted at finalize**. So a\nreference whose definition never arrives leaves a dangling link — the same\nforward-reference cost as link reference definitions. Multiple references to\nthe same footnote each get a **unique id** (`fnref-N`, `fnref-N-2`, …) and the\ndefinition lists **one backref per reference**. Remaining v1 limits:\nsingle-block definitions (no continuation-indent / multi-paragraph) and no\nnested footnotes. The section uses GitHub-style markup\n(`<section class=\"footnotes\">`, `<sup class=\"footnote-ref\">`).\n\n**Math** (`gfmMath`) recognizes both delimiter families LLMs emit — `$…$` /\n`$$…$$` and LaTeX `\\(…\\)` / `\\[…\\]`. Inline math renders to\n`<span class=\"math math-inline\">…</span>`, display math to\n`<div class=\"math math-display\">…</div>` (and inline display to a `math-display`\nspan), each carrying the **HTML-escaped LaTeX as its text content** — exactly\nwhat [KaTeX](https://katex.org)'s auto-render / `rehype-katex` consume. flux-md\nstays **zero-dep**: it produces the KaTeX-ready markup and never processes the\nbody as markdown; you bring the KaTeX pass (or override `components.MathBlock`,\nwhich receives the raw LaTeX as `text`). Single `$` uses the **pandoc rule** so\nprose and currency stay literal — the opener needs a non-space to its right, the\ncloser a non-space to its left and no digit after it, so `$5 and $10` is **not**\nmath. A `$$`/`\\[` block is **blank-line tolerant** (multi-line `\\begin{aligned}…`\nstays one block) and renders incrementally while streaming, like a code fence.\nOff by default (so `$` in plain prose is untouched) — enable it per stream when\nyour model emits LaTeX.\n\n**Bidirectional text** (`dirAuto`) emits `dir=\"auto\"` on each block-level text\nelement (`p`, `h1`–`h6`, `blockquote`, `ul`/`ol`/`li`, `table`), so the browser\nruns the Unicode bidi algorithm **per block** — an Arabic/Hebrew paragraph\nrenders RTL while the English one beside it stays LTR, with no JS direction\ndetection. Code blocks never get it (code is always LTR). This is the per-block\nmodel GitHub uses; it's the right fix for the common failure mode of detecting\none direction for a whole mixed-language document. Off by default (strict\nCommonMark output is unchanged); turn it on for RTL or mixed-direction content.\n\n### `FluxMarkdown` (React)\n\nSubscribes to a `FluxClient`, renders each block keyed by its stable parser-assigned ID. Memoized so unchanged blocks never re-reconcile.\n\n```tsx\n<FluxMarkdown client={client} />\n```\n\nThe root element accepts opt-in `className` (appended to `flux-md`), `id`,\n`role`, and `aria-live` / `aria-atomic`. Set `aria-live=\"polite\"` to make the\noutput a live region so screen readers announce streamed content as it settles —\n`polite` coalesces rapid updates and does **not** read every token. The same\noptions exist on the DOM mount (`mountFluxMarkdown(client, el, { ariaLive: \"polite\" })`),\ncovering the Web Component and the Vue/Svelte/Solid adapters.\n\n#### Custom components / overrides\n\nPass a `components` map to replace how elements render. Keys come in **two\nnamespaces**:\n\n```tsx\nimport { useMemo } from \"react\";\nimport { FluxClient, FluxMarkdown, type Components } from \"flux-md\";\n\nfunction Message({ client }: { client: FluxClient }) {\n  // Memoize (or hoist to module scope). A fresh object every render busts\n  // FluxMarkdown's block memo, so every block re-parses on every patch.\n  const components: Components = useMemo(\n    () => ({\n      // tag-level (lowercase HTML names) — applied inside a block's HTML\n      table: (props) => <table className=\"rounded border\" {...props} />,\n      a: (props) => <a target=\"_blank\" rel=\"noreferrer\" {...props} />,\n      h1: \"h2\", // a string value just swaps the tag\n\n      // block-kind (capitalized BlockKindTag) — replaces the whole block\n      CodeBlock: ({ text, language, open }) => (\n        <MyCodeBlockWithCopyButton code={text} lang={language} streaming={open} />\n      ),\n\n      // GitHub alerts (`> [!NOTE]` / `[!TIP]` / `[!WARNING]` / `[!CAUTION]` /\n      // `[!IMPORTANT]`) — swap in your own callout component. The alert kind\n      // is on `block.kind.data.kind`; `html` is the rendered inner body.\n      Alert: ({ block, html }) => (\n        <MyCallout kind={(block.kind.data as { kind: string }).kind}>\n          <div dangerouslySetInnerHTML={{ __html: html }} />\n        </MyCallout>\n      ),\n    }),\n    [],\n  );\n  return <FluxMarkdown client={client} components={components} />;\n}\n```\n\n**Tag-level** keys (`table`, `thead`, `tr`, `td`, `a`, `code`, `pre`, `h1`–`h6`,\n`ul`, `ol`, `li`, `blockquote`, `p`, `img`, `del`, `input`, `hr`, …) replace that\nelement wherever it appears. The component receives the element's parsed\nattributes (with `class`→`className` and `style` as an object) plus `children`.\n\n**Block-kind** keys (`CodeBlock`, `Mermaid`, `MathBlock`, `Alert`, `Paragraph`,\n`Heading`, `List`, `Blockquote`, `Table`, `Rule`, `Html`) replace the entire\nblock. The component receives [`BlockComponentProps`](#types): `{ block, html,\nopen, speculative }`, plus `text`/`language` for code/math blocks (the alert\ntype is at `block.kind.data.kind`).\n\nRules worth knowing:\n\n- **There is no `node` prop / no hast tree.** Introspect via `className` /\n  `data-*`, or — better — opt into the typed **[structured-data\n  channel](#structured-block-data-setblockdata)** (`blockData: true`) and read\n  `block.kind.data` (and the typed `props.table` / `heading` / `code` / `math` /\n  `list` fields) directly — no HTML re-parsing.\n- **Overrides apply to the OPEN (streaming) block too**, not just settled ones —\n  so a design-system renderer (Tailwind classes on `p`/`ul`/`li`, inline\n  `<a>`/`<code>` overrides) stays styled mid-stream. The tail's HTML is always\n  well-formed (the parser speculatively closes it). If a `sanitize` is supplied\n  it runs first, on every block.\n- **No `components` prop ⇒ the original fast path** (`innerHTML`, byte-identical\n  output). The HTML→React conversion runs only when you actually supply\n  overrides, and is memoized per `(block id, html)` so committed blocks don't\n  re-parse as the stream grows.\n- For **code blocks** the built-in highlighter is the default; it is bypassed\n  (so your override wins) when you pass `components.CodeBlock`, `components.pre`,\n  or `components.code`.\n\n#### Inline text decorators\n\nWrap or replace matched inline **text** while streaming — e.g. bold financial\nfigures — without writing your own HTML re-parser. A `decorators` entry runs\nPOST-parse on real inline **text nodes only** (never URLs, code, or markup), once\nper committed block, so a long document stays **O(n)**.\n\n```tsx\nimport { FluxMarkdown, wrapLink } from \"flux-md\";\n\n// HOIST it (module scope) or memoize — a fresh identity each render busts the\n// per-block memo and re-decorates every block on every patch (a dev warning fires).\nconst decorators = [\n  { match: /\\$[\\d.]+[BMK]|FY\\d{4}|\\d+(?:[-–]\\d+)?%/g, replace: (t) => <mark>{t}</mark> },\n  // Linkify a ticker — route the href through the safe helper (see below):\n  { match: /\\$[A-Z]{1,5}\\b/g, replace: (t) => wrapLink(t, { href: `/sym/${t.slice(1)}` }) },\n];\n\n<FluxMarkdown client={client} decorators={decorators} />;\n```\n\n- **Trusted surface — not sanitized.** A decorator's `replace` output is spliced\n  straight into the tree and does **not** pass through flux's attribute sanitizer\n  (React renders a `javascript:` href without complaint). Treat `decorators`\n  exactly like `components`: build only trusted nodes, and route any link href\n  through `wrapLink` or the exported `safeUrl`.\n- **`skipInside`** defaults to `['a','code','pre','kbd']`; override per decorator.\n- **Per-text-node.** A value split by inline markup (e.g. `$2.<em>5</em>B`) is two\n  text nodes and won't match across them — match against settled, contiguous text.\n- Matching is pure and stateless, so a value streamed char-by-char decorates\n  **identically** to a one-shot render. Same API on `flux-md/dom`\n  (`mountFluxMarkdown(client, el, { decorators })`); a decorator there returns a\n  `Node` or string.\n\n`urlTransform?: (url, { tag, attr }) => string` rewrites `href`/`src`/`poster`\nURLs as blocks render (proxy images, add UTM params). Its output is re-sanitized\n(`safeUrl(urlTransform(safeUrl(value)))`), so a buggy transform can never emit a\n`javascript:` / `data:text/html` URL. Hoist/memoize it for the same reason as\n`decorators`.\n\n### Structured block data (`setBlockData`)\n\nSet `blockData: true` in the per-stream config and each block carries typed\nstructured data on `block.kind.data`, also surfaced as typed fields on the\ncomponent props — so you build toolbars, tables of contents, charts, copy\nbuttons, etc. from **data**, never by re-parsing the rendered HTML (no hast tree,\nno rehype). Off by default; when off, output and CommonMark/GFM conformance are\nbyte-identical, so non-users pay nothing.\n\n| Kind | `block.kind.data` | prop | use |\n|------|-------------------|------|-----|\n| `Table` | `{ headers, rows, aligns }`, cells `{ text, html }` | `props.table` | sort / filter / transpose / CSV / chart |\n| `Heading` | `{ level, text, id }` | `props.heading` | table of contents with anchors |\n| `CodeBlock` | `{ lang, code }` | `props.code` | decoded source (copy / run) |\n| `MathBlock` | `{ latex }` | `props.math` | LaTeX source (re-render) |\n| `List` | `{ ordered, start }` | `props.list` | ordered-list numbering |\n\nEach cell's `text` is inline-stripped plaintext (for sort/filter/CSV/logic);\n`html` is the inline-rendered display HTML. The data **streams** with the\ndocument — a growing table or a heading carries its structured data on every\npatch, in lock-step with the HTML — something a batch HTML-AST cannot do.\n\n```tsx\n// Table of contents from heading data — no DOM, works mid-stream:\nconst toc = client.getSnapshot()\n  .filter((b) => b.kind.type === \"Heading\" && b.kind.data)\n  .map((b) => b.kind.data as { level: number; text: string; id: string });\n```\n\n### Component tags\n\nLLMs increasingly emit custom component tags like `<Thinking>…</Thinking>`. By\ndefault these are inert (escaped, or — with `unsafeHtml` — raw HTML whose body\nis *not* markdown). Opt in by allowlisting the tag names:\n\n```tsx\nconst client = new FluxClient({ config: { componentTags: [\"Thinking\", \"Callout\"] } });\n```\n\nNow a listed tag is a **markdown container**: its inner content is parsed as\nmarkdown, it spans blank lines up to its matching close tag (not split like a\nraw HTML block), it nests, and a `</Tag>` inside a code fence stays content. It's\n**safe without `unsafeHtml`** — the tag is allowlisted and its attributes are\nsanitized (event handlers dropped, dangerous URL schemes → `#`).\n\nEach renders as a `Component` block. Override it in React by tag name (or with\nthe generic `Component` fallback). The override receives `tag`, the sanitized\n`attrs`, the inner content as ready-to-render **`children`** (the easy path), and\nalso `html` (the inner already-rendered markdown string, for\n`dangerouslySetInnerHTML`):\n\n```tsx\n<FluxMarkdown\n  client={client}\n  components={{\n    Thinking: ({ children }) => (\n      <details className=\"thinking\">\n        <summary>Reasoning</summary>\n        {children}\n      </details>\n    ),\n  }}\n/>\n```\n\n> **`children` vs `html`.** A `Component` override that renders *neither* shows\n> **empty** (a common first-try gotcha). Prefer **`children`** — a parsed React\n> tree with nested overrides applied; reach for `dangerouslySetInnerHTML={{ __html:\n> html }}` only when you need the raw string. `attrs` keys are React-form\n> (`class`→`className`, `for`→`htmlFor`) so `{...attrs}` spreads cleanly. While\n> streaming, both reflect the partial inner content and re-render as more arrives.\n> With no override the block renders as `<thinking …>…</thinking>`. Tag names\n> match case-sensitively; off unless `componentTags` is set.\n\n<a id=\"inline-component-tags\"></a>\n\n#### Inline component tags\n\n`componentTags` handles **block** containers (a `<Thinking>` on its own line). For\n**inline** custom elements — ticker chips, citations, `@mentions`, inline tooltips\nthat sit *inside* a paragraph, heading, list item, or **table cell** — use\n`inlineComponentTags`:\n\n```tsx\nconst client = new FluxClient({ config: { inlineComponentTags: [\"tik\"] } });\n\n<FluxMarkdown\n  client={client}\n  components={{\n    tik: ({ symbol, children }) => <span className=\"ticker\">{children ?? symbol}</span>,\n  }}\n/>;\n```\n\nNow `Apple <tik symbol=\"AAPL\">AAPL</tik> rose 2%` (or self-closing\n`<tik symbol=\"AAPL\"/>`) dispatches the inline `<tik>` to `components.tik`: its\ninner is parsed as **inline markdown** (the `children`), its attributes become\nprops, and it's **safe without `unsafeHtml`** (attributes sanitized, allowlisted\ntags only). It works everywhere inline content does — **including table cells**.\nTag names match **case-sensitively** and dispatch verbatim to `components[tag]`\n(`<tik>`→`components.tik`, `<Cite>`→`components.Cite`). The\ntwo lists are independent: list a tag under `componentTags` for blocks,\n`inlineComponentTags` for inline, or both for both. An allowlisted tag used in an\nunsupported position degrades **inertly** (escaped) — it never consumes\nsurrounding content.\n\n> **Link-bridge alternative.** Before `inlineComponentTags`, the way to get an\n> inline custom element was the link bridge: emit `[$AAPL](tik://AAPL)` and\n> override `a` to render a chip when the href scheme matches. It's XSS-safe and\n> renders inline-in-cells too — `inlineComponentTags` simply replaces that\n> workaround with first-class inline elements.\n\n### Safe raw HTML\n\nLLMs emit a little raw HTML — `<br>`, `<sub>`/`<sup>`, `<mark>`, and HTML comments\nas markers (`<!--mk:id-->`). `unsafeHtml` is all-or-nothing; instead opt into a\n**sanitizer** that renders a safe subset natively. Setting `htmlAllowlist` and/or\n`dropHtmlTags` (even to `[]`) engages it:\n\n```ts\n// Render only these inline tags; escape everything else:\nnew FluxClient({ config: { htmlAllowlist: [\"br\", \"sub\", \"sup\", \"mark\"] } });\n\n// Or allow everything except a built-in dangerous set:\nnew FluxClient({ config: { htmlAllowlist: [] } });\n```\n\n- **HTML comments are dropped** — no more `<!--mk:id-->` surfacing as escaped text\n  — in every mode except bare `unsafeHtml` pass-through.\n- **`htmlAllowlist: [\"br\", …]`** renders only those inline tags; everything else is\n  escaped. **`htmlAllowlist: []`** (empty) allows *all* tags **except a built-in\n  dangerous set** (`script`, `style`, `iframe`, `object`, `embed`, `form`, `svg`,\n  `xmp`, `plaintext`, … — **non-overridable**: allowlisting one still drops it).\n- **`dropHtmlTags: [\"mk\", …]`** removes those tags entirely (markup gone; inner\n  text stays as inert text).\n- Every rendered tag's **attributes are sanitized**: `on*` handlers and `style`\n  (a CSS beacon / clickjacking vector) are dropped, and dangerous URL schemes\n  (`javascript:`, …, including multi-encoded) become `#`.\n- **Scope:** *inline* raw HTML. Block-level raw HTML stays escaped for now (use\n  `unsafeHtml` **without** the sanitizer to render block HTML — when the sanitizer\n  is engaged, block HTML stays escaped even if `unsafeHtml` is also on). Tag\n  matching is case-insensitive.\n\n### Types\n\n```ts\ninterface Block {\n  id: number;\n  kind: { type: \"Paragraph\" | \"Heading\" | \"CodeBlock\" | \"List\" | ...; data?: unknown };\n  html: string;        // safe to inject via dangerouslySetInnerHTML\n  open: boolean;       // still being built (last block in active tail)\n  speculative: boolean; // closed by inference, may be revised\n  start: number;\n  end: number;\n}\n\n// Override map for <FluxMarkdown components={...} />\ntype Components = Record<string, React.ComponentType<any> | string>;\n\n// Props a block-kind override receives (e.g. components.CodeBlock)\ninterface BlockComponentProps {\n  block: Block;\n  html: string;\n  open: boolean;\n  speculative: boolean;\n  text?: string;      // decoded source — CodeBlock / MathBlock\n  language?: string;  // info string — CodeBlock\n}\n```\n\n`htmlToReact(html, components)` and `parseTrustedHtml(html)` are also exported\nfor advanced use (e.g. rendering a single block's HTML to a React tree yourself).\n\n### `highlight(code, lang)`\n\nOptional. Tiny native-RegExp tokenizer covering js/ts/tsx/jsx, rust, python, go, bash, sql, json, html, css. Unknown languages fall through to plain escaped text.\n\n```ts\nimport { highlight } from \"flux-md/highlight\";\nconst html = highlight(\"const x = 1;\", \"ts\");\n```\n\n## Coverage\n\n**CommonMark 0.31: 100% (652/652 spec examples)** — every section, including\nthe hard ones (nested/loose lists, link reference definitions, link precedence,\nlazy blockquote continuation). Plus GFM extensions: tables, strikethrough, task\nlists, extended autolinks, GitHub alerts (`> [!NOTE]` → styled callouts),\nfootnotes (`[^1]` + `[^1]:`), and math (`$…$`, `$$…$$`, `\\(…\\)`, `\\[…\\]`).\nAutolinks and alerts are on by default; footnotes and math are opt-in per stream\n(see [Per-stream config](#per-stream-config)). See\n`crates/flux-md-core/tests/{cmark_spec,gfm_spec,footnotes,math}.rs` for runners and floors.\n\nGitHub alerts render to GitHub-compatible markup\n(`<div class=\"markdown-alert markdown-alert-note\">…`), so existing markdown CSS\nstyles them, and they're overridable as a block kind via `components.Alert`.\n\n## What it doesn't do\n\nBy design, not yet, or only partially:\n\n- **Raw HTML in markdown** — escaped by default, not passed through. (Security\n  default. The `unsafeHtml: true` config flag disables the escape but must never\n  be enabled for untrusted input without a `sanitize` hook.)\n- **Forward link references when streaming** — a `[ref]` used *before* its later\n  `[ref]: url` definition can't resolve until the definition arrives; one-shot\n  parsing handles it fully, streaming converges once the definition streams in.\n- **Definition lists** — out of scope for v1.\n- **KaTeX / Mermaid rendering** — flux-md emits KaTeX-ready math markup\n  (`<span>`/`<div class=\"math …\">` with `gfmMath` on) and a `Mermaid` slot, but\n  stays zero-dep: bring your own KaTeX / mermaid pass (or a `components.MathBlock`\n  / `components.Mermaid` override) for the actual SVG/MathML output.\n- **Syntax highlighting on open code blocks** — deferred until close. This is a\n  deliberate perf choice.\n\n## Performance\n\nEvery realistic streaming shape (long paragraph, fenced code block, GFM table,\nblockquote/alert, flat list, math fence, reference-heavy document) parses in\n**O(n) total work**, not O(n²) — at every chunk size from 16 bytes (char-by-char)\nup. Each shape has an incremental cache that mirrors the structure of the block\nso that an append only does work proportional to the *newly arrived* bytes, not\nthe growing tail. See [CHANGELOG.md](./CHANGELOG.md) for per-shape numbers and\nthe regression that prompted each cache; the canonical bench is\n`crates/flux-md-core/examples/bench.rs` (`cargo run --release --example bench`).\n\nHeadline numbers are not durable across machines, but the curve is: chunk size\nshouldn't change the order of magnitude for any shape. If you hit one that does,\nfile an issue with the input and chunking — that's the next bench scenario.\n\n## Security\n\nflux-md is XSS-safe by default — its HTML output is meant to be injected via\n`innerHTML` without a downstream sanitizer:\n\n- **Raw HTML is escaped** (the `unsafeHtml: true` config flag disables this;\n  **never enable it for untrusted input without a `sanitize` hook**).\n- **Dangerous URL schemes are neutralized** in `<a href>` and `<img src>` —\n  `javascript:`, `vbscript:`, `data:text/html`, `data:text/javascript` become\n  `#`. The check runs on the *decoded* URL and strips characters browsers\n  ignore in the scheme, so obfuscations like `javascript&#58;…`,\n  `javascript\\:…`, `&#106;avascript:…`, and embedded tabs/newlines are caught,\n  not just the literal form. (See `crates/flux-md-core/tests/security.rs`.)\n- **`htmlToReact` defends in depth**: it drops inline `on*` event-handler\n  attributes and runs URL attributes through the same scheme filter. It's\n  intended for flux-md's own (already-sanitized) HTML; if you hand it arbitrary\n  third-party HTML, these guards are your only line of defense — prefer a\n  dedicated HTML sanitizer for genuinely hostile input.\n\n### Rendering untrusted / LLM HTML safely\n\nIf you enable `unsafeHtml` to render HTML from an untrusted source (e.g. an LLM\nthat returns raw HTML), **bring a real sanitizer** and pass it via\n`<FluxMarkdown sanitize={…} />`. flux-md applies it to every block's HTML before\ninjection — **including the streaming (open) tail**, which the raw-`innerHTML`\nfast path would otherwise expose. flux-md stays zero-dep; you choose the\nsanitizer. The realistic pattern (matches the live demo):\n\n```tsx\nimport DOMPurify from \"dompurify\";\n\n// Hoist to module scope (or wrap in useCallback). A fresh arrow each render\n// busts FluxMarkdown's per-block memo and re-runs every block through sanitize.\nconst sanitize = (html: string) => DOMPurify.sanitize(html);\n\n// …then in your component:\n<FluxMarkdown client={client} sanitize={sanitize} />\n```\n\nThe built-in code/math renderers operate on already-escaped content and are not\nrun through `sanitize`, so syntax highlighting and math markup are preserved.\nWith no `sanitize` prop, rendering is byte-identical and zero-cost. For\ngenuinely hostile content where CSS-overlay/clickjacking matters, render inside\na sandboxed `<iframe>` instead — sanitization stops injection, not every\nvisual-overlay trick.\n\n### Supply chain & security posture\n\nflux-md ships **zero runtime dependencies** — `dependencies` and\n`optionalDependencies` in `package.json` are both empty. The parsing core is Rust\ncompiled to WebAssembly, reproducibly buildable from `crates/flux-md-core/` via\n`bun run build:wasm`. The package publishes **compiled, non-minified ESM**\n(`dist/*.js` + `.d.ts`); it does not ship raw `.ts`/`.tsx` source.\n\n**Frameworks are optional peers, by design.** `react`, `vue`, `svelte`, and\n`solid-js` are declared as `peerDependencies` with\n`peerDependenciesMeta.optional: true`. You install only the one you use — or none\n(the `flux-md/dom` and `flux-md/element` entries need no framework at all). This\nis the most important supply-chain property of the package: **a React-only\nconsumer never installs `vue` or `solid-js`, so those frameworks' transitive\ninternals never enter that consumer's lockfile.** `npm i flux-md` on its own pulls\nin nothing else.\n\n**Why a registry scan may flag `seroval` and `@vue/compiler-*`.** When a scanner\nresolves *all* declared peers, it surfaces alerts on framework internals reachable\nonly through the optional peers — **none of which is flux-md code, and none of\nwhich is installed unless you opt into that framework:**\n\n- `seroval` (transitive of **solid-js**) — its `deserialize()` uses\n  `(0, eval)(source)` and touches the network. This is Solid's SSR serialization\n  layer; it is also the package some scanners label a \"potential vulnerability\".\n- `@vue/compiler-core` (transitive of **vue**) — uses the `Function` constructor\n  for template codegen.\n- `@vue/compiler-sfc` (transitive of **vue**) — references `globalThis[\"fetch\"]`.\n- minified esm-bundler builds of those compilers read as \"obfuscated code\".\n\nflux-md's own source contains **no `eval` and no `Function(...)` constructor**\n(`grep -rnE '\\beval\\s*\\(|\\bnew Function\\b|\\bFunction\\s*\\(' packages/flux-md/src`\nreturns nothing). The\nrepository's [`socket.yml`](https://github.com/siinghd/flux-md/blob/main/socket.yml)\ndocuments this and disables those upstream-framework alert types for flux-md's own\nCI (which installs every framework as a devDependency for cross-framework tests).\nIf you prefer surgical handling, ignore the specific transitive packages instead\n(e.g. `@SocketSecurity ignore seroval@<version>`).\n\n**flux-md is browser-oriented (Web Worker + WASM).** The default path runs the\nWASM parser inside a Web Worker — ideal for browsers and modern Node\n(`worker_threads`), but **not** intended for non-browser or older environments\nthat lack Workers/WASM. If you need a worker-free, synchronous path (Node SSR /\nReact Server Components), use **`flux-md/server`** — it loads the same WASM\nsynchronously off disk and renders to a string without spawning a worker.\n\n**First-party signals a scanner will (correctly) show.** These describe flux-md\nitself and are kept *visible* rather than silenced:\n\n- **Native code (`hasNativeCode`).** The first-party `dist/wasm/flux_md_core_bg.wasm`\n  (~180 KB) is built from the Rust source in this repo and runs inside a sandboxed\n  Web Worker (browser) or Node worker thread. It is reproducible from source, not a\n  vendored third-party binary.\n- **Network access (`networkAccess`).** Only `<flux-markdown src=\"URL\">` (the URL\n  *you* supply) and the wasm-bindgen glue loading the co-located `.wasm` via\n  `fetch(new URL(\"…_bg.wasm\", import.meta.url))` — which bundlers resolve to a\n  local build artifact. No telemetry, no analytics, no first-party remote\n  endpoints. In privileged contexts (browser extensions, Electron) treat the `src`\n  value as any external URL and allowlist it in your CSP.\n- **Filesystem access (`filesystemAccess`).** Node/SSR only: `flux-md/server` reads\n  the package's own `.wasm` off disk (Node's `fetch` cannot load `file://` URLs).\n  It reads only the package-internal asset, never a caller-supplied path.\n\nThe `socket.yml` at the repository root documents every signal with its\njustification for Socket's GitHub app.\n\n## Scaling\n\n`FluxClient`s share a **worker pool** (`getDefaultPool()`), so concurrency\ndoesn't oversubscribe OS threads. Worker creation is lazy and load-aware:\n\n- **1 stream → 1 worker**, and each new stream gets its own worker until the cap\n  (`Math.min(navigator.hardwareConcurrency || 4, 8)`) — identical to the\n  per-worker behavior for small stream counts.\n- **Past the cap**, new streams attach to the least-loaded worker, which\n  multiplexes them (a `FluxParser` per stream id). So **50 concurrent streams\n  run on ≤8 workers (~6 each)**, not 50 threads.\n\n`destroy()` frees a stream's parser and keeps the worker warm for its siblings;\nthe workers persist for the life of the page. Need isolation or manual\nteardown? Construct your own `new FluxPool(factory, cap)` and pass it to\n`new FluxClient(pool)`, or call `pool.disposeAll()`.\n\n`getDefaultPool()` is **browser-only** (it constructs `Worker`s) and is a\n**per-page singleton** — don't rely on it in SSR/RSC. For isolation between\nindependent feature areas, give each its own `new FluxPool()`.\n\n**Warm the pool to hide WASM init.** The one-time WASM load happens on the first\nworker-bound op, which lands on the first-token critical path. Call\n`getDefaultPool().warm()` on app load / route entry to start it early — the warm\nworker is the one the first stream attaches to, so the init isn't wasted:\n\n```ts\nimport { getDefaultPool } from \"flux-md\";\nuseEffect(() => { getDefaultPool().warm(); }, []); // (or your framework's mount hook)\n```\n\n### Long documents — `virtualize`\n\nFor very long documents (hundreds+ of blocks), pass `virtualize` to apply CSS\n`content-visibility: auto` (+ a per-kind `contain-intrinsic-size`) to **closed**\nblocks, so the browser skips style/layout/paint for off-screen content:\n\n```tsx\n<FluxMarkdown client={client} virtualize />\n```\n\nIt's opt-in (off by default — short docs gain nothing) and never defers the\nstreaming tail (open/speculative blocks always render fully, so no flicker\nwhere you're looking). It cuts **rendering cost, not DOM node count** — nodes\nstay in the document (search, anchors, and a11y all keep working), they just\ndon't lay out while off-screen. Measured on a ~1800-block demo, an off-screen\n**layout pass is ~7× cheaper** (≈1980ms → ≈284ms over 30 forced relayouts),\nidentical node count — i.e. whenever the browser would otherwise lay out\noff-screen blocks (initial paint, resize, font load, scroll), that work is\nskipped. No JS windowing, no scroll math, no dep — the browser does it natively.\n\nWorks best when `<FluxMarkdown>`'s parent uses normal block flow; a `flex`/`grid`\nparent can interact with `contain-intrinsic-size` in surprising ways.\n\n### Stick to bottom while streaming — `stickToBottom`\n\nPass `stickToBottom` and the view **follows the streaming tail, releasing when\nthe user scrolls up** (and re-locking when they scroll back near the bottom) —\nthe behavior every chat UI wants. It's **CSS-only** (CSS Scroll Snap, no JS, no\nscroll listeners): flux-md emits a bottom snap target; you add one line to your\nscroll container:\n\n```tsx\n<div className=\"chat-scroller\">          {/* your existing scroll container */}\n  <FluxMarkdown client={client} stickToBottom />\n</div>\n```\n```css\n.chat-scroller { overflow-y: auto; scroll-snap-type: y proximity; }\n```\n\nThat's the whole feature. `proximity` (not `mandatory`) is what lets the user\nscroll up freely. Note it **follows** the bottom — during very fast streaming\nthe lock can lag by a few px between snaps; it doesn't *hard-pin*. Re-snap on\ncontent growth is solid in Chromium/Firefox; **Safari is weaker** at\nre-snapping during streaming, so treat smooth following there as best-effort.\n\n> **Metrics note:** because workers are shared, `getMetrics().wasmMemoryBytes`\n> is the *shared* worker's heap — clients on the same worker report the same\n> value. Aggregate with `Math.max`, not a sum.\n\n## Architecture\n\n```\n┌── main thread ────────────────────────┐\n│  FluxMarkdown — React, useSyncStore  │\n│  FluxClient — message routing        │\n└──┬──── postMessage(chunk) ────────────┘\n   ▼\n┌── Web Worker ─────────────────────────┐\n│  worker.ts — coalesces chunks per    │\n│              microtask, calls WASM   │\n└──┬──── ffi ───────────────────────────┘\n   ▼\n┌── Rust → WASM (~170 KB after opt) ────┐\n│  StreamParser:                        │\n│    buffer: append-only                │\n│    committed_offset                   │\n│    [committed_blocks]                 │\n│    [active_blocks]  (re-parsed tail)  │\n│                                       │\n│  scanner.rs → raw blocks              │\n│  inline.rs  → emphasis stack + safe   │\n│              link/code rendering      │\n│  render.rs  → HTML with URL sanitize  │\n└───────────────────────────────────────┘\n```\n\nActive tail re-parses on each chunk; committed blocks are frozen forever. Each block's ID is monotonic and is *preserved* across re-parses when its start offset and kind match a previously-seen active block — so React's keyed reconciliation reuses the DOM instead of remounting.\n\n## License\n\nMIT.\n","readmeFilename":"README.md"}