From 65fd48f0a2ce3997eaf05bfb2e9ff4e534346267 Mon Sep 17 00:00:00 2001 From: hardfau1t Date: Wed, 4 Jun 2025 17:26:54 +0530 Subject: [PATCH 01/14] fix(stage3): support for line number in links --- src/stage_3.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/stage_3.rs b/src/stage_3.rs index 6e56490..26d76d1 100644 --- a/src/stage_3.rs +++ b/src/stage_3.rs @@ -220,7 +220,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 +444,7 @@ pub enum LinkTarget { Generic(Vec), Wiki(Vec), Extendable(Vec), + LineNumber(usize), Path(String), Url(String), Timestamp(String), @@ -580,10 +587,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("") } From 919a61ead1091d911de8c1c11e5a72f9745d7444 Mon Sep 17 00:00:00 2001 From: hardfau1t Date: Wed, 4 Jun 2025 17:44:56 +0530 Subject: [PATCH 02/14] fix(stage_3): support for generic links --- src/stage_3.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/stage_3.rs b/src/stage_3.rs index 26d76d1..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()) } From 2fa40d9bacfd89e1b99246ba459149bacceed605 Mon Sep 17 00:00:00 2001 From: hardfau1t Date: Wed, 4 Jun 2025 18:57:08 +0530 Subject: [PATCH 03/14] test(links): add extra tests for links NOTE: scope and wiki links are not yet working --- src/lib.rs | 53 ++++- src/snapshots/rust_norg__tests__links.snap | 230 +++++++++++++++++++++ 2 files changed, 281 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 603c261..d7ec9c4 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,34 @@ mod tests { "This is a !", "<*linkable with markup*> here!", "{:another_file:}", + r#"{:path/to/other-file:}"#, + r#"{:path/to/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: ~ From 279aa4497b97a881a88626375d512488e46f630e Mon Sep 17 00:00:00 2001 From: hardfau1t Date: Thu, 17 Jul 2025 17:06:03 +0530 Subject: [PATCH 04/14] test(links): add few more tests for links --- src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index d7ec9c4..c2236b0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -744,6 +744,8 @@ mod tests { "{: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}"#, From eb2744c7e4fea646b8b5af9019bdd07cce93db80 Mon Sep 17 00:00:00 2001 From: hardfau1t Date: Wed, 3 Sep 2025 07:53:16 +0530 Subject: [PATCH 05/14] test(links): adds workspace and line number link tests --- src/snapshots/rust_norg__tests__links.snap | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/snapshots/rust_norg__tests__links.snap b/src/snapshots/rust_norg__tests__links.snap index 370ae5e..c1bab7e 100644 --- a/src/snapshots/rust_norg__tests__links.snap +++ b/src/snapshots/rust_norg__tests__links.snap @@ -146,6 +146,18 @@ expression: examples targets: - LineNumber: 123 description: ~ +- - Paragraph: + - Link: + filepath: $/path/from/root/file + targets: + - LineNumber: 123 + description: ~ +- - Paragraph: + - Link: + filepath: " $workspace/path/from/root/file" + targets: + - LineNumber: 123 + description: ~ - - Paragraph: - Link: filepath: path/to/file From fc64cd0d8d16136f835b609cce2347268869de3a Mon Sep 17 00:00:00 2001 From: hardfau1t Date: Thu, 4 Sep 2025 11:13:09 +0530 Subject: [PATCH 06/14] test(anchor): adds basic anchor tests --- Cargo.lock | 352 +++++++++++++++++++++++++++++++++-- Cargo.toml | 1 + tests/anchor_tests.rs | 413 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 753 insertions(+), 13 deletions(-) create mode 100644 tests/anchor_tests.rs diff --git a/Cargo.lock b/Cargo.lock index f5ee7fd..e222c03 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,12 +14,71 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + [[package]] name = "allocator-api2" version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +[[package]] +name = "anstream" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" +dependencies = [ + "windows-sys 0.60.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.60.2", +] + [[package]] name = "autocfg" version = "1.3.0" @@ -69,6 +128,12 @@ dependencies = [ "stacker", ] +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + [[package]] name = "console" version = "0.15.8" @@ -78,7 +143,7 @@ dependencies = [ "encode_unicode", "lazy_static", "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -93,6 +158,27 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" +[[package]] +name = "env_filter" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" +dependencies = [ + "log", +] + +[[package]] +name = "env_logger" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "log", +] + [[package]] name = "errno" version = "0.3.9" @@ -100,7 +186,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -149,6 +235,12 @@ dependencies = [ "similar", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + [[package]] name = "itertools" version = "0.13.0" @@ -188,6 +280,36 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "memchr" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + +[[package]] +name = "nu-ansi-term" +version = "0.50.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -204,6 +326,18 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -302,6 +436,17 @@ dependencies = [ "rand_core", ] +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + [[package]] name = "regex-syntax" version = "0.8.4" @@ -317,6 +462,7 @@ dependencies = [ "itertools", "proptest", "serde", + "test-log", "textwrap", "unicode_categories", ] @@ -331,7 +477,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -366,6 +512,15 @@ dependencies = [ "syn", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + [[package]] name = "similar" version = "2.5.0" @@ -411,7 +566,29 @@ dependencies = [ "cfg-if", "fastrand", "rustix", - "windows-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "test-log" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e33b98a582ea0be1168eba097538ee8dd4bbe0f2b01b22ac92ea30054e5be7b" +dependencies = [ + "env_logger", + "test-log-macros", + "tracing-subscriber", +] + +[[package]] +name = "test-log-macros" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "451b374529930d7601b1eef8d32bc79ae870b6079b069401709c2a8bf9e75f36" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] @@ -425,6 +602,63 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex-automata", + "sharded-slab", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + [[package]] name = "unarray" version = "0.1.4" @@ -455,6 +689,18 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + [[package]] name = "version_check" version = "0.9.4" @@ -498,13 +744,28 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.3", ] [[package]] @@ -513,14 +774,31 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm 0.52.5", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", +] + +[[package]] +name = "windows-targets" +version = "0.53.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", ] [[package]] @@ -529,48 +807,96 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + [[package]] name = "windows_aarch64_msvc" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + [[package]] name = "windows_i686_gnu" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + [[package]] name = "windows_i686_msvc" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + [[package]] name = "windows_x86_64_gnu" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + [[package]] name = "windows_x86_64_msvc" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + [[package]] name = "zerocopy" version = "0.7.34" diff --git a/Cargo.toml b/Cargo.toml index 1afe57f..9c3c7de 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,3 +13,4 @@ unicode_categories = "0.1.1" [dev-dependencies] insta = { version = "1.39.0", features = ["yaml"] } proptest = "1.4.0" +test-log = "0.2.18" diff --git a/tests/anchor_tests.rs b/tests/anchor_tests.rs new file mode 100644 index 0000000..e9c06aa --- /dev/null +++ b/tests/anchor_tests.rs @@ -0,0 +1,413 @@ +use rust_norg::{ + parse_tree, LinkTarget, + LinkTarget::Heading, + NorgAST::Paragraph, + ParagraphSegment::{Anchor, AnchorDefinition, Link, Token}, + ParagraphSegmentToken::{Special, Text, Whitespace}, +}; +use test_log::test; + +// Basic Anchor Declaration Tests +#[test] +fn test_anchor_declaration_basic() { + let norg = r#"[Neorg] is a fancy organizational tool. + +[Neorg]{https://github.com/nvim-neorg/neorg}"#; + let result = parse_tree(norg).expect("Failed to parse basic anchor declaration"); + assert_eq!(result, vec![]); + // Should create anchor reference and definition + assert_eq!( + result, + vec![ + Paragraph(vec![ + Anchor { + content: vec![Token(Text("Neorg".to_string()))], + description: None + }, + Token(Whitespace), + Token(Text("is".to_string())), + Token(Whitespace), + Token(Text("a".to_string())), + Token(Whitespace), + Token(Text("fancy".to_string())), + Token(Whitespace), + Token(Text("organizational".to_string())), + Token(Whitespace), + Token(Text("tool".to_string())), + Token(Special('.')) + ]), + Paragraph(vec![AnchorDefinition { + content: vec![Token(Text("Neorg".to_string()))], + target: Box::new(Link { + filepath: None, + targets: vec![LinkTarget::Url( + "https://github.com/nvim-neorg/neorg".to_string() + )], + description: None + }) + }]) + ], + "Failed to run test test_anchor_declaration_basic" + ); +} + +#[test] +fn test_anchor_declaration_standalone() { + let norg = r#"This text references [anchor name] in the content. + +[anchor name]{* Target Heading}"#; + let result = parse_tree(norg).expect("Failed to parse standalone anchor declaration"); + assert_eq!(result, vec![]); + assert_eq!( + result, + vec![ + Paragraph(vec![ + Token(Text("This".to_string())), + Token(Whitespace), + Token(Text("text".to_string())), + Token(Whitespace), + Token(Text("references".to_string())), + Token(Whitespace), + Anchor { + content: vec![ + Token(Text("anchor".to_string())), + Token(Whitespace), + Token(Text("name".to_string())) + ], + description: None + }, + Token(Whitespace), + Token(Text("in".to_string())), + Token(Whitespace), + Token(Text("the".to_string())), + Token(Whitespace), + Token(Text("content".to_string())), + Token(Special('.')) + ]), + Paragraph(vec![AnchorDefinition { + content: vec![ + Token(Text("anchor".to_string())), + Token(Whitespace), + Token(Text("name".to_string())) + ], + target: Box::new(Link { + filepath: None, + targets: vec![Heading { + level: 1, + title: vec![ + Token(Text("Target".to_string())), + Token(Whitespace), + Token(Text("Heading".to_string())) + ] + }], + description: None + }) + }]) + ] + ); +} +#[test] +fn test_anchor_with_description() { + let norg = r#"[anchor][custom description] + +[anchor]{# target-location}"#; + let result = parse_tree(norg).expect("Failed to parse anchor with description"); + assert_eq!(result, vec![]); + assert_eq!( + result, + vec![ + Paragraph(vec![Anchor { + content: vec![Token(Text("anchor".to_string()))], + description: Some(vec![ + Token(Text("custom".to_string())), + Token(Whitespace), + Token(Text("description".to_string())) + ]) + }]), + Paragraph(vec![AnchorDefinition { + content: vec![Token(Text("anchor".to_string()))], + target: Box::new(Link { + filepath: None, + targets: vec![LinkTarget::Generic(vec![ + Token(Text("target".to_string())), + Token(Special('-')), + Token(Text("location".to_string())) + ])], + description: None + }) + }]) + ] + ) +} + +// Anchor Definition Tests +#[test] +fn test_anchor_definition_heading() { + let norg = r#"[section reference]{* Important Section}"#; + let result = parse_tree(norg).expect("Failed to parse anchor definition to heading"); + assert_eq!(result, vec![]); + // Should link anchor to heading + assert_eq!( + result, + vec![Paragraph(vec![AnchorDefinition { + content: vec![ + Token(Text("section".to_string())), + Token(Whitespace), + Token(Text("reference".to_string())) + ], + target: Box::new(Link { + filepath: None, + targets: vec![Heading { + level: 1, + title: vec![ + Token(Text("Important".to_string())), + Token(Whitespace), + Token(Text("Section".to_string())) + ] + }], + description: None + }) + }])] + ); +} + +#[test] +fn test_anchor_definition_external_url() { + let norg = r#"[homepage]{https://example.com}"#; + let result = parse_tree(norg).expect("Failed to parse anchor definition to external URL"); + assert_eq!(result, vec![]); + // Should link anchor to external URL + assert_eq!( + result, + vec![Paragraph(vec![AnchorDefinition { + content: vec![Token(Text("homepage".to_string()))], + target: Box::new(Link { + filepath: None, + targets: vec![LinkTarget::Url("https://example.com".to_string())], + description: None + }) + }])] + ) +} + +#[test] +fn test_anchor_definition_file_location() { + let norg = r#"{:docs/setup:}[documentation]"#; + let result = parse_tree(norg).expect("Failed to parse anchor definition to file location"); + assert_eq!( + result, + vec![Paragraph(vec![AnchorDefinition { + content: vec![Token(Text("documentation".to_string()))], + target: Box::new(Link { + filepath: Some("docs/setup".to_string()), + targets: vec![], + description: None + }) + }])] + ); +} + +/* +// Multiple Anchor Usage +#[test] +fn test_multiple_anchor_declarations() { + let norg = r#"Both [first] and [second] are useful resources. + +[first]{https://first.example.com} +[second]{https://second.example.com}"#; + let result = parse_tree(norg).expect("Failed to parse multiple anchor declarations"); + assert_eq!(result, vec![]); + // Should handle multiple anchors +} + +#[test] +fn test_repeated_anchor_usage() { + let norg = r#"First mention of [tool] and second mention of [tool]. + +[tool]{https://tool.example.com}"#; + let result = parse_tree(norg).expect("Failed to parse repeated anchor usage"); + assert_eq!(result, vec![]); + // Should link both instances to the same target + let link_count = result.matches("href=\"https://tool.example.com\"").count(); +} + +// Anchor URL Mapping Tests (Based on links-mapping.txt) +#[test] +fn test_anchor_url_mapping() { + let norg = r#"Reference to [Neorg] in text. + +[Neorg]{# target-location}"#; + let result = parse_tree(norg).expect("Failed to parse anchor URL mapping"); + assert_eq!(result, vec![]); + // Should map to: http://127.0.0.1/view/#Neorg + result.contains("href=\"#Neorg\"")); +} + +#[test] +fn test_anchor_current_path_mapping() { + let norg = r#"Link to [local-ref] within document. + +[local-ref]{# local-reference}"#; + let result = parse_tree(norg).expect("Failed to parse anchor current path mapping"); + assert_eq!(result, vec![]); + // Should generate current path URL mapping +} + +// Anchor Integration with Other Features +#[test] +fn test_anchor_in_paragraph() { + let norg = r#"This paragraph contains [inline anchor] for reference. + +[inline anchor]{https://example.com/reference}"#; + let result = parse_tree(norg).expect("Failed to parse anchor in paragraph"); + assert_eq!(result, vec![]); + // Should work within paragraph text +} + +#[test] +fn test_anchor_in_list() { + let norg = r#"- First item with [list anchor] +- Second item +- Third item + +[list anchor]{* Target Section}"#; + let result = parse_tree(norg).expect("Failed to parse anchor in list"); + assert_eq!(result, vec![]); + // Should work within list items +} + +#[test] +fn test_anchor_in_heading() { + let norg = r#"* Heading with [heading anchor] reference + +[heading anchor]{https://example.com}"#; + let result = parse_tree(norg).expect("Failed to parse anchor in heading"); + assert_eq!(result, vec![]); + // Should work within headings +} + +// Complex Anchor Scenarios +#[test] +fn test_anchor_with_attached_modifiers() { + let norg = r#"This is *[important anchor]* text. + +[important anchor]{# important-section}"#; + let result = parse_tree(norg).expect("Failed to parse anchor with attached modifiers"); + assert_eq!(result, vec![]); + // Should work within attached modifiers +} + +#[test] +fn test_anchor_forward_reference() { + let norg = r#"Forward reference to [future anchor]. + +Later in document... + +[future anchor]{* Later Section}"#; + let result = parse_tree(norg).expect("Failed to parse anchor forward reference"); + assert_eq!(result, vec![]); + // Should handle forward references +} + +#[test] +fn test_anchor_backward_reference() { + let norg = r#"[early anchor]{* Early Section} + +Later reference to [early anchor]."#; + let result = parse_tree(norg).expect("Failed to parse anchor backward reference"); + assert_eq!(result, vec![]); + // Should handle backward references +} + +// Anchor HTML Generation +#[test] +fn test_anchor_html_structure() { + let norg = r#"Link to [structured anchor] here. + +[structured anchor]{https://structured.example.com}"#; + let result = parse_tree(norg).expect("Failed to parse anchor HTML structure"); + assert_eq!(result, vec![]); + // Should generate proper HTML anchor structure +} + +#[test] +fn test_anchor_css_classes() { + let norg = r#"Text with [classed anchor] link. + +[classed anchor]{# class-target}"#; + let result = parse_tree(norg).expect("Failed to parse anchor CSS classes"); + assert_eq!(result, vec![]); + // Should have appropriate CSS classes + result.contains("anchor") || + result.contains("href=")); +} + +#[test] +fn test_anchor_accessibility() { + let norg = r#"Accessible [screen reader anchor] link. + +[screen reader anchor]{https://accessible.example.com}"#; + let result = parse_tree(norg).expect("Failed to parse anchor accessibility"); + assert_eq!(result, vec![]); + // Should have accessibility attributes + // May have additional accessibility attributes +} + +// Special Characters and Edge Cases +#[test] +fn test_anchor_special_characters() { + let norg = r#"Link with [special & chars!] in name. + +[special & chars!]{# special-target}"#; + let result = parse_tree(norg).expect("Failed to parse anchor with special characters"); + assert_eq!(result, vec![]); + // Should handle special characters +} + +#[test] +fn test_anchor_unicode_characters() { + let norg = r#"Reference to [café anchor] here. + +[café anchor]{https://café.example.com}"#; + let result = parse_tree(norg).expect("Failed to parse anchor with unicode"); + assert_eq!(result, vec![]); + // Should handle unicode characters +} + +#[test] +fn test_anchor_multiword_names() { + let norg = r#"Link to [multi word anchor name] reference. + +[multi word anchor name]{* Target Section}"#; + let result = parse_tree(norg).expect("Failed to parse multiword anchor names"); + assert_eq!(result, vec![]); + // Should handle multi-word anchor names +} + +// Error Handling +#[test] +fn test_anchor_undefined_reference() { + let norg = r#"Reference to [undefined anchor] without definition."#; + let result = parse_tree(norg).expect("Failed to parse undefined anchor reference"); + assert_eq!(result, vec![]); + // Should handle undefined anchors gracefully + // May show as broken link or plain text +} + +#[test] +fn test_anchor_definition_without_reference() { + let norg = r#"[orphan anchor]{https://orphan.example.com}"#; + let result = parse_tree(norg).expect("Failed to parse orphan anchor definition"); + assert_eq!(result, vec![]); + // Should handle orphaned definitions gracefully +} + +#[test] +fn test_anchor_circular_reference() { + let norg = r#"[circular1]{# circular2} +[circular2]{# circular1}"#; + let result = parse_tree(norg).expect("Failed to parse circular anchor reference"); + assert_eq!(result, vec![]); + // Should handle circular references gracefully +} +*/ From a84b9085f51b9dac395237907d2fcfcd771883d1 Mon Sep 17 00:00:00 2001 From: hardfau1t Date: Tue, 9 Sep 2025 17:48:40 +0530 Subject: [PATCH 07/14] build(cargo): insta switch to ron format --- Cargo.lock | 28 ++++++++++++++++++++++++++-- Cargo.toml | 2 +- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e222c03..3caee43 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -85,6 +85,12 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + [[package]] name = "bit-set" version = "0.5.3" @@ -100,6 +106,12 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitflags" version = "2.5.0" @@ -231,6 +243,7 @@ dependencies = [ "console", "lazy_static", "linked-hash-map", + "ron", "serde", "similar", ] @@ -361,7 +374,7 @@ checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" dependencies = [ "bit-set", "bit-vec", - "bitflags", + "bitflags 2.5.0", "lazy_static", "num-traits", "rand", @@ -453,6 +466,17 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +[[package]] +name = "ron" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88073939a61e5b7680558e6be56b419e208420c2adb92be54921fa6b72283f1a" +dependencies = [ + "base64", + "bitflags 1.3.2", + "serde", +] + [[package]] name = "rust-norg" version = "0.1.0" @@ -473,7 +497,7 @@ version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags", + "bitflags 2.5.0", "errno", "libc", "linux-raw-sys", diff --git a/Cargo.toml b/Cargo.toml index 9c3c7de..b3fc0e6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,6 @@ textwrap = "0.16.1" unicode_categories = "0.1.1" [dev-dependencies] -insta = { version = "1.39.0", features = ["yaml"] } +insta = { version = "1.39.0", features = ["ron", "yaml"] } proptest = "1.4.0" test-log = "0.2.18" From 0ba7a0f302f0bcce1992f04da5798df8561cc117 Mon Sep 17 00:00:00 2001 From: hardfau1t Date: Tue, 9 Sep 2025 17:49:11 +0530 Subject: [PATCH 08/14] test(anchor): start using insta tests instead of raw unit tests --- tests/anchor_tests.rs | 285 ++++++------------ ...nchor_tests__anchor_declaration_basic.snap | 39 +++ ..._tests__anchor_declaration_standalone.snap | 52 ++++ ...anchor_tests__anchor_with_description.snap | 37 +++ 4 files changed, 225 insertions(+), 188 deletions(-) create mode 100644 tests/snapshots/anchor_tests__anchor_declaration_basic.snap create mode 100644 tests/snapshots/anchor_tests__anchor_declaration_standalone.snap create mode 100644 tests/snapshots/anchor_tests__anchor_with_description.snap diff --git a/tests/anchor_tests.rs b/tests/anchor_tests.rs index e9c06aa..17ed753 100644 --- a/tests/anchor_tests.rs +++ b/tests/anchor_tests.rs @@ -1,10 +1,5 @@ -use rust_norg::{ - parse_tree, LinkTarget, - LinkTarget::Heading, - NorgAST::Paragraph, - ParagraphSegment::{Anchor, AnchorDefinition, Link, Token}, - ParagraphSegmentToken::{Special, Text, Whitespace}, -}; +use insta::{assert_ron_snapshot, with_settings}; +use rust_norg::parse_tree; use test_log::test; // Basic Anchor Declaration Tests @@ -14,198 +9,112 @@ fn test_anchor_declaration_basic() { [Neorg]{https://github.com/nvim-neorg/neorg}"#; let result = parse_tree(norg).expect("Failed to parse basic anchor declaration"); - assert_eq!(result, vec![]); // Should create anchor reference and definition - assert_eq!( - result, - vec![ - Paragraph(vec![ - Anchor { - content: vec![Token(Text("Neorg".to_string()))], - description: None - }, - Token(Whitespace), - Token(Text("is".to_string())), - Token(Whitespace), - Token(Text("a".to_string())), - Token(Whitespace), - Token(Text("fancy".to_string())), - Token(Whitespace), - Token(Text("organizational".to_string())), - Token(Whitespace), - Token(Text("tool".to_string())), - Token(Special('.')) - ]), - Paragraph(vec![AnchorDefinition { - content: vec![Token(Text("Neorg".to_string()))], - target: Box::new(Link { - filepath: None, - targets: vec![LinkTarget::Url( - "https://github.com/nvim-neorg/neorg".to_string() - )], - description: None - }) - }]) - ], - "Failed to run test test_anchor_declaration_basic" - ); + assert_ron_snapshot!(result); } -#[test] -fn test_anchor_declaration_standalone() { - let norg = r#"This text references [anchor name] in the content. - -[anchor name]{* Target Heading}"#; - let result = parse_tree(norg).expect("Failed to parse standalone anchor declaration"); - assert_eq!(result, vec![]); - assert_eq!( - result, - vec![ - Paragraph(vec![ - Token(Text("This".to_string())), - Token(Whitespace), - Token(Text("text".to_string())), - Token(Whitespace), - Token(Text("references".to_string())), - Token(Whitespace), - Anchor { - content: vec![ - Token(Text("anchor".to_string())), - Token(Whitespace), - Token(Text("name".to_string())) - ], - description: None - }, - Token(Whitespace), - Token(Text("in".to_string())), - Token(Whitespace), - Token(Text("the".to_string())), - Token(Whitespace), - Token(Text("content".to_string())), - Token(Special('.')) - ]), - Paragraph(vec![AnchorDefinition { - content: vec![ - Token(Text("anchor".to_string())), - Token(Whitespace), - Token(Text("name".to_string())) - ], - target: Box::new(Link { - filepath: None, - targets: vec![Heading { - level: 1, - title: vec![ - Token(Text("Target".to_string())), - Token(Whitespace), - Token(Text("Heading".to_string())) - ] - }], - description: None - }) - }]) - ] - ); -} #[test] fn test_anchor_with_description() { let norg = r#"[anchor][custom description] [anchor]{# target-location}"#; let result = parse_tree(norg).expect("Failed to parse anchor with description"); - assert_eq!(result, vec![]); - assert_eq!( - result, - vec![ - Paragraph(vec![Anchor { - content: vec![Token(Text("anchor".to_string()))], - description: Some(vec![ - Token(Text("custom".to_string())), - Token(Whitespace), - Token(Text("description".to_string())) - ]) - }]), - Paragraph(vec![AnchorDefinition { - content: vec![Token(Text("anchor".to_string()))], - target: Box::new(Link { - filepath: None, - targets: vec![LinkTarget::Generic(vec![ - Token(Text("target".to_string())), - Token(Special('-')), - Token(Text("location".to_string())) - ])], - description: None - }) - }]) - ] - ) -} - -// Anchor Definition Tests -#[test] -fn test_anchor_definition_heading() { - let norg = r#"[section reference]{* Important Section}"#; - let result = parse_tree(norg).expect("Failed to parse anchor definition to heading"); - assert_eq!(result, vec![]); - // Should link anchor to heading - assert_eq!( - result, - vec![Paragraph(vec![AnchorDefinition { - content: vec![ - Token(Text("section".to_string())), - Token(Whitespace), - Token(Text("reference".to_string())) - ], - target: Box::new(Link { - filepath: None, - targets: vec![Heading { - level: 1, - title: vec![ - Token(Text("Important".to_string())), - Token(Whitespace), - Token(Text("Section".to_string())) - ] - }], - description: None - }) - }])] - ); -} - -#[test] -fn test_anchor_definition_external_url() { - let norg = r#"[homepage]{https://example.com}"#; - let result = parse_tree(norg).expect("Failed to parse anchor definition to external URL"); - assert_eq!(result, vec![]); - // Should link anchor to external URL - assert_eq!( - result, - vec![Paragraph(vec![AnchorDefinition { - content: vec![Token(Text("homepage".to_string()))], - target: Box::new(Link { - filepath: None, - targets: vec![LinkTarget::Url("https://example.com".to_string())], - description: None - }) - }])] - ) + with_settings!({ + info => &norg, + description => "check ancho declaration with description", + omit_expression => true, + }, {assert_ron_snapshot!(result)}); + // assert_eq!( + // result, + // vec![ + // Paragraph(vec![Anchor { + // content: vec![Token(Text("anchor".to_string()))], + // description: Some(vec![ + // Token(Text("custom".to_string())), + // Token(Whitespace), + // Token(Text("description".to_string())) + // ]) + // }]), + // Paragraph(vec![AnchorDefinition { + // content: vec![Token(Text("anchor".to_string()))], + // target: Box::new(Link { + // filepath: None, + // targets: vec![LinkTarget::Generic(vec![ + // Token(Text("target".to_string())), + // Token(Special('-')), + // Token(Text("location".to_string())) + // ])], + // description: None + // }) + // }]) + // ] + // ) } -#[test] -fn test_anchor_definition_file_location() { - let norg = r#"{:docs/setup:}[documentation]"#; - let result = parse_tree(norg).expect("Failed to parse anchor definition to file location"); - assert_eq!( - result, - vec![Paragraph(vec![AnchorDefinition { - content: vec![Token(Text("documentation".to_string()))], - target: Box::new(Link { - filepath: Some("docs/setup".to_string()), - targets: vec![], - description: None - }) - }])] - ); -} +// // Anchor Definition Tests +// #[test] +// fn test_anchor_definition_heading() { +// let norg = r#"[section reference]{* Important Section}"#; +// let result = parse_tree(norg).expect("Failed to parse anchor definition to heading"); +// // Should link anchor to heading +// assert_eq!( +// result, +// vec![Paragraph(vec![AnchorDefinition { +// content: vec![ +// Token(Text("section".to_string())), +// Token(Whitespace), +// Token(Text("reference".to_string())) +// ], +// target: Box::new(Link { +// filepath: None, +// targets: vec![Heading { +// level: 1, +// title: vec![ +// Token(Text("Important".to_string())), +// Token(Whitespace), +// Token(Text("Section".to_string())) +// ] +// }], +// description: None +// }) +// }])] +// ); +// } +// +// #[test] +// fn test_anchor_definition_external_url() { +// let norg = r#"[homepage]{https://example.com}"#; +// let result = parse_tree(norg).expect("Failed to parse anchor definition to external URL"); +// // Should link anchor to external URL +// assert_eq!( +// result, +// vec![Paragraph(vec![AnchorDefinition { +// content: vec![Token(Text("homepage".to_string()))], +// target: Box::new(Link { +// filepath: None, +// targets: vec![LinkTarget::Url("https://example.com".to_string())], +// description: None +// }) +// }])] +// ) +// } +// +// #[test] +// fn test_anchor_definition_file_location() { +// let norg = r#"{:docs/setup:}[documentation]"#; +// let result = parse_tree(norg).expect("Failed to parse anchor definition to file location"); +// assert_eq!( +// result, +// vec![Paragraph(vec![AnchorDefinition { +// content: vec![Token(Text("documentation".to_string()))], +// target: Box::new(Link { +// filepath: Some("docs/setup".to_string()), +// targets: vec![], +// description: None +// }) +// }])] +// ); +// } /* // Multiple Anchor Usage diff --git a/tests/snapshots/anchor_tests__anchor_declaration_basic.snap b/tests/snapshots/anchor_tests__anchor_declaration_basic.snap new file mode 100644 index 0000000..0e7a562 --- /dev/null +++ b/tests/snapshots/anchor_tests__anchor_declaration_basic.snap @@ -0,0 +1,39 @@ +--- +source: tests/anchor_tests.rs +expression: result +--- +[ + Paragraph([ + Anchor( + content: [ + Token(Text("Neorg")), + ], + description: None, + ), + Token(Whitespace), + Token(Text("is")), + Token(Whitespace), + Token(Text("a")), + Token(Whitespace), + Token(Text("fancy")), + Token(Whitespace), + Token(Text("organizational")), + Token(Whitespace), + Token(Text("tool")), + Token(Special('.')), + ]), + Paragraph([ + AnchorDefinition( + content: [ + Token(Text("Neorg")), + ], + target: Link( + filepath: None, + targets: [ + Url("https://github.com/nvim-neorg/neorg"), + ], + description: None, + ), + ), + ]), +] diff --git a/tests/snapshots/anchor_tests__anchor_declaration_standalone.snap b/tests/snapshots/anchor_tests__anchor_declaration_standalone.snap new file mode 100644 index 0000000..b108c05 --- /dev/null +++ b/tests/snapshots/anchor_tests__anchor_declaration_standalone.snap @@ -0,0 +1,52 @@ +--- +source: tests/anchor_tests.rs +expression: result +--- +[ + Paragraph([ + Token(Text("This")), + Token(Whitespace), + Token(Text("text")), + Token(Whitespace), + Token(Text("references")), + Token(Whitespace), + Anchor( + content: [ + Token(Text("anchor")), + Token(Whitespace), + Token(Text("name")), + ], + description: None, + ), + Token(Whitespace), + Token(Text("in")), + Token(Whitespace), + Token(Text("the")), + Token(Whitespace), + Token(Text("content")), + Token(Special('.')), + ]), + Paragraph([ + AnchorDefinition( + content: [ + Token(Text("anchor")), + Token(Whitespace), + Token(Text("name")), + ], + target: Link( + filepath: None, + targets: [ + Heading( + level: 1, + title: [ + Token(Text("Target")), + Token(Whitespace), + Token(Text("Heading")), + ], + ), + ], + description: None, + ), + ), + ]), +] diff --git a/tests/snapshots/anchor_tests__anchor_with_description.snap b/tests/snapshots/anchor_tests__anchor_with_description.snap new file mode 100644 index 0000000..72638e0 --- /dev/null +++ b/tests/snapshots/anchor_tests__anchor_with_description.snap @@ -0,0 +1,37 @@ +--- +source: tests/anchor_tests.rs +description: check ancho declaration with description +info: "[anchor][custom description]\n\n[anchor]{# target-location}" +--- +[ + Paragraph([ + Anchor( + content: [ + Token(Text("anchor")), + ], + description: Some([ + Token(Text("custom")), + Token(Whitespace), + Token(Text("description")), + ]), + ), + ]), + Paragraph([ + AnchorDefinition( + content: [ + Token(Text("anchor")), + ], + target: Link( + filepath: None, + targets: [ + Generic([ + Token(Text("target")), + Token(Special('-')), + Token(Text("location")), + ]), + ], + description: None, + ), + ), + ]), +] From ab76e6272016b6bbfdb452b604d9f947f00f8235 Mon Sep 17 00:00:00 2001 From: hardfau1t Date: Wed, 10 Sep 2025 12:52:14 +0530 Subject: [PATCH 09/14] test(anchor_tests): add a single test runner for insta using an array --- Cargo.lock | 13 ++++ Cargo.toml | 1 + tests/anchor_tests.rs | 73 +++++++------------ ..._tests__anchor_declaration_standalone.snap | 52 ------------- ...tests__test_anchor_declaration_basic.snap} | 6 +- ..._tests__test_anchor_with_description.snap} | 10 ++- 6 files changed, 51 insertions(+), 104 deletions(-) delete mode 100644 tests/snapshots/anchor_tests__anchor_declaration_standalone.snap rename tests/snapshots/{anchor_tests__anchor_declaration_basic.snap => anchor_tests__test_anchor_declaration_basic.snap} (80%) rename tests/snapshots/{anchor_tests__anchor_with_description.snap => anchor_tests__test_anchor_with_description.snap} (75%) diff --git a/Cargo.lock b/Cargo.lock index 3caee43..7d6d02b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -488,6 +488,7 @@ dependencies = [ "serde", "test-log", "textwrap", + "tracing", "unicode_categories", ] @@ -642,9 +643,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tracing-core" version = "0.1.34" diff --git a/Cargo.toml b/Cargo.toml index b3fc0e6..580993c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ chumsky = "0.9.3" itertools = "0.13.0" serde = { version = "1.0.203", features = ["derive"] } textwrap = "0.16.1" +tracing = "0.1.41" unicode_categories = "0.1.1" [dev-dependencies] diff --git a/tests/anchor_tests.rs b/tests/anchor_tests.rs index 17ed753..a31ddd4 100644 --- a/tests/anchor_tests.rs +++ b/tests/anchor_tests.rs @@ -1,54 +1,35 @@ use insta::{assert_ron_snapshot, with_settings}; use rust_norg::parse_tree; use test_log::test; - -// Basic Anchor Declaration Tests -#[test] -fn test_anchor_declaration_basic() { - let norg = r#"[Neorg] is a fancy organizational tool. - -[Neorg]{https://github.com/nvim-neorg/neorg}"#; - let result = parse_tree(norg).expect("Failed to parse basic anchor declaration"); - // Should create anchor reference and definition - assert_ron_snapshot!(result); -} - +use tracing::info; + +// test and description pair +const ANCHOR_TESTS: [(&str, &str, &str); 2] = [ + ( + r#"[Neorg] is a fancy organizational tool. + [Neorg]{https://github.com/nvim-neorg/neorg}"#, + "Basic Anchor Declaration Tests", + "test_anchor_declaration_basic", + ), + ( + r#"[anchor][custom description]. Here is [anchor]{# target-location}"#, + "check ancho declaration with description", + "test_anchor_with_description", + ), +]; + +// run all anchor tests #[test] -fn test_anchor_with_description() { - let norg = r#"[anchor][custom description] - -[anchor]{# target-location}"#; - let result = parse_tree(norg).expect("Failed to parse anchor with description"); - with_settings!({ - info => &norg, - description => "check ancho declaration with description", +fn run_anchor_tests() { + for (norg_str, desc, name) in ANCHOR_TESTS { + let result = parse_tree(norg_str).expect("Failed to parse basic anchor declaration"); + info!(name, desc, "running test"); + with_settings!({ + info => &norg_str, + description => desc, omit_expression => true, - }, {assert_ron_snapshot!(result)}); - // assert_eq!( - // result, - // vec![ - // Paragraph(vec![Anchor { - // content: vec![Token(Text("anchor".to_string()))], - // description: Some(vec![ - // Token(Text("custom".to_string())), - // Token(Whitespace), - // Token(Text("description".to_string())) - // ]) - // }]), - // Paragraph(vec![AnchorDefinition { - // content: vec![Token(Text("anchor".to_string()))], - // target: Box::new(Link { - // filepath: None, - // targets: vec![LinkTarget::Generic(vec![ - // Token(Text("target".to_string())), - // Token(Special('-')), - // Token(Text("location".to_string())) - // ])], - // description: None - // }) - // }]) - // ] - // ) + }, {assert_ron_snapshot!(name, result)}); + } } // // Anchor Definition Tests diff --git a/tests/snapshots/anchor_tests__anchor_declaration_standalone.snap b/tests/snapshots/anchor_tests__anchor_declaration_standalone.snap deleted file mode 100644 index b108c05..0000000 --- a/tests/snapshots/anchor_tests__anchor_declaration_standalone.snap +++ /dev/null @@ -1,52 +0,0 @@ ---- -source: tests/anchor_tests.rs -expression: result ---- -[ - Paragraph([ - Token(Text("This")), - Token(Whitespace), - Token(Text("text")), - Token(Whitespace), - Token(Text("references")), - Token(Whitespace), - Anchor( - content: [ - Token(Text("anchor")), - Token(Whitespace), - Token(Text("name")), - ], - description: None, - ), - Token(Whitespace), - Token(Text("in")), - Token(Whitespace), - Token(Text("the")), - Token(Whitespace), - Token(Text("content")), - Token(Special('.')), - ]), - Paragraph([ - AnchorDefinition( - content: [ - Token(Text("anchor")), - Token(Whitespace), - Token(Text("name")), - ], - target: Link( - filepath: None, - targets: [ - Heading( - level: 1, - title: [ - Token(Text("Target")), - Token(Whitespace), - Token(Text("Heading")), - ], - ), - ], - description: None, - ), - ), - ]), -] diff --git a/tests/snapshots/anchor_tests__anchor_declaration_basic.snap b/tests/snapshots/anchor_tests__test_anchor_declaration_basic.snap similarity index 80% rename from tests/snapshots/anchor_tests__anchor_declaration_basic.snap rename to tests/snapshots/anchor_tests__test_anchor_declaration_basic.snap index 0e7a562..aeabb2d 100644 --- a/tests/snapshots/anchor_tests__anchor_declaration_basic.snap +++ b/tests/snapshots/anchor_tests__test_anchor_declaration_basic.snap @@ -1,6 +1,7 @@ --- source: tests/anchor_tests.rs -expression: result +description: Basic Anchor Declaration Tests +info: "[Neorg] is a fancy organizational tool.\n [Neorg]{https://github.com/nvim-neorg/neorg}" --- [ Paragraph([ @@ -21,8 +22,7 @@ expression: result Token(Whitespace), Token(Text("tool")), Token(Special('.')), - ]), - Paragraph([ + Token(Whitespace), AnchorDefinition( content: [ Token(Text("Neorg")), diff --git a/tests/snapshots/anchor_tests__anchor_with_description.snap b/tests/snapshots/anchor_tests__test_anchor_with_description.snap similarity index 75% rename from tests/snapshots/anchor_tests__anchor_with_description.snap rename to tests/snapshots/anchor_tests__test_anchor_with_description.snap index 72638e0..92742ea 100644 --- a/tests/snapshots/anchor_tests__anchor_with_description.snap +++ b/tests/snapshots/anchor_tests__test_anchor_with_description.snap @@ -1,7 +1,7 @@ --- source: tests/anchor_tests.rs description: check ancho declaration with description -info: "[anchor][custom description]\n\n[anchor]{# target-location}" +info: "[anchor][custom description]. Here is [anchor]{# target-location}" --- [ Paragraph([ @@ -15,8 +15,12 @@ info: "[anchor][custom description]\n\n[anchor]{# target-location}" Token(Text("description")), ]), ), - ]), - Paragraph([ + Token(Special('.')), + Token(Whitespace), + Token(Text("Here")), + Token(Whitespace), + Token(Text("is")), + Token(Whitespace), AnchorDefinition( content: [ Token(Text("anchor")), From 481c722ceb5b555f1b26d08042728f225301be9c Mon Sep 17 00:00:00 2001 From: hardfau1t Date: Wed, 10 Sep 2025 12:57:40 +0530 Subject: [PATCH 10/14] test(anchor_tests): add anchor test which links to a heading --- tests/anchor_tests.rs | 21 ++++++++----- ...tests__test_anchor_definition_heading.snap | 30 +++++++++++++++++++ 2 files changed, 43 insertions(+), 8 deletions(-) create mode 100644 tests/snapshots/anchor_tests__test_anchor_definition_heading.snap diff --git a/tests/anchor_tests.rs b/tests/anchor_tests.rs index a31ddd4..bc9a75e 100644 --- a/tests/anchor_tests.rs +++ b/tests/anchor_tests.rs @@ -4,24 +4,29 @@ use test_log::test; use tracing::info; // test and description pair -const ANCHOR_TESTS: [(&str, &str, &str); 2] = [ +const ANCHOR_TESTS: [(&str, &str, &str); 3] = [ ( + "test_anchor_declaration_basic", + "Basic Anchor Declaration Tests", r#"[Neorg] is a fancy organizational tool. [Neorg]{https://github.com/nvim-neorg/neorg}"#, - "Basic Anchor Declaration Tests", - "test_anchor_declaration_basic", ), ( - r#"[anchor][custom description]. Here is [anchor]{# target-location}"#, - "check ancho declaration with description", "test_anchor_with_description", + "check ancho declaration with description", + r#"[anchor][custom description]. Here is [anchor]{# target-location}"#, + ), + ( + "test_anchor_definition_heading", + "Should link anchor to heading", + r#"[section reference]{* Important Section}"#, ), ]; // run all anchor tests #[test] fn run_anchor_tests() { - for (norg_str, desc, name) in ANCHOR_TESTS { + for (name, desc, norg_str) in ANCHOR_TESTS { let result = parse_tree(norg_str).expect("Failed to parse basic anchor declaration"); info!(name, desc, "running test"); with_settings!({ @@ -35,9 +40,9 @@ fn run_anchor_tests() { // // Anchor Definition Tests // #[test] // fn test_anchor_definition_heading() { -// let norg = r#"[section reference]{* Important Section}"#; +// let norg = ; // let result = parse_tree(norg).expect("Failed to parse anchor definition to heading"); -// // Should link anchor to heading +// // // assert_eq!( // result, // vec![Paragraph(vec![AnchorDefinition { diff --git a/tests/snapshots/anchor_tests__test_anchor_definition_heading.snap b/tests/snapshots/anchor_tests__test_anchor_definition_heading.snap new file mode 100644 index 0000000..79745be --- /dev/null +++ b/tests/snapshots/anchor_tests__test_anchor_definition_heading.snap @@ -0,0 +1,30 @@ +--- +source: tests/anchor_tests.rs +description: Should link anchor to heading +info: "[section reference]{* Important Section}" +--- +[ + Paragraph([ + AnchorDefinition( + content: [ + Token(Text("section")), + Token(Whitespace), + Token(Text("reference")), + ], + target: Link( + filepath: None, + targets: [ + Heading( + level: 1, + title: [ + Token(Text("Important")), + Token(Whitespace), + Token(Text("Section")), + ], + ), + ], + description: None, + ), + ), + ]), +] From 6503a316fbcf592f9f6d17bef6344396cfa9aaf8 Mon Sep 17 00:00:00 2001 From: hardfau1t Date: Thu, 11 Sep 2025 15:26:24 +0530 Subject: [PATCH 11/14] test(anchor): adads insta anchor tests --- tests/anchor_tests.rs | 359 ++++-------------- ...chor_tests__anchor_backward_reference.snap | 47 +++ ...or_tests__anchor_current_path_mapping.snap | 46 +++ ...nchor_tests__anchor_declaration_basic.snap | 39 ++ ...ests__anchor_definition_file_location.snap | 19 + ...hor_tests__anchor_definition_heading.snap} | 0 .../anchor_tests__anchor_in_heading.snap | 45 +++ .../anchor_tests__anchor_in_list.snap | 73 ++++ .../anchor_tests__anchor_multiword_names.snap | 55 +++ ...chor_tests__anchor_special_characters.snap | 52 +++ ...chor_tests__anchor_unicode_characters.snap | 40 ++ ...tests__anchor_with_attached_modifiers.snap | 48 +++ ...nchor_tests__anchor_with_description.snap} | 0 ...r_tests__multiple_anchor_declarations.snap | 59 +++ .../anchor_tests__repeated_anchor_usage.snap | 51 +++ ..._tests__test_anchor_declaration_basic.snap | 26 +- 16 files changed, 662 insertions(+), 297 deletions(-) create mode 100644 tests/snapshots/anchor_tests__anchor_backward_reference.snap create mode 100644 tests/snapshots/anchor_tests__anchor_current_path_mapping.snap create mode 100644 tests/snapshots/anchor_tests__anchor_declaration_basic.snap create mode 100644 tests/snapshots/anchor_tests__anchor_definition_file_location.snap rename tests/snapshots/{anchor_tests__test_anchor_definition_heading.snap => anchor_tests__anchor_definition_heading.snap} (100%) create mode 100644 tests/snapshots/anchor_tests__anchor_in_heading.snap create mode 100644 tests/snapshots/anchor_tests__anchor_in_list.snap create mode 100644 tests/snapshots/anchor_tests__anchor_multiword_names.snap create mode 100644 tests/snapshots/anchor_tests__anchor_special_characters.snap create mode 100644 tests/snapshots/anchor_tests__anchor_unicode_characters.snap create mode 100644 tests/snapshots/anchor_tests__anchor_with_attached_modifiers.snap rename tests/snapshots/{anchor_tests__test_anchor_with_description.snap => anchor_tests__anchor_with_description.snap} (100%) create mode 100644 tests/snapshots/anchor_tests__multiple_anchor_declarations.snap create mode 100644 tests/snapshots/anchor_tests__repeated_anchor_usage.snap diff --git a/tests/anchor_tests.rs b/tests/anchor_tests.rs index bc9a75e..7e0275e 100644 --- a/tests/anchor_tests.rs +++ b/tests/anchor_tests.rs @@ -4,25 +4,104 @@ use test_log::test; use tracing::info; // test and description pair -const ANCHOR_TESTS: [(&str, &str, &str); 3] = [ +const ANCHOR_TESTS: [(&str, &str, &str); 15] = [ ( - "test_anchor_declaration_basic", + "anchor_declaration_basic", "Basic Anchor Declaration Tests", r#"[Neorg] is a fancy organizational tool. [Neorg]{https://github.com/nvim-neorg/neorg}"#, ), ( - "test_anchor_with_description", + "anchor_with_description", "check ancho declaration with description", r#"[anchor][custom description]. Here is [anchor]{# target-location}"#, ), ( - "test_anchor_definition_heading", + "anchor_definition_heading", "Should link anchor to heading", r#"[section reference]{* Important Section}"#, ), -]; + ( + "test_anchor_declaration_basic", + "Should link anchor to external URL", + r#"[homepage]{https://example.com}"#, + ), + ( + "anchor_definition_file_location", + "anchor definition file location", + r#"[documentation]{:docs/setup:}"#, + ), + ( + "multiple_anchor_declarations", + "Multiple Anchor Usage in a same line", + r#"Both [first] and [second] are useful resources. + [first]{https://first.example.com} + [second]{https://second.example.com}"#, + ), + ( + "repeated_anchor_usage", + "Should link both instances to the same target", + r#"First mention of [tool] and second mention of [tool]. + +[tool]{https://tool.example.com}"#, + ), + ( + "anchor_current_path_mapping", + "Should generate current path URL mapping with magic mapping", + r#"Link to [local-ref] within document. + +[local-ref]{# local-reference}"#, + ), + ( + "anchor_in_list", + "Should work within list items", + r#"- First item with [list anchor] +- Second item +- Third item [list anchor]{* Target Section}"#, + ), + ( + "anchor_in_heading", + "Should work within headings", + r#"* Heading with [heading anchor] reference + +[heading anchor]{https://example.com}"#, + ), + ( + "anchor_with_attached_modifiers", + "Should work within attached modifiers", + r#"This is *[important anchor]* text. + +[important anchor]{# important-section}"#, + ), + ( + "anchor_backward_reference", + "Should handle backward references", + r#"[early anchor]{* Early Section} + +Later reference to [early anchor]."#, + ), + ( + "anchor_special_characters", + "Special Characters and Edge Cases", + r#"Link with [special & chars!] in name. +[special & chars!]{# special-target}"#, + ), + ( + "anchor_unicode_characters", + "Should handle unicode characters", + r#"Reference to [café anchor] here. + +[café anchor]{https://café.example.com}"#, + ), + ( + "anchor_multiword_names", + "Should handle multi-word anchor names", + r#"Link to [multi word anchor name] reference. + +[multi word anchor name]{* Target Section}"#, + ), +]; // run all anchor tests #[test] fn run_anchor_tests() { @@ -36,273 +115,3 @@ fn run_anchor_tests() { }, {assert_ron_snapshot!(name, result)}); } } - -// // Anchor Definition Tests -// #[test] -// fn test_anchor_definition_heading() { -// let norg = ; -// let result = parse_tree(norg).expect("Failed to parse anchor definition to heading"); -// // -// assert_eq!( -// result, -// vec![Paragraph(vec![AnchorDefinition { -// content: vec![ -// Token(Text("section".to_string())), -// Token(Whitespace), -// Token(Text("reference".to_string())) -// ], -// target: Box::new(Link { -// filepath: None, -// targets: vec![Heading { -// level: 1, -// title: vec![ -// Token(Text("Important".to_string())), -// Token(Whitespace), -// Token(Text("Section".to_string())) -// ] -// }], -// description: None -// }) -// }])] -// ); -// } -// -// #[test] -// fn test_anchor_definition_external_url() { -// let norg = r#"[homepage]{https://example.com}"#; -// let result = parse_tree(norg).expect("Failed to parse anchor definition to external URL"); -// // Should link anchor to external URL -// assert_eq!( -// result, -// vec![Paragraph(vec![AnchorDefinition { -// content: vec![Token(Text("homepage".to_string()))], -// target: Box::new(Link { -// filepath: None, -// targets: vec![LinkTarget::Url("https://example.com".to_string())], -// description: None -// }) -// }])] -// ) -// } -// -// #[test] -// fn test_anchor_definition_file_location() { -// let norg = r#"{:docs/setup:}[documentation]"#; -// let result = parse_tree(norg).expect("Failed to parse anchor definition to file location"); -// assert_eq!( -// result, -// vec![Paragraph(vec![AnchorDefinition { -// content: vec![Token(Text("documentation".to_string()))], -// target: Box::new(Link { -// filepath: Some("docs/setup".to_string()), -// targets: vec![], -// description: None -// }) -// }])] -// ); -// } - -/* -// Multiple Anchor Usage -#[test] -fn test_multiple_anchor_declarations() { - let norg = r#"Both [first] and [second] are useful resources. - -[first]{https://first.example.com} -[second]{https://second.example.com}"#; - let result = parse_tree(norg).expect("Failed to parse multiple anchor declarations"); - assert_eq!(result, vec![]); - // Should handle multiple anchors -} - -#[test] -fn test_repeated_anchor_usage() { - let norg = r#"First mention of [tool] and second mention of [tool]. - -[tool]{https://tool.example.com}"#; - let result = parse_tree(norg).expect("Failed to parse repeated anchor usage"); - assert_eq!(result, vec![]); - // Should link both instances to the same target - let link_count = result.matches("href=\"https://tool.example.com\"").count(); -} - -// Anchor URL Mapping Tests (Based on links-mapping.txt) -#[test] -fn test_anchor_url_mapping() { - let norg = r#"Reference to [Neorg] in text. - -[Neorg]{# target-location}"#; - let result = parse_tree(norg).expect("Failed to parse anchor URL mapping"); - assert_eq!(result, vec![]); - // Should map to: http://127.0.0.1/view/#Neorg - result.contains("href=\"#Neorg\"")); -} - -#[test] -fn test_anchor_current_path_mapping() { - let norg = r#"Link to [local-ref] within document. - -[local-ref]{# local-reference}"#; - let result = parse_tree(norg).expect("Failed to parse anchor current path mapping"); - assert_eq!(result, vec![]); - // Should generate current path URL mapping -} - -// Anchor Integration with Other Features -#[test] -fn test_anchor_in_paragraph() { - let norg = r#"This paragraph contains [inline anchor] for reference. - -[inline anchor]{https://example.com/reference}"#; - let result = parse_tree(norg).expect("Failed to parse anchor in paragraph"); - assert_eq!(result, vec![]); - // Should work within paragraph text -} - -#[test] -fn test_anchor_in_list() { - let norg = r#"- First item with [list anchor] -- Second item -- Third item - -[list anchor]{* Target Section}"#; - let result = parse_tree(norg).expect("Failed to parse anchor in list"); - assert_eq!(result, vec![]); - // Should work within list items -} - -#[test] -fn test_anchor_in_heading() { - let norg = r#"* Heading with [heading anchor] reference - -[heading anchor]{https://example.com}"#; - let result = parse_tree(norg).expect("Failed to parse anchor in heading"); - assert_eq!(result, vec![]); - // Should work within headings -} - -// Complex Anchor Scenarios -#[test] -fn test_anchor_with_attached_modifiers() { - let norg = r#"This is *[important anchor]* text. - -[important anchor]{# important-section}"#; - let result = parse_tree(norg).expect("Failed to parse anchor with attached modifiers"); - assert_eq!(result, vec![]); - // Should work within attached modifiers -} - -#[test] -fn test_anchor_forward_reference() { - let norg = r#"Forward reference to [future anchor]. - -Later in document... - -[future anchor]{* Later Section}"#; - let result = parse_tree(norg).expect("Failed to parse anchor forward reference"); - assert_eq!(result, vec![]); - // Should handle forward references -} - -#[test] -fn test_anchor_backward_reference() { - let norg = r#"[early anchor]{* Early Section} - -Later reference to [early anchor]."#; - let result = parse_tree(norg).expect("Failed to parse anchor backward reference"); - assert_eq!(result, vec![]); - // Should handle backward references -} - -// Anchor HTML Generation -#[test] -fn test_anchor_html_structure() { - let norg = r#"Link to [structured anchor] here. - -[structured anchor]{https://structured.example.com}"#; - let result = parse_tree(norg).expect("Failed to parse anchor HTML structure"); - assert_eq!(result, vec![]); - // Should generate proper HTML anchor structure -} - -#[test] -fn test_anchor_css_classes() { - let norg = r#"Text with [classed anchor] link. - -[classed anchor]{# class-target}"#; - let result = parse_tree(norg).expect("Failed to parse anchor CSS classes"); - assert_eq!(result, vec![]); - // Should have appropriate CSS classes - result.contains("anchor") || - result.contains("href=")); -} - -#[test] -fn test_anchor_accessibility() { - let norg = r#"Accessible [screen reader anchor] link. - -[screen reader anchor]{https://accessible.example.com}"#; - let result = parse_tree(norg).expect("Failed to parse anchor accessibility"); - assert_eq!(result, vec![]); - // Should have accessibility attributes - // May have additional accessibility attributes -} - -// Special Characters and Edge Cases -#[test] -fn test_anchor_special_characters() { - let norg = r#"Link with [special & chars!] in name. - -[special & chars!]{# special-target}"#; - let result = parse_tree(norg).expect("Failed to parse anchor with special characters"); - assert_eq!(result, vec![]); - // Should handle special characters -} - -#[test] -fn test_anchor_unicode_characters() { - let norg = r#"Reference to [café anchor] here. - -[café anchor]{https://café.example.com}"#; - let result = parse_tree(norg).expect("Failed to parse anchor with unicode"); - assert_eq!(result, vec![]); - // Should handle unicode characters -} - -#[test] -fn test_anchor_multiword_names() { - let norg = r#"Link to [multi word anchor name] reference. - -[multi word anchor name]{* Target Section}"#; - let result = parse_tree(norg).expect("Failed to parse multiword anchor names"); - assert_eq!(result, vec![]); - // Should handle multi-word anchor names -} - -// Error Handling -#[test] -fn test_anchor_undefined_reference() { - let norg = r#"Reference to [undefined anchor] without definition."#; - let result = parse_tree(norg).expect("Failed to parse undefined anchor reference"); - assert_eq!(result, vec![]); - // Should handle undefined anchors gracefully - // May show as broken link or plain text -} - -#[test] -fn test_anchor_definition_without_reference() { - let norg = r#"[orphan anchor]{https://orphan.example.com}"#; - let result = parse_tree(norg).expect("Failed to parse orphan anchor definition"); - assert_eq!(result, vec![]); - // Should handle orphaned definitions gracefully -} - -#[test] -fn test_anchor_circular_reference() { - let norg = r#"[circular1]{# circular2} -[circular2]{# circular1}"#; - let result = parse_tree(norg).expect("Failed to parse circular anchor reference"); - assert_eq!(result, vec![]); - // Should handle circular references gracefully -} -*/ diff --git a/tests/snapshots/anchor_tests__anchor_backward_reference.snap b/tests/snapshots/anchor_tests__anchor_backward_reference.snap new file mode 100644 index 0000000..2c72f8e --- /dev/null +++ b/tests/snapshots/anchor_tests__anchor_backward_reference.snap @@ -0,0 +1,47 @@ +--- +source: tests/anchor_tests.rs +description: Should handle backward references +info: "[early anchor]{* Early Section}\n\nLater reference to [early anchor]." +--- +[ + Paragraph([ + AnchorDefinition( + content: [ + Token(Text("early")), + Token(Whitespace), + Token(Text("anchor")), + ], + target: Link( + filepath: None, + targets: [ + Heading( + level: 1, + title: [ + Token(Text("Early")), + Token(Whitespace), + Token(Text("Section")), + ], + ), + ], + description: None, + ), + ), + ]), + Paragraph([ + Token(Text("Later")), + Token(Whitespace), + Token(Text("reference")), + Token(Whitespace), + Token(Text("to")), + Token(Whitespace), + Anchor( + content: [ + Token(Text("early")), + Token(Whitespace), + Token(Text("anchor")), + ], + description: None, + ), + Token(Special('.')), + ]), +] diff --git a/tests/snapshots/anchor_tests__anchor_current_path_mapping.snap b/tests/snapshots/anchor_tests__anchor_current_path_mapping.snap new file mode 100644 index 0000000..d77e7b3 --- /dev/null +++ b/tests/snapshots/anchor_tests__anchor_current_path_mapping.snap @@ -0,0 +1,46 @@ +--- +source: tests/anchor_tests.rs +description: Should generate current path URL mapping +info: "Link to [local-ref] within document.\n\n[local-ref]{# local-reference}" +--- +[ + Paragraph([ + Token(Text("Link")), + Token(Whitespace), + Token(Text("to")), + Token(Whitespace), + Anchor( + content: [ + Token(Text("local")), + Token(Special('-')), + Token(Text("ref")), + ], + description: None, + ), + Token(Whitespace), + Token(Text("within")), + Token(Whitespace), + Token(Text("document")), + Token(Special('.')), + ]), + Paragraph([ + AnchorDefinition( + content: [ + Token(Text("local")), + Token(Special('-')), + Token(Text("ref")), + ], + target: Link( + filepath: None, + targets: [ + Generic([ + Token(Text("local")), + Token(Special('-')), + Token(Text("reference")), + ]), + ], + description: None, + ), + ), + ]), +] diff --git a/tests/snapshots/anchor_tests__anchor_declaration_basic.snap b/tests/snapshots/anchor_tests__anchor_declaration_basic.snap new file mode 100644 index 0000000..aeabb2d --- /dev/null +++ b/tests/snapshots/anchor_tests__anchor_declaration_basic.snap @@ -0,0 +1,39 @@ +--- +source: tests/anchor_tests.rs +description: Basic Anchor Declaration Tests +info: "[Neorg] is a fancy organizational tool.\n [Neorg]{https://github.com/nvim-neorg/neorg}" +--- +[ + Paragraph([ + Anchor( + content: [ + Token(Text("Neorg")), + ], + description: None, + ), + Token(Whitespace), + Token(Text("is")), + Token(Whitespace), + Token(Text("a")), + Token(Whitespace), + Token(Text("fancy")), + Token(Whitespace), + Token(Text("organizational")), + Token(Whitespace), + Token(Text("tool")), + Token(Special('.')), + Token(Whitespace), + AnchorDefinition( + content: [ + Token(Text("Neorg")), + ], + target: Link( + filepath: None, + targets: [ + Url("https://github.com/nvim-neorg/neorg"), + ], + description: None, + ), + ), + ]), +] diff --git a/tests/snapshots/anchor_tests__anchor_definition_file_location.snap b/tests/snapshots/anchor_tests__anchor_definition_file_location.snap new file mode 100644 index 0000000..b0b6118 --- /dev/null +++ b/tests/snapshots/anchor_tests__anchor_definition_file_location.snap @@ -0,0 +1,19 @@ +--- +source: tests/anchor_tests.rs +description: anchor definition file location +info: "[documentation]{:docs/setup:}" +--- +[ + Paragraph([ + AnchorDefinition( + content: [ + Token(Text("documentation")), + ], + target: Link( + filepath: Some("docs/setup"), + targets: [], + description: None, + ), + ), + ]), +] diff --git a/tests/snapshots/anchor_tests__test_anchor_definition_heading.snap b/tests/snapshots/anchor_tests__anchor_definition_heading.snap similarity index 100% rename from tests/snapshots/anchor_tests__test_anchor_definition_heading.snap rename to tests/snapshots/anchor_tests__anchor_definition_heading.snap diff --git a/tests/snapshots/anchor_tests__anchor_in_heading.snap b/tests/snapshots/anchor_tests__anchor_in_heading.snap new file mode 100644 index 0000000..85453c2 --- /dev/null +++ b/tests/snapshots/anchor_tests__anchor_in_heading.snap @@ -0,0 +1,45 @@ +--- +source: tests/anchor_tests.rs +description: Should work within headings +info: "* Heading with [heading anchor] reference\n\n[heading anchor]{https://example.com}" +--- +[ + Heading( + level: 1, + title: [ + Token(Text("Heading")), + Token(Whitespace), + Token(Text("with")), + Token(Whitespace), + Anchor( + content: [ + Token(Text("heading")), + Token(Whitespace), + Token(Text("anchor")), + ], + description: None, + ), + Token(Whitespace), + Token(Text("reference")), + ], + extensions: [], + content: [ + Paragraph([ + AnchorDefinition( + content: [ + Token(Text("heading")), + Token(Whitespace), + Token(Text("anchor")), + ], + target: Link( + filepath: None, + targets: [ + Url("https://example.com"), + ], + description: None, + ), + ), + ]), + ], + ), +] diff --git a/tests/snapshots/anchor_tests__anchor_in_list.snap b/tests/snapshots/anchor_tests__anchor_in_list.snap new file mode 100644 index 0000000..998a3e9 --- /dev/null +++ b/tests/snapshots/anchor_tests__anchor_in_list.snap @@ -0,0 +1,73 @@ +--- +source: tests/anchor_tests.rs +description: Should work within list items +info: "- First item with [list anchor]\n- Second item\n- Third item [list anchor]{* Target Section}" +--- +[ + NestableDetachedModifier( + modifier_type: UnorderedList, + level: 1, + extensions: [], + text: Paragraph([ + Token(Text("First")), + Token(Whitespace), + Token(Text("item")), + Token(Whitespace), + Token(Text("with")), + Token(Whitespace), + Anchor( + content: [ + Token(Text("list")), + Token(Whitespace), + Token(Text("anchor")), + ], + description: None, + ), + ]), + content: [], + ), + NestableDetachedModifier( + modifier_type: UnorderedList, + level: 1, + extensions: [], + text: Paragraph([ + Token(Text("Second")), + Token(Whitespace), + Token(Text("item")), + ]), + content: [], + ), + NestableDetachedModifier( + modifier_type: UnorderedList, + level: 1, + extensions: [], + text: Paragraph([ + Token(Text("Third")), + Token(Whitespace), + Token(Text("item")), + Token(Whitespace), + AnchorDefinition( + content: [ + Token(Text("list")), + Token(Whitespace), + Token(Text("anchor")), + ], + target: Link( + filepath: None, + targets: [ + Heading( + level: 1, + title: [ + Token(Text("Target")), + Token(Whitespace), + Token(Text("Section")), + ], + ), + ], + description: None, + ), + ), + ]), + content: [], + ), +] diff --git a/tests/snapshots/anchor_tests__anchor_multiword_names.snap b/tests/snapshots/anchor_tests__anchor_multiword_names.snap new file mode 100644 index 0000000..7db1ad3 --- /dev/null +++ b/tests/snapshots/anchor_tests__anchor_multiword_names.snap @@ -0,0 +1,55 @@ +--- +source: tests/anchor_tests.rs +description: Should handle multi-word anchor names +info: "Link to [multi word anchor name] reference.\n\n[multi word anchor name]{* Target Section}" +--- +[ + Paragraph([ + Token(Text("Link")), + Token(Whitespace), + Token(Text("to")), + Token(Whitespace), + Anchor( + content: [ + Token(Text("multi")), + Token(Whitespace), + Token(Text("word")), + Token(Whitespace), + Token(Text("anchor")), + Token(Whitespace), + Token(Text("name")), + ], + description: None, + ), + Token(Whitespace), + Token(Text("reference")), + Token(Special('.')), + ]), + Paragraph([ + AnchorDefinition( + content: [ + Token(Text("multi")), + Token(Whitespace), + Token(Text("word")), + Token(Whitespace), + Token(Text("anchor")), + Token(Whitespace), + Token(Text("name")), + ], + target: Link( + filepath: None, + targets: [ + Heading( + level: 1, + title: [ + Token(Text("Target")), + Token(Whitespace), + Token(Text("Section")), + ], + ), + ], + description: None, + ), + ), + ]), +] diff --git a/tests/snapshots/anchor_tests__anchor_special_characters.snap b/tests/snapshots/anchor_tests__anchor_special_characters.snap new file mode 100644 index 0000000..19cd602 --- /dev/null +++ b/tests/snapshots/anchor_tests__anchor_special_characters.snap @@ -0,0 +1,52 @@ +--- +source: tests/anchor_tests.rs +description: Special Characters and Edge Cases +info: "Link with [special & chars!] in name.\n\n[special & chars!]{# special-target}" +--- +[ + Paragraph([ + Token(Text("Link")), + Token(Whitespace), + Token(Text("with")), + Token(Whitespace), + Anchor( + content: [ + Token(Text("special")), + Token(Whitespace), + Token(Text("&")), + Token(Whitespace), + Token(Text("chars")), + Token(Special('!')), + ], + description: None, + ), + Token(Whitespace), + Token(Text("in")), + Token(Whitespace), + Token(Text("name")), + Token(Special('.')), + ]), + Paragraph([ + AnchorDefinition( + content: [ + Token(Text("special")), + Token(Whitespace), + Token(Text("&")), + Token(Whitespace), + Token(Text("chars")), + Token(Special('!')), + ], + target: Link( + filepath: None, + targets: [ + Generic([ + Token(Text("special")), + Token(Special('-')), + Token(Text("target")), + ]), + ], + description: None, + ), + ), + ]), +] diff --git a/tests/snapshots/anchor_tests__anchor_unicode_characters.snap b/tests/snapshots/anchor_tests__anchor_unicode_characters.snap new file mode 100644 index 0000000..678ef77 --- /dev/null +++ b/tests/snapshots/anchor_tests__anchor_unicode_characters.snap @@ -0,0 +1,40 @@ +--- +source: tests/anchor_tests.rs +description: Should handle unicode characters +info: "Reference to [café anchor] here.\n\n[café anchor]{https://café.example.com}" +--- +[ + Paragraph([ + Token(Text("Reference")), + Token(Whitespace), + Token(Text("to")), + Token(Whitespace), + Anchor( + content: [ + Token(Text("café")), + Token(Whitespace), + Token(Text("anchor")), + ], + description: None, + ), + Token(Whitespace), + Token(Text("here")), + Token(Special('.')), + ]), + Paragraph([ + AnchorDefinition( + content: [ + Token(Text("café")), + Token(Whitespace), + Token(Text("anchor")), + ], + target: Link( + filepath: None, + targets: [ + Url("https://café.example.com"), + ], + description: None, + ), + ), + ]), +] diff --git a/tests/snapshots/anchor_tests__anchor_with_attached_modifiers.snap b/tests/snapshots/anchor_tests__anchor_with_attached_modifiers.snap new file mode 100644 index 0000000..35902b8 --- /dev/null +++ b/tests/snapshots/anchor_tests__anchor_with_attached_modifiers.snap @@ -0,0 +1,48 @@ +--- +source: tests/anchor_tests.rs +description: Should work within attached modifiers +info: "This is *[important anchor]* text.\n\n[important anchor]{# important-section}" +--- +[ + Paragraph([ + Token(Text("This")), + Token(Whitespace), + Token(Text("is")), + Token(Whitespace), + AttachedModifier( + modifier_type: '*', + content: [ + Anchor ( + content: [ + Token(Text("important")), + Token(Whitespace), + Token(Text("anchor")), + ], + ), + ], + ), + Token(Whitespace), + Token(Text("text")), + Token(Special('.')), + ]), + Paragraph([ + AnchorDefinition( + content: [ + Token(Text("important")), + Token(Whitespace), + Token(Text("anchor")), + ], + target: Link( + filepath: None, + targets: [ + Generic([ + Token(Text("important")), + Token(Special('-')), + Token(Text("section")), + ]), + ], + description: None, + ), + ), + ]), +] diff --git a/tests/snapshots/anchor_tests__test_anchor_with_description.snap b/tests/snapshots/anchor_tests__anchor_with_description.snap similarity index 100% rename from tests/snapshots/anchor_tests__test_anchor_with_description.snap rename to tests/snapshots/anchor_tests__anchor_with_description.snap diff --git a/tests/snapshots/anchor_tests__multiple_anchor_declarations.snap b/tests/snapshots/anchor_tests__multiple_anchor_declarations.snap new file mode 100644 index 0000000..4d08008 --- /dev/null +++ b/tests/snapshots/anchor_tests__multiple_anchor_declarations.snap @@ -0,0 +1,59 @@ +--- +source: tests/anchor_tests.rs +description: Multiple Anchor Usage in a same line +info: "Both [first] and [second] are useful resources.\n [first]{https://first.example.com}\n [second]{https://second.example.com}" +--- +[ + Paragraph([ + Token(Text("Both")), + Token(Whitespace), + Anchor( + content: [ + Token(Text("first")), + ], + description: None, + ), + Token(Whitespace), + Token(Text("and")), + Token(Whitespace), + Anchor( + content: [ + Token(Text("second")), + ], + description: None, + ), + Token(Whitespace), + Token(Text("are")), + Token(Whitespace), + Token(Text("useful")), + Token(Whitespace), + Token(Text("resources")), + Token(Special('.')), + Token(Whitespace), + AnchorDefinition( + content: [ + Token(Text("first")), + ], + target: Link( + filepath: None, + targets: [ + Url("https://first.example.com"), + ], + description: None, + ), + ), + Token(Whitespace), + AnchorDefinition( + content: [ + Token(Text("second")), + ], + target: Link( + filepath: None, + targets: [ + Url("https://second.example.com"), + ], + description: None, + ), + ), + ]), +] diff --git a/tests/snapshots/anchor_tests__repeated_anchor_usage.snap b/tests/snapshots/anchor_tests__repeated_anchor_usage.snap new file mode 100644 index 0000000..b405b86 --- /dev/null +++ b/tests/snapshots/anchor_tests__repeated_anchor_usage.snap @@ -0,0 +1,51 @@ +--- +source: tests/anchor_tests.rs +description: Should link both instances to the same target +info: "First mention of [tool] and second mention of [tool].\n\n[tool]{https://tool.example.com}" +--- +[ + Paragraph([ + Token(Text("First")), + Token(Whitespace), + Token(Text("mention")), + Token(Whitespace), + Token(Text("of")), + Token(Whitespace), + Anchor( + content: [ + Token(Text("tool")), + ], + description: None, + ), + Token(Whitespace), + Token(Text("and")), + Token(Whitespace), + Token(Text("second")), + Token(Whitespace), + Token(Text("mention")), + Token(Whitespace), + Token(Text("of")), + Token(Whitespace), + Anchor( + content: [ + Token(Text("tool")), + ], + description: None, + ), + Token(Special('.')), + ]), + Paragraph([ + AnchorDefinition( + content: [ + Token(Text("tool")), + ], + target: Link( + filepath: None, + targets: [ + Url("https://tool.example.com"), + ], + description: None, + ), + ), + ]), +] diff --git a/tests/snapshots/anchor_tests__test_anchor_declaration_basic.snap b/tests/snapshots/anchor_tests__test_anchor_declaration_basic.snap index aeabb2d..b48387c 100644 --- a/tests/snapshots/anchor_tests__test_anchor_declaration_basic.snap +++ b/tests/snapshots/anchor_tests__test_anchor_declaration_basic.snap @@ -1,36 +1,18 @@ --- source: tests/anchor_tests.rs -description: Basic Anchor Declaration Tests -info: "[Neorg] is a fancy organizational tool.\n [Neorg]{https://github.com/nvim-neorg/neorg}" +description: Should link anchor to external URL +info: "[homepage]{https://example.com}" --- [ Paragraph([ - Anchor( - content: [ - Token(Text("Neorg")), - ], - description: None, - ), - Token(Whitespace), - Token(Text("is")), - Token(Whitespace), - Token(Text("a")), - Token(Whitespace), - Token(Text("fancy")), - Token(Whitespace), - Token(Text("organizational")), - Token(Whitespace), - Token(Text("tool")), - Token(Special('.')), - Token(Whitespace), AnchorDefinition( content: [ - Token(Text("Neorg")), + Token(Text("homepage")), ], target: Link( filepath: None, targets: [ - Url("https://github.com/nvim-neorg/neorg"), + Url("https://example.com"), ], description: None, ), From 93863b65fa1c5dda832a00fd28b55d68ca68fe51 Mon Sep 17 00:00:00 2001 From: hardfau1t Date: Thu, 11 Sep 2025 15:41:31 +0530 Subject: [PATCH 12/14] ci(github): add format and clippy checks --- .github/workflows/rust.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 813178c..ce321a9 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -14,6 +14,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + - name: format check + run: cargo fmt --check + - name: clippy check + run: cargo clippy --check - name: Build run: cargo build --verbose - name: Run tests From f4a0e7dc8bb96713dbde058564755fdfc3bfc973 Mon Sep 17 00:00:00 2001 From: hardfau1t Date: Thu, 11 Sep 2025 15:57:44 +0530 Subject: [PATCH 13/14] chore(main): format with cargo fmt --- src/metadata/mod.rs | 2 +- src/stage_1.rs | 3 +- src/stage_4.rs | 85 +++++++++++++++++++++------------------------ 3 files changed, 42 insertions(+), 48 deletions(-) diff --git a/src/metadata/mod.rs b/src/metadata/mod.rs index a329821..cb1a8fc 100644 --- a/src/metadata/mod.rs +++ b/src/metadata/mod.rs @@ -124,7 +124,7 @@ mod tests { "keys: { in: objects: [] - }" + }", ] .into_iter() .map(|example| example.to_string() + "\n") diff --git a/src/stage_1.rs b/src/stage_1.rs index 11621cd..e8bee14 100644 --- a/src/stage_1.rs +++ b/src/stage_1.rs @@ -60,8 +60,7 @@ pub fn stage_1() -> impl Parser, Error = chumsky::error::Si *c == '\n' || *c == '\r' || c.is_separator_line() || c.is_separator_paragraph() }); - let newline = parse_newline - .to(NorgToken::SingleNewline); + let newline = parse_newline.to(NorgToken::SingleNewline); let newlines = parse_newline .repeated() diff --git a/src/stage_4.rs b/src/stage_4.rs index ed08eea..2f3d215 100644 --- a/src/stage_4.rs +++ b/src/stage_4.rs @@ -260,52 +260,47 @@ pub fn stage_4(flat: Vec) -> Vec { name, parameters, next_object, - } => { - match *next_object.clone() { - NorgASTFlat::Heading { - level, - title, - extensions, - } => { - let content = consume_heading_content(&level, &flat, &mut i); - ast.push(NorgAST::CarryoverTag { - tag_type: tag_type.clone(), - name: name.to_vec(), - parameters: parameters.to_vec(), - next_object: Box::new(NorgAST::Heading { - level, - title, - extensions, - content, - }), - }) - } - NorgASTFlat::NestableDetachedModifier { - modifier_type, - level, - extensions, - content, - } => { - let new_content = - consume_nestable_detached_mod_content(&level, &flat, &mut i); - ast.push(NorgAST::CarryoverTag { - tag_type: tag_type.clone(), - name: name.to_vec(), - parameters: parameters.to_vec(), - next_object: Box::new(NorgAST::NestableDetachedModifier { - modifier_type, - level, - extensions, - text: content, - content: new_content, - }), - }) - } - _ => { - ast.push(convert(item.clone())) - } + } => match *next_object.clone() { + NorgASTFlat::Heading { + level, + title, + extensions, + } => { + let content = consume_heading_content(&level, &flat, &mut i); + ast.push(NorgAST::CarryoverTag { + tag_type: tag_type.clone(), + name: name.to_vec(), + parameters: parameters.to_vec(), + next_object: Box::new(NorgAST::Heading { + level, + title, + extensions, + content, + }), + }) } - } + NorgASTFlat::NestableDetachedModifier { + modifier_type, + level, + extensions, + content, + } => { + let new_content = consume_nestable_detached_mod_content(&level, &flat, &mut i); + ast.push(NorgAST::CarryoverTag { + tag_type: tag_type.clone(), + name: name.to_vec(), + parameters: parameters.to_vec(), + next_object: Box::new(NorgAST::NestableDetachedModifier { + modifier_type, + level, + extensions, + text: content, + content: new_content, + }), + }) + } + _ => ast.push(convert(item.clone())), + }, NorgASTFlat::NestableDetachedModifier { level: start_level, modifier_type, From d7111990567d52f1b9219000ec8fb1ba2b8472f9 Mon Sep 17 00:00:00 2001 From: hardfau1t Date: Thu, 11 Sep 2025 16:00:32 +0530 Subject: [PATCH 14/14] ci(rust): cargo clippy command fixed --- .github/workflows/rust.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index ce321a9..4b24d02 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -17,7 +17,7 @@ jobs: - name: format check run: cargo fmt --check - name: clippy check - run: cargo clippy --check + run: cargo clippy - name: Build run: cargo build --verbose - name: Run tests