fix: apply state.xxx pattern and exports to regenerated modules
All checks were successful
CI / lint (push) Successful in 11s
CI / security (push) Successful in 17s
CI / test (push) Successful in 15s
CI / build (push) Successful in 3s

This commit is contained in:
Bruno Charest 2026-05-28 16:50:06 -04:00
parent 6d36b53b3a
commit 97d14d867a
3 changed files with 157 additions and 157 deletions

View File

@ -1,12 +1,12 @@
/* ObsiGate — Auto-extracted module */ /* ObsiGate — Auto-extracted module */
import { state } from './state.js'; import { state } from './state.js';;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Search History Service (localStorage, LIFO, max 50, dedup) // Search History Service (localStorage, LIFO, max 50, dedup)
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
const SearchHistory = { const SearchHistory = {
_load() { _load() {
try { try {
const raw = localStorage.getItem(SEARCH_HISTORY_KEY); const raw = localStorage.getItem(state.SEARCH_HISTORY_KEY);
return raw ? JSON.parse(raw) : []; return raw ? JSON.parse(raw) : [];
} catch { } catch {
return []; return [];
@ -14,7 +14,7 @@ const SearchHistory = {
}, },
_save(entries) { _save(entries) {
try { try {
localStorage.setItem(SEARCH_HISTORY_KEY, JSON.stringify(entries)); localStorage.setItem(state.SEARCH_HISTORY_KEY, JSON.stringify(entries));
} catch {} } catch {}
}, },
getAll() { getAll() {
@ -25,7 +25,7 @@ const SearchHistory = {
const q = query.trim(); const q = query.trim();
let entries = this._load().filter((e) => e !== q); let entries = this._load().filter((e) => e !== q);
entries.unshift(q); entries.unshift(q);
if (entries.length > MAX_HISTORY_ENTRIES) entries = entries.slice(0, MAX_HISTORY_ENTRIES); if (entries.length > state.MAX_HISTORY_ENTRIES) entries = entries.slice(0, state.MAX_HISTORY_ENTRIES);
this._save(entries); this._save(entries);
}, },
remove(query) { remove(query) {
@ -167,8 +167,8 @@ const AutocompleteDropdown = {
hide() { hide() {
if (this._dropdown) this._dropdown.hidden = true; if (this._dropdown) this._dropdown.hidden = true;
dropdownActiveIndex = -1; state.dropdownActiveIndex = -1;
dropdownItems = []; state.dropdownItems = [];
}, },
isVisible() { isVisible() {
@ -179,9 +179,9 @@ const AutocompleteDropdown = {
async populate(inputValue, cursorPos) { async populate(inputValue, cursorPos) {
if (this._suppressNext) { this._suppressNext = false; return; } if (this._suppressNext) { this._suppressNext = false; return; }
// Cancel previous suggestion request // Cancel previous suggestion request
if (suggestAbortController) { if (state.suggestAbortController) {
suggestAbortController.abort(); state.suggestAbortController.abort();
suggestAbortController = null; state.suggestAbortController = null;
} }
const ctx = QueryParser.getContext(inputValue, cursorPos); const ctx = QueryParser.getContext(inputValue, cursorPos);
@ -228,10 +228,10 @@ const AutocompleteDropdown = {
}, },
async _fetchSuggestions(prefix, vault) { async _fetchSuggestions(prefix, vault) {
suggestAbortController = new AbortController(); state.suggestAbortController = new AbortController();
// Fetch titles // Fetch titles
try { try {
const titlesRes = await api(`/api/suggest?q=${encodeURIComponent(prefix)}&vault=${encodeURIComponent(vault)}&limit=5`, { signal: suggestAbortController.signal }); const titlesRes = await api(`/api/suggest?q=${encodeURIComponent(prefix)}&vault=${encodeURIComponent(vault)}&limit=5`, { signal: state.suggestAbortController.signal });
this._renderTitles(titlesRes.suggestions || [], prefix); this._renderTitles(titlesRes.suggestions || [], prefix);
this._titlesSection.hidden = !(titlesRes.suggestions || []).length; this._titlesSection.hidden = !(titlesRes.suggestions || []).length;
if (titlesRes.suggestions?.length) this.show(); if (titlesRes.suggestions?.length) this.show();
@ -241,7 +241,7 @@ const AutocompleteDropdown = {
} }
// Fetch tags — keep section always visible to confirm it works // Fetch tags — keep section always visible to confirm it works
try { try {
const tagsRes = await api(`/api/tags/suggest?q=${encodeURIComponent(prefix)}&vault=${encodeURIComponent(vault)}&limit=5`, { signal: suggestAbortController.signal }); const tagsRes = await api(`/api/tags/suggest?q=${encodeURIComponent(prefix)}&vault=${encodeURIComponent(vault)}&limit=5`, { signal: state.suggestAbortController.signal });
const items = tagsRes.suggestions || []; const items = tagsRes.suggestions || [];
if (items.length > 0) { if (items.length > 0) {
this._renderTags(items, prefix); this._renderTags(items, prefix);
@ -363,30 +363,30 @@ const AutocompleteDropdown = {
}, },
_collectItems() { _collectItems() {
dropdownItems = Array.from(this._dropdown.querySelectorAll(".search-dropdown__item")); state.dropdownItems = Array.from(this._dropdown.querySelectorAll(".search-dropdown__item"));
dropdownActiveIndex = -1; state.dropdownActiveIndex = -1;
dropdownItems.forEach((item) => item.classList.remove("active")); state.dropdownItems.forEach((item) => item.classList.remove("active"));
}, },
navigateDown() { navigateDown() {
if (!this.isVisible() || dropdownItems.length === 0) return; if (!this.isVisible() || state.dropdownItems.length === 0) return;
if (dropdownActiveIndex >= 0) dropdownItems[dropdownActiveIndex].classList.remove("active"); if (dropdownActiveIndex >= 0) state.dropdownItems[state.dropdownActiveIndex].classList.remove("active");
dropdownActiveIndex = (dropdownActiveIndex + 1) % dropdownItems.length; state.dropdownActiveIndex = (dropdownActiveIndex + 1) % state.dropdownItems.length;
dropdownItems[dropdownActiveIndex].classList.add("active"); state.dropdownItems[state.dropdownActiveIndex].classList.add("active");
dropdownItems[dropdownActiveIndex].scrollIntoView({ block: "nearest" }); state.dropdownItems[state.dropdownActiveIndex].scrollIntoView({ block: "nearest" });
}, },
navigateUp() { navigateUp() {
if (!this.isVisible() || dropdownItems.length === 0) return; if (!this.isVisible() || state.dropdownItems.length === 0) return;
if (dropdownActiveIndex >= 0) dropdownItems[dropdownActiveIndex].classList.remove("active"); if (dropdownActiveIndex >= 0) state.dropdownItems[state.dropdownActiveIndex].classList.remove("active");
dropdownActiveIndex = dropdownActiveIndex <= 0 ? dropdownItems.length - 1 : dropdownActiveIndex - 1; state.dropdownActiveIndex = dropdownActiveIndex <= 0 ? state.dropdownItems.length - 1 : dropdownActiveIndex - 1;
dropdownItems[dropdownActiveIndex].classList.add("active"); state.dropdownItems[state.dropdownActiveIndex].classList.add("active");
dropdownItems[dropdownActiveIndex].scrollIntoView({ block: "nearest" }); state.dropdownItems[state.dropdownActiveIndex].scrollIntoView({ block: "nearest" });
}, },
selectActive() { selectActive() {
if (dropdownActiveIndex >= 0 && dropdownActiveIndex < dropdownItems.length) { if (dropdownActiveIndex >= 0 && dropdownActiveIndex < state.dropdownItems.length) {
dropdownItems[dropdownActiveIndex].click(); state.dropdownItems[state.dropdownActiveIndex].click();
return true; return true;
} }
return false; return false;
@ -460,8 +460,8 @@ const SearchChips = {
function _triggerAdvancedSearch(rawQuery) { function _triggerAdvancedSearch(rawQuery) {
const q = (rawQuery || "").trim(); const q = (rawQuery || "").trim();
const vault = document.getElementById("vault-filter").value; const vault = document.getElementById("vault-filter").value;
const tagFilter = selectedTags.length > 0 ? selectedTags.join(",") : null; const tagFilter = state.selectedTags.length > 0 ? state.selectedTags.join(",") : null;
advancedSearchOffset = 0; state.advancedSearchOffset = 0;
if (q.length > 0 || tagFilter) { if (q.length > 0 || tagFilter) {
SearchHistory.add(q); SearchHistory.add(q);
performAdvancedSearch(q, vault, tagFilter); performAdvancedSearch(q, vault, tagFilter);
@ -490,17 +490,17 @@ function initSearch() {
const countEl = document.getElementById("search-match-count"); const countEl = document.getElementById("search-match-count");
function _updateToggleUI() { function _updateToggleUI() {
caseBtn.classList.toggle("active", searchCaseSensitive); caseBtn.classList.toggle("active", state.searchCaseSensitive);
wordBtn.classList.toggle("active", searchWholeWord); wordBtn.classList.toggle("active", state.searchWholeWord);
regexBtn.classList.toggle("active", searchRegex); regexBtn.classList.toggle("active", state.searchRegex);
filterBtn.classList.toggle("active", searchFilterVisible); filterBtn.classList.toggle("active", state.searchFilterVisible);
} }
// Toggle buttons // Toggle buttons
caseBtn.addEventListener("click", () => { searchCaseSensitive = !searchCaseSensitive; _updateToggleUI(); _research(); }); caseBtn.addEventListener("click", () => { state.searchCaseSensitive = !state.searchCaseSensitive; _updateToggleUI(); _research(); });
if (wordBtn) wordBtn.addEventListener("click", () => { searchWholeWord = !searchWholeWord; _updateToggleUI(); _research(); }); if (wordBtn) wordBtn.addEventListener("click", () => { state.searchWholeWord = !state.searchWholeWord; _updateToggleUI(); _research(); });
if (regexBtn) regexBtn.addEventListener("click", () => { searchRegex = !searchRegex; _updateToggleUI(); _research(); }); if (regexBtn) regexBtn.addEventListener("click", () => { state.searchRegex = !state.searchRegex; _updateToggleUI(); _research(); });
if (filterBtn) filterBtn.addEventListener("click", () => { searchFilterVisible = !searchFilterVisible; if (filterRow) filterRow.style.display = searchFilterVisible ? "flex" : "none"; _updateToggleUI(); }); if (filterBtn) filterBtn.addEventListener("click", () => { state.searchFilterVisible = !state.searchFilterVisible; if (filterRow) filterRow.style.display = searchFilterVisible ? "flex" : "none"; _updateToggleUI(); });
// ── Result navigation (up/down arrows + Enter) ── // ── Result navigation (up/down arrows + Enter) ──
let _searchResultIdx = -1; let _searchResultIdx = -1;
@ -536,11 +536,11 @@ function initSearch() {
function _research() { function _research() {
const q = input.value.trim(); const q = input.value.trim();
if (q.length >= _getEffective("min_query_length", 2)) { if (q.length >= _getEffective("min_query_length", 2)) {
clearTimeout(searchTimeout); clearTimeout(state.searchTimeout);
searchTimeout = setTimeout(() => { state.searchTimeout = setTimeout(() => {
const vault = document.getElementById("vault-filter").value; const vault = document.getElementById("vault-filter").value;
const tagFilter = selectedTags.length > 0 ? selectedTags.join(",") : null; const tagFilter = state.selectedTags.length > 0 ? state.selectedTags.join(",") : null;
advancedSearchOffset = 0; state.advancedSearchOffset = 0;
performAdvancedSearch(q, vault, tagFilter); performAdvancedSearch(q, vault, tagFilter);
}, _getEffective("debounce_ms", 300)); }, _getEffective("debounce_ms", 300));
} }
@ -572,14 +572,14 @@ function initSearch() {
AutocompleteDropdown.populate(input.value, input.selectionStart); AutocompleteDropdown.populate(input.value, input.selectionStart);
// Debounced search execution // Debounced search execution
clearTimeout(searchTimeout); clearTimeout(state.searchTimeout);
searchTimeout = setTimeout( state.searchTimeout = setTimeout(
() => { () => {
const q = input.value.trim(); const q = input.value.trim();
const vault = document.getElementById("vault-filter").value; const vault = document.getElementById("vault-filter").value;
const tagFilter = selectedTags.length > 0 ? selectedTags.join(",") : null; const tagFilter = state.selectedTags.length > 0 ? state.selectedTags.join(",") : null;
advancedSearchOffset = 0; state.advancedSearchOffset = 0;
if (q.length >= _getEffective("min_query_length", MIN_SEARCH_LENGTH) || tagFilter) { if (q.length >= _getEffective("min_query_length", state.MIN_SEARCH_LENGTH) || tagFilter) {
performAdvancedSearch(q, vault, tagFilter); performAdvancedSearch(q, vault, tagFilter);
} else if (q.length === 0) { } else if (q.length === 0) {
SearchChips.clear(); SearchChips.clear();
@ -630,10 +630,10 @@ function initSearch() {
const q = input.value.trim(); const q = input.value.trim();
if (q) { if (q) {
SearchHistory.add(q); SearchHistory.add(q);
clearTimeout(searchTimeout); clearTimeout(state.searchTimeout);
advancedSearchOffset = 0; state.advancedSearchOffset = 0;
const vault = document.getElementById("vault-filter").value; const vault = document.getElementById("vault-filter").value;
const tagFilter = selectedTags.length > 0 ? selectedTags.join(",") : null; const tagFilter = state.selectedTags.length > 0 ? state.selectedTags.join(",") : null;
performAdvancedSearch(q, vault, tagFilter); performAdvancedSearch(q, vault, tagFilter);
} }
e.preventDefault(); e.preventDefault();
@ -654,10 +654,10 @@ function initSearch() {
const q = input.value.trim(); const q = input.value.trim();
if (q) { if (q) {
SearchHistory.add(q); SearchHistory.add(q);
clearTimeout(searchTimeout); clearTimeout(state.searchTimeout);
advancedSearchOffset = 0; state.advancedSearchOffset = 0;
const vault = document.getElementById("vault-filter").value; const vault = document.getElementById("vault-filter").value;
const tagFilter = selectedTags.length > 0 ? selectedTags.join(",") : null; const tagFilter = state.selectedTags.length > 0 ? state.selectedTags.join(",") : null;
performAdvancedSearch(q, vault, tagFilter); performAdvancedSearch(q, vault, tagFilter);
} }
e.preventDefault(); e.preventDefault();
@ -667,9 +667,9 @@ function initSearch() {
clearBtn.addEventListener("click", () => { clearBtn.addEventListener("click", () => {
input.value = ""; input.value = "";
if (clearBtn) clearBtn.style.display = "none"; if (clearBtn) clearBtn.style.display = "none";
searchCaseSensitive = false; state.searchCaseSensitive = false;
searchWholeWord = false; state.searchWholeWord = false;
searchRegex = false; state.searchRegex = false;
_updateToggleUI(); _updateToggleUI();
SearchChips.clear(); SearchChips.clear();
AutocompleteDropdown.hide(); AutocompleteDropdown.hide();
@ -706,47 +706,47 @@ function _isInputFocused() {
// --- Backward-compatible search (existing /api/search endpoint) --- // --- Backward-compatible search (existing /api/search endpoint) ---
async function performSearch(query, vaultFilter, tagFilter) { async function performSearch(query, vaultFilter, tagFilter) {
if (searchAbortController) searchAbortController.abort(); if (state.searchAbortController) state.searchAbortController.abort();
searchAbortController = new AbortController(); state.searchAbortController = new AbortController();
const searchId = ++currentSearchId; const searchId = ++state.currentSearchId;
showLoading(); showLoading();
let url = `/api/search?q=${encodeURIComponent(query)}&vault=${encodeURIComponent(vaultFilter)}`; let url = `/api/search?q=${encodeURIComponent(query)}&vault=${encodeURIComponent(vaultFilter)}`;
if (tagFilter) url += `&tag=${encodeURIComponent(tagFilter)}`; if (tagFilter) url += `&tag=${encodeURIComponent(tagFilter)}`;
try { try {
const data = await api(url, { signal: searchAbortController.signal }); const data = await api(url, { signal: state.searchAbortController.signal });
if (searchId !== currentSearchId) return; if (searchId !== state.currentSearchId) return;
renderSearchResults(data, query, tagFilter); renderSearchResults(data, query, tagFilter);
} catch (err) { } catch (err) {
if (err.name === "AbortError") return; if (err.name === "AbortError") return;
if (searchId !== currentSearchId) return; if (searchId !== state.currentSearchId) return;
showWelcome(); showWelcome();
} finally { } finally {
hideProgressBar(); hideProgressBar();
if (searchId === currentSearchId) searchAbortController = null; if (searchId === state.currentSearchId) state.searchAbortController = null;
} }
} }
// --- Advanced search with TF-IDF, facets, pagination --- // --- Advanced search with TF-IDF, facets, pagination ---
async function performAdvancedSearch(query, vaultFilter, tagFilter, offset, sort) { async function performAdvancedSearch(query, vaultFilter, tagFilter, offset, sort) {
if (searchAbortController) searchAbortController.abort(); if (state.searchAbortController) state.searchAbortController.abort();
searchAbortController = new AbortController(); state.searchAbortController = new AbortController();
const searchId = ++currentSearchId; const searchId = ++state.currentSearchId;
showLoading(); showLoading();
const ofs = offset !== undefined ? offset : advancedSearchOffset; const ofs = offset !== undefined ? offset : state.advancedSearchOffset;
const sortBy = sort || advancedSearchSort; const sortBy = sort || state.advancedSearchSort;
advancedSearchLastQuery = query; state.advancedSearchLastQuery = query;
// Update chips from parsed query // Update chips from parsed query
const parsed = QueryParser.parse(query); const parsed = QueryParser.parse(query);
SearchChips.update(parsed); SearchChips.update(parsed);
const effectiveLimit = _getEffective("results_per_page", ADVANCED_SEARCH_LIMIT); const effectiveLimit = _getEffective("results_per_page", state.ADVANCED_SEARCH_LIMIT);
let url = `/api/search/advanced?q=${encodeURIComponent(query)}&vault=${encodeURIComponent(vaultFilter)}&limit=${effectiveLimit}&offset=${ofs}&sort=${sortBy}`; let url = `/api/search/advanced?q=${encodeURIComponent(query)}&vault=${encodeURIComponent(vaultFilter)}&limit=${effectiveLimit}&offset=${ofs}&sort=${sortBy}`;
if (tagFilter) url += `&tag=${encodeURIComponent(tagFilter)}`; if (tagFilter) url += `&tag=${encodeURIComponent(tagFilter)}`;
if (searchCaseSensitive) url += "&case_sensitive=true"; if (state.searchCaseSensitive) url += "&case_sensitive=true";
if (searchWholeWord) url += "&whole_word=true"; if (state.searchWholeWord) url += "&whole_word=true";
if (searchRegex) url += "&regex=true"; if (state.searchRegex) url += "&regex=true";
const includeEl = document.getElementById("search-include-input"); const includeEl = document.getElementById("search-include-input");
const excludeEl = document.getElementById("search-exclude-input"); const excludeEl = document.getElementById("search-exclude-input");
if (includeEl?.value.trim()) url += `&include_paths=${encodeURIComponent(includeEl.value.trim())}`; if (includeEl?.value.trim()) url += `&include_paths=${encodeURIComponent(includeEl.value.trim())}`;
@ -755,26 +755,26 @@ async function performAdvancedSearch(query, vaultFilter, tagFilter, offset, sort
// Search timeout — abort if server takes too long // Search timeout — abort if server takes too long
const timeoutId = setTimeout( const timeoutId = setTimeout(
() => { () => {
if (searchAbortController) searchAbortController.abort(); if (state.searchAbortController) state.searchAbortController.abort();
}, },
_getEffective("search_timeout_ms", SEARCH_TIMEOUT_MS), _getEffective("search_timeout_ms", state.SEARCH_TIMEOUT_MS),
); );
try { try {
const data = await api(url, { signal: searchAbortController.signal }); const data = await api(url, { signal: state.searchAbortController.signal });
clearTimeout(timeoutId); clearTimeout(timeoutId);
if (searchId !== currentSearchId) return; if (searchId !== state.currentSearchId) return;
advancedSearchTotal = data.total; state.advancedSearchTotal = data.total;
advancedSearchOffset = ofs; state.advancedSearchOffset = ofs;
renderAdvancedSearchResults(data, query, tagFilter); renderAdvancedSearchResults(data, query, tagFilter);
} catch (err) { } catch (err) {
clearTimeout(timeoutId); clearTimeout(timeoutId);
if (err.name === "AbortError") return; if (err.name === "AbortError") return;
if (searchId !== currentSearchId) return; if (searchId !== state.currentSearchId) return;
showWelcome(); showWelcome();
} finally { } finally {
hideProgressBar(); hideProgressBar();
if (searchId === currentSearchId) searchAbortController = null; if (searchId === state.currentSearchId) state.searchAbortController = null;
} }
} }
@ -797,7 +797,7 @@ function renderSearchResults(data, query, tagFilter) {
const titleDiv = el("div", { class: "search-result-title" }); const titleDiv = el("div", { class: "search-result-title" });
if (query && query.trim()) { if (query && query.trim()) {
highlightSearchText(titleDiv, r.title, query, searchCaseSensitive); highlightSearchText(titleDiv, r.title, query, state.searchCaseSensitive);
} else { } else {
titleDiv.textContent = r.title; titleDiv.textContent = r.title;
} }
@ -805,7 +805,7 @@ function renderSearchResults(data, query, tagFilter) {
if (r.snippet && r.snippet.includes("<mark>")) { if (r.snippet && r.snippet.includes("<mark>")) {
snippetDiv.innerHTML = r.snippet; snippetDiv.innerHTML = r.snippet;
} else if (query && query.trim() && r.snippet) { } else if (query && query.trim() && r.snippet) {
highlightSearchText(snippetDiv, r.snippet, query, searchCaseSensitive); highlightSearchText(snippetDiv, r.snippet, query, state.searchCaseSensitive);
} else { } else {
snippetDiv.textContent = r.snippet || ""; snippetDiv.textContent = r.snippet || "";
} }
@ -869,9 +869,9 @@ function renderAdvancedSearchResults(data, query, tagFilter) {
// Active filter badges // Active filter badges
const filtersRow = el("div", { class: "search-filters-row" }); const filtersRow = el("div", { class: "search-filters-row" });
if (searchCaseSensitive) filtersRow.appendChild(el("span", { class: "search-filter-badge" }, [document.createTextNode("Aa")])); if (state.searchCaseSensitive) filtersRow.appendChild(el("span", { class: "search-filter-badge" }, [document.createTextNode("Aa")]));
if (searchWholeWord) filtersRow.appendChild(el("span", { class: "search-filter-badge" }, [document.createTextNode("wd")])); if (state.searchWholeWord) filtersRow.appendChild(el("span", { class: "search-filter-badge" }, [document.createTextNode("wd")]));
if (searchRegex) filtersRow.appendChild(el("span", { class: "search-filter-badge" }, [document.createTextNode(".*")])); if (state.searchRegex) filtersRow.appendChild(el("span", { class: "search-filter-badge" }, [document.createTextNode(".*")]));
const inclEl = document.getElementById("search-include-input"); const inclEl = document.getElementById("search-include-input");
const exclEl = document.getElementById("search-exclude-input"); const exclEl = document.getElementById("search-exclude-input");
if (inclEl?.value.trim()) filtersRow.appendChild(el("span", { class: "search-filter-badge path" }, [document.createTextNode("incl: " + inclEl.value.trim())])); if (inclEl?.value.trim()) filtersRow.appendChild(el("span", { class: "search-filter-badge path" }, [document.createTextNode("incl: " + inclEl.value.trim())]));
@ -880,19 +880,19 @@ function renderAdvancedSearchResults(data, query, tagFilter) {
// Sort controls // Sort controls
const sortDiv = el("div", { class: "search-sort" }); const sortDiv = el("div", { class: "search-sort" });
const btnRelevance = el("button", { class: "search-sort__btn" + (advancedSearchSort === "relevance" ? " active" : ""), type: "button" }); const btnRelevance = el("button", { class: "search-sort__btn" + (state.advancedSearchSort === "relevance" ? " active" : ""), type: "button" });
btnRelevance.textContent = "Pertinence"; btnRelevance.textContent = "Pertinence";
btnRelevance.addEventListener("click", () => { btnRelevance.addEventListener("click", () => {
advancedSearchSort = "relevance"; state.advancedSearchSort = "relevance";
advancedSearchOffset = 0; state.advancedSearchOffset = 0;
const vault = document.getElementById("vault-filter").value; const vault = document.getElementById("vault-filter").value;
performAdvancedSearch(query, vault, tagFilter, 0, "relevance"); performAdvancedSearch(query, vault, tagFilter, 0, "relevance");
}); });
const btnDate = el("button", { class: "search-sort__btn" + (advancedSearchSort === "modified" ? " active" : ""), type: "button" }); const btnDate = el("button", { class: "search-sort__btn" + (state.advancedSearchSort === "modified" ? " active" : ""), type: "button" });
btnDate.textContent = "Date"; btnDate.textContent = "Date";
btnDate.addEventListener("click", () => { btnDate.addEventListener("click", () => {
advancedSearchSort = "modified"; state.advancedSearchSort = "modified";
advancedSearchOffset = 0; state.advancedSearchOffset = 0;
const vault = document.getElementById("vault-filter").value; const vault = document.getElementById("vault-filter").value;
performAdvancedSearch(query, vault, tagFilter, 0, "modified"); performAdvancedSearch(query, vault, tagFilter, 0, "modified");
}); });
@ -913,9 +913,9 @@ function renderAdvancedSearchResults(data, query, tagFilter) {
body: JSON.stringify({ body: JSON.stringify({
query: query, query: query,
vault: document.getElementById("vault-filter")?.value || "all", vault: document.getElementById("vault-filter")?.value || "all",
case_sensitive: searchCaseSensitive, case_sensitive: state.searchCaseSensitive,
whole_word: searchWholeWord, whole_word: state.searchWholeWord,
regex: searchRegex, regex: state.searchRegex,
include_paths: inclEl?.value || "", include_paths: inclEl?.value || "",
exclude_paths: exclEl?.value || "", exclude_paths: exclEl?.value || "",
}), }),
@ -927,9 +927,9 @@ function renderAdvancedSearchResults(data, query, tagFilter) {
area.appendChild(header); area.appendChild(header);
// Active sidebar tag chips // Active sidebar tag chips
if (selectedTags.length > 0) { if (state.selectedTags.length > 0) {
const activeTags = el("div", { class: "search-results-active-tags" }); const activeTags = el("div", { class: "search-results-active-tags" });
selectedTags.forEach((tag) => { state.selectedTags.forEach((tag) => {
const removeBtn = el( const removeBtn = el(
"button", "button",
{ {
@ -1012,7 +1012,7 @@ function renderAdvancedSearchResults(data, query, tagFilter) {
const titleDiv = el("div", { class: "search-result-title" }); const titleDiv = el("div", { class: "search-result-title" });
if (freeText) { if (freeText) {
highlightSearchText(titleDiv, r.title, freeText, searchCaseSensitive); highlightSearchText(titleDiv, r.title, freeText, state.searchCaseSensitive);
} else { } else {
titleDiv.textContent = r.title; titleDiv.textContent = r.title;
} }
@ -1022,7 +1022,7 @@ function renderAdvancedSearchResults(data, query, tagFilter) {
if (r.snippet && r.snippet.includes("<mark>")) { if (r.snippet && r.snippet.includes("<mark>")) {
snippetDiv.innerHTML = r.snippet; snippetDiv.innerHTML = r.snippet;
} else if (freeText && r.snippet) { } else if (freeText && r.snippet) {
highlightSearchText(snippetDiv, r.snippet, freeText, searchCaseSensitive); highlightSearchText(snippetDiv, r.snippet, freeText, state.searchCaseSensitive);
} else { } else {
snippetDiv.textContent = r.snippet || ""; snippetDiv.textContent = r.snippet || "";
} }
@ -1060,30 +1060,30 @@ function renderAdvancedSearchResults(data, query, tagFilter) {
area.appendChild(container); area.appendChild(container);
// Pagination // Pagination
if (data.total > ADVANCED_SEARCH_LIMIT) { if (data.total > state.ADVANCED_SEARCH_LIMIT) {
const paginationDiv = el("div", { class: "search-pagination" }); const paginationDiv = el("div", { class: "search-pagination" });
const prevBtn = el("button", { class: "search-pagination__btn", type: "button" }); const prevBtn = el("button", { class: "search-pagination__btn", type: "button" });
prevBtn.textContent = "← Précédent"; prevBtn.textContent = "← Précédent";
prevBtn.disabled = advancedSearchOffset === 0; prevBtn.disabled = state.advancedSearchOffset === 0;
prevBtn.addEventListener("click", () => { prevBtn.addEventListener("click", () => {
advancedSearchOffset = Math.max(0, advancedSearchOffset - ADVANCED_SEARCH_LIMIT); state.advancedSearchOffset = Math.max(0, advancedSearchOffset - state.ADVANCED_SEARCH_LIMIT);
const vault = document.getElementById("vault-filter").value; const vault = document.getElementById("vault-filter").value;
performAdvancedSearch(query, vault, tagFilter, advancedSearchOffset); performAdvancedSearch(query, vault, tagFilter, state.advancedSearchOffset);
document.getElementById("content-area").scrollTop = 0; document.getElementById("content-area").scrollTop = 0;
}); });
const info = el("span", { class: "search-pagination__info" }); const info = el("span", { class: "search-pagination__info" });
const from = advancedSearchOffset + 1; const from = advancedSearchOffset + 1;
const to = Math.min(advancedSearchOffset + ADVANCED_SEARCH_LIMIT, data.total); const to = Math.min(advancedSearchOffset + state.ADVANCED_SEARCH_LIMIT, data.total);
info.textContent = `${from}${to} sur ${data.total}`; info.textContent = `${from}${to} sur ${data.total}`;
const nextBtn = el("button", { class: "search-pagination__btn", type: "button" }); const nextBtn = el("button", { class: "search-pagination__btn", type: "button" });
nextBtn.textContent = "Suivant →"; nextBtn.textContent = "Suivant →";
nextBtn.disabled = advancedSearchOffset + ADVANCED_SEARCH_LIMIT >= data.total; nextBtn.disabled = advancedSearchOffset + ADVANCED_SEARCH_LIMIT >= data.total;
nextBtn.addEventListener("click", () => { nextBtn.addEventListener("click", () => {
advancedSearchOffset += ADVANCED_SEARCH_LIMIT; advancedSearchOffset += state.ADVANCED_SEARCH_LIMIT;
const vault = document.getElementById("vault-filter").value; const vault = document.getElementById("vault-filter").value;
performAdvancedSearch(query, vault, tagFilter, advancedSearchOffset); performAdvancedSearch(query, vault, tagFilter, state.advancedSearchOffset);
document.getElementById("content-area").scrollTop = 0; document.getElementById("content-area").scrollTop = 0;
}); });

View File

@ -1,10 +1,10 @@
/* ObsiGate — Auto-extracted module */ /* ObsiGate — Auto-extracted module */
import { state } from './state.js'; import { state } from './state.js';;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Right Sidebar Manager // Right Sidebar Manager
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
const RightSidebarManager = { export const RightSidebarManager = {
init() { init() {
this.loadState(); this.loadState();
this.initToggle(); this.initToggle();
@ -16,11 +16,11 @@ const RightSidebarManager = {
const savedWidth = localStorage.getItem("obsigate-right-sidebar-width"); const savedWidth = localStorage.getItem("obsigate-right-sidebar-width");
if (savedVisible !== null) { if (savedVisible !== null) {
rightSidebarVisible = savedVisible === "true"; state.rightSidebarVisible = savedVisible === "true";
} }
if (savedWidth) { if (savedWidth) {
rightSidebarWidth = parseInt(savedWidth) || 280; state.rightSidebarWidth = parseInt(savedWidth) || 280;
} }
this.applyState(); this.applyState();
@ -34,9 +34,9 @@ const RightSidebarManager = {
if (!sidebar) return; if (!sidebar) return;
if (rightSidebarVisible) { if (state.rightSidebarVisible) {
sidebar.classList.remove("hidden"); sidebar.classList.remove("hidden");
sidebar.style.width = `${rightSidebarWidth}px`; sidebar.style.width = `${state.rightSidebarWidth}px`;
if (handle) handle.classList.remove("hidden"); if (handle) handle.classList.remove("hidden");
if (tocBtn) { if (tocBtn) {
tocBtn.classList.add("active"); tocBtn.classList.add("active");
@ -64,8 +64,8 @@ const RightSidebarManager = {
}, },
toggle() { toggle() {
rightSidebarVisible = !rightSidebarVisible; state.rightSidebarVisible = !state.rightSidebarVisible;
localStorage.setItem("obsigate-right-sidebar-visible", rightSidebarVisible); localStorage.setItem("obsigate-right-sidebar-visible", state.rightSidebarVisible);
this.applyState(); this.applyState();
}, },
@ -105,7 +105,7 @@ const RightSidebarManager = {
newWidth = Math.max(200, Math.min(400, newWidth)); newWidth = Math.max(200, Math.min(400, newWidth));
sidebar.style.width = `${newWidth}px`; sidebar.style.width = `${newWidth}px`;
rightSidebarWidth = newWidth; state.rightSidebarWidth = newWidth;
}; };
const onMouseUp = () => { const onMouseUp = () => {
@ -116,7 +116,7 @@ const RightSidebarManager = {
document.body.style.cursor = ""; document.body.style.cursor = "";
document.body.style.userSelect = ""; document.body.style.userSelect = "";
localStorage.setItem("obsigate-right-sidebar-width", rightSidebarWidth); localStorage.setItem("obsigate-right-sidebar-width", state.rightSidebarWidth);
}; };
handle.addEventListener("mousedown", onMouseDown); handle.addEventListener("mousedown", onMouseDown);
@ -741,12 +741,12 @@ function buildFrontmatterCard(frontmatter) {
const nextPath = result.new_path; const nextPath = result.new_path;
await refreshSidebarTreePreservingState(); await refreshSidebarTreePreservingState();
if (type === 'file' && currentVault === vault && currentPath === path) { if (type === 'file' && state.currentVault === vault && state.currentPath === path) {
await openFile(vault, nextPath); await openFile(vault, nextPath);
} else if (type === 'directory' && currentVault === vault && currentPath && (currentPath === path || currentPath.startsWith(`${path}/`))) { } else if (type === 'directory' && state.currentVault === vault && currentPath && (state.currentPath === path || state.currentPath.startsWith(`${path}/`))) {
const suffix = currentPath === path ? '' : currentPath.slice(path.length); const suffix = state.currentPath === path ? '' : state.currentPath.slice(path.length);
currentPath = `${nextPath}${suffix}`; state.currentPath = `${nextPath}${suffix}`;
await focusPathInSidebar(vault, currentPath, { alignToTop: false }); await focusPathInSidebar(vault, state.currentPath, { alignToTop: false });
} }
showToast(type === 'directory' ? 'Dossier renommé' : 'Fichier renommé', 'success'); showToast(type === 'directory' ? 'Dossier renommé' : 'Fichier renommé', 'success');
@ -830,7 +830,7 @@ function buildFrontmatterCard(frontmatter) {
this._closeModal(overlay); this._closeModal(overlay);
await refreshSidebarTreePreservingState(); await refreshSidebarTreePreservingState();
if (currentVault === vault && currentPath && currentPath.startsWith(path)) { if (state.currentVault === vault && currentPath && state.currentPath.startsWith(path)) {
showWelcome(); showWelcome();
} }
} catch (err) { } catch (err) {
@ -892,7 +892,7 @@ function buildFrontmatterCard(frontmatter) {
this._closeModal(overlay); this._closeModal(overlay);
await refreshSidebarTreePreservingState(); await refreshSidebarTreePreservingState();
if (currentVault === vault && currentPath === path) { if (state.currentVault === vault && state.currentPath === path) {
showWelcome(); showWelcome();
} }
} catch (err) { } catch (err) {

View File

@ -1,5 +1,5 @@
/* ObsiGate — Auto-extracted module */ /* ObsiGate — Auto-extracted module */
import { state } from './state.js'; import { state } from './state.js';;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Outline/TOC Manager // Outline/TOC Manager
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -114,7 +114,7 @@ const OutlineManager = {
outlineList.appendChild(item); outlineList.appendChild(item);
}); });
headingsCache = headings; state.headingsCache = headings;
}, },
/** /**
@ -144,9 +144,9 @@ const OutlineManager = {
* Set active heading in outline * Set active heading in outline
*/ */
setActiveHeading(headingId) { setActiveHeading(headingId) {
if (activeHeadingId === headingId) return; if (state.activeHeadingId === headingId) return;
activeHeadingId = headingId; state.activeHeadingId = headingId;
const items = document.querySelectorAll(".outline-item"); const items = document.querySelectorAll(".outline-item");
items.forEach((item) => { items.forEach((item) => {
@ -178,8 +178,8 @@ const OutlineManager = {
destroy() { destroy() {
ScrollSpyManager.destroy(); ScrollSpyManager.destroy();
ReadingProgressManager.destroy(); ReadingProgressManager.destroy();
headingsCache = []; state.headingsCache = [];
activeHeadingId = null; state.activeHeadingId = null;
}, },
}; };
@ -309,10 +309,10 @@ const ReadingProgressManager = {
// File viewer // File viewer
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
async function openFile(vaultName, filePath) { async function openFile(vaultName, filePath) {
currentVault = vaultName; state.currentVault = vaultName;
currentPath = filePath; state.currentPath = filePath;
showingSource = false; state.showingSource = false;
cachedRawSource = null; state.cachedRawSource = null;
// Highlight active // Highlight active
syncActiveFileTreeItem(vaultName, filePath); syncActiveFileTreeItem(vaultName, filePath);
@ -435,12 +435,12 @@ function renderFile(data) {
copyBtn.addEventListener("click", async () => { copyBtn.addEventListener("click", async () => {
try { try {
// Fetch raw content if not already cached // Fetch raw content if not already cached
if (!cachedRawSource) { if (!state.cachedRawSource) {
const rawUrl = `/api/file/${encodeURIComponent(data.vault)}/raw?path=${encodeURIComponent(data.path)}`; const rawUrl = `/api/file/${encodeURIComponent(data.vault)}/raw?path=${encodeURIComponent(data.path)}`;
const rawData = await api(rawUrl); const rawData = await api(rawUrl);
cachedRawSource = rawData.raw; state.cachedRawSource = rawData.raw;
} }
await navigator.clipboard.writeText(cachedRawSource); await navigator.clipboard.writeText(state.cachedRawSource);
copyBtn.lastChild.textContent = "Copié !"; copyBtn.lastChild.textContent = "Copié !";
setTimeout(() => (copyBtn.lastChild.textContent = "Copier"), 1500); setTimeout(() => (copyBtn.lastChild.textContent = "Copier"), 1500);
} catch (err) { } catch (err) {
@ -541,15 +541,15 @@ function renderFile(data) {
const raw = document.getElementById("file-raw-content"); const raw = document.getElementById("file-raw-content");
if (!rendered || !raw) return; if (!rendered || !raw) return;
showingSource = !showingSource; state.showingSource = !state.showingSource;
if (showingSource) { if (state.showingSource) {
sourceBtn.classList.add("active"); sourceBtn.classList.add("active");
if (!cachedRawSource) { if (!state.cachedRawSource) {
const rawUrl = `/api/file/${encodeURIComponent(data.vault)}/raw?path=${encodeURIComponent(data.path)}`; const rawUrl = `/api/file/${encodeURIComponent(data.vault)}/raw?path=${encodeURIComponent(data.path)}`;
const rawData = await api(rawUrl); const rawData = await api(rawUrl);
cachedRawSource = rawData.raw; state.cachedRawSource = rawData.raw;
} }
raw.textContent = cachedRawSource; raw.textContent = state.cachedRawSource;
rendered.style.display = "none"; rendered.style.display = "none";
raw.style.display = "block"; raw.style.display = "block";
} else { } else {
@ -725,7 +725,7 @@ function attachTreeItemLongPress(itemEl, getMenuData) {
} }
function getVaultIcon(vaultName, size = 16) { function getVaultIcon(vaultName, size = 16) {
const v = allVaults.find((val) => val.name === vaultName); const v = state.allVaults.find((val) => val.name === vaultName);
const type = v ? v.type : "VAULT"; const type = v ? v.type : "VAULT";
if (type === "DIR") { if (type === "DIR") {
@ -948,10 +948,10 @@ function showWelcome() {
DashboardConflictsWidget.load(); DashboardConflictsWidget.load();
} }
if (typeof DashboardRecentWidget !== "undefined") { if (typeof DashboardRecentWidget !== "undefined") {
DashboardRecentWidget.load(selectedContextVault); DashboardRecentWidget.load(state.selectedContextVault);
} }
if (typeof DashboardBookmarkWidget !== "undefined") { if (typeof DashboardBookmarkWidget !== "undefined") {
DashboardBookmarkWidget.load(selectedContextVault); DashboardBookmarkWidget.load(state.selectedContextVault);
} }
if (typeof DashboardSharedWidget !== "undefined") { if (typeof DashboardSharedWidget !== "undefined") {
DashboardSharedWidget.load(); DashboardSharedWidget.load();
@ -1002,9 +1002,9 @@ async function loadSavedSearches() {
// Apply the saved search // Apply the saved search
const input = document.getElementById("search-input"); const input = document.getElementById("search-input");
if (input) input.value = s.query; if (input) input.value = s.query;
searchCaseSensitive = s.case_sensitive || false; state.searchCaseSensitive = s.case_sensitive || false;
searchWholeWord = s.whole_word || false; state.searchWholeWord = s.whole_word || false;
searchRegex = s.regex || false; state.searchRegex = s.regex || false;
if (typeof _updateToggleUI === "function") _updateToggleUI(); if (typeof _updateToggleUI === "function") _updateToggleUI();
if (s.include_paths) { if (s.include_paths) {
const incl = document.getElementById("search-include-input"); const incl = document.getElementById("search-include-input");
@ -1019,8 +1019,8 @@ async function loadSavedSearches() {
AutocompleteDropdown._suppressNext = true; AutocompleteDropdown._suppressNext = true;
const vault = s.vault || "all"; const vault = s.vault || "all";
if (input) { input.dispatchEvent(new Event("input")); } if (input) { input.dispatchEvent(new Event("input")); }
clearTimeout(searchTimeout); clearTimeout(state.searchTimeout);
advancedSearchOffset = 0; state.advancedSearchOffset = 0;
performAdvancedSearch(s.query, vault, null); performAdvancedSearch(s.query, vault, null);
}); });
}); });
@ -1059,10 +1059,10 @@ function goHome() {
document.querySelectorAll(".tree-item.active").forEach((el) => el.classList.remove("active")); document.querySelectorAll(".tree-item.active").forEach((el) => el.classList.remove("active"));
currentVault = null; state.currentVault = null;
currentPath = null; state.currentPath = null;
showingSource = false; state.showingSource = false;
cachedRawSource = null; state.cachedRawSource = null;
closeMobileSidebar(); closeMobileSidebar();
showWelcome(); showWelcome();
@ -1216,15 +1216,15 @@ const IndexUpdateManager = (() => {
// Toast removed: silent auto-indexing — no notification needed // Toast removed: silent auto-indexing — no notification needed
// Refresh sidebar and tags if affected vault matches current context // Refresh sidebar and tags if affected vault matches current context
const affectsCurrentVault = selectedContextVault === "all" || (data.vaults || []).includes(selectedContextVault); const affectsCurrentVault = state.selectedContextVault === "all" || (data.vaults || []).includes(state.selectedContextVault);
if (affectsCurrentVault) { if (affectsCurrentVault) {
try { try {
await Promise.all([refreshSidebarTreePreservingState(), refreshTagsForContext()]); await Promise.all([refreshSidebarTreePreservingState(), refreshTagsForContext()]);
// Refresh current file if it was updated // Refresh current file if it was updated
if (currentVault && currentPath) { if (currentVault && state.currentPath) {
const changed = (data.changes || []).some((c) => c.vault === currentVault && c.path === currentPath); const changed = (data.changes || []).some((c) => c.vault === currentVault && c.path === state.currentPath);
if (changed) { if (changed) {
openFile(currentVault, currentPath); openFile(state.currentVault, state.currentPath);
} }
} }
} catch (err) { } catch (err) {
@ -1233,7 +1233,7 @@ const IndexUpdateManager = (() => {
} }
// Refresh recent tab if it is active // Refresh recent tab if it is active
if (activeSidebarTab === "recent") { if (state.activeSidebarTab === "recent") {
const vaultFilter = document.getElementById("recent-vault-filter"); const vaultFilter = document.getElementById("recent-vault-filter");
loadRecentFiles(vaultFilter ? vaultFilter.value || null : null); loadRecentFiles(vaultFilter ? vaultFilter.value || null : null);
} }