diff --git a/src/lib.rs b/src/lib.rs index 603c261..c2236b0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -210,8 +210,9 @@ mod tests { "- (+) recurring", "~ (+ Friday) recurring with date", "** ( |# Low|< Feb 1) undone, low, & before Feb", - "** (# Two Words|x| |!|+|_|+ 5th|=|-|< Feb 1|> 2025|@ Jan 1 2025) All of them" - ].into_iter() + "** (# Two Words|x| |!|+|_|+ 5th|=|-|< Feb 1|> 2025|@ Jan 1 2025) All of them", + ] + .into_iter() .map(|example| example.to_string() + "\n") .map(|str| parse(&str)) .try_collect() @@ -709,6 +710,26 @@ mod tests { #[test] fn links() { let examples: Vec<_> = [ + // expected to fail + // r#"{:path:/ file}"#, + // r#"{:path:@ timestamp}"#, + // r#"{:path:https://my-url}"#, + // r#"{$$ Text}"#, + // r#"{\n * linkable}"#, + // r#"[linkable\n ]"#, + // r#"<\n this certainly isn't a linkable\n >"#, + // r#"{*text}"#, + // r#"{:file:https://github.com}"#, + // r#"{:file:/ file.txt}"#, + // r#"{:file:@ Wednesday 30th Jan}"#, + // r#"{\n * text}"#, + // r#"{\n * text\n }"#, + // r#"{* text\n }"#, + // r#"{ * text}"#, + // r#"{* text}[\n text\n ]"#, + // r#"{* text}[text\n ]"#, + // r#"{* text}[\n text]"#, + // these are the correct links "{https://github.com/nvim-neorg/neorg}", "{$ hello!}", "{/ a-path.txt}", @@ -721,6 +742,36 @@ mod tests { "This is a !", "<*linkable with markup*> here!", "{:another_file:}", + r#"{:path/to/other-file:}"#, + r#"{:path/to/file:123}"#, + r#"{:$/path/from/root/file:123}"#, + r#"{: $workspace/path/from/root/file:123}"#, + r#"{:path/to/file:# Generic Location within that file}"#, + r#"{:path/to/file:** Level 2 heading}"#, + r#"{file://my/file.norg}"#, + // * Path Modifiers: + // - /my/file - Root of the file system. + // - ~/Documents/my-file - User's home directory. + // - $/my/file - Root of the Neorg workspace. + // - $notes/my/file - Links to a file from another workspace. + // - Line Number: + r#"{2}"#, + r#"{:file:4}"#, + // - Detached Modifier: + r#"{* I am a level 1 heading}"#, + // - Custom Detached Modifiers: + r#"{# My Location}"#, + r#"{/ /path/to/my/file.txt}"#, + r#"{/ my-file.txt:123}"#, + r#"{@ 5th May}"#, + r#"{? mammals}"#, + r#"{= Neorg2022}(my_bibliography)"#, + // - Inline Linkables: + r#"{# Carryover Tags}"#, + r#"{# Inline Link Targets}"#, + // - Scoping: + r#"{* Heading Name : *** Level 3 heading}"#, + r#"{* heading1 : ** heading2 : ^ Footnote}"#, ] .into_iter() .map(|example| example.to_string() + "\n") diff --git a/src/snapshots/rust_norg__tests__links.snap b/src/snapshots/rust_norg__tests__links.snap index 4c08abb..370ae5e 100644 --- a/src/snapshots/rust_norg__tests__links.snap +++ b/src/snapshots/rust_norg__tests__links.snap @@ -135,3 +135,233 @@ expression: examples filepath: another_file targets: [] description: ~ +- - Paragraph: + - Link: + filepath: path/to/other-file + targets: [] + description: ~ +- - Paragraph: + - Link: + filepath: path/to/file + targets: + - LineNumber: 123 + description: ~ +- - Paragraph: + - Link: + filepath: path/to/file + targets: + - Generic: + - Token: + Text: Generic + - Token: Whitespace + - Token: + Text: Location + - Token: Whitespace + - Token: + Text: within + - Token: Whitespace + - Token: + Text: that + - Token: Whitespace + - Token: + Text: file + description: ~ +- - Paragraph: + - Link: + filepath: path/to/file + targets: + - Heading: + level: 2 + title: + - Token: + Text: Level + - Token: Whitespace + - Token: + Text: "2" + - Token: Whitespace + - Token: + Text: heading + description: ~ +- - Paragraph: + - Link: + filepath: ~ + targets: + - Url: "file://my/file.norg" + description: ~ +- - Paragraph: + - Link: + filepath: ~ + targets: + - LineNumber: 2 + description: ~ +- - Paragraph: + - Link: + filepath: file + targets: + - LineNumber: 4 + description: ~ +- - Paragraph: + - Link: + filepath: ~ + targets: + - Heading: + level: 1 + title: + - Token: + Text: I + - Token: Whitespace + - Token: + Text: am + - Token: Whitespace + - Token: + Text: a + - Token: Whitespace + - Token: + Text: level + - Token: Whitespace + - Token: + Text: "1" + - Token: Whitespace + - Token: + Text: heading + description: ~ +- - Paragraph: + - Link: + filepath: ~ + targets: + - Generic: + - Token: + Text: My + - Token: Whitespace + - Token: + Text: Location + description: ~ +- - Paragraph: + - Link: + filepath: ~ + targets: + - Path: /path/to/my/file.txt + description: ~ +- - Paragraph: + - Link: + filepath: ~ + targets: + - Path: "my-file.txt:123" + description: ~ +- - Paragraph: + - Link: + filepath: ~ + targets: + - Timestamp: 5th May + description: ~ +- - Paragraph: + - Link: + filepath: ~ + targets: + - Url: "? mammals" + description: ~ +- - Paragraph: + - Link: + filepath: ~ + targets: + - Extendable: + - Token: + Text: Neorg2022 + description: ~ + - Token: + Special: ( + - Token: + Text: my + - Token: + Special: _ + - Token: + Text: bibliography + - Token: + Special: ) +- - Paragraph: + - Link: + filepath: ~ + targets: + - Generic: + - Token: + Text: Carryover + - Token: Whitespace + - Token: + Text: Tags + description: ~ +- - Paragraph: + - Link: + filepath: ~ + targets: + - Generic: + - Token: + Text: Inline + - Token: Whitespace + - Token: + Text: Link + - Token: Whitespace + - Token: + Text: Targets + description: ~ +- - Paragraph: + - Link: + filepath: ~ + targets: + - Heading: + level: 1 + title: + - Token: + Text: Heading + - Token: Whitespace + - Token: + Text: Name + - Token: Whitespace + - Token: + Special: ":" + - Token: Whitespace + - Token: + Special: "*" + - Token: + Special: "*" + - Token: + Special: "*" + - Token: Whitespace + - Token: + Text: Level + - Token: Whitespace + - Token: + Text: "3" + - Token: Whitespace + - Token: + Text: heading + description: ~ +- - Paragraph: + - Link: + filepath: ~ + targets: + - Heading: + level: 1 + title: + - Token: + Text: heading1 + - Token: Whitespace + - Token: + Special: ":" + - Token: Whitespace + - Token: + Special: "*" + - Token: + Special: "*" + - Token: Whitespace + - Token: + Text: heading2 + - Token: Whitespace + - Token: + Special: ":" + - Token: Whitespace + - Token: + Special: ^ + - Token: Whitespace + - Token: + Text: Footnote + description: ~ diff --git a/src/stage_3.rs b/src/stage_3.rs index 6e56490..109dde2 100644 --- a/src/stage_3.rs +++ b/src/stage_3.rs @@ -177,6 +177,7 @@ fn paragraph_parser_opener_candidates_and_links() -> impl Parser< just(ParagraphSegmentToken::Special('=')).to("=".to_string()), just(ParagraphSegmentToken::Special('?')).to("?".to_string()), just(ParagraphSegmentToken::Special('@')).to("@".to_string()), + just(ParagraphSegmentToken::Special('#')).to("#".to_string()), )) .then_ignore( just(ParagraphSegmentToken::Whitespace) @@ -206,6 +207,7 @@ fn paragraph_parser_opener_candidates_and_links() -> impl Parser< "^" => LinkTarget::Footnote(parse_paragraph(content).unwrap()), "?" => LinkTarget::Wiki(parse_paragraph(content).unwrap()), "=" => LinkTarget::Extendable(parse_paragraph(content).unwrap()), + "#" => LinkTarget::Generic(parse_paragraph(content).unwrap()), "/" => { LinkTarget::Path(content.into_iter().map_into::().collect()) } @@ -220,7 +222,13 @@ fn paragraph_parser_opener_candidates_and_links() -> impl Parser< }, } } else { - LinkTarget::Url(content.into_iter().map_into::().collect()) + let content_str: String = + content.into_iter().map_into::().collect(); + if let Ok(line_number) = content_str.trim().parse::() { + LinkTarget::LineNumber(line_number) + } else { + LinkTarget::Url(content_str) + } }] } else { vec![] @@ -438,6 +446,7 @@ pub enum LinkTarget { Generic(Vec), Wiki(Vec), Extendable(Vec), + LineNumber(usize), Path(String), Url(String), Timestamp(String), @@ -580,10 +589,7 @@ fn detached_modifier_extensions() -> impl Parser< .or_not() .map(|tokens| { if let Some(tokens) = tokens { - tokens - .into_iter() - .map_into::() - .collect() + tokens.into_iter().map_into::().collect() } else { String::from("") }