use tree_sitter_language::LanguageFn;
extern "C" {
fn tree_sitter_html() -> *const ();
}
pub const LANGUAGE: LanguageFn = unsafe { LanguageFn::from_raw(tree_sitter_html) };
pub fn language() -> tree_sitter::Language {
LANGUAGE.into()
}
pub const HIGHLIGHTS_QUERY: &str = include_str!("../queries/highlights.scm");
pub const INJECTIONS_QUERY: &str = include_str!("../queries/injections.scm");
pub const NODE_TYPES: &str = include_str!("node-types.json");
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_can_load_grammar() {
let mut parser = tree_sitter::Parser::new();
parser
.set_language(&LANGUAGE.into())
.expect("Failed to load HTML grammar");
}
#[test]
fn test_parse_simple_html() {
let mut parser = tree_sitter::Parser::new();
parser.set_language(&LANGUAGE.into()).unwrap();
let source = "<div>Hello</div>";
let tree = parser.parse(source, None).unwrap();
assert!(!tree.root_node().has_error());
assert_eq!(tree.root_node().kind(), "document");
}
#[test]
fn test_parse_void_elements() {
let mut parser = tree_sitter::Parser::new();
parser.set_language(&LANGUAGE.into()).unwrap();
let source = r#"<img src="test.png"><br><input type="text"><hr>"#;
let tree = parser.parse(source, None).unwrap();
assert!(!tree.root_node().has_error());
}
#[test]
fn test_parse_self_closing_void() {
let mut parser = tree_sitter::Parser::new();
parser.set_language(&LANGUAGE.into()).unwrap();
let source = r#"<img src="test.png" /><br /><input type="text" />"#;
let tree = parser.parse(source, None).unwrap();
assert!(!tree.root_node().has_error());
}
#[test]
fn test_parse_script_element() {
let mut parser = tree_sitter::Parser::new();
parser.set_language(&LANGUAGE.into()).unwrap();
let source = r#"<script>const x = "<div></div>";</script>"#;
let tree = parser.parse(source, None).unwrap();
assert!(!tree.root_node().has_error());
}
#[test]
fn test_parse_style_element() {
let mut parser = tree_sitter::Parser::new();
parser.set_language(&LANGUAGE.into()).unwrap();
let source = r#"<style>div { color: red; }</style>"#;
let tree = parser.parse(source, None).unwrap();
assert!(!tree.root_node().has_error());
}
#[test]
fn test_parse_textarea_element() {
let mut parser = tree_sitter::Parser::new();
parser.set_language(&LANGUAGE.into()).unwrap();
let source = r#"<textarea>Some <b>text</b> here</textarea>"#;
let tree = parser.parse(source, None).unwrap();
assert!(!tree.root_node().has_error());
let element = tree.root_node().child(0).unwrap();
assert_eq!(element.kind(), "element");
}
#[test]
fn test_parse_title_element() {
let mut parser = tree_sitter::Parser::new();
parser.set_language(&LANGUAGE.into()).unwrap();
let source = r#"<title>Page <Title> Test</title>"#;
let tree = parser.parse(source, None).unwrap();
assert!(!tree.root_node().has_error());
let element = tree.root_node().child(0).unwrap();
assert_eq!(element.kind(), "element");
}
#[test]
fn test_parse_implicit_end_tags() {
let mut parser = tree_sitter::Parser::new();
parser.set_language(&LANGUAGE.into()).unwrap();
let source = r#"<ul><li>One<li>Two<li>Three</ul>"#;
let tree = parser.parse(source, None).unwrap();
assert!(!tree.root_node().has_error());
}
#[test]
fn test_parse_void_elements_do_not_capture_following_text() {
let mut parser = tree_sitter::Parser::new();
parser.set_language(&LANGUAGE.into()).unwrap();
let source = "<div><input>x</div>";
let tree = parser.parse(source, None).unwrap();
assert!(!tree.root_node().has_error());
assert_eq!(
tree.root_node().to_sexp(),
"(document (element (start_tag name: (tag_name)) (element (start_tag name: (tag_name))) (text) (end_tag name: (tag_name))))"
);
}
#[test]
fn test_parse_p_implicit_close() {
let mut parser = tree_sitter::Parser::new();
parser.set_language(&LANGUAGE.into()).unwrap();
let source = r#"<p>Paragraph<div>Block</div>"#;
let tree = parser.parse(source, None).unwrap();
assert!(!tree.root_node().has_error());
}
#[test]
fn test_parse_entities() {
let mut parser = tree_sitter::Parser::new();
parser.set_language(&LANGUAGE.into()).unwrap();
let source = r#"<p>& < > < <</p>"#;
let tree = parser.parse(source, None).unwrap();
assert!(!tree.root_node().has_error());
}
#[test]
fn test_parse_doctype() {
let mut parser = tree_sitter::Parser::new();
parser.set_language(&LANGUAGE.into()).unwrap();
let source = r#"<!DOCTYPE html><html></html>"#;
let tree = parser.parse(source, None).unwrap();
assert!(!tree.root_node().has_error());
}
#[test]
fn test_parse_comments() {
let mut parser = tree_sitter::Parser::new();
parser.set_language(&LANGUAGE.into()).unwrap();
let source = r#"<!-- Comment --><div><!-- Another --></div>"#;
let tree = parser.parse(source, None).unwrap();
assert!(!tree.root_node().has_error());
}
#[test]
fn test_parse_attributes() {
let mut parser = tree_sitter::Parser::new();
parser.set_language(&LANGUAGE.into()).unwrap();
let source = r#"<div id="test" class='cls' data-value=123 disabled></div>"#;
let tree = parser.parse(source, None).unwrap();
assert!(!tree.root_node().has_error());
}
}