flux-md 0.3.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -6
- package/README.md +15 -6
- package/package.json +1 -1
- package/src/hi.ts +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,16 @@ Notable changes to flux-md. Format based on
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/); this project aims to follow
|
|
5
5
|
[Semantic Versioning](https://semver.org/).
|
|
6
6
|
|
|
7
|
+
## 0.3.2 — 2026-05-27
|
|
8
|
+
|
|
9
|
+
### Documentation
|
|
10
|
+
|
|
11
|
+
- Rewrote the README to describe flux-md on its own terms and removed all
|
|
12
|
+
references to and comparisons with other libraries. No code changes — the
|
|
13
|
+
published API and behavior are identical to 0.3.1.
|
|
14
|
+
- Fixed the React quick-start example: import `useEffect` and guard the async
|
|
15
|
+
append loop so it can't run after unmount or a stream change.
|
|
16
|
+
|
|
7
17
|
## 0.3.1 — 2026-05-27
|
|
8
18
|
|
|
9
19
|
### Performance
|
|
@@ -34,12 +44,11 @@ Notable changes to flux-md. Format based on
|
|
|
34
44
|
`<div class="math math-display">`) carrying the LaTeX as text content — bring
|
|
35
45
|
your own KaTeX (flux-md stays zero-dep) or override `components.MathBlock`
|
|
36
46
|
(which receives the LaTeX as `text`). Display fences are blank-line tolerant
|
|
37
|
-
and stream incrementally.
|
|
47
|
+
and stream incrementally. Off by default.
|
|
38
48
|
- **`dirAuto`** — opt-in per-block `dir="auto"` on block-level text elements
|
|
39
49
|
(`p`, `h1`–`h6`, `blockquote`, `ul`/`ol`/`li`, `table`, alerts, footnotes), so
|
|
40
50
|
the browser detects each block's direction (RTL/LTR) independently in
|
|
41
|
-
mixed-language documents. Code blocks stay LTR.
|
|
42
|
-
Off by default.
|
|
51
|
+
mixed-language documents. Code blocks stay LTR. Off by default.
|
|
43
52
|
|
|
44
53
|
### Performance
|
|
45
54
|
|
|
@@ -67,6 +76,3 @@ Notable changes to flux-md. Format based on
|
|
|
67
76
|
- Initial public release: zero-dep streaming markdown, Rust→WASM core, one Web
|
|
68
77
|
Worker per stream, CommonMark 0.31 (652/652) + GFM (tables, strikethrough,
|
|
69
78
|
task lists, extended autolinks, GitHub alerts, footnotes).
|
|
70
|
-
|
|
71
|
-
[Streamdown #522]: https://github.com/vercel/streamdown/issues/522
|
|
72
|
-
[Streamdown #509]: https://github.com/vercel/streamdown/issues/509
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Zero-dep streaming markdown for the browser. Rust→WASM core, one Web Worker per stream, incremental parse with speculative closure for mid-stream constructs.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Parsing 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/).
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
@@ -37,18 +37,27 @@ client.finalize();
|
|
|
37
37
|
In React:
|
|
38
38
|
|
|
39
39
|
```tsx
|
|
40
|
-
import { useMemo } from "react";
|
|
40
|
+
import { useEffect, useMemo } from "react";
|
|
41
41
|
import { FluxClient, FluxMarkdown } from "flux-md";
|
|
42
42
|
|
|
43
43
|
export function ChatMessage({ stream }: { stream: AsyncIterable<string> }) {
|
|
44
44
|
const client = useMemo(() => new FluxClient(), []);
|
|
45
|
+
|
|
45
46
|
useEffect(() => {
|
|
47
|
+
let cancelled = false;
|
|
46
48
|
(async () => {
|
|
47
|
-
for await (const chunk of stream)
|
|
48
|
-
|
|
49
|
+
for await (const chunk of stream) {
|
|
50
|
+
if (cancelled) return; // stream changed / unmounted mid-flight
|
|
51
|
+
client.append(chunk);
|
|
52
|
+
}
|
|
53
|
+
if (!cancelled) client.finalize();
|
|
49
54
|
})();
|
|
50
|
-
return () =>
|
|
55
|
+
return () => {
|
|
56
|
+
cancelled = true;
|
|
57
|
+
client.destroy();
|
|
58
|
+
};
|
|
51
59
|
}, [stream]);
|
|
60
|
+
|
|
52
61
|
return <FluxMarkdown client={client} />;
|
|
53
62
|
}
|
|
54
63
|
```
|
|
@@ -57,7 +66,7 @@ Multiple concurrent streams just need multiple clients — each runs in its own
|
|
|
57
66
|
|
|
58
67
|
## What it does
|
|
59
68
|
|
|
60
|
-
| Concern | flux-md |
|
|
69
|
+
| Concern | flux-md | conventional main-thread renderer |
|
|
61
70
|
|---|---|---|
|
|
62
71
|
| Re-parse on each token | No — only the active tail | Yes, full string |
|
|
63
72
|
| Where parse runs | Web Worker (off main thread) | Main thread |
|
package/package.json
CHANGED
package/src/hi.ts
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* languages fall through to plain escaped text. ~6KB minified.
|
|
6
6
|
*
|
|
7
7
|
* Highlighting is per-block, runs once when the block closes. We never
|
|
8
|
-
* highlight an open (streaming) block
|
|
9
|
-
*
|
|
8
|
+
* highlight an open (streaming) block, which avoids re-highlighting the same
|
|
9
|
+
* code on every chunk — the main perf win for streaming code.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
const KEYWORDS_JS = new Set(
|