Citation dialog: stricter cleanup of search value (#5185)

* citation dlg: cleaner search value

Additional cleanup of the search value to not include
some punctuation ("(),.;:"), localized "and",
ampersand, and localized "et al". That way, if one
copies a citation like "(Smith et al., 2020)" and pastes it into the
citation dialog, it is more likely that appropriate search
results will appear.

Fixes: #1864

* handle citations with locators

Clean the input before fetching the locator so that
if one copies and pastes (Smith et al., 2025, p. 15),
the locator is still correctly extracted.
This commit is contained in:
abaevbog 2025-04-08 20:56:20 -07:00 • committed by GitHub
parent b0b9442c95
commit 4fc7730181
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 16 additions and 7 deletions

View file

@ -312,7 +312,7 @@ class Layout {
while (!this.itemsView.collectionTreeRow) {
await Zotero.Promise.delay(10);
}
await this.itemsView.setFilter('citation-search', value);
await this.itemsView.setFilter('citation-search', SearchHandler.searchValue);
}
SearchHandler.searching = false;
@ -1024,7 +1024,8 @@ const IOManager = {
// If the last input has a locator, add it into the item
let input = _id("bubble-input").getCurrentInput();
let locator = Helpers.extractLocator(input.value || "");
let inputValue = SearchHandler.cleanSearchQuery(input?.value || "");
let locator = Helpers.extractLocator(inputValue);
// If there is no locator, make sure we clear it from the citation item
for (let item of items) {
item.label = locator?.label || null;
@ -1312,6 +1313,7 @@ const IOManager = {
},
_handleInput({ query, eventType }) {
query = SearchHandler.cleanSearchQuery(query);
// If there is a locator typed, exclude it from the query
let locator = Helpers.extractLocator(query);
if (locator) {
@ -1319,7 +1321,7 @@ const IOManager = {
}
// Do not rerun search if the search value is the same
// (e.g. focus returns into the last input)
if (SearchHandler.cleanSearchQuery(query) == SearchHandler.searchValue) {
if (query == SearchHandler.searchValue) {
return;
}
currentLayout.search(query, { skipDebounce: eventType == "focus" });

View file

@ -209,19 +209,19 @@ export class CitationDialogHelpers {
// Check if this word has a locator label in its full or short form (e.g. "line" or "l" or "l.")
// If a locator string is found, check if the string without it is a valid locator value.
if (potentialLocatorValue.startsWith(fullLocator)) {
if (potentialLocatorValue.toLowerCase().startsWith(fullLocator)) {
// e.g. 'US history chapter "one and two" '
locatorLabelString = fullLocator;
// potential locator value: "one and two"
potentialLocatorValue = potentialLocatorValue.substring(fullLocator.length).trim();
}
else if (potentialLocatorValue.startsWith(shortLocator)) {
else if (potentialLocatorValue.toLowerCase().startsWith(shortLocator)) {
// e.g. 'US history chapt."one and two" '
locatorLabelString = shortLocator;
// potential locator value: "one and two"
potentialLocatorValue = potentialLocatorValue.substring(shortLocator.length).trim();
}
else if (potentialLocatorValue.startsWith(shortLocatorNoPunctuation)) {
else if (potentialLocatorValue.toLowerCase().startsWith(shortLocatorNoPunctuation)) {
// e.g. 'US history chapt11-12 '
locatorLabelString = shortLocatorNoPunctuation;
// potential locator value: 11-12

View file

@ -194,7 +194,14 @@ export class CitationDialogSearchHandler {
}
cleanSearchQuery(str) {
str = str.replace(/ (?:&|and) /g, " ", "g").replace(/^,/, '');
// Remove brackets, some punctuation, "et al", and localized "and" from the search string.
// This allows one to paste an existing citation like "(Smith et al., 2020)" and
// still get appropriate search results.
str = str.replace(/[()]/g, '').replace(/[&,.:;]/g, '');
str = str.replace(" " + Zotero.getString("general.and") + " ", " ");
let etAl = Zotero.getString("general.etAl").replace(/\./g, "");
str = str.replace(new RegExp(" " + etAl + "(?:.\\s*|\\s+|$)", "g"), " ");
let isbn = Zotero.Utilities.cleanISBN(str);
let doi = Zotero.Utilities.cleanDOI(str);
// if the string looks like an identifier, do not try to extract the year