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("")
}