From 4fc7730181679b8b26cf516f1af605826940ea01 Mon Sep 17 00:00:00 2001 From: abaevbog Date: Tue, 8 Apr 2025 20:56:20 -0700 Subject: [PATCH] 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. --- chrome/content/zotero/integration/citationDialog.js | 8 +++++--- .../zotero/integration/citationDialog/helpers.mjs | 6 +++--- .../zotero/integration/citationDialog/searchHandler.mjs | 9 ++++++++- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/chrome/content/zotero/integration/citationDialog.js b/chrome/content/zotero/integration/citationDialog.js index d7f8922825..7cde71b937 100644 --- a/chrome/content/zotero/integration/citationDialog.js +++ b/chrome/content/zotero/integration/citationDialog.js @@ -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" }); diff --git a/chrome/content/zotero/integration/citationDialog/helpers.mjs b/chrome/content/zotero/integration/citationDialog/helpers.mjs index 6e226f949d..b5d4317b00 100644 --- a/chrome/content/zotero/integration/citationDialog/helpers.mjs +++ b/chrome/content/zotero/integration/citationDialog/helpers.mjs @@ -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 diff --git a/chrome/content/zotero/integration/citationDialog/searchHandler.mjs b/chrome/content/zotero/integration/citationDialog/searchHandler.mjs index 84ba31c25d..8aac1d1958 100644 --- a/chrome/content/zotero/integration/citationDialog/searchHandler.mjs +++ b/chrome/content/zotero/integration/citationDialog/searchHandler.mjs @@ -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