Skip to content

Commit

Permalink
Run rustfmt and clippy
Browse files Browse the repository at this point in the history
  • Loading branch information
Johann committed Nov 2, 2015
1 parent 4036dc1 commit 46b3b42
Show file tree
Hide file tree
Showing 17 changed files with 274 additions and 437 deletions.
79 changes: 46 additions & 33 deletions src/html.rs
Expand Up @@ -5,19 +5,19 @@ use parser::Span;
use parser::Span::{Break, Text, Emphasis, Strong, Code, Link, Image};

// takes a number of elements and returns their collective text as a slug
fn slugify(elements : &[Span]) -> String {
fn slugify(elements: &[Span]) -> String {
let mut ret = String::new();

for el in elements {
let next = match *el {
Break => "".to_owned(),
Text(ref text)
| Link(ref text, _, _)
| Image(ref text, _, _)
| Code(ref text) => text.trim().replace(" ", "_").to_lowercase().to_owned(),
Text(ref text) |
Link(ref text, _, _) |
Image(ref text, _, _) |
Code(ref text) => text.trim().replace(" ", "_").to_lowercase().to_owned(),
Strong(ref content) | Emphasis(ref content) => slugify(content),
};
if !ret.is_empty(){
if !ret.is_empty() {
ret.push('_');
}
ret.push_str(&next);
Expand All @@ -26,17 +26,17 @@ fn slugify(elements : &[Span]) -> String {
ret
}

pub fn to_html (blocks : &[Block]) -> String {
pub fn to_html(blocks: &[Block]) -> String {
let mut ret = String::new();
for block in blocks.iter(){
for block in blocks.iter() {
let next = match *block {
Header (ref elements, level) => format_header(elements, level),
Paragraph (ref elements) => format_paragraph(elements),
Blockquote (ref elements) => format_blockquote(elements),
CodeBlock (ref elements) => format_codeblock(elements),
UnorderedList (ref elements) => format_unordered_list(elements),
Raw (ref elements) => elements.to_owned(),
Hr => format!("<hr>")
Header(ref elements, level) => format_header(elements, level),
Paragraph(ref elements) => format_paragraph(elements),
Blockquote(ref elements) => format_blockquote(elements),
CodeBlock(ref elements) => format_codeblock(elements),
UnorderedList(ref elements) => format_unordered_list(elements),
Raw(ref elements) => elements.to_owned(),
Hr => format!("<hr>"),
};
ret.push_str(&next)
}
Expand All @@ -45,63 +45,76 @@ pub fn to_html (blocks : &[Block]) -> String {
ret
}

fn format_spans(elements : &[Span]) -> String {
fn format_spans(elements: &[Span]) -> String {
let mut ret = String::new();
for element in elements.iter(){
let next = match *element {
for element in elements.iter() {
let next = match *element {
Break => format!("<br />"),
Text(ref text) => format!("{}", &escape(text)),
Code(ref text) => format!("<code>{}</code>", &escape(text)),
Link(ref text, ref url, None) => format!("<a href='{}'>{}</a>", &escape(url), &escape(text)),
Link(ref text, ref url, Some(ref title)) => format!("<a href='{}' title='{}'>{}</a>", &escape(url), &escape(title), &escape(text)),
Image(ref text, ref url, None) => format!("<img src='{}' alt='{}' />", &escape(url), &escape(text)),
Image(ref text, ref url, Some(ref title)) => format!("<img src='{}' title='{}' alt='{}' />", &escape(url), &escape(title), &escape(text)),
Link(ref text, ref url, None) =>
format!("<a href='{}'>{}</a>", &escape(url), &escape(text)),
Link(ref text, ref url, Some(ref title)) => format!("<a href='{}' title='{}'>{}</a>",
&escape(url),
&escape(title),
&escape(text)),
Image(ref text, ref url, None) =>
format!("<img src='{}' alt='{}' />", &escape(url), &escape(text)),
Image(ref text, ref url, Some(ref title)) =>
format!("<img src='{}' title='{}' alt='{}' />",
&escape(url),
&escape(title),
&escape(text)),
Emphasis(ref content) => format!("<em>{}</em>", format_spans(content)),
Strong(ref content) => format!("<strong>{}</strong>", format_spans(content))
Strong(ref content) => format!("<strong>{}</strong>", format_spans(content)),
};
ret.push_str(&next)
}
ret
}

fn escape(text: &str) -> String{
fn escape(text: &str) -> String {
text.replace("&", "&amp;")
.replace("<", "&lt;")
.replace("\"", "&quot;")
.replace("'", "&#8217;")
.replace(">", "&gt;")
}

fn format_unordered_list(elements : &[ListItem]) -> String{
fn format_unordered_list(elements: &[ListItem]) -> String {
let mut ret = String::new();
for list_item in elements{
for list_item in elements {
let mut content = String::new();
match *list_item {
ListItem::Simple(ref els) => {
content.push_str(&format_spans(els))
},
}
ListItem::Paragraph(ref paragraphs) => {
content.push_str(&format!("\n{}", to_html(paragraphs)))
},
}
}

ret.push_str(&format!("\n<li>{}</li>\n", content))
}
format!("<ul>{}</ul>\n\n", ret)
}

fn format_codeblock(elements : &str) -> String{
fn format_codeblock(elements: &str) -> String {
format!("<pre><code>{}</code></pre>\n\n", &escape(elements))
}

fn format_blockquote(elements : &[Block]) -> String{
fn format_blockquote(elements: &[Block]) -> String {
format!("<blockquote>\n{}</blockquote>\n\n", to_html(elements))
}

fn format_paragraph(elements : &[Span]) -> String{
fn format_paragraph(elements: &[Span]) -> String {
format!("<p>{}</p>\n\n", format_spans(elements))
}

fn format_header(elements : &[Span], level : usize) -> String{
format!("<h{} id='{}'>{}</h{}>\n\n", level, slugify(elements), format_spans(elements), level)
fn format_header(elements: &[Span], level: usize) -> String {
format!("<h{} id='{}'>{}</h{}>\n\n",
level,
slugify(elements),
format_spans(elements),
level)
}
15 changes: 7 additions & 8 deletions src/lib.rs
@@ -1,7 +1,7 @@
//! A crate for parsing Markdown in Rust
#![crate_name = "markdown"]
#![deny(missing_docs)]
//#![deny(warnings)]
// #![deny(warnings)]

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
Expand All @@ -21,30 +21,29 @@ mod html;
use parser::Block;

/// Converts a Markdown string to HTML
pub fn to_html(text : &str) -> String{
pub fn to_html(text: &str) -> String {
let result = parser::parse(text);
html::to_html(&result)
}

/// Converts a Markdown string to a tokenset of Markdown items
pub fn tokenize(text : &str) -> Vec<Block>{
pub fn tokenize(text: &str) -> Vec<Block> {
parser::parse(text)
}

/// Opens a file and converts its contents to HTML
pub fn file_to_html(path : &Path) -> Result<String, Error>{
pub fn file_to_html(path: &Path) -> Result<String, Error> {
let mut file = match File::open(path) {
Ok(file) => file,
Err(e) => return Err(e)
Err(e) => return Err(e),
};

let mut text = String::new();
match file.read_to_string(&mut text) {
Ok(_) => (),
Err(e) => return Err(e)
};
Err(e) => return Err(e),
}

let result = parser::parse(&text);
Ok(html::to_html(&result))
}

3 changes: 1 addition & 2 deletions src/main.rs
Expand Up @@ -7,8 +7,7 @@ fn main() {
let args: Vec<String> = env::args().collect();
println!("{:?}", args);
let path = Path::new(&args[1]);
//let display = path.display();
// let display = path.display();

println!("{}", markdown::file_to_html(&path).unwrap());
}

81 changes: 28 additions & 53 deletions src/parser/block/atx_header.rs
Expand Up @@ -6,15 +6,11 @@ use parser::span::parse_spans;
pub fn parse_atx_header(lines: &[&str]) -> Option<(Block, usize)> {
let atx_header = Regex::new(r"^(?P<level>#{1,6})\s(?P<text>.*?)(?:\s#*)?$").unwrap();

if atx_header.is_match(lines[0]){
if atx_header.is_match(lines[0]) {
let caps = atx_header.captures(lines[0]).unwrap();
return Some((
Header(
parse_spans(caps.name("text").unwrap()),
caps.name("level").unwrap().len()
),
1
));
return Some((Header(parse_spans(caps.name("text").unwrap()),
caps.name("level").unwrap().len()),
1));
}
None
}
Expand All @@ -27,65 +23,44 @@ mod test {

#[test]
fn finds_atx_header() {
assert_eq!(
parse_atx_header(&vec!["### Test", "testtest"]).unwrap(),
(Header(vec![Text("Test".to_owned())], 3), 1)
);
assert_eq!(parse_atx_header(&vec!["### Test", "testtest"]).unwrap(),
(Header(vec![Text("Test".to_owned())], 3), 1));

assert_eq!(
parse_atx_header(&vec!["# Test", "testtest"]).unwrap(),
(Header(vec![Text("Test".to_owned())], 1), 1)
);
assert_eq!(parse_atx_header(&vec!["# Test", "testtest"]).unwrap(),
(Header(vec![Text("Test".to_owned())], 1), 1));

assert_eq!(
parse_atx_header(&vec!["###### Test", "testtest"]).unwrap(),
(Header(vec![Text("Test".to_owned())], 6), 1)
);
assert_eq!(parse_atx_header(&vec!["###### Test", "testtest"]).unwrap(),
(Header(vec![Text("Test".to_owned())], 6), 1));

assert_eq!(
parse_atx_header(&vec!["### Test and a pretty long sentence", "testtest"]).unwrap(),
(Header(vec![Text("Test and a pretty long sentence".to_owned())], 3), 1)
);
assert_eq!(parse_atx_header(&vec!["### Test and a pretty long sentence", "testtest"])
.unwrap(),
(Header(vec![Text("Test and a pretty long sentence".to_owned())], 3),
1));
}

#[test]
fn ignores_closing_hashes() {
assert_eq!(
parse_atx_header(&vec!["### Test ###", "testtest"]).unwrap(),
(Header(vec![Text("Test".to_owned())], 3), 1)
);
assert_eq!(parse_atx_header(&vec!["### Test ###", "testtest"]).unwrap(),
(Header(vec![Text("Test".to_owned())], 3), 1));

assert_eq!(
parse_atx_header(&vec!["# Test #", "testtest"]).unwrap(),
(Header(vec![Text("Test".to_owned())], 1), 1)
);
assert_eq!(parse_atx_header(&vec!["# Test #", "testtest"]).unwrap(),
(Header(vec![Text("Test".to_owned())], 1), 1));

assert_eq!(
parse_atx_header(&vec!["###### Test ##", "testtest"]).unwrap(),
(Header(vec![Text("Test".to_owned())], 6), 1)
);
assert_eq!(parse_atx_header(&vec!["###### Test ##", "testtest"]).unwrap(),
(Header(vec![Text("Test".to_owned())], 6), 1));

assert_eq!(
parse_atx_header(&vec!["### Test and a pretty long sentence #########", "testtest"]).unwrap(),
(Header(vec![Text("Test and a pretty long sentence".to_owned())], 3), 1)
);
assert_eq!(parse_atx_header(&vec!["### Test and a pretty long sentence #########",
"testtest"])
.unwrap(),
(Header(vec![Text("Test and a pretty long sentence".to_owned())], 3),
1));
}


#[test]
fn no_false_positives() {
assert_eq!(
parse_atx_header(&vec!["####### Test", "testtest"]),
None
);
assert_eq!(
parse_atx_header(&vec!["Test #", "testtest"]),
None
);
assert_eq!(
parse_atx_header(&vec!["T ### est #", "testtest"]),
None
);
assert_eq!(parse_atx_header(&vec!["####### Test", "testtest"]), None);
assert_eq!(parse_atx_header(&vec!["Test #", "testtest"]), None);
assert_eq!(parse_atx_header(&vec!["T ### est #", "testtest"]), None);
}
}

24 changes: 9 additions & 15 deletions src/parser/block/blockquote.rs
Expand Up @@ -2,7 +2,7 @@ use parser::block::parse_blocks;
use parser::Block;
use parser::Block::Blockquote;

pub fn parse_blockquote(lines: &[&str]) -> Option<(Block, usize)>{
pub fn parse_blockquote(lines: &[&str]) -> Option<(Block, usize)> {
// if the first char isnt a blockquote don't even bother
if lines[0].is_empty() || &lines[0][0..1] != ">" {
return None;
Expand All @@ -28,7 +28,7 @@ pub fn parse_blockquote(lines: &[&str]) -> Option<(Block, usize)>{
}
if line.is_empty() {
prev_newline = true;
}else{
} else {
prev_newline = false;
}
let mut begin = 0;
Expand All @@ -41,7 +41,7 @@ pub fn parse_blockquote(lines: &[&str]) -> Option<(Block, usize)>{
if i > 0 {
content.push('\n');
}
content.push_str(&line[begin .. line.len()]);
content.push_str(&line[begin..line.len()]);
i += 1;
}

Expand All @@ -61,37 +61,31 @@ mod test {
fn finds_blockquote() {
match parse_blockquote(&vec!["> A citation", "> is good"]) {
Some((Blockquote(_), 2)) => (),
_ => panic!()
_ => panic!(),
}

match parse_blockquote(&vec!["> A citation", "> is good,", "very good"]) {
Some((Blockquote(_), 3)) => (),
_ => panic!()
_ => panic!(),
}
}

#[test]
fn knows_when_to_stop() {
match parse_blockquote(&vec!["> A citation", "> is good", "", "whatever"]) {
Some((Blockquote(_), 3)) => (),
_ => panic!()
_ => panic!(),
}
}

#[test]
fn no_false_positives() {
assert_eq!(
parse_blockquote(&vec!["wat > this"]),
None
);
assert_eq!(parse_blockquote(&vec!["wat > this"]), None);
}

#[test]
fn no_early_matching() {
assert_eq!(
parse_blockquote(&vec!["Hello", "> A citation", "> is good", "", "whatever"]),
None
);
assert_eq!(parse_blockquote(&vec!["Hello", "> A citation", "> is good", "", "whatever"]),
None);
}
}

0 comments on commit 46b3b42

Please sign in to comment.