Skip to content

Commit

Permalink
Merge branch 'main' into readme
Browse files Browse the repository at this point in the history
  • Loading branch information
max-heller authored Jan 12, 2025
2 parents f9956dd + 752475e commit c80266b
Show file tree
Hide file tree
Showing 9 changed files with 1,128 additions and 723 deletions.
80 changes: 1 addition & 79 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ anyhow = "1.0.47"
cssparser = "0.34.0"
env_logger = "0.11.0"
html5ever = "0.29.0"
indexmap = "2.7.0"
log = "0.4.0"
mdbook = { version = "0.4.35", default-features = false }
normpath = "1.0.0"
once_cell = "1.0.0"
pulldown-cmark = { version = "0.10.0", default-features = false }
regex = "1.5.5"
scraper = { git = "https://github.com/rust-scraper/scraper", rev = "1896e4f2c57438b5d42aade714d2b8f3019e983f", features = ["deterministic"] }
ego-tree = "0.10.0"
replace_with = "0.1.7"
semver = "1.0.0"
Expand Down
58 changes: 20 additions & 38 deletions src/html.rs
Original file line number Diff line number Diff line change
@@ -1,42 +1,24 @@
use std::cell::Cell;
use crate::preprocess;

use html5ever::{interface::TreeSink, namespace_url, ns, LocalName, QualName};
pub type Parser<'book> = html5ever::Parser<preprocess::tree::HtmlTreeSink<'book>>;

pub type NodeId = <scraper::HtmlTreeSink as TreeSink>::Handle;
pub type Parser = html5ever::Parser<scraper::HtmlTreeSink>;

pub fn name(local: LocalName) -> QualName {
QualName::new(None, ns!(), local)
}

/// Determines the HTML element to which child events should be appended based on the state of the parser.
pub fn most_recently_created_open_element(parser: &Parser) -> NodeId {
struct Tracer<'a> {
html: &'a scraper::Html,
prev: Cell<Option<NodeId>>,
next: Cell<Option<NodeId>>,
}

impl html5ever::interface::Tracer for Tracer<'_> {
type Handle = NodeId;

fn trace_handle(&self, handle: &Self::Handle) {
if let Some(node) = self.html.tree.get(*handle) {
if node.value().is_element() {
self.prev.swap(&self.next);
self.next.set(Some(*handle))
}
}
#[macro_export]
macro_rules! html_name {
(html $name:tt) => {{
use html5ever::namespace_url;
html5ever::QualName {
prefix: None,
ns: html5ever::ns!(html),
local: html5ever::local_name!($name),
}
}

let sink = &parser.tokenizer.sink;
let html = sink.sink.0.borrow();
let tracer = Tracer {
html: &html,
prev: Default::default(),
next: Default::default(),
};
sink.trace_handles(&tracer);
tracer.prev.into_inner().unwrap()
}};
($name:tt) => {{
use html5ever::namespace_url;
html5ever::QualName {
prefix: None,
ns: html5ever::ns!(),
local: html5ever::local_name!($name),
}
}};
}
pub use crate::html_name as name;
48 changes: 39 additions & 9 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1242,6 +1242,44 @@ some text here
"##);
}

#[test]
fn implicitly_closed_tags() {
let book = MDBook::init()
.config(Config::latex())
.chapter(Chapter::new(
"",
r#"
- before
- [Box<T>](#foo)
- after
# Foo
"#,
"chapter.md",
))
.build();
insta::assert_snapshot!(book, @r##"
├─ log output
│ INFO mdbook::book: Running the pandoc backend
│ INFO mdbook_pandoc::pandoc::renderer: Running pandoc
│ INFO mdbook_pandoc::pandoc::renderer: Wrote output to book/latex/output.tex
├─ latex/output.tex
│ \begin{itemize}
│ \tightlist
│ \item
│ before
│ \item
│ \hyperref[book__latex__src__chapter.md__foo]{Box}
│ \item
│ after
│ \end{itemize}
│ \chapter{Foo}\label{book__latex__src__chapter.md__foo}
├─ latex/src/chapter.md
│ [BulletList [[Plain [Str "before"]], [Plain [Link ("", [], []) [Str "Box", RawInline (Format "html") "<t>", RawInline (Format "html") "</t>"] ("#foo", "")]], [Plain [Str "after"]]], Header 1 ("foo", [], []) [Str "Foo"]]
"##);
}

#[test]
fn rust_reference_regression_nested_elements() {
let book = MDBook::init()
Expand Down Expand Up @@ -1411,11 +1449,9 @@ some text here
text
</summary>
<p>
more **markdown**
</p>
</details>
outside divs
Expand Down Expand Up @@ -1447,14 +1483,8 @@ outside divs
│ , Para [ Str "text" ]
│ ]
│ , RawBlock (Format "html") "</summary>"
│ , Plain [ Str "\n" , RawInline (Format "html") "<p>" ]
│ , Div
│ ( "" , [] , [] )
│ [ Plain [ Str "\n" ]
│ , Para [ Str "more " , Strong [ Str "markdown" ] ]
│ ]
│ , RawBlock (Format "html") "</p>"
│ , Plain [ Str "\n" ]
│ , Para [ Str "more " , Strong [ Str "markdown" ] ]
│ ]
│ , RawBlock (Format "html") "</details>"
│ , Plain [ Str "\n" ]
Expand Down
31 changes: 15 additions & 16 deletions src/pandoc/native.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ use std::{

use anyhow::anyhow;
use escape::Escape;
use html5ever::{local_name, serialize::HtmlSerializer};
use html5ever::serialize::HtmlSerializer;
use pulldown_cmark::CowStr;

use crate::{html, preprocess::PreprocessChapter};
use crate::preprocess::{self, PreprocessChapter};

use super::OutputFormat;

Expand Down Expand Up @@ -68,22 +68,22 @@ where
}
}

