Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 42 additions & 16 deletions src/rs/formats/epub/xhtml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,28 @@ use markup5ever_rcdom::{Handle, NodeData, RcDom};
use std::{fmt::Write, slice};
use typst::diag::EcoString;

/// Returns true if the given tag name is an HTML void element.
/// Void elements are self-closing and cannot have children.
fn is_void_element(tag_name: &str) -> bool {
matches!(
tag_name,
"area"
| "base"
| "br"
| "col"
| "embed"
| "hr"
| "img"
| "input"
| "link"
| "meta"
| "param"
| "source"
| "track"
| "wbr"
)
}

/// Metadata about features used by the HTML generated by Typst.
pub struct HtmlInfo {
/// True if the document uses Javascript in any way.
Expand Down Expand Up @@ -102,25 +124,29 @@ pub fn html_to_portable_xhtml(html_string: &str, heading_ids: &[EcoString]) -> (
write!(self.buf, " id=\"{id}\"").unwrap();
}

write!(self.buf, ">").unwrap();
// Void elements use self-closing syntax in XHTML.
if is_void_element(&name.local) {
write!(self.buf, "/>").unwrap();
} else {
write!(self.buf, ">").unwrap();

// Wrap the children of the body in an <article>.
//
// TODO: should this be done within the Typst generator?
if &name.local == "body" {
self.buf.push_str("<article>");
}
// Wrap the children of the body in an <article>.
//
// TODO: should this be done within the Typst generator?
if &name.local == "body" {
self.buf.push_str("<article>");
}

for child in handle.children.borrow().iter() {
self.walk(child);
}
for child in handle.children.borrow().iter() {
self.walk(child);
}

if &name.local == "body" {
self.buf.push_str("</article>");
}
if &name.local == "body" {
self.buf.push_str("</article>");
}

// Unconditionally close all tags, to handle case like unclosed `<p>` or `<meta>`.
write!(self.buf, "</{}>", name.local).unwrap();
write!(self.buf, "</{}>", name.local).unwrap();
}
}

