diff options
author | Ben Bridle <ben@derelict.engineering> | 2025-01-19 18:49:36 +1300 |
---|---|---|
committer | Ben Bridle <ben@derelict.engineering> | 2025-01-19 18:51:10 +1300 |
commit | d0ff550b264206109349f0385c145f340ddf992b (patch) | |
tree | d7ffcb3f22bf5698ae00756b96c532db62de8bd6 | |
parent | 5c9ff7c79fec508017ea6c15b2612bc99276a9b6 (diff) | |
download | markdown-d0ff550b264206109349f0385c145f340ddf992b.zip |
Change syntax
Internal links are now delimited with braces, and external links are
now delimited with angle brackets. A label is separated from a path in
an external link with two consecutive colons.
Embed blocks are now delimited with angle brackets in the same manner
as external links, with label separated from path with two consecutive
colons. Embed blocks still begin with a single exclamation mark.
Bold line elements are now delimited with only a single * character,
instead of two. This is to match the other delimiters, which each use
only a single character.
-rw-r--r-- | src/block.rs | 2 | ||||
-rw-r--r-- | src/lib.rs | 31 | ||||
-rw-r--r-- | src/line.rs | 36 | ||||
-rw-r--r-- | src/token.rs | 7 |
4 files changed, 36 insertions, 40 deletions
diff --git a/src/block.rs b/src/block.rs index a11d356..1d6ac60 100644 --- a/src/block.rs +++ b/src/block.rs @@ -15,6 +15,6 @@ pub enum Block { Note(Vec<Line>), Table(Table), Break, - Embedded { label: String, path: String }, + Embed { label: String, path: String }, Fragment { language: String, content: String }, } @@ -108,8 +108,8 @@ impl MarkdownDocument { Block::Heading { level, line: Line::from_str(&line) }), BlockLine::Break => blocks.push(Block::Break), BlockLine::BlankLine => (), - BlockLine::Paragraph(line) => match parse_embedded(&line) { - Some(embedded) => blocks.push(embedded), + BlockLine::Paragraph(line) => match parse_embed(&line) { + Some(embed) => blocks.push(embed), None => blocks.push(Block::Paragraph(Line::from_str(&line))), } } @@ -139,24 +139,21 @@ enum BlockMultiline<'a> { Fragment { language: &'a str, content: Vec<&'a str> }, } -fn parse_embedded(line: &str) -> Option<Block> { +fn parse_embed(line: &str) -> Option<Block> { let line = line.trim(); - if let Some(("", line)) = line.split_once(".collect(); - if parts.len() == 2 { - let label = parts[0].to_string(); - let path = parts[1].to_string(); - return Some(Block::Embedded { label, path }) + if let Some(stripped) = line.strip_prefix("!<") { + if let Some(stripped) = stripped.strip_suffix(">") { + if let Some((label, path)) = stripped.split_once("::") { + let label = label.trim().to_string(); + let path = path.trim().to_string(); + return Some(Block::Embed { label, path }) + } else { + let label = String::new(); + let path = stripped.trim().to_string(); + return Some(Block::Embed { label, path }) } } } - if let Some(("", line)) = line.split_once("![[") { - if let Some((line, "")) = line.rsplit_once("]]") { - let label = line.to_string(); - let path = line.to_string(); - return Some(Block::Embedded { label, path }) - } - } return None; } + diff --git a/src/line.rs b/src/line.rs index fce628c..b60b55c 100644 --- a/src/line.rs +++ b/src/line.rs @@ -82,31 +82,27 @@ impl ToString for Line { } -fn unlabeled_extern_link(path: String) -> Option<Token> { - Some( Token::ExternalLink { path, label:String::new() } ) -} - -fn labelled_extern_link(s: String) -> Option<Token> { - let (label, path) = match s.split_once("](") { - Some((l, t)) => (l.to_string(), t.to_string()), - None => return None, - }; - if label.contains("]") || path.contains("]") { return None } - Some( Token::ExternalLink { label, path } ) +fn external_link(inside: String) -> Option<Token> { + if let Some((label, path)) = inside.split_once("::") { + let label = label.trim().to_string(); + let path = path.trim().to_string(); + Some( Token::ExternalLink { label, path } ) + } else { + Some( Token::ExternalLink { label: String::new(), path: inside }) + } } -macro_rules! con { +macro_rules! make { ($v:expr) => {|s| Some($v(s)) }; } -const DELIMITERS: [(fn(String)->Option<Token>, &str, &str, &str); 7] = [ - ( con!(Token::Bold), "**", "**", "*" ), - ( con!(Token::Italic), "_", "_", "_" ), - ( con!(Token::Monospace), "`", "`", "`" ), - ( con!(Token::Math), "$", "$", "$" ), - ( con!(Token::InternalLink), "[[", "]]", "[]" ), - ( labelled_extern_link, "[", ")", "[]()" ), - ( unlabeled_extern_link, "<", ">", "<>" ), +const DELIMITERS: [(fn(String)->Option<Token>, &str, &str, &str); 6] = [ + ( make!(Token::Bold), "*", "*", "*" ), + ( make!(Token::Italic), "_", "_", "_" ), + ( make!(Token::Monospace), "`", "`", "`" ), + ( make!(Token::Math), "$", "$", "$" ), + ( make!(Token::InternalLink), "{", "}", "{}" ), + ( external_link, "<", ">", "<>" ), ]; fn is_whitespace(c: &char) -> bool { diff --git a/src/token.rs b/src/token.rs index c2b1179..f1f8288 100644 --- a/src/token.rs +++ b/src/token.rs @@ -17,8 +17,11 @@ impl AsRef<str> for Token { Token::Italic(text) => text, Token::Monospace(text) => text, Token::Math(text) => text, - Token::InternalLink(label) => label, - Token::ExternalLink { label, ..} => label, + Token::InternalLink(name) => name, + Token::ExternalLink { label, path } => match !label.is_empty() { + true => label, + false => path, + }, } } } |