From 6f49ee0bc8362ed8e251c7c6c4607e9350285b14 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Mon, 13 Apr 2026 00:05:29 +0000 Subject: [PATCH 1/6] chore(deps): lock file maintenance --- Cargo.lock | 28 ++++++++++++++-------------- flake.lock | 24 ++++++++++++------------ 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8f34603..8fb1027 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -135,9 +135,9 @@ checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" [[package]] name = "cc" -version = "1.2.59" +version = "1.2.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7a4d3ec6524d28a329fc53654bbadc9bdd7b0431f5d65f1a56ffb28a1ee5283" +checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20" dependencies = [ "find-msvc-tools", "shlex", @@ -432,9 +432,9 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "js-sys" -version = "0.3.94" +version = "0.3.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9" +checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca" dependencies = [ "once_cell", "wasm-bindgen", @@ -454,9 +454,9 @@ checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" [[package]] name = "libredox" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ddbf48fd451246b1f8c2610bd3b4ac0cc6e149d89832867093ab69a17194f08" +checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" dependencies = [ "libc", ] @@ -1016,9 +1016,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.117" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0" +checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89" dependencies = [ "cfg-if", "once_cell", @@ -1029,9 +1029,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.117" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86be" +checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1039,9 +1039,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.117" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2" +checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904" dependencies = [ "bumpalo", "proc-macro2", @@ -1052,9 +1052,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.117" +version = "0.2.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39129a682a6d2d841b6c429d0c51e5cb0ed1a03829d8b3d1e69a011e62cb3d3b" +checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129" dependencies = [ "unicode-ident", ] diff --git a/flake.lock b/flake.lock index 009c465..0c44fe5 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "crane": { "locked": { - "lastModified": 1775236976, - "narHash": "sha256-gCgX+AXN7K1gAIEqcLcZHxmC+QoZcwn9m6Z9r2Az+N8=", + "lastModified": 1775839657, + "narHash": "sha256-SPm9ck7jh3Un9nwPuMGbRU04UroFmOHjLP56T10MOeM=", "owner": "ipetkov", "repo": "crane", - "rev": "6c23998526351a53ce734f0ac84940da988ccef1", + "rev": "7cf72d978629469c4bd4206b95c402514c1f6000", "type": "github" }, "original": { @@ -40,11 +40,11 @@ ] }, "locked": { - "lastModified": 1775036584, - "narHash": "sha256-zW0lyy7ZNNT/x8JhzFHBsP2IPx7ATZIPai4FJj12BgU=", + "lastModified": 1775585728, + "narHash": "sha256-8Psjt+TWvE4thRKktJsXfR6PA/fWWsZ04DVaY6PUhr4=", "owner": "cachix", "repo": "git-hooks.nix", - "rev": "4e0eb042b67d863b1b34b3f64d52ceb9cd926735", + "rev": "580633fa3fe5fc0379905986543fd7495481913d", "type": "github" }, "original": { @@ -76,11 +76,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1775036866, - "narHash": "sha256-ZojAnPuCdy657PbTq5V0Y+AHKhZAIwSIT2cb8UgAz/U=", + "lastModified": 1775710090, + "narHash": "sha256-ar3rofg+awPB8QXDaFJhJ2jJhu+KqN/PRCXeyuXR76E=", "owner": "nixos", "repo": "nixpkgs", - "rev": "6201e203d09599479a3b3450ed24fa81537ebc4e", + "rev": "4c1018dae018162ec878d42fec712642d214fdfa", "type": "github" }, "original": { @@ -105,11 +105,11 @@ ] }, "locked": { - "lastModified": 1775358767, - "narHash": "sha256-f2eC+WIfhjevCPQILuV08i/kmKZzYZpUvkom/33VxCA=", + "lastModified": 1775963625, + "narHash": "sha256-OmwF0Rd/HDbEGC0ZcBS2jPMvmCcn3HDqUypjXrR7KfM=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "20fd44bc663daa53a2575e01293e24e681d62244", + "rev": "573a61faa8ec910a6b8576cc3c145844245574f3", "type": "github" }, "original": { From e15e6f105313dc373650ad6a51a3390b4921c296 Mon Sep 17 00:00:00 2001 From: Konstantin Fickel Date: Mon, 13 Apr 2026 19:26:09 +0200 Subject: [PATCH 2/6] fix: broken tasks extraction --- src/extract/parser.rs | 68 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 62 insertions(+), 6 deletions(-) diff --git a/src/extract/parser.rs b/src/extract/parser.rs index 1326371..b1d0374 100644 --- a/src/extract/parser.rs +++ b/src/extract/parser.rs @@ -12,6 +12,8 @@ struct BlockInfo { end_line: usize, block_type: BlockType, events: Vec>, + /// Nested list items contained within this block (for ListItem blocks with sub-lists). + nested_items: Vec, } #[derive(Debug, Clone, PartialEq)] @@ -110,12 +112,14 @@ pub fn parse_markdown_file(file_name: &str, file_content: &str) -> StreamFile { fn collect_blocks(content: &str, parser: Parser) -> Vec { let mut blocks = Vec::new(); let mut current_block: Option = None; - let _current_events: Vec> = Vec::new(); let mut depth = 0; let mut list_items: Vec = Vec::new(); let mut in_list = false; let mut list_start_line = 0; + // Stack for nested lists: (saved current_block, saved list_items, saved list_start_line) + let mut list_nesting_stack: Vec<(Option, Vec, usize)> = Vec::new(); + // Pre-compute line starts for offset-to-line mapping let line_starts: Vec = std::iter::once(0) .chain(content.match_indices('\n').map(|(i, _)| i + 1)) @@ -135,6 +139,7 @@ fn collect_blocks(content: &str, parser: Parser) -> Vec { end_line: line, block_type: BlockType::Paragraph, events: Vec::new(), + nested_items: Vec::new(), }); } depth += 1; @@ -166,6 +171,7 @@ fn collect_blocks(content: &str, parser: Parser) -> Vec { end_line: line, block_type: BlockType::Heading(heading_level), events: Vec::new(), + nested_items: Vec::new(), }); } depth += 1; @@ -186,7 +192,15 @@ fn collect_blocks(content: &str, parser: Parser) -> Vec { } } Event::Start(Tag::List(_)) => { - if !in_list { + if in_list { + // Entering a nested list: save current list item and collected items + list_nesting_stack.push(( + current_block.take(), + std::mem::take(&mut list_items), + list_start_line, + )); + list_start_line = line; + } else { in_list = true; list_start_line = line; list_items.clear(); @@ -195,7 +209,18 @@ fn collect_blocks(content: &str, parser: Parser) -> Vec { } Event::End(TagEnd::List(_)) => { depth -= 1; - if depth == 0 && in_list { + if let Some((parent_block, parent_items, parent_start_line)) = + list_nesting_stack.pop() + { + // Nested list ended: attach collected items as nested children of parent item + let nested = std::mem::take(&mut list_items); + list_start_line = parent_start_line; + list_items = parent_items; + current_block = parent_block.map(|mut item| { + item.nested_items = nested; + item + }); + } else if depth == 0 && in_list { in_list = false; // Create a list block containing all list items if !list_items.is_empty() { @@ -204,6 +229,7 @@ fn collect_blocks(content: &str, parser: Parser) -> Vec { end_line: line, block_type: BlockType::List, events: vec![], // List events are handled through list_items + nested_items: vec![], }); // Store list items for later processing for item in list_items.drain(..) { @@ -222,6 +248,7 @@ fn collect_blocks(content: &str, parser: Parser) -> Vec { end_line: line, block_type: BlockType::ListItem, events: Vec::new(), + nested_items: Vec::new(), }); } } @@ -240,6 +267,7 @@ fn collect_blocks(content: &str, parser: Parser) -> Vec { end_line: line, block_type: BlockType::CodeBlock, events: Vec::new(), + nested_items: Vec::new(), }); } depth += 1; @@ -507,13 +535,21 @@ fn parse_single_block_shard( } } BlockType::List | BlockType::ListItem => { - // List handling is complex - for now, extract any markers/tags let (markers, tags) = extract_block_markers_and_tags(block); - if markers.is_empty() { + // Recursively build child shards from nested list items + let children: Vec = block + .nested_items + .iter() + .filter_map(|item| { + let (child, _) = parse_single_block_shard(item, item.start_line, item.end_line); + child + }) + .collect(); + if markers.is_empty() && children.is_empty() { (None, tags) } else { ( - Some(build_shard(start_line, end_line, markers, tags, vec![])), + Some(build_shard(start_line, end_line, markers, tags, children)), vec![], ) } @@ -716,6 +752,26 @@ mod tests { ); } + #[test] + fn test_parse_nested_list_creates_three_shards() { + let content = "* @Task 1\n * @Task 2\n* @Task 3"; + let result = parse_markdown_file(&make_file_name(), content); + let root = result.shard.unwrap(); + // The root shard should have two top-level children: @Task 1 and @Task 3 + assert_eq!(root.children.len(), 2, "expected 2 top-level shards"); + let task1 = &root.children[0]; + let task3 = &root.children[1]; + // @Task 1 must carry its marker and contain @Task 2 as a child + assert_eq!(task1.markers, vec!["Task"], "@Task 1 marker"); + assert_eq!(task1.children.len(), 1, "@Task 1 should have one child"); + let task2 = &task1.children[0]; + assert_eq!(task2.markers, vec!["Task"], "@Task 2 marker"); + assert!(task2.children.is_empty(), "@Task 2 should have no children"); + // @Task 3 is a sibling of @Task 1 + assert_eq!(task3.markers, vec!["Task"], "@Task 3 marker"); + assert!(task3.children.is_empty(), "@Task 3 should have no children"); + } + #[test] fn test_parse_continues_looking_for_markers_after_first_link_marker() { let result = parse_markdown_file( From b653590c366a818b4781b41bd0aff11f1f80db50 Mon Sep 17 00:00:00 2001 From: Konstantin Fickel Date: Mon, 13 Apr 2026 19:30:59 +0200 Subject: [PATCH 3/6] feat(localize): extract file_type from filename prefix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add `extract_file_type_from_file_name` to parse prefixes like `_daily` from filenames (e.g. `20260412-123456_daily.md` → `"daily"`). Insert the result into `initial_location` in `localize_stream_file` so all localized shards carry a `file_type` dimension value. Also register the `file_type` dimension in `TaskConfiguration` so the propagation contract is documented. --- src/localize/datetime.rs | 72 +++++++++++++++++++++++++++++++++++ src/localize/mod.rs | 2 +- src/localize/preconfigured.rs | 6 +++ src/localize/shard.rs | 8 +++- 4 files changed, 86 insertions(+), 2 deletions(-) diff --git a/src/localize/datetime.rs b/src/localize/datetime.rs index 9f6d2ec..f5fd601 100644 --- a/src/localize/datetime.rs +++ b/src/localize/datetime.rs @@ -9,6 +9,11 @@ use std::path::Path; static FILE_NAME_REGEX: Lazy = Lazy::new(|| Regex::new(r"^(?P\d{8})(?:-(?P