Skip to main content

max / quasi

Markdown is standard: docengine is not a feature The rich feature was default-on, on the reasoning that a consumer with no rich text should not pay for a markdown parser. Markdown turns out to be what these apps are mostly made of, so the saving was hypothetical and what the flag bought was a build in which a described screen draws **bold** at the reader. A renderer either honours the description or it is not a renderer for it. The dependency is unpinned deliberately: docengine is in-tree and moves with us, and a pinned minor means editing two files to release one.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-08-10 17:20 UTC
Signed with PGP, not checked
Commit: 8d483425583fe35b4bd218828cf5af1dbf786cfb
Parent: 5604d6d
3 files changed, +28 insertions, -31 deletions
M Cargo.lock +9 -9
@@ -723,7 +723,7 @@
723 723
724 724 [[package]]
725 725 name = "docengine"
726 - version = "0.4.0"
726 + version = "0.5.0"
727 727 dependencies = [
728 728 "ammonia",
729 729 "pulldown-cmark",
@@ -4888,14 +4888,6 @@
4888 4888 source = "registry+https://github.com/rust-lang/crates.io-index"
4889 4889 checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
4890 4890
4891 - [[patch.unused]]
4892 - name = "synckit-client"
4893 - version = "0.8.0"
4894 -
4895 - [[patch.unused]]
4896 - name = "synckit-config"
4897 - version = "0.2.0"
4898 -
4899 4891 [[patch.unused]]
4900 4892 name = "kberg"
4901 4893 version = "0.1.0"
@@ -4907,3 +4899,11 @@
4907 4899 [[patch.unused]]
4908 4900 name = "tagtree"
4909 4901 version = "0.4.0"
4902 +
4903 + [[patch.unused]]
4904 + name = "synckit-client"
4905 + version = "0.8.0"
4906 +
4907 + [[patch.unused]]
4908 + name = "synckit-config"
4909 + version = "0.2.0"
@@ -18,14 +18,16 @@
18 18 makeover-layout = "0.12.0"
19 19 makeover-webview = "0.22.1"
20 20 # `Node::Rich` carries markdown source and this is what turns it into markup.
21 - # Optional and default-on: a renderer that cannot render the member makes the
22 - # member do nothing, and a consumer with no rich text should not pay for a
23 - # markdown parser. Sanitising comes with it, which is why the node can carry
24 - # what a user typed.
25 - docengine = { git = "https://makenot.work/git/max/docengine.git", version = "0.4.0", optional = true }
26 -
27 - [features]
28 - default = ["rich"]
29 - # Render `Node::Rich`. Without it the node emits its source as text, which is
30 - # what every renderer did before the member existed.
31 - rich = ["dep:docengine"]
21 + # Sanitising comes with it, which is why the node can carry what a user typed.
22 + #
23 + # Not optional. It was, default-on, on the reasoning that a consumer with no
24 + # rich text should not pay for a markdown parser; markdown turns out to be what
25 + # these apps are mostly made of (every task, project and event description, and
26 + # every mail body an HTML message produced), so the saving was hypothetical and
27 + # what the flag really bought was a build in which a described screen silently
28 + # renders its prose as syntax. A renderer either honours the description or it
29 + # is not a renderer for it.
30 + #
31 + # Unpinned deliberately: docengine is in-tree and moves with us, and a pinned
32 + # minor here means editing two files to release one.
33 + docengine = { git = "https://makenot.work/git/max/docengine.git" }
@@ -127,18 +127,13 @@
127 127 /// rendering as text rather than as markup, which is the outcome
128 128 /// [`Node::Text`] would have given anyway.
129 129 ///
130 - /// Without the `rich` feature the source is escaped and emitted as it was
131 - /// written. That is lossy and visible rather than silent, and it is what the
132 - /// node did before it could be rendered at all.
130 + /// Unconditional. This sat behind a default-on `rich` feature until markdown
131 + /// was made standard, and turning the feature off did not remove a cost so much
132 + /// as produce a renderer that draws `**bold**` at the user. Markdown is what
133 + /// these descriptions are made of, so rendering it is part of being a renderer
134 + /// rather than an extra somebody opts into.
133 135 fn rich_html(source: &str) -> String {
134 - #[cfg(feature = "rich")]
135 - {
136 - docengine::render_strict(source)
137 - }
138 - #[cfg(not(feature = "rich"))]
139 - {
140 - escape(source)
141 - }
136 + docengine::render_strict(source)
142 137 }
143 138
144 139 /// JSON-encode a string, for an `hx-vals` payload.