flux-md 0.11.0 → 0.12.0

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,18 @@ 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.12.0 — 2026-05-30
8
+
9
+ ### Added
10
+
11
+ - **Optional default theme — `import "flux-md/styles.css"`.** A drop-in stylesheet
12
+ for good-looking output out of the box, **including the built-in syntax
13
+ highlighter's colors** (without any CSS, `highlight()` output is uncolored).
14
+ Scoped to `.flux-md`, driven by `--flux-*` CSS variables (re-theme by overriding
15
+ a few), light by default with automatic dark via `prefers-color-scheme` (force
16
+ with `class="flux-md flux-dark"` / `flux-light`). Opt-in and zero-runtime — the
17
+ rendered HTML is unchanged; skip the import to bring your own CSS.
18
+
7
19
  ## 0.11.0 — 2026-05-30
8
20
 
9
21
  ### Added
package/README.md CHANGED
@@ -280,6 +280,32 @@ if you hit a transform edge, `mountFluxMarkdown` from `flux-md/dom` inside
280
280
  | Heavy renderers (syntax, math, mermaid) | Deferred until block close | Re-run per chunk |
281
281
  | XSS sanitization | Allowlist in Rust + URL scheme check | Downstream sanitizer pass on the JS thread |
282
282
 
283
+ ## Styling
284
+
285
+ flux-md emits semantic HTML under a `.flux-md` root and **ships no CSS by
286
+ default** — bring your own design system, or opt into the bundled theme:
287
+
288
+ ```ts
289
+ import "flux-md/styles.css";
290
+ ```
291
+
292
+ It gives good-looking output out of the box, **including the built-in syntax
293
+ highlighter's colors** (without any CSS, `highlight()` renders uncolored). The
294
+ theme is scoped to `.flux-md`, zero-runtime, and **does not change the rendered
295
+ HTML** — skip the import and nothing is styled.
296
+
297
+ Re-theme by overriding a few CSS variables; it's light by default and switches to
298
+ dark automatically via `prefers-color-scheme` (force a mode with
299
+ `class="flux-md flux-dark"` or `flux-light`):
300
+
301
+ ```css
302
+ .flux-md {
303
+ --flux-accent: #7c3aed; /* links */
304
+ --flux-bg-code: #faf7ff; /* code background */
305
+ --flux-t-kw: #c026d3; /* syntax: keywords (also --flux-t-str/num/com/fn/ty/…) */
306
+ }
307
+ ```
308
+
283
309
  ## Public API
284
310
 
285
311
  ### `FluxClient`
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "flux-md",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
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
- "sideEffects": ["./src/worker.ts"],
6
+ "sideEffects": ["./src/worker.ts", "./src/styles.css"],
7
7
  "main": "./src/index.ts",
8
8
  "types": "./src/index.ts",
9
9
  "exports": {
@@ -16,7 +16,8 @@
16
16
  "./svelte": "./src/svelte.ts",
17
17
  "./solid": "./src/solid.tsx",
18
18
  "./highlight": "./src/hi.ts",
19
- "./types": "./src/types.ts"
19
+ "./types": "./src/types.ts",
20
+ "./styles.css": "./src/styles.css"
20
21
  },
