Skip to main content

textlane_html/actions/html/
parse.rs

1use std::collections::HashMap;
2
3use textlane_core::hast::Node;
4use textlane_core::{Allocator, File, Lines, Message, Point, Position};
5
6use crate::helpers::reason::find_reason;
7use crate::models::options::Parse;
8use crate::utils::builder::convert::convert_dom;
9use crate::utils::builder::parser::Parser;
10
11/// Parse HTML into hast as parse5 and hast-util-from-html do, recording parse errors on
12/// `file` when `emit_parse_errors` is set.
13pub fn parse_html<'a>(
14    input: &str,
15    options: &Parse,
16    file: &mut File,
17    alloc: &'a Allocator,
18) -> Node<'a> {
19    let mut parser = if options.fragment {
20        Parser::for_fragment(input)
21    } else {
22        Parser::for_document(input)
23    };
24    parser.run();
25    let root = if options.fragment {
26        parser.take_fragment()
27    } else {
28        parser.document
29    };
30    let lines = (options.emit_parse_errors || options.verbose).then(|| Lines::new(input));
31    if options.emit_parse_errors
32        && let Some(lines) = &lines
33    {
34        parser.errors.append(&mut parser.tokenizer.errors);
35        for error in std::mem::take(&mut parser.errors) {
36            let place = lines.to_unist_position(&Position::span(
37                Point::new(error.start, 0),
38                Point::new(error.end, 0),
39            ));
40            file.messages.push(Message {
41                reason: find_reason(error.code.as_str()).to_string(),
42                source: Some("hast-util-from-html".to_string()),
43                rule: Some(error.code.as_str().to_string()),
44                place: Some(place),
45            });
46        }
47    }
48    let verbose = lines.as_ref().filter(|_| options.verbose);
49    convert_dom(
50        &parser.dom,
51        root,
52        input.len(),
53        alloc,
54        &mut HashMap::new(),
55        verbose,
56    )
57}