refactor md parser, TODO: parse_str
This commit is contained in:
@@ -1,61 +1,65 @@
|
||||
use crate::ast::Inline;
|
||||
use crate::{MdParseError, ast::Inline};
|
||||
|
||||
pub fn parse_inlines(input: &str) -> Vec<Inline> {
|
||||
pub fn parse_inlines(input: &str) -> Result<Vec<Inline>, MdParseError> {
|
||||
let mut inlines = Vec::new();
|
||||
let mut chars = input.chars().peekable();
|
||||
|
||||
while let Some(c) = chars.next() {
|
||||
match c {
|
||||
'*' => {
|
||||
let inner = collect_until(&mut chars, '*');
|
||||
inlines.push(Inline::Bold(parse_inlines(&inner)));
|
||||
let inner = collect_until(&mut chars, '*')?;
|
||||
inlines.push(Inline::Bold(parse_inlines(&inner)?));
|
||||
}
|
||||
'_' => {
|
||||
let inner = collect_until(&mut chars, '_');
|
||||
inlines.push(Inline::Italic(parse_inlines(&inner)));
|
||||
let inner = collect_until(&mut chars, '_')?;
|
||||
inlines.push(Inline::Italic(parse_inlines(&inner)?));
|
||||
}
|
||||
'`' => {
|
||||
let code = collect_until(&mut chars, '`');
|
||||
let code = collect_until(&mut chars, '`')?;
|
||||
inlines.push(Inline::Code(code));
|
||||
}
|
||||
'[' => {
|
||||
let text = collect_until(&mut chars, ']');
|
||||
if chars.next() == Some('(') {
|
||||
let href = collect_until(&mut chars, ')');
|
||||
let text = collect_until(&mut chars, ']')?;
|
||||
if let Some('(') = chars.next() {
|
||||
let href = collect_until(&mut chars, ')')?;
|
||||
inlines.push(Inline::Link {
|
||||
text: parse_inlines(&text),
|
||||
text: parse_inlines(&text)?,
|
||||
href,
|
||||
});
|
||||
} else {
|
||||
Err(MdParseError::new(
|
||||
"(<href>)",
|
||||
chars.next().unwrap_or_default(),
|
||||
))?;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
let mut text = String::new();
|
||||
text.push(c);
|
||||
while let Some(&nc) = chars.peek() {
|
||||
while let Some(nc) = chars.next() {
|
||||
if matches!(nc, '*' | '_' | '`' | '[') {
|
||||
break;
|
||||
}
|
||||
text.push(chars.next().unwrap());
|
||||
text.push(nc);
|
||||
}
|
||||
inlines.push(Inline::Text(text));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inlines
|
||||
Ok(inlines)
|
||||
}
|
||||
|
||||
fn collect_until<I: Iterator<Item = char>>(
|
||||
chars: &mut std::iter::Peekable<I>,
|
||||
end: char,
|
||||
) -> String {
|
||||
) -> Result<String, MdParseError> {
|
||||
let mut s = String::new();
|
||||
while let Some(&c) = chars.peek() {
|
||||
while let Some(c) = chars.next() {
|
||||
if c == end {
|
||||
chars.next();
|
||||
break;
|
||||
return Ok(s);
|
||||
}
|
||||
s.push(chars.next().unwrap());
|
||||
s.push(c);
|
||||
}
|
||||
s
|
||||
Err(MdParseError::new(end, ""))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user