#![cfg(feature = "spans")] use std::include_str; use codespan_reporting::{ self, diagnostic::{Diagnostic, Label}, files::SimpleFiles, term::{self, termcolor::Buffer}, }; use html5tokenizer::{ BufferQueue, Tag, Token, TokenSink, TokenSinkResult, Tokenizer, TokenizerOpts, }; #[derive(Default)] struct TagSink { tags: Vec, } impl TokenSink for TagSink { fn process_token(&mut self, token: Token, _line_number: u64) -> TokenSinkResult { if let Token::TagToken(tag) = token { self.tags.push(tag); } TokenSinkResult::Continue } } #[test] fn test() { let sink = TagSink::default(); let mut input = BufferQueue::new(); let text = include_str!("files/test.html"); input.push_back(text.to_string()); let mut tok = Tokenizer::new(sink, TokenizerOpts::default()); let _ = tok.feed(&mut input); let mut files = SimpleFiles::new(); let file_id = files.add("test.html", text); let mut labels = Vec::new(); let tags = tok.sink.tags; for tag in &tags[..2] { labels.push( Label::primary(file_id, tag.name_span.clone()).with_message(format!("{:?}", tag.kind)), ); } labels.push( Label::primary(file_id, tags[2].attrs[0].name_span.clone()).with_message("attribute name"), ); labels.push( Label::primary(file_id, tags[2].attrs[0].value_span.clone()) .with_message("attribute value"), ); labels.push( Label::primary(file_id, tags[4].attrs[0].value_span.clone()) .with_message("in single quotes"), ); labels.push( Label::primary(file_id, tags[4].attrs[1].value_span.clone()) .with_message("in double quotes"), ); let diagnostic = Diagnostic::note().with_labels(labels); let mut writer = Buffer::no_color(); let config = codespan_reporting::term::Config::default(); term::emit(&mut writer, &config, &files, &diagnostic).unwrap(); let actual = remove_trailing_spaces(std::str::from_utf8(writer.as_slice()).unwrap()); let expected = include_str!("files/test.out"); if actual != expected { println!( "EXPECTED:\n{banner}\n{expected}{banner}\n\nACTUAL OUTPUT:\n{banner}\n{actual}{banner}", banner = "-".repeat(30), expected = expected, actual = actual ); panic!("failed"); } } fn remove_trailing_spaces(text: &str) -> String { text.lines() .map(|l| l.trim_end()) .collect::>() .join("\n") }