Skip to content

Commit

Permalink
Allow Epub generation from multiple bookmarks hoarder-app#295
Browse files Browse the repository at this point in the history
Added a library to generate epub files
added a button to create epubs for single link bookmarks
  • Loading branch information
kamtschatka committed Nov 22, 2024
1 parent 378ad9b commit fb37f84
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 0 deletions.
65 changes: 65 additions & 0 deletions apps/web/app/api/epub/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { inArray } from "drizzle-orm";
import epub, { Chapter } from "epub-gen-memory";

import { db } from "@hoarder/db";
import { bookmarkLinks } from "@hoarder/db/schema";

export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const assetIds = searchParams.getAll("assetId");

if (!assetIds || assetIds.length === 0) {
return new Response("", {
status: 404,
});
}

const bookmarkInformation = await db
.select({
title: bookmarkLinks.title,
htmlContent: bookmarkLinks.htmlContent,
})
.from(bookmarkLinks)
.where(inArray(bookmarkLinks.id, assetIds));

if (!bookmarkInformation || bookmarkInformation.length === 0) {
return new Response("", {
status: 404,
});
}

const chapters = bookmarkInformation.map((information) => {
return {
content: information.htmlContent ?? "",
title: information.title ?? "",
};
});

const title = getTitle(chapters);

const generatedEpub = await epub(title, chapters);

return new Response(generatedEpub, {
status: 200,
headers: {
"Content-Type": "application/epub+zip",
"Content-Disposition": `attachment; filename=${createFilename()}`,
},
});
}

function createFilename(): string {
const date = new Date();
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");

return `${year}-${month}-${day}-hoarder-bookmarks.epub`;
}

function getTitle(chapters: Chapter[]): string {
if (chapters.length === 1 && chapters[0].title) {
return chapters[0].title;
}
return "Hoarder EPub export";
}
10 changes: 10 additions & 0 deletions apps/web/components/dashboard/bookmarks/BookmarkOptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { useToast } from "@/components/ui/use-toast";
import { useClientConfig } from "@/lib/clientConfig";
import { useTranslation } from "@/lib/i18n/client";
import {
Download,
FileDown,
Link,
List,
Expand Down Expand Up @@ -187,6 +188,7 @@ export default function BookmarkOptions({ bookmark }: { bookmark: ZBookmark }) {
)}

{bookmark.content.type === BookmarkTypes.LINK && (
<>
<DropdownMenuItem
onClick={() => {
navigator.clipboard.writeText(
Expand All @@ -200,6 +202,14 @@ export default function BookmarkOptions({ bookmark }: { bookmark: ZBookmark }) {
<Link className="mr-2 size-4" />
<span>{t("actions.copy_link")}</span>
</DropdownMenuItem>

<DropdownMenuItem>
<Download className="mr-2 size-4"></Download>
<a href={`/api/epub?assetId=${bookmark.id}`}>
Download as EPUB
</a>
</DropdownMenuItem>
</>
)}
<DropdownMenuItem onClick={() => setTagModalIsOpen(true)}>
<Tags className="mr-2 size-4" />
Expand Down
1 change: 1 addition & 0 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"csv-parse": "^5.5.6",
"dayjs": "^1.11.10",
"drizzle-orm": "^0.33.0",
"epub-gen-memory": "^1.0.10",
"fastest-levenshtein": "^1.0.16",
"i18next": "^23.16.5",
"i18next-resources-to-backend": "^1.2.1",
Expand Down

0 comments on commit fb37f84

Please sign in to comment.