Skip to main content

max / makeover-webview

Say where a placeholder's way out landed placeholder_html_placed is the fourth of the placed family and the last one the described vocabulary needed: a way out is the one member a placeholder holds, `offering` places it, and a guard on it is a run of one. The range covers the `placeholder-action` wrapper as well as the markup inside it, because the wrapper is emitted only when there is something to put in it and goes when that goes. A caller compiling this into a template needs the bytes that actually disappear, not the ones it handed over.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session
https://claude.ai/code/session_01P8ostB2UmZJGj5WjSHRSot
Author: Max Johnson <me@maxj.phd> · 2026-09-08 21:17 UTC
Signed with PGP, not checked
Commit: 112216fd0389641c3ee0485bc676d97a7c9a0491
Parent: 32fcb8e
2 files changed, +38 insertions, -1 deletion
M Cargo.toml +1 -1
@@ -1,6 +1,6 @@
1 1 [package]
2 2 name = "makeover-webview"
3 - version = "0.75.1"
3 + version = "0.76.0"
4 4 edition = "2024"
5 5 # One copy of this renderer per dependency graph, enforced by cargo rather than
6 6 # by remembering. Two versions means the generated stylesheet and the emitted
@@ -75,6 +75,39 @@
75 75 action: Option<Markup<'_>>,
76 76 opts: &Emit,
77 77 out: &mut String,
78 + ) {
79 + emit_placeholder(state, message, action, opts, out, None);
80 + }
81 +
82 + /// A placeholder, saying where the way out landed.
83 + ///
84 + /// Byte-identical to [`placeholder_html_into`], and where there is a way out it
85 + /// sets `placed` to the offsets in `out` between which the whole
86 + /// `placeholder-action` block was written -- the wrapper included, since the
87 + /// wrapper is what goes with it. `None` stays `None` when there is no action.
88 + ///
89 + /// Same reason as the other placed forms in this crate: a caller compiling this
90 + /// markup into a template has to know which bytes the way out produced, and the
91 + /// way out is a caller-supplied string that may appear elsewhere in the
92 + /// document.
93 + pub fn placeholder_html_placed(
94 + state: Readiness,
95 + message: &str,
96 + action: Option<Markup<'_>>,
97 + opts: &Emit,
98 + out: &mut String,
99 + placed: &mut Option<core::ops::Range<usize>>,
100 + ) {
101 + emit_placeholder(state, message, action, opts, out, Some(placed));
102 + }
103 +
104 + fn emit_placeholder(
105 + state: Readiness,
106 + message: &str,
107 + action: Option<Markup<'_>>,
108 + opts: &Emit,
109 + out: &mut String,
110 + placed: Option<&mut Option<core::ops::Range<usize>>>,
78 111 ) {
79 112 if state.shows_content() {
80 113 return;
@@ -103,11 +136,15 @@
103 136 escape_into(message, out);
104 137 out.push_str("</p>");
105 138 if let Some(Markup(markup)) = action {
139 + let at = out.len();
106 140 out.push_str("<div class=\"");
107 141 push_class(out, "placeholder-action", opts);
108 142 out.push_str("\">");
109 143 out.push_str(markup);
110 144 out.push_str("</div>");
145 + if let Some(placed) = placed {
146 + *placed = Some(at..out.len());
147 + }
111 148 }
112 149 out.push_str("</div>");
113 150 }