version 0.1.2 #3
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -4,7 +4,7 @@ version = 4
|
||||
|
||||
[[package]]
|
||||
name = "marginal"
|
||||
version = "0.1.0"
|
||||
version = "0.1.2"
|
||||
dependencies = [
|
||||
"nom",
|
||||
]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "marginal"
|
||||
version = "0.1.0"
|
||||
version = "0.1.2"
|
||||
edition = "2024"
|
||||
publish = ["gitea"]
|
||||
|
||||
|
||||
@@ -66,6 +66,7 @@ command = [
|
||||
"cargo", "nextest", "run",
|
||||
"--hide-progress-bar",
|
||||
"--failure-output", "final",
|
||||
"--no-fail-fast",
|
||||
]
|
||||
need_stdout = true
|
||||
analyzer = "nextest"
|
||||
|
||||
@@ -31,4 +31,6 @@ pub enum Block {
|
||||
Code { content: String, lang: String },
|
||||
Quote { inner: Box<Block> },
|
||||
Paragraph { inner: Vec<Inline> },
|
||||
UnorderedList { items: Vec<Block> },
|
||||
OrderedList { items: Vec<Block> },
|
||||
}
|
||||
|
||||
@@ -15,12 +15,28 @@ impl ToHtml for Vec<Block> {
|
||||
impl ToHtml for Block {
|
||||
fn to_html(&self) -> String {
|
||||
match self {
|
||||
Block::Paragraph { inner } => format!("<p>{}</p><br>", inner.to_html()),
|
||||
Block::Paragraph { inner } => format!("<p>{}</p>", inner.to_html()),
|
||||
Block::Heading { inner, level } => {
|
||||
format!("<h{}>{}</h{}>", level, inner.to_html(), level)
|
||||
}
|
||||
Block::Code { content, lang: _ } => format!("<pre><code>{content}</code></pre>"),
|
||||
Block::Quote { inner } => format!("<div class=\"quote\">{}</div>", inner.to_html()),
|
||||
Block::UnorderedList { items } => {
|
||||
let mut html = "<ul>".to_string();
|
||||
for item in items {
|
||||
html.push_str(&format!("<li>{}</li>", &item.to_html()));
|
||||
}
|
||||
html.push_str("</ul>");
|
||||
html
|
||||
}
|
||||
Block::OrderedList { items } => {
|
||||
let mut html = "<ol>".to_string();
|
||||
for item in items {
|
||||
html.push_str(&format!("<li>{}</li>", &item.to_html()));
|
||||
}
|
||||
html.push_str("</ol>");
|
||||
html
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ use nom::{
|
||||
IResult, Parser,
|
||||
branch::alt,
|
||||
bytes::complete::{tag, take_until},
|
||||
combinator::peek,
|
||||
multi::{many_m_n, many0, many1},
|
||||
sequence::{delimited, terminated},
|
||||
};
|
||||
@@ -14,8 +15,16 @@ pub fn blocks(input: &str) -> IResult<&str, Vec<Block>, MarkdownParseError> {
|
||||
}
|
||||
|
||||
pub fn block(input: &str) -> IResult<&str, Block, MarkdownParseError> {
|
||||
//alt((heading_block, code_block, quote_block, paragraph_block)).parse(input)
|
||||
terminated(
|
||||
alt((heading_block, code_block, quote_block, paragraph_block)),
|
||||
alt((
|
||||
heading_block,
|
||||
code_block,
|
||||
quote_block,
|
||||
paragraph_block,
|
||||
ordered_list,
|
||||
unordered_list,
|
||||
)),
|
||||
tag("\n"),
|
||||
)
|
||||
.parse(input)
|
||||
@@ -45,7 +54,7 @@ fn code_block(input: &str) -> IResult<&str, Block, MarkdownParseError> {
|
||||
delimited(
|
||||
tag("```"),
|
||||
(take_until("\n"), tag("\n"), take_until("```\n")),
|
||||
tag("```\n"),
|
||||
(tag("```"), peek(tag("\n"))),
|
||||
)
|
||||
.parse(input)
|
||||
.map(|(rem, (lang, _, code))| {
|
||||
@@ -72,6 +81,20 @@ fn quote_block(input: &str) -> IResult<&str, Block, MarkdownParseError> {
|
||||
})
|
||||
}
|
||||
|
||||
fn unordered_list(input: &str) -> IResult<&str, Block, MarkdownParseError> {
|
||||
many1((tag("- "), block)).parse(input).map(|(rem, v)| {
|
||||
let items = v.into_iter().map(|(_, b)| b).collect();
|
||||
(rem, Block::UnorderedList { items })
|
||||
})
|
||||
}
|
||||
|
||||
fn ordered_list(input: &str) -> IResult<&str, Block, MarkdownParseError> {
|
||||
many1((tag("1. "), block)).parse(input).map(|(rem, v)| {
|
||||
let items = v.into_iter().map(|(_, b)| b).collect();
|
||||
(rem, Block::OrderedList { items })
|
||||
})
|
||||
}
|
||||
|
||||
//|-------------------------------------------------------------------------------|
|
||||
//| TESTS TESTS TESTS TESTS TESTS TESTS TESTS TESTS TESTS TESTS TESTS TESTS TESTS |
|
||||
//|-------------------------------------------------------------------------------|
|
||||
@@ -83,10 +106,10 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn single_paragraph() {
|
||||
let md = "Hello markdown!!";
|
||||
let md = "Hello markdown!!\n";
|
||||
let (rem, block) = paragraph_block(md).unwrap();
|
||||
|
||||
assert_eq!(rem, "");
|
||||
assert_eq!(rem, "\n");
|
||||
assert_eq!(
|
||||
block,
|
||||
Block::Paragraph {
|
||||
@@ -107,7 +130,7 @@ fn main() {
|
||||
";
|
||||
let (rem, block) = code_block(md).unwrap();
|
||||
|
||||
assert_eq!(rem, "");
|
||||
assert_eq!(rem, "\n");
|
||||
assert_eq!(
|
||||
block,
|
||||
Block::Code {
|
||||
@@ -125,7 +148,7 @@ echo \"hello world\"
|
||||
";
|
||||
let (rem, block) = code_block(md).unwrap();
|
||||
|
||||
assert_eq!(rem, "");
|
||||
assert_eq!(rem, "\n");
|
||||
assert_eq!(
|
||||
block,
|
||||
Block::Code {
|
||||
@@ -145,11 +168,11 @@ echo hello
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn level_1_heading() {
|
||||
let md = "## Heading2";
|
||||
fn level_2_heading() {
|
||||
let md = "## Heading2\n";
|
||||
let (rem, block) = heading_block(md).unwrap();
|
||||
|
||||
assert_eq!(rem, "");
|
||||
assert_eq!(rem, "\n");
|
||||
assert_eq!(
|
||||
block,
|
||||
Block::Heading {
|
||||
@@ -163,16 +186,16 @@ echo hello
|
||||
|
||||
#[test]
|
||||
fn heading_no_space() {
|
||||
let md = "#heading";
|
||||
let md = "#heading\n";
|
||||
assert!(heading_block(md).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn level_6_heading() {
|
||||
let md = "###### Heading6";
|
||||
let md = "###### Heading6\n";
|
||||
let (rem, block) = heading_block(md).unwrap();
|
||||
|
||||
assert_eq!(rem, "");
|
||||
assert_eq!(rem, "\n");
|
||||
assert_eq!(
|
||||
block,
|
||||
Block::Heading {
|
||||
@@ -186,7 +209,7 @@ echo hello
|
||||
|
||||
#[test]
|
||||
fn no_level_7_heading() {
|
||||
let md = "####### Heading7";
|
||||
let md = "####### Heading7\n";
|
||||
assert!(heading_block(md).is_err());
|
||||
}
|
||||
|
||||
@@ -233,4 +256,84 @@ Hello MD
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simple_unordered_list() {
|
||||
let md = "- a\n- b\n- c\n- b again with some `code`\n\n";
|
||||
let (rem, block) = unordered_list(md).unwrap();
|
||||
|
||||
assert_eq!(rem, "\n");
|
||||
assert_eq!(
|
||||
block,
|
||||
Block::UnorderedList {
|
||||
items: vec![
|
||||
Block::Paragraph {
|
||||
inner: vec![Inline::Text {
|
||||
content: "a".to_string()
|
||||
}]
|
||||
},
|
||||
Block::Paragraph {
|
||||
inner: vec![Inline::Text {
|
||||
content: "b".to_string()
|
||||
}]
|
||||
},
|
||||
Block::Paragraph {
|
||||
inner: vec![Inline::Text {
|
||||
content: "c".to_string()
|
||||
}]
|
||||
},
|
||||
Block::Paragraph {
|
||||
inner: vec![
|
||||
Inline::Text {
|
||||
content: "b again with some ".to_string()
|
||||
},
|
||||
Inline::Code {
|
||||
content: "code".to_string()
|
||||
}
|
||||
]
|
||||
},
|
||||
]
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simple_ordered_list() {
|
||||
let md = "1. a\n1. b\n1. c\n1. b again with some `code`\n\n";
|
||||
let (rem, block) = ordered_list(md).unwrap();
|
||||
|
||||
assert_eq!(rem, "\n");
|
||||
assert_eq!(
|
||||
block,
|
||||
Block::OrderedList {
|
||||
items: vec![
|
||||
Block::Paragraph {
|
||||
inner: vec![Inline::Text {
|
||||
content: "a".to_string()
|
||||
}]
|
||||
},
|
||||
Block::Paragraph {
|
||||
inner: vec![Inline::Text {
|
||||
content: "b".to_string()
|
||||
}]
|
||||
},
|
||||
Block::Paragraph {
|
||||
inner: vec![Inline::Text {
|
||||
content: "c".to_string()
|
||||
}]
|
||||
},
|
||||
Block::Paragraph {
|
||||
inner: vec![
|
||||
Inline::Text {
|
||||
content: "b again with some ".to_string()
|
||||
},
|
||||
Inline::Code {
|
||||
content: "code".to_string()
|
||||
}
|
||||
]
|
||||
},
|
||||
]
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,10 +85,10 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn single_text() {
|
||||
let md = "hello normal inline";
|
||||
let md = "hello normal inline\n";
|
||||
let (rem, parsed) = text_inline(md).unwrap();
|
||||
|
||||
assert_eq!(rem, "");
|
||||
assert_eq!(rem, "\n");
|
||||
assert_eq!(
|
||||
parsed,
|
||||
Inline::Text {
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
//! A weird markdown parser. Please don't forget to add a newline in the end of a file or it won't
|
||||
//! work :)
|
||||
|
||||
use std::fmt::{Debug, Display};
|
||||
|
||||
pub mod block;
|
||||
|
||||
Reference in New Issue
Block a user