Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 41 additions & 4 deletions src/utils/highlighter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,43 @@ export interface StoredData {

type HighlightsStorage = Record<string, StoredData>;

/**
* Finds all storage keys that map to the current logical page URL.
* Intended use: read-path only fallback for query/hash URL decorations.
*/
function getMatchingHighlightStorageKeys(allHighlights: HighlightsStorage, currentUrl: string): string[] {
// Keep URL canonicalization local to read-time matching so persisted href values remain untouched.
const toMatchKey = (url: string): string => {
try {
const parsedUrl = new URL(url);
parsedUrl.search = '';
parsedUrl.hash = '';
return parsedUrl.href;
} catch (_error) {
return url;
}
};

const currentUrlKey = toMatchKey(currentUrl);
return Object.keys(allHighlights).filter((storedUrl) => toMatchKey(storedUrl) === currentUrlKey);
}

/**
* Reads and merges highlights for every matching URL key.
* Intended use: preserve compatibility with legacy datasets split across base/hash/query keys.
*/
function collectHighlightsForCurrentPage(allHighlights: HighlightsStorage, currentUrl: string): AnyHighlightData[] {
const matchingKeys = getMatchingHighlightStorageKeys(allHighlights, currentUrl);

return matchingKeys
// Resolve matching URL keys to storage records.
.map((storageKey) => allHighlights[storageKey])
// Merge every record's highlight array into one read dataset.
.flatMap((storedData) => (Array.isArray(storedData?.highlights) ? storedData.highlights : []))
// Ignore malformed entries that are not highlight objects.
.filter((highlight): highlight is AnyHighlightData => Boolean(highlight && typeof highlight === 'object'));
}

export function updateHighlights(newHighlights: AnyHighlightData[]) {
const oldHighlights = [...highlights];
highlights = newHighlights;
Expand Down Expand Up @@ -961,10 +998,10 @@ export async function loadHighlights() {
const url = window.location.href;
const result = await browser.storage.local.get('highlights');
const allHighlights = (result.highlights || {}) as HighlightsStorage;
const storedData = allHighlights[url];
const mergedHighlights = collectHighlightsForCurrentPage(allHighlights, url);

if (storedData && Array.isArray(storedData.highlights) && storedData.highlights.length > 0) {
highlights = storedData.highlights;
if (mergedHighlights.length > 0) {
highlights = mergedHighlights;

// Load settings to check if "Always show highlights" is enabled
await loadSettings();
Expand Down Expand Up @@ -1075,4 +1112,4 @@ function findLastTextNode(element: Element): Text | null {
return lastNode as Text | null;
}

export { getElementXPath } from './dom-utils';
export { getElementXPath } from './dom-utils';