Packages
mdex
0.1.11
0.13.3
0.13.2
0.13.1
0.13.0
0.12.5
retired
0.12.4
0.12.3
0.12.2
0.12.1
0.12.0
0.11.7
0.11.6
0.11.5
0.11.4
0.11.3
0.11.2
0.11.1
0.11.0
0.10.0
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.6
0.8.5
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.2
0.6.1
0.6.0
0.5.0
0.4.3
0.4.2
0.4.1
0.4.0
0.3.3
0.3.2
0.3.1
0.3.0
0.2.0
0.1.18
0.1.17
0.1.16
0.1.15
0.1.14
0.1.13
0.1.12
0.1.11
0.1.10
0.1.9
0.1.8
0.1.7
0.1.6
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
Fast and extensible Markdown for Elixir
Current section
Files
Jump to
Current section
Files
native/comrak_nif/vendor/autumn/src/lib.rs
pub mod themes;
pub use crate::themes::Theme;
use inkjet::Language;
use tree_sitter_highlight::{HighlightEvent, Highlighter};
pub fn highlight_source_code(
source: &str,
lang: Language,
theme: &Theme,
pre_class: Option<&str>,
code_class: Option<&str>,
) -> String {
let mut output = String::new();
let mut highlighter = Highlighter::new();
let config = lang.config();
let highlights = highlighter
.highlight(
config,
source.as_bytes(),
None,
|token| match Language::from_token(token) {
Some(lang) => Some(lang.config()),
None => None,
},
)
// TODO: fallback to plain text
.expect("expected to generate the syntax highlight events");
output.push_str(
format!(
"{}{}",
open_pre_tag(theme, pre_class),
open_code_tag(lang, code_class)
)
.as_str(),
);
for event in highlights {
// TODO: fallback to plain text
let event = event.expect("expected a highlight event");
let highlight = inner_highlights(source, event, theme);
output.push_str(highlight.as_str())
}
output.push_str(format!("{}{}", close_code_tag(), close_pre_tag()).as_str());
output
}
pub fn open_tags(
lang: Language,
theme: &Theme,
pre_class: Option<&str>,
code_class: Option<&str>,
) -> String {
format!(
"{}{}",
open_pre_tag(theme, pre_class),
open_code_tag(lang, code_class)
)
}
pub fn close_tags() -> String {
String::from("</code></pre>")
}
pub fn open_pre_tag(theme: &Theme, class: Option<&str>) -> String {
let class = class.unwrap_or("autumn highlight");
let (_class, background_style) = theme.get_scope("background");
let (_class, text_style) = theme.get_scope("text");
format!(
"<pre class=\"{}\" style=\"{} {}\">",
class, background_style, text_style
)
}
pub fn close_pre_tag() -> String {
String::from("</pre>")
}
pub fn open_code_tag(lang: Language, class: Option<&str>) -> String {
let lang = format!("{}-{}", "language", format!("{:?}", lang).to_lowercase());
let class = class.unwrap_or_else(|| &lang);
format!("<code class=\"{}\" translate=\"no\">", class)
}
pub fn close_code_tag() -> String {
String::from("</code>")
}
pub fn inner_highlights(source: &str, event: HighlightEvent, theme: &Theme) -> String {
let mut output = String::new();
match event {
HighlightEvent::Source { start, end } => {
let span = source
.get(start..end)
// TODO: fallback to plain text
.expect("source bounds should be in bounds!");
let span = v_htmlescape::escape(span).to_string();
output.push_str(span.as_str())
}
HighlightEvent::HighlightStart(idx) => {
let scope = inkjet::constants::HIGHLIGHT_NAMES[idx.0];
let (class, style) = theme.get_scope(scope);
let element = format!("<span class=\"{}\" style=\"{}\">", class, style);
output.push_str(element.as_str())
}
HighlightEvent::HighlightEnd => output.push_str("</span>"),
}
output
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_highlight_source_code() {
let theme = themes::theme("onedark").unwrap();
let output = highlight_source_code("mod themes;", Language::Rust, theme, None, None);
assert_eq!(
output,
"<pre class=\"autumn highlight\" style=\"background-color: #282C34; color: #ABB2BF;\"><code class=\"language-rust\" translate=\"no\"><span class=\"keyword control import\" style=\"color: #E06C75;\">mod</span> <span class=\"namespace\" style=\"color: #61AFEF;\">themes</span><span class=\"\" style=\"color: #ABB2BF;\">;</span></code></pre>"
);
}
#[test]
fn test_highlight_source_code_with_pre_class() {
let theme = themes::theme("onedark").unwrap();
let output = highlight_source_code(
"mod themes;",
Language::Rust,
theme,
Some("pre_class"),
None,
);
assert_eq!(
output,
"<pre class=\"pre_class\" style=\"background-color: #282C34; color: #ABB2BF;\"><code class=\"language-rust\" translate=\"no\"><span class=\"keyword control import\" style=\"color: #E06C75;\">mod</span> <span class=\"namespace\" style=\"color: #61AFEF;\">themes</span><span class=\"\" style=\"color: #ABB2BF;\">;</span></code></pre>"
);
}
#[test]
fn test_highlight_source_code_with_code_class() {
let theme = themes::theme("onedark").unwrap();
let output = highlight_source_code(
"mod themes;",
Language::Rust,
theme,
None,
Some("code_class"),
);
assert_eq!(
output,
"<pre class=\"autumn highlight\" style=\"background-color: #282C34; color: #ABB2BF;\"><code class=\"code_class\" translate=\"no\"><span class=\"keyword control import\" style=\"color: #E06C75;\">mod</span> <span class=\"namespace\" style=\"color: #61AFEF;\">themes</span><span class=\"\" style=\"color: #ABB2BF;\">;</span></code></pre>"
);
}
}