max / makeover-webview
- Co-Authored-By
- Claude Opus 5 (1M context) <noreply@anthropic.com>
1 file changed,
+46 insertions,
-8 deletions
| @@ -401,6 +401,14 @@ | |||
| 401 | 401 | // `tables.css` in its own build.rs from [`list::narrowing_css`], and those | |
| 402 | 402 | // rules are as generated as the ones here. | |
| 403 | 403 | pub use makeover_geometry::{CSS_LAYER, in_css_layer}; | |
| 404 | + | ||
| 405 | + | /// This crate's version, as the generated stylesheet reports it. | |
| 406 | + | /// | |
| 407 | + | /// A consumer whose lockfile still pins an old `makeover-webview` gets a | |
| 408 | + | /// well-formed sheet with components missing and no error anywhere, so the | |
| 409 | + | /// emitter has to name itself in what it writes. Read by | |
| 410 | + | /// `makeover_build::layout_css` through [`stylesheet`]. | |
| 411 | + | pub const VERSION: &str = env!("CARGO_PKG_VERSION"); | |
| 404 | 412 | use makeover_layout::{ | |
| 405 | 413 | Bevel, CellPart, Depth, Fallback, Fill, Flow, Intent, RowPart, Selector, Sort, State, Token, | |
| 406 | 414 | Tone, | |
| @@ -1762,20 +1770,29 @@ | |||
| 1762 | 1770 | /// an at-rule. | |
| 1763 | 1771 | #[must_use] | |
| 1764 | 1772 | pub fn stylesheet(opts: &Emit) -> String { | |
| 1773 | + | let body = in_css_layer(&format!( | |
| 1774 | + | ":root {{\n{}}}\n\n{}\n{}", | |
| 1775 | + | bevel_properties(opts), | |
| 1776 | + | depth_rules(opts), | |
| 1777 | + | component_rules(opts) | |
| 1778 | + | )); | |
| 1779 | + | // Counted from the body rather than through `vocabulary::names`, which | |
| 1780 | + | // calls back into here. | |
| 1781 | + | let classes = vocabulary::classes_in_css(&body).len(); | |
| 1782 | + | let version = VERSION; | |
| 1765 | 1783 | format!( | |
| 1766 | - | "/* Generated by makeover-webview from makeover-layout. Do not edit.\n \ | |
| 1784 | + | "/* Generated by makeover-webview {version} from makeover-layout, \ | |
| 1785 | + | {classes} classes.\n \ | |
| 1786 | + | Do not edit. The version and the count are here because a stale\n \ | |
| 1787 | + | lockfile fails silently: an older emitter writes a well-formed sheet\n \ | |
| 1788 | + | with components missing, and nothing else in the file says so. If\n \ | |
| 1789 | + | this version trails what the manifest asks for, re-resolve.\n\n \ | |
| 1767 | 1790 | Depth is a fill and an edge together; naming them apart is what let\n \ | |
| 1768 | 1791 | them disagree. See the crate's README and wiki note makeover-layout.\n\n \ | |
| 1769 | 1792 | Everything below is in the `{CSS_LAYER}` cascade layer. Declare the\n \ | |
| 1770 | 1793 | order once in your own stylesheet, or this layer's position is decided\n \ | |
| 1771 | 1794 | by whichever generated file the browser happens to see first:\n\n \ | |
| 1772 | - | @layer {CSS_LAYER}, base, components, responsive; */\n{}", | |
| 1773 | - | in_css_layer(&format!( | |
| 1774 | - | ":root {{\n{}}}\n\n{}\n{}", | |
| 1775 | - | bevel_properties(opts), | |
| 1776 | - | depth_rules(opts), | |
| 1777 | - | component_rules(opts) | |
| 1778 | - | )) | |
| 1795 | + | @layer {CSS_LAYER}, base, components, responsive; */\n{body}" | |
| 1779 | 1796 | ) | |
| 1780 | 1797 | } | |
| 1781 | 1798 | ||
| @@ -2032,6 +2049,27 @@ | |||
| 2032 | 2049 | assert!(css.starts_with("/* Generated by makeover-webview")); | |
| 2033 | 2050 | } | |
| 2034 | 2051 | ||
| 2052 | + | #[test] | |
| 2053 | + | fn the_banner_names_the_emitter_so_a_stale_pin_is_visible_on_sight() { | |
| 2054 | + | // A consumer whose lockfile pins an old version gets a well-formed | |
| 2055 | + | // sheet with components missing and no error. balanced_breakfast ran | |
| 2056 | + | // on 657 bytes from a 0.1.0 emitter while its manifest asked for | |
| 2057 | + | // 0.5.1, and the only way it surfaced was diffing two apps' generated | |
| 2058 | + | // files. The version and the count are what the file says instead. | |
| 2059 | + | let css = stylesheet(&Emit::default()); | |
| 2060 | + | let banner = css.lines().next().unwrap(); | |
| 2061 | + | assert!( | |
| 2062 | + | banner.contains(VERSION), | |
| 2063 | + | "{banner} does not name the emitter" | |
| 2064 | + | ); | |
| 2065 | + | let classes = vocabulary::classes_in_css(&css).len(); | |
| 2066 | + | assert!(classes > 0); | |
| 2067 | + | assert!( | |
| 2068 | + | banner.contains(&format!("{classes} classes")), | |
| 2069 | + | "{banner} does not carry the class count" | |
| 2070 | + | ); | |
| 2071 | + | } | |
| 2072 | + | ||
| 2035 | 2073 | #[test] | |
| 2036 | 2074 | fn a_primitive_owns_every_state_it_implies() { | |
| 2037 | 2075 | // The whole point of 0.10.0. Anything emitting a hover rule owes the |