Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow keeping templates as they are #30

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/target
**/*.rs.bk
Cargo.lock
*.go
*.go
/.idea
63 changes: 55 additions & 8 deletions src/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,21 @@ use std::collections::HashSet;
use tendril::StrTendril;
use tendril::TendrilSink;

#[derive(Clone, Debug, Default)]
#[non_exhaustive]
/// Parser options
pub struct ParseOptions {
/// Keep the content of `<template>` tags in place.
pub keep_templates: bool,
}

impl ParseOptions {
pub fn keep_templates(mut self, keep_templates: bool) -> Self {
self.keep_templates = keep_templates;
self
}
}

/// Document represents an HTML document to be manipulated.
pub struct Document {
/// The document's dom tree.
Expand All @@ -25,6 +40,9 @@ pub struct Document {

/// The document's quirks mode.
pub quirks_mode: QuirksMode,

/// Keep content of templates
pub keep_templates: bool,
}

impl Default for Document {
Expand All @@ -33,6 +51,7 @@ impl Default for Document {
tree: Tree::new(NodeData::Document),
errors: vec![],
quirks_mode: tree_builder::NoQuirks,
keep_templates: false,
}
}
}
Expand Down Expand Up @@ -60,6 +79,23 @@ impl Document {
pub fn root(&self) -> NodeRef<NodeData> {
self.tree.root()
}

/// Parse a document allowing to provide additional options
pub fn parse<S>(options: ParseOptions, html: S) -> Self
where
S: AsRef<str>,
{
let ParseOptions { keep_templates } = options;

parse_document(
Document {
keep_templates,
..Document::default()
},
Default::default(),
)
.one(html.as_ref())
}
}

impl TreeSink for Document {
Expand Down Expand Up @@ -87,14 +123,19 @@ impl TreeSink for Document {

// Get a handle to a template's template contents. The tree builder promises this will never be called with
// something else than a template element.
// If templates are kept in place, return the actual node id.
fn get_template_contents(&mut self, target: &NodeId) -> NodeId {
self.tree.query_node(target, |node| match node.data {
NodeData::Element(Element {
template_contents: Some(ref contents),
..
}) => contents.clone(),
_ => panic!("not a template element!"),
})
if self.keep_templates {
target.clone()
} else {
self.tree.query_node(target, |node| match node.data {
NodeData::Element(Element {
template_contents: Some(ref contents),
..
}) => contents.clone(),
_ => panic!("not a template element!"),
})
}
}

// Set the document's quirks mode.
Expand Down Expand Up @@ -126,7 +167,7 @@ impl TreeSink for Document {
attrs: Vec<Attribute>,
flags: ElementFlags,
) -> NodeId {
let template_contents = if flags.template {
let template_contents = if !self.keep_templates && flags.template {
Some(self.tree.create_node(NodeData::Document))
} else {
None
Expand Down Expand Up @@ -282,6 +323,12 @@ impl TreeSink for Document {
}
}

impl Document {
pub fn get_node(&self, id: &NodeId) -> NodeData {
self.tree.query_node(id, |node| node.data.clone())
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ mod selection;
mod traversal;

pub use document::Document;
pub use document::ParseOptions;
pub use dom_tree::Node;
#[doc(hidden)]
pub use dom_tree::NodeId;
Expand Down
45 changes: 45 additions & 0 deletions tests/templates.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use markup5ever::interface::TreeSink;
use nipper::{Document, ParseOptions};

#[test]
fn test_templates() {
let mut doc = Document::parse(
ParseOptions {
keep_templates: true,
},
r#"
<html>
<body>
<template>
<p>Hello world!</p>
</template>
</body>
</html>
"#,
);

let nodes = doc
.select("template")
.nodes()
.iter()
.map(|n| n.id)
.collect::<Vec<_>>();
for node in nodes {
let c = doc.get_template_contents(&node);
println!("Node: {c:?}");
let data = doc.get_node(&node);
println!("Data: {data:?}");
}

let result = doc.html().to_string();
assert_eq!(
result,
r#"<html><head></head><body>
<template>
<p>Hello world!</p>
</template>


</body></html>"#
);
}