diff options
| author | Mohamed Bassem <me@mbassem.com> | 2025-06-01 22:43:13 +0000 |
|---|---|---|
| committer | Mohamed Bassem <me@mbassem.com> | 2025-06-01 22:43:13 +0000 |
| commit | 1bae66f7785289818eba3249f651a320f497c6a4 (patch) | |
| tree | 9c01aca6f2d8924d912f05d90e3e8e768479740d /apps/web/lib/importBookmarkParser.ts | |
| parent | e59be245d5e3005b5b5dadf78ad7115cc800c663 (diff) | |
| download | karakeep-1bae66f7785289818eba3249f651a320f497c6a4.tar.zst | |
feat: Maintain list structure when importing from netscape. Fixes #538
Diffstat (limited to 'apps/web/lib/importBookmarkParser.ts')
| -rw-r--r-- | apps/web/lib/importBookmarkParser.ts | 22 |
1 files changed, 21 insertions, 1 deletions
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) { |
