#![deny(warnings, clippy::all)]
use std::path::Path;
use std::sync::OnceLock;
use insta::{assert_snapshot, glob};
use pulldown_cmark::{Options, Parser};
use syntect::parsing::SyntaxSet;
use url::Url;
use mdcat::resources::*;
use mdcat::terminal::{TerminalProgram, TerminalSize};
use mdcat::{Environment, Multiplexer, Settings, Theme};
static TEST_READ_LIMIT: u64 = 5_242_880;
static SYNTAX_SET: OnceLock<SyntaxSet> = OnceLock::new();
fn syntax_set() -> &'static SyntaxSet {
SYNTAX_SET.get_or_init(SyntaxSet::load_defaults_newlines)
}
fn resource_handler() -> DispatchingResourceHandler {
let handlers: Vec<Box<dyn ResourceUrlHandler>> =
vec![Box::new(FileResourceHandler::new(TEST_READ_LIMIT))];
DispatchingResourceHandler::new(handlers)
}
fn render_to_string<P: AsRef<Path>>(markdown_file: P, settings: &Settings) -> String {
let markdown = std::fs::read_to_string(&markdown_file).unwrap();
let parser = Parser::new_ext(
&markdown,
Options::ENABLE_TASKLISTS | Options::ENABLE_STRIKETHROUGH | Options::ENABLE_TABLES,
);
let abs_path = std::fs::canonicalize(&markdown_file).unwrap();
let base_dir = abs_path
.parent()
.expect("Absolute file name must have a parent!");
let mut sink = Vec::new();
let env = Environment {
hostname: "HOSTNAME".to_string(),
..Environment::for_local_directory(&base_dir).unwrap()
};
mdcat::push_tty(settings, &env, &resource_handler(), &mut sink, parser).unwrap();
String::from_utf8(sink).unwrap()
}
#[test]
fn test_render() {
let cwd = std::env::current_dir().expect("Require working directory");
let mut cwd_url = Url::from_directory_path(&cwd).expect("Working directory URL");
let mut root_url = cwd_url.join("/").expect("Join root URL");
root_url.set_host(Some("HOSTNAME")).unwrap();
cwd_url.set_host(Some("HOSTNAME")).unwrap();
let dumb_settings = Settings {
terminal_capabilities: TerminalProgram::Dumb.capabilities(),
terminal_size: TerminalSize::default(),
multiplexer: Multiplexer::default(),
theme: Theme::default(),
syntax_set: syntax_set(),
wrap_code: false,
};
let ansi_settings = Settings {
terminal_capabilities: TerminalProgram::Ansi.capabilities(),
terminal_size: TerminalSize::default(),
multiplexer: Multiplexer::default(),
theme: Theme::default(),
syntax_set: syntax_set(),
wrap_code: false,
};
let iterm2_settings = Settings {
terminal_capabilities: TerminalProgram::ITerm2.capabilities(),
terminal_size: TerminalSize::default(),
multiplexer: Multiplexer::default(),
theme: Theme::default(),
syntax_set: syntax_set(),
wrap_code: false,
};
glob!("markdown/**/*.md", |markdown_file| {
let mut settings = insta::Settings::clone_current();
settings.set_snapshot_path("snapshots/render");
settings.set_prepend_module_to_snapshot(false);
settings.add_filter(
regex::escape(cwd_url.as_str()).as_str(),
"file://HOSTNAME/WORKING_DIRECTORY/",
);
settings.add_filter(
regex::escape(root_url.as_str()).as_str(),
"file://HOSTNAME/ROOT/",
);
let category = markdown_file
.parent()
.unwrap()
.file_name()
.unwrap()
.to_str()
.unwrap();
let name = markdown_file.file_stem().unwrap().to_str().unwrap();
settings.set_snapshot_suffix(format!("{category}-{name}"));
let _guard = settings.bind_to_scope();
assert_snapshot!("dumb", render_to_string(markdown_file, &dumb_settings));
assert_snapshot!("ansi", render_to_string(markdown_file, &ansi_settings));
assert_snapshot!("iterm2", render_to_string(markdown_file, &iterm2_settings));
drop(_guard);
});
}