Skip to content

Commit a291551

Browse files
authored
Merge pull request #70 from deyak360/preselect-matching-aliases-66
Fix overlapping title/alias matching and fix alias pre-selection in UI
2 parents 6cc87a6 + ae6cd6b commit a291551

File tree

3 files changed

+58
-16
lines changed

3 files changed

+58
-16
lines changed

src/rs/matching/link_finder.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ fn build_link_finder(target_note: &Note) -> LinkFinder {
7777
let escaped_title = escape(&*target_note.title()).to_string();
7878
escaped_search_strings.push(escaped_title);
7979

80+
// Sort by length (desc) to prioritize longer matches when alternatives overlap
81+
escaped_search_strings.sort_by(|a, b| b.len().cmp(&a.len()));
82+
8083
let regex_string = concat_as_regex_string(&escaped_search_strings);
8184
//log(&format!("Regex string: {}", regex_string));
8285

@@ -101,14 +104,23 @@ fn find_link_matches(target_note: &Note, note_to_check: &mut Note) -> Option<Vec
101104
/// If the link match is already in the list, it is merged with the existing link match.
102105
/// If the link match is not in the list, it is added to the list.
103106
fn merge_link_match_into_link_matches(mut merged_link_matches: Vec<LinkMatch>, link_match: LinkMatch) -> Vec<LinkMatch> {
107+
// Find an existing match that starts at the same character position
104108
let index = merged_link_matches.iter()
105-
.position(|m: &LinkMatch| m.position().is_equal_to(&link_match.position()));
109+
.position(|m: &LinkMatch| m.position().start() == link_match.position().start());
106110

107111
if let Some(index) = index {
108-
// merge it into the existing match, if the position is the same
109-
merged_link_matches[index].merge_link_target_candidates(link_match);
112+
// For same-start matches, prefer the one that covers more characters
113+
if link_match.position().end() > merged_link_matches[index].position().end() {
114+
// New match is longer: make it the primary span and pull in old candidates
115+
let mut new_link_match = link_match;
116+
new_link_match.merge_link_target_candidates(merged_link_matches[index].clone());
117+
merged_link_matches[index] = new_link_match;
118+
} else {
119+
// Existing match is longer or equal: keep its span, just add new candidates
120+
merged_link_matches[index].merge_link_target_candidates(link_match);
121+
}
110122
} else {
111-
// otherwise push a new match
123+
// No same-start match yet: add as a new entry
112124
merged_link_matches.push(link_match);
113125
}
114126
merged_link_matches

src/rs/matching/link_match.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ impl LinkMatch {
5252
target_note.title(),
5353
target_note.path(),
5454
target_note.aliases_vec(),
55-
regex_match.capture_index
55+
&regex_match.matched_text
5656
)];
5757
Self::new(
5858
regex_match.position.clone(),

src/rs/matching/link_target_candidate.rs

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use js_sys::Array;
2+
use std::collections::HashSet;
23
use serde::{Deserialize, Serialize};
34
use wasm_bindgen::prelude::*;
45

@@ -37,20 +38,49 @@ impl LinkTargetCandidate {
3738
}
3839

3940
impl LinkTargetCandidate {
40-
pub fn new(title: String, path: String, aliases: &[String], selected_index: usize) -> Self {
41+
pub fn new(title: String, path: String, aliases: &[String], matched_text: &str) -> Self {
42+
let mut seen_candidates: HashSet<String> = HashSet::new();
4143
let mut _replacement_candidates: Vec<PreferrableItem> = vec![];
42-
let replacement_candidate_title = PreferrableItem::new(title.clone(), true);
43-
_replacement_candidates.push(replacement_candidate_title);
44-
45-
aliases.iter().enumerate().for_each(|(index, alias)| {
46-
let replacement_candidate_alias = PreferrableItem::new(
47-
alias.clone(),
48-
// add one because the index starts with the title at 0
49-
true,
50-
);
44+
45+
let mut case_sensitive_match_index: Option<usize> = None;
46+
let mut case_insensitive_match_index: Option<usize> = None;
47+
48+
seen_candidates.insert(title.clone());
49+
_replacement_candidates.push(PreferrableItem::new(title.clone(), false));
50+
if title == matched_text {
51+
case_sensitive_match_index = Some(0);
52+
} else if title.eq_ignore_ascii_case(matched_text) {
53+
case_insensitive_match_index = Some(0);
54+
}
55+
56+
aliases.iter().for_each(|alias| {
57+
if seen_candidates.contains(alias) {
58+
return;
59+
}
60+
61+
let candidate_index = _replacement_candidates.len();
62+
63+
if alias == matched_text && case_sensitive_match_index.is_none() {
64+
case_sensitive_match_index = Some(candidate_index);
65+
} else if alias.eq_ignore_ascii_case(matched_text)
66+
&& case_insensitive_match_index.is_none()
67+
{
68+
case_insensitive_match_index = Some(candidate_index);
69+
}
70+
71+
seen_candidates.insert(alias.clone());
72+
let replacement_candidate_alias = PreferrableItem::new(alias.clone(), false);
5173
_replacement_candidates.push(replacement_candidate_alias);
5274
});
5375

76+
let preferred_index = case_sensitive_match_index
77+
.or(case_insensitive_match_index)
78+
.unwrap_or(0);
79+
80+
if let Some(preferred_candidate) = _replacement_candidates.get_mut(preferred_index) {
81+
preferred_candidate.is_preferred = true;
82+
}
83+
5484
LinkTargetCandidate {
5585
title,
5686
path,
@@ -65,4 +95,4 @@ pub fn link_target_candidate_vec_into_array(link_target_candidates: Vec<LinkTarg
6595
link_target_candidates_array.push(&link_target_candidate.into());
6696
}
6797
link_target_candidates_array
68-
}
98+
}

0 commit comments

Comments
 (0)