Packages
mdex
0.4.1
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
Security advisory:
This version has known vulnerabilities.
View advisories
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>,
inline_style: bool,
) -> 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,
},
)
.expect("expected to generate the syntax highlight events");
output.push_str(
format!(
"{}{}",
open_pre_tag(theme, pre_class, inline_style),
open_code_tag(lang)
)
.as_str(),
);
for event in highlights {
let event = event.expect("expected a highlight event");
let highlight = inner_highlights(source, event, theme, inline_style);
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>,
inline_style: bool,
) -> String {
format!(
"{}{}",
open_pre_tag(theme, pre_class, inline_style),
open_code_tag(lang)
)
}
pub fn close_tags() -> String {
String::from("</code></pre>")
}
pub fn open_pre_tag(theme: &Theme, class: Option<&str>, inline_style: bool) -> String {
let class = match class {
Some(class) => format!("autumn-hl {}", class),
None => "autumn-hl".to_string(),
};
if inline_style {
let background_style = theme.get_global_style("background");
let foreground_style = theme.get_global_style("foreground");
format!(
"<pre class=\"{}\" style=\"{} {}\">",
class, background_style, foreground_style
)
} else {
format!("<pre class=\"{}\">", class)
}
}
pub fn close_pre_tag() -> String {
String::from("</pre>")
}
pub fn open_code_tag(lang: Language) -> String {
let class = format!("language-{}", format!("{:?}", lang).to_lowercase());
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,
inline_style: bool,
) -> String {
let mut output = String::new();
match event {
HighlightEvent::Source { start, end } => {
let span = source
.get(start..end)
.expect("source bounds should be in bounds!");
let span = v_htmlescape::escape(span)
.to_string()
.replace('{', "{")
.replace('}', "}");
output.push_str(&span);
}
HighlightEvent::HighlightStart(idx) => {
let scope = inkjet::constants::HIGHLIGHT_NAMES[idx.0];
let class = themes::HIGHLIGHT_CLASS_NAMES[idx.0];
if inline_style {
let style = theme.get_style(scope);
let element = format!("<span class=\"{}\" style=\"{}\">", class, style);
output.push_str(element.as_str())
} else {
let element = format!("<span class=\"{}\">", class);
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_with_defaults() {
let theme = themes::theme("onedark").unwrap();
let output = highlight_source_code("mod themes;", Language::Rust, theme, None, true);
assert_eq!(
output,
"<pre class=\"autumn-hl\" style=\"background-color: #282C34; color: #ABB2BF;\"><code class=\"language-rust\" translate=\"no\"><span class=\"ahl-keyword ahl-control ahl-import\" style=\"color: #E06C75;\">mod</span> <span class=\"ahl-namespace\" style=\"color: #61AFEF;\">themes</span><span class=\"ahl-punctuation ahl-delimiter\" style=\"color: #ABB2BF;\">;</span></code></pre>"
);
}
#[test]
fn test_highlight_source_code_without_inline_style() {
let theme = themes::theme("onedark").unwrap();
let output = highlight_source_code("mod themes;", Language::Rust, theme, None, false);
assert_eq!(
output,
"<pre class=\"autumn-hl\"><code class=\"language-rust\" translate=\"no\"><span class=\"ahl-keyword ahl-control ahl-import\">mod</span> <span class=\"ahl-namespace\">themes</span><span class=\"ahl-punctuation ahl-delimiter\">;</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"),
true,
);
assert_eq!(
output,
"<pre class=\"autumn-hl pre_class\" style=\"background-color: #282C34; color: #ABB2BF;\"><code class=\"language-rust\" translate=\"no\"><span class=\"ahl-keyword ahl-control ahl-import\" style=\"color: #E06C75;\">mod</span> <span class=\"ahl-namespace\" style=\"color: #61AFEF;\">themes</span><span class=\"ahl-punctuation ahl-delimiter\" style=\"color: #ABB2BF;\">;</span></code></pre>"
);
}
#[test]
fn test_escape_curly_braces_in_code_block() {
let theme = themes::theme("onedark").unwrap();
let output = highlight_source_code(
"```\n{:my_var, MyApp.Mod}\n```",
Language::Elixir,
theme,
None,
true,
);
assert_eq!(output, "<pre class=\"autumn-hl\" style=\"background-color: #282C34; color: #ABB2BF;\"><code class=\"language-elixir\" translate=\"no\">```\n<span class=\"ahl-punctuation ahl-bracket\" style=\"color: #ABB2BF;\">{</span><span class=\"ahl-string ahl-special ahl-symbol\" style=\"color: #98C379;\">:my_var</span><span class=\"ahl-punctuation ahl-delimiter\" style=\"color: #ABB2BF;\">,</span> <span class=\"ahl-namespace\" style=\"color: #61AFEF;\">MyApp.Mod</span><span class=\"ahl-punctuation ahl-bracket\" style=\"color: #ABB2BF;\">}</span>\n```</code></pre>");
}
#[test]
fn test_escape_curly_braces_in_inline_code() {
let theme = themes::theme("onedark").unwrap();
let output = highlight_source_code(
"`{:my_var, MyApp.Mod}`",
Language::Elixir,
theme,
None,
true,
);
assert_eq!(output, "<pre class=\"autumn-hl\" style=\"background-color: #282C34; color: #ABB2BF;\"><code class=\"language-elixir\" translate=\"no\">`<span class=\"ahl-punctuation ahl-bracket\" style=\"color: #ABB2BF;\">{</span><span class=\"ahl-string ahl-special ahl-symbol\" style=\"color: #98C379;\">:my_var</span><span class=\"ahl-punctuation ahl-delimiter\" style=\"color: #ABB2BF;\">,</span> <span class=\"ahl-namespace\" style=\"color: #61AFEF;\">MyApp.Mod</span><span class=\"ahl-punctuation ahl-bracket\" style=\"color: #ABB2BF;\">}</span>`</code></pre>");
}
}