Add url parsing

pull/1/head
trivernis 5 years ago
parent 1e038ed404
commit 6db54b449f

@ -385,6 +385,9 @@ impl Parser {
} }
fn parse_subtext(&mut self) -> Result<SubText, ParseError> { fn parse_subtext(&mut self) -> Result<SubText, ParseError> {
if let Ok(url) = self.parse_url() {
return Ok(SubText::Url(url));
}
match self.current_char { match self.current_char {
'*' => { '*' => {
parse_option!(self.next_char(), self.index); parse_option!(self.next_char(), self.index);
@ -433,21 +436,74 @@ impl Parser {
if self.current_char == '`' { if self.current_char == '`' {
parse_option!(self.next_char(), self.index) parse_option!(self.next_char(), self.index)
} }
Ok(SubText::Monospace(MonospaceText { Ok(SubText::Monospace(MonospaceText { value: plain_text }))
value: Box::new(plain_text),
}))
} }
'\n' | '|' => Err(ParseError::new(self.index)), '\n' | '|' => Err(ParseError::new(self.index)),
_ => Ok(SubText::Plain(self.parse_plain_text()?)), _ => Ok(SubText::Plain(self.parse_plain_text()?)),
} }
} }
// parses an url
fn parse_url(&mut self) -> Result<Url, ParseError> {
let start_index = self.index;
self.seek_inline_whitespace();
if self.current_char != '[' {
let err = ParseError::new(self.index);
self.revert_to(start_index)?;
return Err(err);
}
let mut title = String::new();
while let Some(character) = self.next_char() {
if character == ']' || character == '\n' {
break;
}
title.push(character);
}
if self.current_char != ']' {
// it stopped at a linebreak or EOF
let err = ParseError::new(self.index);
self.revert_to(start_index)?;
return Err(err);
}
if let Some(character) = self.next_char() {
if character != '(' {
// the next char isn't the start of the encased url
let err = ParseError::new(self.index);
self.revert_to(start_index)?;
return Err(err);
}
}
self.seek_inline_whitespace();
let mut url = String::new();
while let Some(character) = self.next_char() {
if character == ')' || character == '\n' {
break;
}
url.push(character);
}
if self.current_char != ')' || url.is_empty() {
let err = ParseError::new(self.index);
self.revert_to(start_index)?;
return Err(err);
}
parse_option!(self.next_char(), self.index);
if title.is_empty() {
Ok(Url::new(url.clone(), url))
} else {
Ok(Url::new(title, url))
}
}
fn parse_plain_text(&mut self) -> Result<PlainText, ParseError> { fn parse_plain_text(&mut self) -> Result<PlainText, ParseError> {
let mut current_char = self.current_char; let mut current_char = self.current_char;
let mut characters = String::new(); let mut characters = String::new();
let mut count = 0;
loop { loop {
match current_char { match current_char {
'\n' | '*' | '_' | '~' | '|' | '`' => break, '\n' | '*' | '_' | '~' | '|' | '`' => break,
'[' if count > 0 => break, // if its the first it means that the url parsing has failed
_ => characters.push(current_char), _ => characters.push(current_char),
} }
if let Some(character) = self.next_char() { if let Some(character) = self.next_char() {
@ -455,6 +511,7 @@ impl Parser {
} else { } else {
break; break;
} }
count += 1;
} }
if characters.len() > 0 { if characters.len() > 0 {

@ -92,6 +92,7 @@ pub enum SubText {
Underlined(UnderlinedText), Underlined(UnderlinedText),
Striked(StrikedText), Striked(StrikedText),
Monospace(MonospaceText), Monospace(MonospaceText),
Url(Url),
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -121,9 +122,17 @@ pub struct StrikedText {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct MonospaceText { pub struct MonospaceText {
pub(crate) value: Box<PlainText>, pub(crate) value: PlainText,
} }
#[derive(Clone, Debug)]
pub struct Url {
title: String,
url: String,
}
// implementations
impl Document { impl Document {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
@ -223,4 +232,10 @@ impl Row {
} }
} }
impl Url {
pub fn new(title: String, url: String) -> Self {
Self { title, url }
}
}
// TODO: Images, URIs // TODO: Images, URIs

Loading…
Cancel
Save