From 1bae66f7785289818eba3249f651a320f497c6a4 Mon Sep 17 00:00:00 2001 From: Mohamed Bassem Date: Sun, 1 Jun 2025 22:43:13 +0000 Subject: feat: Maintain list structure when importing from netscape. Fixes #538 --- apps/web/lib/importBookmarkParser.ts | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'apps/web/lib') diff --git a/apps/web/lib/importBookmarkParser.ts b/apps/web/lib/importBookmarkParser.ts index aba11689..2e354ffe 100644 --- a/apps/web/lib/importBookmarkParser.ts +++ b/apps/web/lib/importBookmarkParser.ts @@ -16,6 +16,7 @@ export interface ParsedBookmark { addDate?: number; notes?: string; archived?: boolean; + paths: string[][]; } export async function parseNetscapeBookmarkFile( @@ -42,11 +43,24 @@ export async function parseNetscapeBookmarkFile( /* empty */ } const url = $a.attr("href"); + + // Build folder path by traversing up the hierarchy + const path: string[] = []; + let current = $a.parent(); + while (current && current.length > 0) { + const h3 = current.find("> h3").first(); + if (h3.length > 0) { + path.unshift(h3.text()); + } + current = current.parent(); + } + return { title: $a.text(), content: url ? { type: BookmarkTypes.LINK as const, url } : undefined, tags, addDate: typeof addDate === "undefined" ? undefined : parseInt(addDate), + paths: [path], }; }) .get(); @@ -75,6 +89,7 @@ export async function parsePocketBookmarkFile( tags: record.tags.length > 0 ? record.tags.split("|") : [], addDate: parseInt(record.time_added), archived: record.status === "archive", + paths: [], // TODO }; }); } @@ -111,6 +126,7 @@ export async function parseKarakeepBookmarkFile( addDate: bookmark.createdAt, notes: bookmark.note ?? undefined, archived: bookmark.archived, + paths: [], // TODO }; }); } @@ -143,6 +159,7 @@ export async function parseOmnivoreBookmarkFile( tags: bookmark.labels, addDate: bookmark.savedAt.getTime() / 1000, archived: bookmark.state === "Archived", + paths: [], }; }); } @@ -179,6 +196,7 @@ export async function parseLinkwardenBookmarkFile( content: { type: BookmarkTypes.LINK as const, url: bookmark.url }, tags: bookmark.tags.map((tag) => tag.name), addDate: bookmark.createdAt.getTime() / 1000, + paths: [], // TODO })); }); } @@ -219,6 +237,7 @@ export async function parseTabSessionManagerStateFile( content: { type: BookmarkTypes.LINK as const, url: tab.url }, tags: [], addDate: tab.lastAccessed, + paths: [], // Tab Session Manager doesn't have folders })), ); } @@ -236,7 +255,8 @@ export function deduplicateBookmarks( const existing = deduplicatedBookmarksMap.get(url)!; // Merge tags existing.tags = [...new Set([...existing.tags, ...bookmark.tags])]; - // Keep earliest date + // Merge paths + existing.paths = [...existing.paths, ...bookmark.paths]; const existingDate = existing.addDate ?? Infinity; const newDate = bookmark.addDate ?? Infinity; if (newDate < existingDate) { -- cgit v1.2.3-70-g09d2