diff --git a/crates/typst-html/src/lib.rs b/crates/typst-html/src/lib.rs
index aa769976e..0e3833400 100644
--- a/crates/typst-html/src/lib.rs
+++ b/crates/typst-html/src/lib.rs
@@ -5,9 +5,12 @@ mod encode;
pub use self::encode::html;
use comemo::{Track, Tracked, TrackedMut};
-use typst_library::diag::{bail, warning, At, SourceResult};
+pub use ecow::EcoVec;
+use typst_library::diag::{bail, warning, At, SourceDiagnostic, SourceResult, StrResult};
use typst_library::engine::{Engine, Route, Sink, Traced};
-use typst_library::foundations::{Content, StyleChain, Target, TargetElem};
+use typst_library::foundations::{
+ Content, Datetime, Smart, StyleChain, Target, TargetElem,
+};
use typst_library::html::{
attr, tag, FrameElem, HtmlDocument, HtmlElem, HtmlElement, HtmlNode,
};
@@ -84,7 +87,7 @@ fn html_document_impl(
let output = handle_list(&mut engine, &mut locator, children.iter().copied())?;
let introspector = Introspector::html(&output);
- let root = root_element(output, &info)?;
+ let root = root_element(&mut engine, output, &info)?;
Ok(HtmlDocument { info, root, introspector })
}
@@ -262,18 +265,24 @@ fn handle(
/// Wrap the nodes in `` and `
` if they are not yet rooted,
/// supplying a suitable ``.
-fn root_element(output: Vec, info: &DocumentInfo) -> SourceResult {
+fn root_element(
+ engine: &mut Engine,
+ output: Vec,
+ info: &DocumentInfo,
+) -> SourceResult {
+ let head = head_element(engine, info).map_err(|err| {
+ EcoVec::from([SourceDiagnostic::warning(Span::detached(), err)])
+ })?;
let body = match classify_output(output)? {
OutputKind::Html(element) => return Ok(element),
OutputKind::Body(body) => body,
OutputKind::Leafs(leafs) => HtmlElement::new(tag::body).with_children(leafs),
};
- Ok(HtmlElement::new(tag::html)
- .with_children(vec![head_element(info).into(), body.into()]))
+ Ok(HtmlElement::new(tag::html).with_children(vec![head.into(), body.into()]))
}
/// Generate a `` element.
-fn head_element(info: &DocumentInfo) -> HtmlElement {
+fn head_element(engine: &mut Engine, info: &DocumentInfo) -> StrResult {
let mut children = vec![];
children.push(HtmlElement::new(tag::meta).with_attr(attr::charset, "utf-8").into());
@@ -302,7 +311,47 @@ fn head_element(info: &DocumentInfo) -> HtmlElement {
);
}
- HtmlElement::new(tag::head).with_children(children)
+ if !info.author.is_empty() {
+ children.push(
+ HtmlElement::new(tag::meta)
+ .with_attr(attr::name, "authors")
+ .with_attr(attr::content, info.author.join(", "))
+ .into(),
+ )
+ }
+
+ if !info.keywords.is_empty() {
+ children.push(
+ HtmlElement::new(tag::meta)
+ .with_attr(attr::name, "keywords")
+ .with_attr(attr::content, info.keywords.join(", "))
+ .into(),
+ )
+ }
+
+ match info.date {
+ Smart::Auto => children.push(
+ HtmlElement::new(tag::meta)
+ .with_attr(attr::name, "date")
+ .with_attr(
+ attr::content,
+ Datetime::today(engine, Smart::Auto)?.display(Smart::Auto)?,
+ )
+ .into(),
+ ),
+ Smart::Custom(optional_date) => {
+ if let Some(date) = optional_date {
+ children.push(
+ HtmlElement::new(tag::meta)
+ .with_attr(attr::name, "date")
+ .with_attr(attr::content, date.display(Smart::Auto).unwrap())
+ .into(),
+ )
+ }
+ }
+ }
+
+ Ok(HtmlElement::new(tag::head).with_children(children))
}
/// Determine which kind of output the user generated.
diff --git a/tests/ref/html/basic-table.html b/tests/ref/html/basic-table.html
index 189a5b314..7d0bf1c50 100644
--- a/tests/ref/html/basic-table.html
+++ b/tests/ref/html/basic-table.html
@@ -3,6 +3,7 @@
+
diff --git a/tests/ref/html/block-html.html b/tests/ref/html/block-html.html
index d1716c6d7..93a792a08 100644
--- a/tests/ref/html/block-html.html
+++ b/tests/ref/html/block-html.html
@@ -3,6 +3,7 @@
+
Paragraph
diff --git a/tests/ref/html/box-html.html b/tests/ref/html/box-html.html
index b2a26533b..0bedecd74 100644
--- a/tests/ref/html/box-html.html
+++ b/tests/ref/html/box-html.html
@@ -3,6 +3,7 @@
+
Text Span.
diff --git a/tests/ref/html/col-gutter-table.html b/tests/ref/html/col-gutter-table.html
index 54170f534..d78ff99e1 100644
--- a/tests/ref/html/col-gutter-table.html
+++ b/tests/ref/html/col-gutter-table.html
@@ -3,6 +3,7 @@
+
diff --git a/tests/ref/html/col-row-gutter-table.html b/tests/ref/html/col-row-gutter-table.html
index 54170f534..d78ff99e1 100644
--- a/tests/ref/html/col-row-gutter-table.html
+++ b/tests/ref/html/col-row-gutter-table.html
@@ -3,6 +3,7 @@
+
diff --git a/tests/ref/html/enum-par.html b/tests/ref/html/enum-par.html
index 60d4592b7..25ebb1037 100644
--- a/tests/ref/html/enum-par.html
+++ b/tests/ref/html/enum-par.html
@@ -3,6 +3,7 @@
+
diff --git a/tests/ref/html/enum-start.html b/tests/ref/html/enum-start.html
index fc9b3c061..b4abaa77b 100644
--- a/tests/ref/html/enum-start.html
+++ b/tests/ref/html/enum-start.html
@@ -3,6 +3,7 @@
+
diff --git a/tests/ref/html/heading-html-basic.html b/tests/ref/html/heading-html-basic.html
index 54a22faf4..7c1762789 100644
--- a/tests/ref/html/heading-html-basic.html
+++ b/tests/ref/html/heading-html-basic.html
@@ -3,6 +3,7 @@
+
Level 1
diff --git a/tests/ref/html/link-basic.html b/tests/ref/html/link-basic.html
index 89cb54db5..6be58d33d 100644
--- a/tests/ref/html/link-basic.html
+++ b/tests/ref/html/link-basic.html
@@ -3,6 +3,7 @@
+
https://example.com/
diff --git a/tests/ref/html/list-par.html b/tests/ref/html/list-par.html
index 7c747ff44..813562ee5 100644
--- a/tests/ref/html/list-par.html
+++ b/tests/ref/html/list-par.html
@@ -3,6 +3,7 @@
+
diff --git a/tests/ref/html/par-semantic-html.html b/tests/ref/html/par-semantic-html.html
index 09c7d2fd0..80dfcc70f 100644
--- a/tests/ref/html/par-semantic-html.html
+++ b/tests/ref/html/par-semantic-html.html
@@ -3,6 +3,7 @@
+
Heading is no paragraph
diff --git a/tests/ref/html/quote-attribution-link.html b/tests/ref/html/quote-attribution-link.html
index c12d2ae2d..809fac6cc 100644
--- a/tests/ref/html/quote-attribution-link.html
+++ b/tests/ref/html/quote-attribution-link.html
@@ -3,6 +3,7 @@
+
Compose papers faster
diff --git a/tests/ref/html/quote-nesting-html.html b/tests/ref/html/quote-nesting-html.html
index 6b05a94a0..9a9a383b8 100644
--- a/tests/ref/html/quote-nesting-html.html
+++ b/tests/ref/html/quote-nesting-html.html
@@ -3,6 +3,7 @@
+
When you said that “he surely meant that ‘she intended to say “I'm sorry”’”, I was quite confused.
diff --git a/tests/ref/html/quote-plato.html b/tests/ref/html/quote-plato.html
index 039835082..a4fdcccff 100644
--- a/tests/ref/html/quote-plato.html
+++ b/tests/ref/html/quote-plato.html
@@ -3,6 +3,7 @@
+
… ἔοικα γοῦν τούτου γε σμικρῷ τινι αὐτῷ τούτῳ σοφώτερος εἶναι, ὅτι ἃ μὴ οἶδα οὐδὲ οἴομαι εἰδέναι.
diff --git a/tests/ref/html/row-gutter-table.html b/tests/ref/html/row-gutter-table.html
index 54170f534..d78ff99e1 100644
--- a/tests/ref/html/row-gutter-table.html
+++ b/tests/ref/html/row-gutter-table.html
@@ -3,6 +3,7 @@
+
diff --git a/tests/ref/html/terms-par.html b/tests/ref/html/terms-par.html
index 78bc5df16..a070aa919 100644
--- a/tests/ref/html/terms-par.html
+++ b/tests/ref/html/terms-par.html
@@ -3,6 +3,7 @@
+