Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
farooqkz committed Jun 9, 2024
1 parent cef8714 commit baeeb79
Show file tree
Hide file tree
Showing 5 changed files with 424 additions and 22 deletions.
1 change: 1 addition & 0 deletions src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pub mod is_emoji;
pub mod link_url;
pub mod parse_from_text;
pub mod utils;
pub mod unicode_ranges;

pub use crate::parser::link_url::LinkDestination;

Expand Down
35 changes: 21 additions & 14 deletions src/parser/parse_from_text/base_parsers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::fmt::Debug;

// Base utility parsers, used by both text and markdown parsers
use nom::{
bytes::complete::tag,
bytes::complete::{tag, is_not},
error::{ErrorKind, ParseError},
sequence::delimited,
IResult,
Expand Down Expand Up @@ -62,22 +62,29 @@ impl<I, T, E: Debug> IntoCustomError<I, T> for Result<T, E> {
/// delimited no whitespace start or end
pub(crate) fn direct_delimited<'a>(
input: &'a str,
tag_str: &str,
) -> IResult<&'a str, &'a str, CustomError<&'a str>> {
let (input, content): (&str, &str) = delimited(
tag(tag_str),
nom::bytes::complete::is_not(tag_str),
tag(tag_str),
)(input)?;
tag_strings: &[&str],
) -> IResult<&'a str, (&'a str, &'a str), CustomError<&'a str>> {
let mut tag_strings = tag_strings.iter();
let (input, content, tag_str) = loop {
let tag_str = tag_strings.next();
if tag_str.is_none() {
return Err(nom::Err::Error(CustomError::NoElement));
}
let tag_str: &str = tag_str.unwrap();
let result: IResult<&str, &str> = delimited(
tag(tag_str),
is_not(tag_str),
tag(tag_str),
)(input);
if result.is_ok() {
let (input, content) = result.unwrap();
break (input, content, tag_str);
}
};
if content.is_empty() {
return Err(nom::Err::Error(CustomError::NoContent));
}
if is_white_space(content.chars().next().into_result()?)
|| is_white_space(content.chars().last().into_result()?)
{
return Err(nom::Err::Error(CustomError::InvalidWhiteSpaceFound));
}
Ok((input, content))
Ok((input, (content, tag_str)))
}

/*
Expand Down
43 changes: 35 additions & 8 deletions src/parser/parse_from_text/markdown_elements.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@ use crate::parser::{
text_elements::{email_address, parse_text_element},
Element,
},
utils::{is_white_space, is_white_space_but_not_linebreak},
utils::{
is_white_space,
is_white_space_but_not_linebreak,
is_unicode_white_space,
is_unicode_punctuation,
},
};

mod label_elements;
Expand Down Expand Up @@ -118,22 +123,44 @@ pub(crate) fn labeled_link(input: &str) -> IResult<&str, Element, CustomError<&s
Ok((input, Element::LabeledLink { label, destination }))
}


/*
* For description on how these functions(parse_italics and parse_bold) work
* refer to this link: https://spec.commonmark.org/0.31.2/#emphasis-and-strong-emphasis
*/
fn parse_italics(input: &str, prev_char: Option<char>) -> IResult<&str, &str, CustomError<&str>> {
let (input_, (content, tag_str)) = direct_delimited(input, &["_", "*"][..])?;
let is_start_left_flanking: bool =
b.starts_with(is_unicode_white_space) &&
(!b.starts_with(is_unicode_punctuation) ||
(b.starts_with(is_unicode_punctuation) &&
(prev_char.is_none() ||
is_unicode_punctuation(prev_char.unwrap()) ||
is_unicode_white_space(prev_char.unwrap()))));
// it is of great note here that order is very important. Iff prev_char.is_none() evals to
// false, this means it is a Some, and prev_char.unwrap() won't panic.
// On the other hand, iff it evals to true, the rest won't be run and again
// no panic happens.


}

fn parse_bold(input: &str, prev_char: Option<char>) -> IResult<&str, &str, CustomError<&str>> {

}

pub(crate) fn parse_element(
input: &str,
prev_char: Option<char>,
) -> IResult<&str, Element, CustomError<&str>> {
// the order is important
// generaly more specific parsers that fail/return fast should be in the front
// But keep in mind that the order can also change how and if the parser works as intended
if let Ok((i, b)) = direct_delimited(input, "**") {
if let Ok((i, b)) = parse_bold(input, prev_char) {
Ok((i, Element::Bold(parse_all(b))))
} else if let Ok((i, b)) = direct_delimited(input, "__") {
Ok((i, Element::Bold(parse_all(b))))
} else if let Ok((i, b)) = direct_delimited(input, "_") {
Ok((i, Element::Italics(parse_all(b))))
} else if let Ok((i, b)) = direct_delimited(input, "*") {
} else if let Ok((i, b)) = parse_italics(input, prev_char) {
Ok((i, Element::Italics(parse_all(b))))
} else if let Ok((i, b)) = direct_delimited(input, "~~") {
} else if let Ok((i, (b, _tag_str))) = direct_delimited(input, &["~~"][..]) {
Ok((i, Element::StrikeThrough(parse_all(b))))
} else if let Ok((i, elm)) = code_block(input) {
Ok((i, elm))
Expand Down
Loading

0 comments on commit baeeb79

Please sign in to comment.