flux-md 0.18.0 → 0.18.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 CHANGED
@@ -4,6 +4,54 @@ 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.18.2 — 2026-06-29
8
+
9
+ ### Fixed
10
+
11
+ - **Streaming O(n²) cliff on a paragraph followed by a long link-reference /
12
+ footnote definition run** (e.g. reference-heavy LLM output: prose, then a
13
+ block of `[id]: url` definitions). The paragraph stayed speculative until
14
+ `finalize()` — a definition is not a renderable block, so the paragraph never
15
+ became "the last block" and `committed_offset` stalled, re-scanning the whole
16
+ growing definition run on every append. A 235 KB document streamed at a
17
+ 256-byte chunk took **~59 s**; it now takes **~20 ms**, and streaming is linear
18
+ in document size across all chunk sizes. A renderable block followed by a
19
+ definition run now commits (a definition only parses at a block boundary, so
20
+ the block is closed). Narrow behavior note, within the existing
21
+ forward-reference limitation: the single paragraph immediately before such a
22
+ run now commits before the later definitions, so a *forward* reference from it
23
+ renders literally instead of resolving at finalize — consistent with every
24
+ earlier paragraph, which already commits mid-stream.
25
+
26
+ ## 0.18.1 — 2026-06-29
27
+
28
+ Performance + size pass. No API or output changes — CommonMark 652/652 and
29
+ GFM 23/24 are byte-for-byte unchanged.
30
+
31
+ ### Changed
32
+
33
+ - **WASM binary −9.6 KB (175.1 KB → 165.5 KB, −5.4%).** Three levers, measured:
34
+ a compact stable merge sort replaces the standard library's general-purpose
35
+ stable sort (driftsort) at the two sort sites (−7.3 KB incl. simpler escape
36
+ codegen); `wasm-opt` switches from `-O3` to `-Oz` (−2.3 KB) — and since the
37
+ Rust codegen is already `opt-level=z`, `-Oz` is a Pareto win (equal-or-slightly
38
+ faster parse, never slower, in a Node WASM A/B).
39
+ - **Faster HTML escaping.** `escape_html` / `escape_attr` now scan bytes and copy
40
+ plain runs with one `push_str` (a memcpy) instead of decoding + re-encoding
41
+ every character. Output is byte-identical (only ASCII `< > & " '` are
42
+ rewritten). Measured **+9–23%** parse throughput on escape-heavy documents —
43
+ large fenced code, display math, and HTML/list-heavy content (the common
44
+ LLM-output shape); prose is unchanged.
45
+ - **Fewer allocations on the render path.** Paragraphs, headings, and list items
46
+ render their inline content directly into the output buffer and trim in place,
47
+ dropping one temporary `String` + copy per block (helps the SSR / one-shot
48
+ `renderToString` / `parseToBlocks` path).
49
+ - **One fewer React render per patch (default path).** `<FluxMarkdown>` fed a
50
+ changing value to `useDeferredValue` even when tail deferral was off (the
51
+ default), so React scheduled a throwaway low-priority catch-up render every
52
+ patch. It now feeds a stable value unless `deferTail` is set, so the default
53
+ path renders exactly once per patch.
54
+
7
55
  ## 0.18.0 — 2026-06-29
8
56
 
9
57
  ### Added
package/dist/react.js CHANGED
@@ -14,6 +14,7 @@ import { CodeBlock } from "./renderers/CodeBlock.js";
14
14
  import { MathBlock } from "./renderers/Math.js";
15
15
  import { Mermaid } from "./renderers/Mermaid.js";
16
16
  import { htmlToReact } from "./html-to-react.js";
17
+ const NO_DEFER_BLOCKS = [];
17
18
  function FluxMarkdownFromClient({
18
19
  client,
19
20
  components,
@@ -30,7 +31,7 @@ function FluxMarkdownFromClient({
30
31
  deferTail
31
32
  }) {
32
33
  const blocks = useSyncExternalStore(client.subscribe, client.getSnapshot, client.getSnapshot);
33
- const deferred = useDeferredValue(blocks);
34
+ const deferred = useDeferredValue(deferTail ? blocks : NO_DEFER_BLOCKS);
34
35
  const rendered = deferTail ? deferred : blocks;
35
36
  const isDeferring = deferTail ? rendered !== blocks : false;
36
37
  const comps = useMemo(
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flux-md",
3
- "version": "0.18.0",
3
+ "version": "0.18.2",
4
4
  "description": "Zero-dep streaming markdown for the browser. Rust→WASM core, Web Worker per stream, incremental parse with speculative closure.",
5
5
  "type": "module",
6
6
  "sideEffects": ["./dist/worker.js", "./dist/styles.css"],