1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#![deny(warnings)]
#[macro_use]
extern crate error_chain;
extern crate svgbob;
extern crate comic;
extern crate csv;
extern crate comrak;
extern crate typed_arena;
use typed_arena::Arena;
use comrak::{parse_document, format_html, ComrakOptions};
use comrak::nodes::{AstNode, NodeValue, NodeHtmlBlock};
use std::collections::HashMap;
use errors::*;
mod errors {
error_chain!{
}
}
fn bob_handler(s: &str) -> Result<String> {
Ok(svgbob::to_svg(s).to_string())
}
fn comic_handler(s: &str) -> Result<String> {
Ok(comic::to_svg(s).to_string())
}
fn csv_handler(s: &str) -> Result<String>{
let mut buff = String::new();
let mut rdr = csv::Reader::from_string(s);
buff.push_str("<table>");
buff.push_str("<thead>");
for header in rdr.byte_headers(){
buff.push_str("<tr>");
for h in header{
buff.push_str(&format!("<th>{}</th>", String::from_utf8(h).unwrap_or("".into())));
}
buff.push_str("</tr>");
}
buff.push_str("</thead>");
buff.push_str("</thead>");
buff.push_str("<tbody>");
for record in rdr.byte_records().map(|r| r.unwrap()) {
buff.push_str("<tr>");
for r in record{
buff.push_str(&format!("<td>{}</td>",String::from_utf8(r).unwrap_or("".into())));
}
buff.push_str("</tr>");
}
buff.push_str("</tbody>");
buff.push_str("</table>");
Ok(buff)
}
pub fn parse(arg: &str) -> String{
let mut plugins:HashMap<String, Box<Fn(&str)-> Result<String>>> = HashMap::new();
plugins.insert("bob".into(), Box::new(bob_handler));
plugins.insert("comic".into(), Box::new(comic_handler));
plugins.insert("csv".into(), Box::new(csv_handler));
parse_via_comrak(arg, &plugins)
}
fn parse_via_comrak(arg: &str, plugins: &HashMap<String, Box<Fn(&str) -> Result<String>>>)->String{
let arena = Arena::new();
let option = ComrakOptions {
hardbreaks: true,
github_pre_lang: true,
width: 0,
ext_strikethrough: true,
ext_tagfilter: true,
ext_table: true,
ext_autolink: true,
ext_tasklist: true,
ext_superscript: false,
};
let root = parse_document(
&arena,
arg,
&option);
fn iter_nodes<'a, F>(node: &'a AstNode<'a>, f: &F)
where F : Fn(&'a AstNode<'a>) {
f(node);
for c in node.children() {
iter_nodes(c, f);
}
}
iter_nodes(root, &|node| {
let ref mut value = node.data.borrow_mut().value;
let new_value = match value{
&mut NodeValue::CodeBlock(ref codeblock) => {
match plugins.get(&codeblock.info) {
Some(handler) => {
match handler(&codeblock.literal){
Ok(out) => {
NodeValue::HtmlBlock(
NodeHtmlBlock{
literal: out,
block_type: 0
}
)
},
Err(_) => {
NodeValue::CodeBlock(codeblock.clone())
}
}
}
None => {
NodeValue::CodeBlock(codeblock.clone())
}
}
}
_ => value.to_owned(),
};
*value = new_value;
});
let html: String = format_html(root, &ComrakOptions::default());
html
}