diff --git a/dist/obsidian-omnisearch-google.user.js b/dist/obsidian-omnisearch-google.user.js index d888638..7078d98 100644 --- a/dist/obsidian-omnisearch-google.user.js +++ b/dist/obsidian-omnisearch-google.user.js @@ -58,21 +58,45 @@ isInit(); }); // Obsidian logo - const logo = ` + const logo = ` `; + + + /** + * Highlights keywords within a text string using the tag. + * Follows SOLID by separating the formatting logic. + */ + function highlightText(text, words) { + if (!words || words.length === 0) return text; + + // Sort words by length descending to prevent partial replacements (e.g., 'plugin' before 'plugins') + const sortedWords = [...new Set(words)].sort((a, b) => b.length - a.length); + + let highlighted = text; + for (const word of sortedWords) { + // Escape special regex characters in the word + const escapedWord = word.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + // Use word boundaries \b to ensure we don't mark inside HTML tags or partial matches incorrectly + const regex = new RegExp(`\\b(${escapedWord})\\b`, 'gi'); + highlighted = highlighted.replace(regex, '$1'); + } + return highlighted; + } + function omnisearch() { const port = gmc.get("port"); const nbResults = gmc.get("nbResults"); // Extract the ?q= part of the URL with URLSearchParams const params = new URLSearchParams(window.location.search); const query = params.get("q"); - if (!query) + if (!query){ return; + } injectLoadingLabel(); GM.xmlHttpRequest({ method: "GET", @@ -87,58 +111,59 @@ data.splice(nbResults); const resultsDiv = $(`#${resultsDivId}`); // Delete all existing data-omnisearch-result + resultsDiv.empty(); $("[data-omnisearch-result]").remove(); // Inject results for (const item of data) { const url = `obsidian://open?vault=${encodeURIComponent(item.vault)}&file=${encodeURIComponent(item.path)}`; + + // Prepare highlighted excerpt + const cleanExcerpt = item.excerpt.replaceAll("
", " ").replaceAll("
", " "); + const highlightedExcerpt = highlightText(cleanExcerpt, item.foundWords); + const element = $(`
-
-
-
-
-
- -
-

${item.basename}

-
-
- - - - - `); + `); resultsDiv.append(element); } }, @@ -147,7 +172,8 @@ const span = $("#" + loadingSpanId)[0]; if (span) { span.innerHTML = `Error: Obsidian is not running or the Omnisearch server is not enabled. -
Open Obsidian.`; +
+ Open Obsidian.`; } }, }); @@ -155,19 +181,27 @@ function injectTitle() { const id = "OmnisearchObsidianConfig"; if (!$("#" + id)[0]) { - const btn = $(`
- ${logo} Omnisearch results + const btn = $(`${logo} + Omnisearch results () -
`); - $(`#${resultsDivId}`).append(btn); - $(document).on("click", "#" + id, function () { + `); + $(`#OmnisearchHeader`).append(btn); + $(document).on("click", "#" + id, function (e) { + e.preventDefault(); // Prevent collapse when clicking settings gmc.open(); }); } } function injectResultsContainer() { - const resultsDiv = $(`
`); - $(sidebarSelector).prepend(resultsDiv); + const resultsDetailsSummary = $(` +
+ + + +
+
+ `); + $(sidebarSelector).prepend(resultsDetailsSummary); } function injectLoadingLabel() { if (!$("#" + loadingSpanId)[0]) { @@ -178,8 +212,7 @@ function removeLoadingLabel(foundResults = true) { if (foundResults) { $("#" + loadingSpanId).remove(); - } - else { + } else { $("#" + loadingSpanId).text("No results found"); } }