use comrak::plugins::syntect::SyntectAdapterBuilder; use comrak::{markdown_to_html_with_plugins, Options, Plugins}; use syntect::highlighting::ThemeSet; use syntect::html::{css_for_theme_with_class_style, ClassStyle}; use syntect::parsing::SyntaxDefinition; use crate::domain::MarkdownRenderer; const TYPESCRIPT_SYNTAX: &str = include_str!("../../resources/syntaxes/TypeScript.sublime-syntax"); fn build_syntax_set() -> syntect::parsing::SyntaxSet { let mut builder = syntect::parsing::SyntaxSet::load_defaults_nonewlines().into_builder(); if let Ok(def) = SyntaxDefinition::load_from_str(TYPESCRIPT_SYNTAX, true, None) { builder.add(def); } builder.build() } pub struct ComrakRenderer; pub struct ComrakPreviewRenderer; impl MarkdownRenderer for ComrakRenderer { fn render(&self, content: &str) -> String { let adapter = SyntectAdapterBuilder::new() .syntax_set(build_syntax_set()) .css() .build(); let mut options = Options::default(); options.extension.table = true; options.extension.strikethrough = true; options.extension.autolink = true; options.extension.tasklist = true; let mut plugins = Plugins::default(); plugins.render.codefence_syntax_highlighter = Some(&adapter); markdown_to_html_with_plugins(content, &options, &plugins) } } impl MarkdownRenderer for ComrakPreviewRenderer { fn render(&self, content: &str) -> String { let adapter = SyntectAdapterBuilder::new() .syntax_set(build_syntax_set()) .css() .build(); let options = Options::default(); let mut plugins = Plugins::default(); plugins.render.codefence_syntax_highlighter = Some(&adapter); markdown_to_html_with_plugins(content, &options, &plugins) } } pub fn syntax_css_for_theme(syntect_theme_name: &str) -> String { let ts = ThemeSet::load_defaults(); let theme = match ts.themes.get(syntect_theme_name) { Some(t) => t, None => return String::new(), }; match css_for_theme_with_class_style(theme, ClassStyle::Spaced) { Ok(css) => css.replace(".code {", ".syntax-highlighting {"), Err(_) => String::new(), } } #[cfg(test)] mod tests { use super::*; #[test] fn render_outputs_syntax_highlighting_class() { let r = ComrakRenderer; let html = r.render("```rust\nfn main() {}\n```\n"); assert!(html.contains("syntax-highlighting")); } #[test] fn render_outputs_classed_spans() { let r = ComrakRenderer; let html = r.render("```rust\nfn main() {}\n```\n"); assert!(html.contains("