use std::fmt::Write;
use parsing::{ScopeStackOp, Scope, SCOPE_REPO};
use highlighting::{Style, self};
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum ClassStyle {
Spaced,
}
fn scope_to_classes(s: &mut String, scope: Scope, style: ClassStyle) {
assert!(style == ClassStyle::Spaced); let repo = SCOPE_REPO.lock().unwrap();
for i in 0..(scope.len()) {
let atom = scope.atom_at(i as usize);
let atom_s = repo.atom_str(atom);
if i != 0 {
s.push_str(" ")
}
s.push_str(atom_s);
}
}
pub fn tokens_to_classed_html(line: &str, ops: &[(usize, ScopeStackOp)], style: ClassStyle) -> String {
let mut s = String::with_capacity(line.len()+ops.len()*8); let mut cur_index = 0;
for &(i, ref op) in ops {
if i > cur_index {
s.push_str(&line[cur_index..i]);
cur_index = i
}
match op {
&ScopeStackOp::Push(scope) => {
s.push_str("<span class=\"");
scope_to_classes(&mut s, scope, style);
s.push_str("\">");
},
&ScopeStackOp::Pop(n) => {
for _ in 0..n {
s.push_str("</span>");
}
},
&ScopeStackOp::Noop => panic!("ops shouldn't have no-ops")
}
}
s
}
pub fn styles_to_coloured_html(v: &[(Style, &str)], bg: bool) -> String {
let mut s: String = String::new();
for &(ref style, text) in v.iter() {
write!(s,"<span style=\"").unwrap();
if bg {
write!(s,
"background-color:#{:02x}{:02x}{:02x};",
style.background.r,
style.background.g,
style.background.b)
.unwrap();
}
if style.font_style.contains(highlighting::FONT_STYLE_UNDERLINE) {
write!(s, "text-decoration:underline;").unwrap();
}
if style.font_style.contains(highlighting::FONT_STYLE_BOLD) {
write!(s, "font-weight:bold;").unwrap();
}
if style.font_style.contains(highlighting::FONT_STYLE_ITALIC) {
write!(s, "font-style:italic;").unwrap();
}
write!(s,
"color:#{:02x}{:02x}{:02x};\">{}</span>",
style.foreground.r,
style.foreground.g,
style.foreground.b,
text)
.unwrap();
}
s
}
#[cfg(test)]
mod tests {
use super::*;
use parsing::{SyntaxSet, ParseState, ScopeStack};
use highlighting::{ThemeSet, Style, Highlighter, HighlightIterator, HighlightState};
#[test]
fn tokens() {
let ps = SyntaxSet::load_from_folder("testdata/Packages").unwrap();
let syntax = ps.find_syntax_by_name("Markdown").unwrap();
let mut state = ParseState::new(syntax);
let line = "[w](t.co) *hi* **five**";
let ops = state.parse_line(line);
let html = tokens_to_classed_html(line, &ops[..], ClassStyle::Spaced);
assert_eq!(html, include_str!("../testdata/test2.html").trim_right());
let ts = ThemeSet::load_defaults();
let highlighter = Highlighter::new(&ts.themes["InspiredGitHub"]);
let mut highlight_state = HighlightState::new(&highlighter, ScopeStack::new());
let iter = HighlightIterator::new(&mut highlight_state, &ops[..], line, &highlighter);
let regions: Vec<(Style, &str)> = iter.collect();
let html2 = styles_to_coloured_html(®ions[..], true);
assert_eq!(html2, include_str!("../testdata/test1.html").trim_right());
}
}