_ => {}
Expand Down Expand Up @@ -158,7 +184,7 @@ fn test_html_to_xhtml() {
let expected = r#"<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head>
<meta name="foo" content="bar"></meta>
<meta name="foo" content="bar"/>
</head>
<body><article>
<h2 id="test">Test</h2>
Expand Down
2 changes: 1 addition & 1 deletion tests/ref/examples/blog_post/epub/blog_post.metadata.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"filetype": "epub",
"file_size": 6720367,
"file_size": 6720194,
"title": "Blog Post",
"language": "en",
"spine_files": [
Expand Down
32 changes: 16 additions & 16 deletions tests/ref/examples/blog_post/epub/xhtml/portable_epubs.xhtml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion tests/ref/examples/blog_site/epub/blog_site.metadata.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"filetype": "epub",
"file_size": 4665720,
"file_size": 4665620,
"title": "Screening the Subject | Severance",
"language": "en",
"spine_files": [
Expand Down
14 changes: 7 additions & 7 deletions tests/ref/examples/blog_site/epub/xhtml/severance-ep-1.xhtml

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions tests/ref/examples/blog_site/epub/xhtml/severance-ep-2.xhtml

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions tests/ref/examples/blog_site/epub/xhtml/severance-ep-3.xhtml

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"filetype": "epub",
"file_size": 4112,
"file_size": 4076,
"title": "Epub Inferred Spine",
"language": "en",
"spine_files": [
Expand Down
4 changes: 2 additions & 2 deletions tests/ref/examples/epub_inferred_spine/epub/xhtml/a.xhtml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head>
<meta charset="utf-8"></meta>
<meta name="viewport" content="width=device-width, initial-scale=1"></meta>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Part A</title>
</head>
<body><article>
Expand Down
4 changes: 2 additions & 2 deletions tests/ref/examples/epub_inferred_spine/epub/xhtml/b.xhtml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head>
<meta charset="utf-8"></meta>
<meta name="viewport" content="width=device-width, initial-scale=1"></meta>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Part B</title>
</head>
<body><article>
Expand Down
4 changes: 2 additions & 2 deletions tests/ref/examples/epub_inferred_spine/epub/xhtml/c.xhtml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head>
<meta charset="utf-8"></meta>
<meta name="viewport" content="width=device-width, initial-scale=1"></meta>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Part C</title>
</head>
<body><article>
Expand Down
2 changes: 1 addition & 1 deletion tests/ref/examples/fcl_site/epub/fcl_site.metadata.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"filetype": "epub",
"file_size": 1307566,
"file_size": 1307535,
"title": "The Free Computing Lab",
"language": "en",
"spine_files": [
Expand Down
10 changes: 5 additions & 5 deletions tests/ref/examples/fcl_site/epub/xhtml/index.xhtml

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"filetype": "epub",
"file_size": 4042,
"file_size": 4018,
"title": "Link Transformation Test",
"language": "en",
"spine_files": [
Expand Down
4 changes: 2 additions & 2 deletions tests/ref/examples/link_transformation/epub/xhtml/doc1.xhtml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head>
<meta charset="utf-8"></meta>
<meta name="viewport" content="width=device-width, initial-scale=1"></meta>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
</head>
<body><article>
<h2 id="document-1">Document 1</h2>
Expand Down
4 changes: 2 additions & 2 deletions tests/ref/examples/link_transformation/epub/xhtml/doc2.xhtml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head>
<meta charset="utf-8"></meta>
<meta name="viewport" content="width=device-width, initial-scale=1"></meta>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
</head>
<body><article>
<h2 id="document-2">Document 2</h2>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"filetype": "epub",
"file_size": 4412,
"file_size": 4388,
"title": "Links with Fragments Test",
"language": "en",
"spine_files": [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head>
<meta charset="utf-8"></meta>
<meta name="viewport" content="width=device-width, initial-scale=1"></meta>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
</head>
<body><article>
<h2 id="page-1">Page 1</h2>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head>
<meta charset="utf-8"></meta>
<meta name="viewport" content="width=device-width, initial-scale=1"></meta>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
</head>
<body><article>
<h2 id="page-2">Page 2</h2>
Expand Down
2 changes: 1 addition & 1 deletion tests/ref/examples/rheo_docs/epub/rheo_docs.metadata.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"filetype": "epub",
"file_size": 53115,
"file_size": 52727,
"title": "Rheo Manual",
"language": "en",
"spine_files": [
Expand Down
6 changes: 3 additions & 3 deletions tests/ref/examples/rheo_docs/epub/xhtml/build-dir.xhtml
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head>
<meta charset="utf-8"></meta>
<meta name="viewport" content="width=device-width, initial-scale=1"></meta>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Build directory</title>
</head>
<body><article>
<h2 id="build-directory">Build directory</h2>
<p>Rheo produces outputs in a simple directory structure with one subdirectory for each kind of output. By default, Rheo produces all outputs (PDF, HTML, and EPUB) in a <code>build</code> directory instide the project directory:</p>
<pre><code>build/<br></br>├── epub<br></br>│   └── blog_post.epub<br></br>├── html<br></br>│   ├── portable_epubs.html<br></br>│   └── style.css<br></br>└── pdf<br></br> └── portable_epubs.pdf</code></pre>
<pre><code>build/<br/>├── epub<br/>│   └── blog_post.epub<br/>├── html<br/>│   ├── portable_epubs.html<br/>│   └── style.css<br/>└── pdf<br/> └── portable_epubs.pdf</code></pre>
<p>The build directory path is calculated <em>relative to the content directory</em>. This is important, as if you change the <a href="./content-dir.xhtml">content directory</a>, then your build directory path will become relevant to that directory.</p>
<h2 id="configuration">Configuration</h2>
<h3 id="cli-flag">CLI flag</h3>
Expand Down
4 changes: 2 additions & 2 deletions tests/ref/examples/rheo_docs/epub/xhtml/content-dir.xhtml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head>
<meta charset="utf-8"></meta>
<meta name="viewport" content="width=device-width, initial-scale=1"></meta>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Content directory</title>
</head>
<body><article>
Expand Down
4 changes: 2 additions & 2 deletions tests/ref/examples/rheo_docs/epub/xhtml/custom-css.xhtml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head>
<meta charset="utf-8"></meta>
<meta name="viewport" content="width=device-width, initial-scale=1"></meta>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Custom CSS</title>
</head>
<body><article>
Expand Down
6 changes: 3 additions & 3 deletions tests/ref/examples/rheo_docs/epub/xhtml/faq.xhtml
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head>
<meta charset="utf-8"></meta>
<meta name="viewport" content="width=device-width, initial-scale=1"></meta>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Rheo</title>
</head>
<body><article>
<h2 id="frequently-asked-questions">Frequently Asked Questions</h2>
<h3 id="what-is-the-difference-between-typst-and-rheo?">What is the difference between Typst and Rheo?</h3>
<p><a href="https://typst.app/">Typst</a> is a markup/programming language that provides its own toolchain which includes a CLI. You can use the Typst CLI to compile one Typst document to one kind of output file:</p>
<pre><code data-lang="sh"><span style="color: #4b69c6">typst</span> compile source.typ <span style="color: #74747c">#</span><span style="color: #74747c"> compile to PDF</span><br></br><span style="color: #4b69c6">typst</span> compile --features html --format html source.typ <span style="color: #74747c">#</span><span style="color: #74747c"> compile to HTML</span></code></pre>
<pre><code data-lang="sh"><span style="color: #4b69c6">typst</span> compile source.typ <span style="color: #74747c">#</span><span style="color: #74747c"> compile to PDF</span><br/><span style="color: #4b69c6">typst</span> compile --features html --format html source.typ <span style="color: #74747c">#</span><span style="color: #74747c"> compile to HTML</span></code></pre>
<p>Rheo compiles a <em>project folder</em> to three outputs—PDF, HTML, and EPUB—concurrently. It allows you to configure how certain source files should be merged (to produce a ‘combined’ EPUB or PDF file, for example, via <a href="./spines.xhtml">spines</a>), and also allows you to enrich certain outputs (such as HTML via <a href="./custom-css.xhtml">custom CSS</a>) with non-Typst content. Rheo supports EPUB natively, which is not currently supported by the upstream Typst CLI (though it is <a href="https://github.com/typst/typst/issues/188">on the roadmap</a>). In summary, Rheo is a opinionated way to manage writing projects with Typst.</p>
<h3 id="how-do-i-read-epubs-on-my-system?">How do I read EPUBs on my system?</h3>
<p>Mileage varies greatly on EPUB reading niceness across systems! If you’re interested to learn more, we have written more about this <a href="https://willcrichton.net/notes/portable-epubs/">here</a>. If you don’t have a good EPUB reading experience currently, we recommend trying <a href="https://github.com/nota-lang/bene">bene</a>, an EPUB reading system that we are developing.</p>
Expand Down
6 changes: 3 additions & 3 deletions tests/ref/examples/rheo_docs/epub/xhtml/formats.xhtml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head>
<meta charset="utf-8"></meta>
<meta name="viewport" content="width=device-width, initial-scale=1"></meta>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Formats</title>
</head>
<body><article>
Expand All @@ -17,7 +17,7 @@
<h3 id="configuration">Configuration</h3>
<h4 id="cli-flag">CLI flag</h4>
<p>You can constrain Rheo to producing one or more formats by passing one or more of the following flags to <code>compile</code> or <code>watch</code>:</p>
<pre><code data-lang="bash"><span style="color: #4b69c6">rheo</span> compile path/to/project --pdf<br></br><span style="color: #4b69c6">rheo</span> compile path/to/project --html<br></br><span style="color: #4b69c6">rheo</span> compile path/to/project --epub</code></pre>
<pre><code data-lang="bash"><span style="color: #4b69c6">rheo</span> compile path/to/project --pdf<br/><span style="color: #4b69c6">rheo</span> compile path/to/project --html<br/><span style="color: #4b69c6">rheo</span> compile path/to/project --epub</code></pre>
<h4 id="rheo.toml"><code>rheo.toml</code></h4>
<p>You can also specify formats at the top level of <code>rheo.toml</code> in an array that contains one or more formats. The default, if <code>formats</code> is not specified, is an array with all three formats:</p>
<pre><code data-lang="toml"><span style="color: #4b69c6">formats</span> = [<span style="color: #198810">"</span><span style="color: #198810">pdf</span><span style="color: #198810">"</span>, <span style="color: #198810">"</span><span style="color: #198810">html</span><span style="color: #198810">"</span>, <span style="color: #198810">"</span><span style="color: #198810">epub</span><span style="color: #198810">"</span>] </code></pre>
Expand Down
Loading