Consistent sizing for html.frame (#6505)

This commit is contained in:
Laurenz 2025-06-26 10:07:41 +02:00 committed by GitHub
parent 35809387f8
commit 6a1d6c08e2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 30 additions and 11 deletions

View File

@ -3,9 +3,8 @@ use std::fmt::Write;
use typst_library::diag::{bail, At, SourceResult, StrResult};
use typst_library::foundations::Repr;
use typst_library::html::{
attr, charsets, tag, HtmlDocument, HtmlElement, HtmlNode, HtmlTag,
attr, charsets, tag, HtmlDocument, HtmlElement, HtmlFrame, HtmlNode, HtmlTag,
};
use typst_library::layout::Frame;
use typst_syntax::Span;
/// Encodes an HTML document into a string.
@ -304,9 +303,15 @@ fn write_escape(w: &mut Writer, c: char) -> StrResult<()> {
}
/// Encode a laid out frame into the writer.
fn write_frame(w: &mut Writer, frame: &Frame) {
fn write_frame(w: &mut Writer, frame: &HtmlFrame) {
// FIXME: This string replacement is obviously a hack.
let svg = typst_svg::svg_frame(frame)
.replace("<svg class", "<svg style=\"overflow: visible;\" class");
let svg = typst_svg::svg_frame(&frame.inner).replace(
"<svg class",
&format!(
"<svg style=\"overflow: visible; width: {}em; height: {}em;\" class",
frame.inner.width() / frame.text_size,
frame.inner.height() / frame.text_size,
),
);
w.buf.push_str(&svg);
}

View File

@ -9,7 +9,7 @@ use typst_library::diag::{bail, warning, At, SourceResult};
use typst_library::engine::{Engine, Route, Sink, Traced};
use typst_library::foundations::{Content, StyleChain, Target, TargetElem};
use typst_library::html::{
attr, tag, FrameElem, HtmlDocument, HtmlElem, HtmlElement, HtmlNode,
attr, tag, FrameElem, HtmlDocument, HtmlElem, HtmlElement, HtmlFrame, HtmlNode,
};
use typst_library::introspection::{
Introspector, Locator, LocatorLink, SplitLocator, TagElem,
@ -246,7 +246,10 @@ fn handle(
styles.chain(&style),
Region::new(Size::splat(Abs::inf()), Axes::splat(false)),
)?;
output.push(HtmlNode::Frame(frame));
output.push(HtmlNode::Frame(HtmlFrame {
inner: frame,
text_size: TextElem::size_in(styles),
}));
} else {
engine.sink.warn(warning!(
child.span(),

View File

@ -7,7 +7,7 @@ use typst_utils::{PicoStr, ResolvedPicoStr};
use crate::diag::{bail, HintedStrResult, StrResult};
use crate::foundations::{cast, Dict, Repr, Str};
use crate::introspection::{Introspector, Tag};
use crate::layout::Frame;
use crate::layout::{Abs, Frame};
use crate::model::DocumentInfo;
/// An HTML document.
@ -30,8 +30,8 @@ pub enum HtmlNode {
Text(EcoString, Span),
/// Another element.
Element(HtmlElement),
/// A frame that will be displayed as an embedded SVG.
Frame(Frame),
/// Layouted content that will be embedded into HTML as an SVG.
Frame(HtmlFrame),
}
impl HtmlNode {
@ -263,6 +263,17 @@ cast! {
v: Str => Self::intern(&v)?,
}
/// Layouted content that will be embedded into HTML as an SVG.
#[derive(Debug, Clone, Hash)]
pub struct HtmlFrame {
/// The frame that will be displayed as an SVG.
pub inner: Frame,
/// The text size where the frame was defined. This is used to size the
/// frame with em units to make text in and outside of the frame sized
/// consistently.
pub text_size: Abs,
}
/// Defines syntactical properties of HTML tags, attributes, and text.
pub mod charsets {
/// Check whether a character is in a tag name.

View File

@ -446,7 +446,7 @@ impl IntrospectorBuilder {
HtmlNode::Element(elem) => self.discover_in_html(sink, &elem.children),
HtmlNode::Frame(frame) => self.discover_in_frame(
sink,
frame,
&frame.inner,
NonZeroUsize::ONE,
Transform::identity(),
),