impl Attributes for &scraper::node::Attributes {
impl Attributes for &preprocess::tree::Attributes {
fn id(&self) -> Option<&str> {
self.get(&html::name(local_name!("id"))).map(|s| s.as_ref())
self.id.as_deref()
}

fn classes(&self) -> impl Iterator<Item = &str> {
self.get(&html::name(local_name!("class")))
.filter(|s| !s.is_empty())
(!self.classes.is_empty())
.then_some(self.classes.split_ascii_whitespace())
.into_iter()
.flat_map(|s| s.split(' '))
.flatten()
}

fn attrs(&self) -> impl Iterator<Item = (&str, &str)> {
self.iter()
.filter(|(k, _)| !matches!(k.local, local_name!("id") | local_name!("class")))
.map(|(k, v)| (k.local.as_ref(), v.as_ref()))
self.rest
.iter()
.map(|(name, value)| (name.local.as_ref(), value.as_ref()))
}
}

Expand Down Expand Up @@ -797,18 +797,17 @@ impl<'a, 'book, 'p, W: io::Write> SerializeBlock<'a, 'book, 'p, W> {

/// Table, with attributes, caption, optional short caption, column alignments and widths
/// (required), table head, table bodies, and table foot
pub fn serialize_table<S>(
pub fn serialize_table(
self,
state: &mut S,
attrs: impl Attributes,
cols: impl IntoIterator<Item = (Alignment, Option<ColWidth>)>,
header: (
impl Attributes,
impl FnOnce(&mut S, &mut SerializeRows<'_, 'book, 'p, W>) -> anyhow::Result<()>,
impl FnOnce(&mut SerializeRows<'_, 'book, 'p, W>) -> anyhow::Result<()>,
),
body: (
impl Attributes,
impl FnOnce(&mut S, &mut SerializeRows<'_, 'book, 'p, W>) -> anyhow::Result<()>,
impl FnOnce(&mut SerializeRows<'_, 'book, 'p, W>) -> anyhow::Result<()>,
),
) -> anyhow::Result<()> {
write!(self.serializer.unescaped(), "Table ")?;
Expand Down Expand Up @@ -846,7 +845,7 @@ impl<'a, 'book, 'p, W: io::Write> SerializeBlock<'a, 'book, 'p, W> {
self.serializer.write_attributes(attrs)?;
write!(self.serializer.unescaped(), " ")?;
let mut serializer = SerializeList::new(self.serializer, Row)?;
rows(state, &mut serializer)?;
rows(&mut serializer)?;
serializer.finish()?;
write!(self.serializer.unescaped(), ")")?;
}
Expand All @@ -858,7 +857,7 @@ impl<'a, 'book, 'p, W: io::Write> SerializeBlock<'a, 'book, 'p, W> {
self.serializer.write_attributes(attrs)?;
write!(self.serializer.unescaped(), " (RowHeadColumns 0) [] ")?;
let mut serializer = SerializeList::new(self.serializer, Row)?;
rows(state, &mut serializer)?;
rows(&mut serializer)?;
serializer.finish()?;
write!(self.serializer.unescaped(), ")]")?;
}
Expand Down
Loading

0 comments on commit c80266b

Please sign in to comment.