Skip to content

Commit

Permalink
feature: Add support for importing bookmarks from Omnivore. Fixes hoa…
Browse files Browse the repository at this point in the history
  • Loading branch information
MohamedBassem committed Nov 3, 2024
1 parent 7042f26 commit 7ec5746
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 1 deletion.
17 changes: 16 additions & 1 deletion apps/web/components/settings/ImportExport.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
ParsedBookmark,
parseHoarderBookmarkFile,
parseNetscapeBookmarkFile,
parseOmnivoreBookmarkFile,
parsePocketBookmarkFile,
} from "@/lib/importBookmarkParser";
import { cn } from "@/lib/utils";
Expand Down Expand Up @@ -128,14 +129,16 @@ export function ImportExportRow() {
source,
}: {
file: File;
source: "html" | "pocket" | "hoarder";
source: "html" | "pocket" | "omnivore" | "hoarder";
}) => {
if (source === "html") {
return await parseNetscapeBookmarkFile(file);
} else if (source === "pocket") {
return await parsePocketBookmarkFile(file);
} else if (source === "hoarder") {
return await parseHoarderBookmarkFile(file);
} else if (source === "omnivore") {
return await parseOmnivoreBookmarkFile(file);
} else {
throw new Error("Unknown source");
}
Expand Down Expand Up @@ -223,6 +226,18 @@ export function ImportExportRow() {
<Upload />
<p>Import Bookmarks from Pocket export</p>
</FilePickerButton>
<FilePickerButton
loading={false}
accept=".json"
multiple={false}
className="flex items-center gap-2"
onFileSelect={(file) =>
runUploadBookmarkFile({ file, source: "omnivore" })
}
>
<Upload />
<p>Import Bookmarks from Omnivore export</p>
</FilePickerButton>
<FilePickerButton
loading={false}
accept=".json"
Expand Down
31 changes: 31 additions & 0 deletions apps/web/lib/importBookmarkParser.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copied from https://gist.github.com/devster31/4e8c6548fd16ffb75c02e6f24e27f9b9
import * as cheerio from "cheerio";
import { parse } from "csv-parse/sync";
import { z } from "zod";

import { BookmarkTypes } from "@hoarder/shared/types/bookmarks";

Expand Down Expand Up @@ -109,3 +110,33 @@ export async function parseHoarderBookmarkFile(
};
});
}

export async function parseOmnivoreBookmarkFile(
file: File,
): Promise<ParsedBookmark[]> {
const textContent = await file.text();
const zOmnivoreExportSchema = z.array(
z.object({
title: z.string(),
url: z.string(),
labels: z.array(z.string()),
savedAt: z.coerce.date(),
}),
);

const parsed = zOmnivoreExportSchema.safeParse(JSON.parse(textContent));
if (!parsed.success) {
throw new Error(
`The uploaded JSON file contains an invalid omnivore bookmark file: ${parsed.error.toString()}`,
);
}

return parsed.data.map((bookmark) => {
return {
title: bookmark.title ?? "",
content: { type: BookmarkTypes.LINK as const, url: bookmark.url },
tags: bookmark.labels,
addDate: bookmark.savedAt.getTime() / 1000,
};
});
}

0 comments on commit 7ec5746

Please sign in to comment.