diff --git a/crates/typst-html/src/convert.rs b/crates/typst-html/src/convert.rs
index 171b4cb7e..817b0f025 100644
--- a/crates/typst-html/src/convert.rs
+++ b/crates/typst-html/src/convert.rs
@@ -109,10 +109,7 @@ fn handle(
styles.chain(&style),
Region::new(Size::splat(Abs::inf()), Axes::splat(false)),
)?;
- output.push(HtmlNode::Frame(HtmlFrame {
- inner: frame,
- text_size: styles.resolve(TextElem::size),
- }));
+ output.push(HtmlNode::Frame(HtmlFrame::new(frame, styles)));
} else {
engine.sink.warn(warning!(
child.span(),
diff --git a/crates/typst-html/src/dom.rs b/crates/typst-html/src/dom.rs
index cf74e1bfc..d7287d42d 100644
--- a/crates/typst-html/src/dom.rs
+++ b/crates/typst-html/src/dom.rs
@@ -2,10 +2,11 @@ use std::fmt::{self, Debug, Display, Formatter};
use ecow::{EcoString, EcoVec};
use typst_library::diag::{bail, HintedStrResult, StrResult};
-use typst_library::foundations::{cast, Dict, Repr, Str};
+use typst_library::foundations::{cast, Dict, Repr, Str, StyleChain};
use typst_library::introspection::{Introspector, Tag};
use typst_library::layout::{Abs, Frame};
use typst_library::model::DocumentInfo;
+use typst_library::text::TextElem;
use typst_syntax::Span;
use typst_utils::{PicoStr, ResolvedPicoStr};
@@ -279,3 +280,10 @@ pub struct HtmlFrame {
/// consistently.
pub text_size: Abs,
}
+
+impl HtmlFrame {
+ /// Wraps a laid-out frame.
+ pub fn new(inner: Frame, styles: StyleChain) -> Self {
+ Self { inner, text_size: styles.resolve(TextElem::size) }
+ }
+}
diff --git a/crates/typst-html/src/encode.rs b/crates/typst-html/src/encode.rs
index be8137399..4447186b8 100644
--- a/crates/typst-html/src/encode.rs
+++ b/crates/typst-html/src/encode.rs
@@ -121,6 +121,7 @@ fn write_children(w: &mut Writer, element: &HtmlElement) -> SourceResult<()> {
let pretty_inside = allows_pretty_inside(element.tag)
&& element.children.iter().any(|node| match node {
HtmlNode::Element(child) => wants_pretty_around(child.tag),
+ HtmlNode::Frame(_) => true,
_ => false,
});
@@ -305,14 +306,6 @@ fn write_escape(w: &mut Writer, c: char) -> StrResult<()> {
/// Encode a laid out frame into the writer.
fn write_frame(w: &mut Writer, frame: &HtmlFrame) {
- // FIXME: This string replacement is obviously a hack.
- let svg = typst_svg::svg_frame(&frame.inner).replace(
- "