21
22
  "files": [
22
23
  "src",
package/src/styles.css ADDED
@@ -0,0 +1,182 @@
1
+ /*
2
+ * flux-md — optional default theme.
3
+ *
4
+ * import "flux-md/styles.css";
5
+ *
6
+ * Opt-in: import it for good-looking output out of the box (including the
7
+ * built-in syntax highlighter's colors); skip it to bring your own CSS — the
8
+ * rendered HTML is identical either way. Everything is scoped to `.flux-md`
9
+ * (the renderer's root) and driven by CSS custom properties, so you re-theme by
10
+ * overriding a few `--flux-*` vars rather than rewriting selectors.
11
+ *
12
+ * Light by default; dark automatically via `prefers-color-scheme`. Force a mode
13
+ * with `<div class="flux-md flux-dark">` or `flux-light`.
14
+ */
15
+
16
+ .flux-md {
17
+ /* surfaces + text (light) */
18
+ --flux-fg: #1f2328;
19
+ --flux-fg-muted: #59636e;
20
+ --flux-fg-faint: #818b98;
21
+ --flux-border: #d1d9e0;
22
+ --flux-bg-code: #f6f8fa;
23
+ --flux-bg-inline: rgba(129, 139, 152, 0.16);
24
+ --flux-bg-quote: rgba(129, 139, 152, 0.08);
25
+ --flux-accent: #0969da;
26
+ /* syntax tokens (light) */
27
+ --flux-t-kw: #cf222e;
28
+ --flux-t-str: #0a3069;
29
+ --flux-t-num: #0550ae;
30
+ --flux-t-com: #59636e;
31
+ --flux-t-fn: #6639ba;
32
+ --flux-t-ty: #953800;
33
+ --flux-t-mac: #1f6feb;
34
+ --flux-t-attr: #116329;
35
+ --flux-t-tag: #116329;
36
+ --flux-t-var: #953800;
37
+ --flux-t-pun: var(--flux-fg);
38
+ /* sizing */
39
+ --flux-radius: 6px;
40
+ --flux-gap: 16px;
41
+
42
+ color: var(--flux-fg);
43
+ font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
44
+ line-height: 1.6;
45
+ font-size: 1rem;
46
+ word-wrap: break-word;
47
+ overflow-wrap: anywhere;
48
+ }
49
+
50
+ /* Dark — automatic, and as an explicit `.flux-dark` escape hatch. */
51
+ @media (prefers-color-scheme: dark) {
52
+ .flux-md:not(.flux-light) {
53
+ --flux-fg: #e6edf3;
54
+ --flux-fg-muted: #9198a1;
55
+ --flux-fg-faint: #6e7681;
56
+ --flux-border: #3d444d;
57
+ --flux-bg-code: #151b23;
58
+ --flux-bg-inline: rgba(101, 108, 118, 0.2);
59
+ --flux-bg-quote: rgba(101, 108, 118, 0.1);
60
+ --flux-accent: #4493f8;
61
+ --flux-t-kw: #ff7b72;
62
+ --flux-t-str: #a5d6ff;
63
+ --flux-t-num: #79c0ff;
64
+ --flux-t-com: #8b949e;
65
+ --flux-t-fn: #d2a8ff;
66
+ --flux-t-ty: #ffa657;
67
+ --flux-t-mac: #79c0ff;
68
+ --flux-t-attr: #7ee787;
69
+ --flux-t-tag: #7ee787;
70
+ --flux-t-var: #ffa657;
71
+ }
72
+ }
73
+ .flux-md.flux-dark {
74
+ --flux-fg: #e6edf3;
75
+ --flux-fg-muted: #9198a1;
76
+ --flux-fg-faint: #6e7681;
77
+ --flux-border: #3d444d;
78
+ --flux-bg-code: #151b23;
79
+ --flux-bg-inline: rgba(101, 108, 118, 0.2);
80
+ --flux-bg-quote: rgba(101, 108, 118, 0.1);
81
+ --flux-accent: #4493f8;
82
+ --flux-t-kw: #ff7b72;
83
+ --flux-t-str: #a5d6ff;
84
+ --flux-t-num: #79c0ff;
85
+ --flux-t-com: #8b949e;
86
+ --flux-t-fn: #d2a8ff;
87
+ --flux-t-ty: #ffa657;
88
+ --flux-t-mac: #79c0ff;
89
+ --flux-t-attr: #7ee787;
90
+ --flux-t-tag: #7ee787;
91
+ --flux-t-var: #ffa657;
92
+ }
93
+
94
+ /* ---- block rhythm ---------------------------------------------------------- */
95
+ .flux-md > * { margin: 0 0 var(--flux-gap) 0; }
96
+ .flux-md > *:last-child { margin-bottom: 0; }
97
+
98
+ /* ---- headings -------------------------------------------------------------- */
99
+ .flux-md h1, .flux-md h2, .flux-md h3,
100
+ .flux-md h4, .flux-md h5, .flux-md h6 {
101
+ font-weight: 600;
102
+ line-height: 1.25;
103
+ margin: 24px 0 var(--flux-gap);
104
+ }
105
+ .flux-md h1 { font-size: 2em; padding-bottom: 0.3em; border-bottom: 1px solid var(--flux-border); }
106
+ .flux-md h2 { font-size: 1.5em; padding-bottom: 0.3em; border-bottom: 1px solid var(--flux-border); }
107
+ .flux-md h3 { font-size: 1.25em; }
108
+ .flux-md h4 { font-size: 1em; }
109
+ .flux-md h5 { font-size: 0.875em; }
110
+ .flux-md h6 { font-size: 0.85em; color: var(--flux-fg-muted); }
111
+ .flux-md > h1:first-child, .flux-md > h2:first-child, .flux-md > h3:first-child { margin-top: 0; }
112
+
113
+ /* ---- inline ---------------------------------------------------------------- */
114
+ .flux-md a { color: var(--flux-accent); text-decoration: none; }
115
+ .flux-md a:hover { text-decoration: underline; }
116
+ .flux-md strong { font-weight: 600; }
117
+ .flux-md em { font-style: italic; }
118
+ .flux-md del { color: var(--flux-fg-muted); }
119
+ .flux-md img { max-width: 100%; height: auto; }
120
+
121
+ /* ---- lists ----------------------------------------------------------------- */
122
+ .flux-md ul, .flux-md ol { padding-left: 2em; }
123
+ .flux-md li { margin: 0.25em 0; }
124
+ .flux-md li > ul, .flux-md li > ol { margin: 0.25em 0; }
125
+ .flux-md li::marker { color: var(--flux-fg-faint); }
126
+ .flux-md input[type="checkbox"] { margin: 0 0.4em 0 0; }
127
+
128
+ /* ---- blockquote + alerts --------------------------------------------------- */
129
+ .flux-md blockquote {
130
+ margin: 0 0 var(--flux-gap);
131
+ padding: 0.4em 1em;
132
+ color: var(--flux-fg-muted);
133
+ border-left: 0.25em solid var(--flux-border);
134
+ background: var(--flux-bg-quote);
135
+ }
136
+ .flux-md blockquote > :last-child { margin-bottom: 0; }
137
+
138
+ /* ---- tables ---------------------------------------------------------------- */
139
+ .flux-md table { border-collapse: collapse; width: 100%; display: block; overflow-x: auto; }
140
+ .flux-md th, .flux-md td { padding: 6px 13px; border: 1px solid var(--flux-border); }
141
+ .flux-md th { font-weight: 600; background: var(--flux-bg-code); }
142
+ .flux-md tr:nth-child(2n) td { background: var(--flux-bg-quote); }
143
+
144
+ /* ---- code ------------------------------------------------------------------ */
145
+ .flux-md code, .flux-md pre {
146
+ font-family: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;
147
+ font-size: 0.9em;
148
+ }
149
+ .flux-md :not(pre) > code {
150
+ padding: 0.2em 0.4em;
151
+ border-radius: var(--flux-radius);
152
+ background: var(--flux-bg-inline);
153
+ }
154
+ .flux-md pre {
155
+ padding: 14px 16px;
156
+ overflow-x: auto;
157
+ border-radius: var(--flux-radius);
158
+ background: var(--flux-bg-code);
159
+ line-height: 1.5;
160
+ }
161
+ .flux-md pre code { padding: 0; background: none; border: 0; }
162
+
163
+ /* ---- rule ------------------------------------------------------------------ */
164
+ .flux-md hr { height: 1px; border: 0; background: var(--flux-border); margin: 24px 0; }
165
+
166
+ /* ---- syntax highlighter (the built-in `highlight()` token spans) ----------- */
167
+ .flux-md .t-kw { color: var(--flux-t-kw); }
168
+ .flux-md .t-str,
169
+ .flux-md .t-rx { color: var(--flux-t-str); }
170
+ .flux-md .t-num,
171
+ .flux-md .t-lt { color: var(--flux-t-num); }
172
+ .flux-md .t-com { color: var(--flux-t-com); font-style: italic; }
173
+ .flux-md .t-fn { color: var(--flux-t-fn); }
174
+ .flux-md .t-ty { color: var(--flux-t-ty); }
175
+ .flux-md .t-mac,
176
+ .flux-md .t-dec { color: var(--flux-t-mac); }
177
+ .flux-md .t-attr,
178
+ .flux-md .t-sel { color: var(--flux-t-attr); }
179
+ .flux-md .t-tag { color: var(--flux-t-tag); }
180
+ .flux-md .t-var { color: var(--flux-t-var); }
181
+ .flux-md .t-pun { color: var(--flux-t-pun); }
182
+ .flux-md .t-txt { color: inherit; }
Binary file
@@ -2,7 +2,7 @@
2
2
  "name": "flux-md-core",
3
3
  "type": "module",
4
4
  "description": "Incremental, streaming-aware markdown parser with speculative closure",
5
- "version": "0.11.0",
5
+ "version": "0.12.0",
6
6
  "license": "MIT",
7
7
  "files": [
8
8
  "flux_md_core_bg.wasm",