diff --git a/crates/typst-html/src/convert.rs b/crates/typst-html/src/convert.rs
index 208ea3dd3..65a4dabab 100644
--- a/crates/typst-html/src/convert.rs
+++ b/crates/typst-html/src/convert.rs
@@ -3,13 +3,12 @@ use typst_library::diag::{SourceResult, warning};
use typst_library::engine::Engine;
use typst_library::foundations::{Content, StyleChain, Target, TargetElem};
use typst_library::introspection::{SplitLocator, TagElem};
-use typst_library::layout::{Abs, Axes, BlockBody, BlockElem, BoxElem, Region, Size};
-use typst_library::model::ParElem;
+use typst_library::layout::{Abs, Axes, Region, Size};
use typst_library::routines::Pair;
use typst_library::text::{LinebreakElem, SmartQuoteElem, SpaceElem, TextElem};
use crate::fragment::html_fragment;
-use crate::{FrameElem, HtmlElem, HtmlElement, HtmlFrame, HtmlNode, attr, tag};
+use crate::{FrameElem, HtmlElem, HtmlElement, HtmlFrame, HtmlNode, tag};
/// Converts realized content into HTML nodes.
pub fn convert_to_nodes<'a>(
@@ -46,44 +45,6 @@ fn handle(
span: elem.span(),
};
output.push(element.into());
- } else if let Some(elem) = child.to_packed::() {
- let children =
- html_fragment(engine, &elem.body, locator.next(&elem.span()), styles)?;
- output.push(
- HtmlElement::new(tag::p)
- .with_children(children)
- .spanned(elem.span())
- .into(),
- );
- } else if let Some(elem) = child.to_packed::() {
- // TODO: This is rather incomplete.
- if let Some(body) = elem.body.get_ref(styles) {
- let children =
- html_fragment(engine, body, locator.next(&elem.span()), styles)?;
- output.push(
- HtmlElement::new(tag::span)
- .with_attr(attr::style, "display: inline-block;")
- .with_children(children)
- .spanned(elem.span())
- .into(),
- )
- }
- } else if let Some((elem, body)) =
- child
- .to_packed::()
- .and_then(|elem| match elem.body.get_ref(styles) {
- Some(BlockBody::Content(body)) => Some((elem, body)),
- _ => None,
- })
- {
- // TODO: This is rather incomplete.
- let children = html_fragment(engine, body, locator.next(&elem.span()), styles)?;
- output.push(
- HtmlElement::new(tag::div)
- .with_children(children)
- .spanned(elem.span())
- .into(),
- );
} else if child.is::() {
output.push(HtmlNode::text(' ', child.span()));
} else if let Some(elem) = child.to_packed::() {
diff --git a/crates/typst-html/src/rules.rs b/crates/typst-html/src/rules.rs
index 472e155b0..c30e8bd5f 100644
--- a/crates/typst-html/src/rules.rs
+++ b/crates/typst-html/src/rules.rs
@@ -1,17 +1,17 @@
use std::num::NonZeroUsize;
use ecow::{EcoVec, eco_format};
-use typst_library::diag::{At, warning};
+use typst_library::diag::{At, bail, warning};
use typst_library::foundations::{
Content, NativeElement, NativeRuleMap, ShowFn, Smart, StyleChain, Target,
};
use typst_library::introspection::{Counter, Locator};
use typst_library::layout::resolve::{Cell, CellGrid, Entry, table_to_cellgrid};
-use typst_library::layout::{OuterVAlignment, Sizing};
+use typst_library::layout::{BlockBody, BlockElem, BoxElem, OuterVAlignment, Sizing};
use typst_library::model::{
Attribution, CiteElem, CiteGroup, Destination, EmphElem, EnumElem, FigureCaption,
- FigureElem, HeadingElem, LinkElem, LinkTarget, ListElem, ParbreakElem, QuoteElem,
- RefElem, StrongElem, TableCell, TableElem, TermsElem, TitleElem,
+ FigureElem, HeadingElem, LinkElem, LinkTarget, ListElem, ParElem, ParbreakElem,
+ QuoteElem, RefElem, StrongElem, TableCell, TableElem, TermsElem, TitleElem,
};
use typst_library::text::{
HighlightElem, LinebreakElem, OverlineElem, RawElem, RawLine, SmallcapsElem,
@@ -26,6 +26,7 @@ pub fn register(rules: &mut NativeRuleMap) {
use Target::{Html, Paged};
// Model.
+ rules.register(Html, PAR_RULE);
rules.register(Html, STRONG_RULE);
rules.register(Html, EMPH_RULE);
rules.register(Html, LIST_RULE);
@@ -52,6 +53,10 @@ pub fn register(rules: &mut NativeRuleMap) {
rules.register(Html, RAW_RULE);
rules.register(Html, RAW_LINE_RULE);
+ // Layout.
+ rules.register(Html, BLOCK_RULE);
+ rules.register(Html, BOX_RULE);
+
// Visualize.
rules.register(Html, IMAGE_RULE);
@@ -61,6 +66,9 @@ pub fn register(rules: &mut NativeRuleMap) {
rules.register::(Paged, |elem, _, _| Ok(elem.body.clone()));
}
+const PAR_RULE: ShowFn =
+ |elem, _, _| Ok(HtmlElem::new(tag::p).with_body(Some(elem.body.clone())).pack());
+
const STRONG_RULE: ShowFn =
|elem, _, _| Ok(HtmlElem::new(tag::strong).with_body(Some(elem.body.clone())).pack());
@@ -454,6 +462,32 @@ pub fn html_span_filled(content: Content, color: Color) -> Content {
const RAW_LINE_RULE: ShowFn = |elem, _, _| Ok(elem.body.clone());
+// TODO: This is rather incomplete.
+const BLOCK_RULE: ShowFn = |elem, _, styles| {
+ let body = match elem.body.get_cloned(styles) {
+ None => None,
+ Some(BlockBody::Content(body)) => Some(body),
+ // These are only generated by native `typst-layout` show rules.
+ Some(BlockBody::SingleLayouter(_) | BlockBody::MultiLayouter(_)) => {
+ bail!(
+ elem.span(),
+ "blocks with layout routines should not occur in \
+ HTML export – this is a bug"
+ )
+ }
+ };
+
+ Ok(HtmlElem::new(tag::div).with_body(body).pack())
+};
+
+// TODO: This is rather incomplete.
+const BOX_RULE: ShowFn = |elem, _, styles| {
+ Ok(HtmlElem::new(tag::span)
+ .with_styles(css::Properties::new().with("display", "inline-block"))
+ .with_body(elem.body.get_cloned(styles))
+ .pack())
+};
+
const IMAGE_RULE: ShowFn = |elem, engine, styles| {
let image = elem.decode(engine, styles)?;
diff --git a/tests/ref/html/box-html.html b/tests/ref/html/box-html.html
index b2a26533b..7e860255b 100644
--- a/tests/ref/html/box-html.html
+++ b/tests/ref/html/box-html.html
@@ -5,6 +5,6 @@
- Text Span.
+ Text Span.