From df07ac2d09f0e29d40170a58f70e4bf88a659790 Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Tue, 3 Nov 2026 22:23:03 -0500 Subject: [PATCH] fix(engine): never let document text close the generated HTML style element (#1955) --- crates/engine/src/dev/codegen/html.rs | 5 ++++- crates/engine/src/html_codegen_tests.rs | 13 +++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/crates/engine/src/dev/codegen/html.rs b/crates/engine/src/dev/codegen/html.rs index d1b144cae..ac23e6a5b 100644 --- a/crates/engine/src/dev/codegen/html.rs +++ b/crates/engine/src/dev/codegen/html.rs @@ -90,7 +90,10 @@ pub(super) fn html(doc: &Document, id: NodeId) -> String { let ctx = Ctx::new(doc, id); let mut out = Markup::new(&ctx, CodeLang::Html); out.node(id, None, 0, ""); - format!("{}\n\n", out.markup, out.tokens.root_rule(), out.styles) + // Document text can reach the stylesheet through any property: `<\/` reads back as `\n{css}\n", out.markup) } /// Markup being built for a layer tree: HTML (`class`), React JSX (`className`), Vue diff --git a/crates/engine/src/html_codegen_tests.rs b/crates/engine/src/html_codegen_tests.rs index cd1318ee0..ab7115554 100644 --- a/crates/engine/src/html_codegen_tests.rs +++ b/crates/engine/src/html_codegen_tests.rs @@ -163,3 +163,16 @@ fn rem_preserves_text_property_default() { } } } + +#[test] +fn the_stylesheet_never_contains_a_closing_style_tag_from_document_text() { + let mut s = Session::new(); + let f = id(s.execute("frame.create", &json!({"x": 0, "y": 0, "width": 100, "height": 100})).unwrap()); + let t = id(s.execute("text.create", &json!({"text": "x", "x": 0, "y": 0})).unwrap()); + s.execute("node.set", &json!({"id": t, "props": {"fontFamily": "a"}})).unwrap(); + s.execute("node.reparent", &json!({"ids": [t], "parent": f})).unwrap(); + let code = code_for(s.doc().unwrap(), f, CodeLang::Html); + let (_, css) = code.split_once("").count(), 1, "{code}"); + assert!(!code.contains("