Skip to main content

max / makeover-webview

Mark a datetime that asks to be submitted as an instant makeover-layout 0.37.0's Field::as_instant. `<input type="datetime-local">` submits what the user typed and nothing in HTML turns it into a moment, so in a browser the conversion is script's. This emits the mark; quasi-webview's script does the converting, the same division as data-clock, where the markup says what to do and the shipped script is what a browser knows that a description cannot. Only DateTime is marked. A date and a time are each half a moment and cannot name one on their own, so the flag is ignored there rather than emitting a mark nothing can honour. Takes makeover-touch 0.27.0 along with it: one makeover-layout per graph.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-08-28 15:00 UTC
Signed with PGP, not checked
Commit: 18c1e2dd7defb193aa963da5af56043b6c64f0ad
Parent: b92f759
2 files changed, +48 insertions, -3 deletions
M Cargo.toml +3 -3
@@ -1,6 +1,6 @@
1 1 [package]
2 2 name = "makeover-webview"
3 - version = "0.62.0"
3 + version = "0.63.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
@@ -17,7 +17,7 @@
17 17 # patch satisfy the requirement and still fail to compile. That happened once
18 18 # with `form::radio_html` calling `FieldKind::Radio`, and makeover-build is where
19 19 # it surfaced, one release later.
20 - makeover-layout = "0.36.0"
20 + makeover-layout = "0.37.0"
21 21 # The capability axis. `makeover-touch` decides whether a hover rule should be
22 22 # gated at all; `makeover-geometry` spells the gate as a media condition. Both
23 23 # answers are owned elsewhere and neither is re-derived here.
@@ -27,7 +27,7 @@
27 27 # satisfies "0.8" and keeps a second makeover-geometry in the graph next to the
28 28 # 0.7 this crate asks for. `Density` is nominally distinct across the two and
29 29 # the build fails on a type that reads as identical.
30 - makeover-touch = "0.26.0"
30 + makeover-touch = "0.27.0"
31 31 makeover-geometry = "0.7"
32 32
33 33 [lints.rust]
M src/form.rs +45
@@ -422,6 +422,20 @@
422 422 let _ = write!(out, " maxlength=\"{limit}\"");
423 423 }
424 424 push_bounds(out, field);
425 + // The description asks for the wall-clock value to be submitted as the
426 + // moment it names, and in a browser that conversion is script's: `<input
427 + // type="datetime-local">` submits what the user typed and nothing in HTML
428 + // turns it into an instant. So this emits the mark and quasi-webview's
429 + // `instant.js` does the converting -- the same division as `data-clock`,
430 + // where the markup says what to do and the shipped script is what a browser
431 + // knows that a description cannot.
432 + //
433 + // Only DateTime. A date and a time are each half a moment and cannot name
434 + // one on their own, so the flag is ignored there rather than emitting a
435 + // mark nothing can honour.
436 + if field.as_instant && matches!(field.kind, FieldKind::DateTime) {
437 + out.push_str(" data-instant=\"true\"");
438 + }
425 439 if field.invalid() {
426 440 out.push_str(" aria-invalid=\"true\"");
427 441 }
@@ -2127,6 +2141,37 @@
2127 2141 assert!(html.contains("class=\"mk-field\""), "{html}");
2128 2142 }
2129 2143
2144 + #[test]
2145 + fn a_datetime_asking_for_an_instant_is_marked_for_the_script_that_converts_it() {
2146 + let mut f = field(FieldKind::DateTime);
2147 + f.as_instant = true;
2148 + let html = field_html(&f, &Filling::default(), &Emit::default());
2149 + assert!(html.contains("data-instant=\"true\""), "{html}");
2150 + // The control is unchanged: the flag says what is submitted, not what
2151 + // is drawn.
2152 + assert!(html.contains("type=\"datetime-local\""), "{html}");
2153 + }
2154 +
2155 + #[test]
2156 + fn only_a_datetime_can_name_a_moment_so_only_a_datetime_is_marked() {
2157 + for kind in [FieldKind::Date, FieldKind::Text, FieldKind::Number] {
2158 + let mut f = field(kind);
2159 + f.as_instant = true;
2160 + let html = field_html(&f, &Filling::default(), &Emit::default());
2161 + assert!(!html.contains("data-instant"), "{kind:?}: {html}");
2162 + }
2163 + }
2164 +
2165 + #[test]
2166 + fn a_datetime_that_did_not_ask_carries_no_mark() {
2167 + let html = field_html(
2168 + &field(FieldKind::DateTime),
2169 + &Filling::default(),
2170 + &Emit::default(),
2171 + );
2172 + assert!(!html.contains("data-instant"), "{html}");
2173 + }
2174 +
2130 2175 #[test]
2131 2176 fn an_extended_field_says_so_and_leaves_the_disclosure_to_the_form() {
2132 2177 let mut f = field(FieldKind::Text);