diff --git a/apps/desktop/changelog/0.3.13.md b/apps/desktop/changelog/0.3.13.md
index 48ed46019..eabfafb6a 100644
--- a/apps/desktop/changelog/0.3.13.md
+++ b/apps/desktop/changelog/0.3.13.md
@@ -3,6 +3,7 @@
## New Features
- New Action Language setting
+- Export entry content to a PDF file
## Improvements
diff --git a/apps/desktop/locales/app/ar-DZ.json b/apps/desktop/locales/app/ar-DZ.json
index 0e9fc14c0..f97018a92 100644
--- a/apps/desktop/locales/app/ar-DZ.json
+++ b/apps/desktop/locales/app/ar-DZ.json
@@ -15,6 +15,8 @@
"discover.rss_url": "رابط RSS",
"discover.select_placeholder": "اختر",
"entry_actions.copy_link": "نسخ الرابط",
+ "entry_actions.exported_notify": "تم تصدير المقال كملف PDF.",
+ "entry_actions.export_as_pdf": "تصدير كملف PDF",
"entry_actions.failed_to_save_to_eagle": "فشل في الحفظ إلى Eagle.",
"entry_actions.failed_to_save_to_instapaper": "فشل في الحفظ إلى Instapaper.",
"entry_actions.failed_to_save_to_obsidian": "فشل في الحفظ إلى Obsidian.",
diff --git a/apps/desktop/locales/app/ar-IQ.json b/apps/desktop/locales/app/ar-IQ.json
index 607a076fd..5765b22f9 100644
--- a/apps/desktop/locales/app/ar-IQ.json
+++ b/apps/desktop/locales/app/ar-IQ.json
@@ -15,6 +15,8 @@
"discover.rss_url": "رابط RSS",
"discover.select_placeholder": "اختر",
"entry_actions.copy_link": "نسخ الرابط",
+ "entry_actions.exported_notify": "تم تصدير المقال كملف PDF.",
+ "entry_actions.export_as_pdf": "تصدير كملف PDF",
"entry_actions.failed_to_save_to_eagle": "فشل في الحفظ إلى Eagle.",
"entry_actions.failed_to_save_to_instapaper": "فشل في الحفظ إلى Instapaper.",
"entry_actions.failed_to_save_to_obsidian": "فشل في الحفظ إلى Obsidian.",
diff --git a/apps/desktop/locales/app/ar-KW.json b/apps/desktop/locales/app/ar-KW.json
index f1b0b4d42..e20e1000f 100644
--- a/apps/desktop/locales/app/ar-KW.json
+++ b/apps/desktop/locales/app/ar-KW.json
@@ -15,6 +15,8 @@
"discover.rss_url": "رابط RSS",
"discover.select_placeholder": "اختر",
"entry_actions.copy_link": "نسخ الرابط",
+ "entry_actions.exported_notify": "تم تصدير المقال كملف PDF.",
+ "entry_actions.export_as_pdf": "تصدير كملف PDF",
"entry_actions.failed_to_save_to_eagle": "فشل في الحفظ إلى Eagle.",
"entry_actions.failed_to_save_to_instapaper": "فشل في الحفظ إلى Instapaper.",
"entry_actions.failed_to_save_to_obsidian": "فشل في الحفظ إلى Obsidian",
diff --git a/apps/desktop/locales/app/ar-MA.json b/apps/desktop/locales/app/ar-MA.json
index ad7a5fe0d..e3fcc656f 100644
--- a/apps/desktop/locales/app/ar-MA.json
+++ b/apps/desktop/locales/app/ar-MA.json
@@ -15,6 +15,8 @@
"discover.rss_url": "رابط RSS",
"discover.select_placeholder": "اختر",
"entry_actions.copy_link": "نسخ الرابط",
+ "entry_actions.exported_notify": "تم تصدير المقال كملف PDF.",
+ "entry_actions.export_as_pdf": "تصدير كملف PDF",
"entry_actions.failed_to_save_to_eagle": "فشل الحفظ إلى Eagle.",
"entry_actions.failed_to_save_to_instapaper": "فشل الحفظ إلى Instapaper.",
"entry_actions.failed_to_save_to_obsidian": "فشل الحفظ في Obsidian",
diff --git a/apps/desktop/locales/app/ar-SA.json b/apps/desktop/locales/app/ar-SA.json
index 3058725ee..a6359d1c5 100644
--- a/apps/desktop/locales/app/ar-SA.json
+++ b/apps/desktop/locales/app/ar-SA.json
@@ -15,6 +15,8 @@
"discover.rss_url": "عنوان URL لخلاصة RSS",
"discover.select_placeholder": "اختيار",
"entry_actions.copy_link": "نسخ الرابط",
+ "entry_actions.exported_notify": "تم تصدير المقال كملف PDF.",
+ "entry_actions.export_as_pdf": "تصدير كملف PDF",
"entry_actions.failed_to_save_to_eagle": "فشل في الحفظ إلى Eagle.",
"entry_actions.failed_to_save_to_instapaper": "فشل في الحفظ إلى Instapaper.",
"entry_actions.failed_to_save_to_readwise": "فشل في الحفظ إلى Readwise.",
diff --git a/apps/desktop/locales/app/ar-TN.json b/apps/desktop/locales/app/ar-TN.json
index de9223186..703d068f6 100644
--- a/apps/desktop/locales/app/ar-TN.json
+++ b/apps/desktop/locales/app/ar-TN.json
@@ -15,6 +15,8 @@
"discover.rss_url": "رابط RSS",
"discover.select_placeholder": "اختر",
"entry_actions.copy_link": "نسخ الرابط",
+ "entry_actions.exported_notify": "تم تصدير المقال كملف PDF.",
+ "entry_actions.export_as_pdf": "تصدير كملف PDF",
"entry_actions.failed_to_save_to_eagle": "فشل في الحفظ إلى Eagle.",
"entry_actions.failed_to_save_to_instapaper": "فشل في الحفظ إلى Instapaper.",
"entry_actions.failed_to_save_to_readwise": "فشل في الحفظ إلى Readwise.",
diff --git a/apps/desktop/locales/app/de.json b/apps/desktop/locales/app/de.json
index 84394d8a0..f27733a69 100644
--- a/apps/desktop/locales/app/de.json
+++ b/apps/desktop/locales/app/de.json
@@ -15,6 +15,8 @@
"discover.rss_url": "RSS-URL",
"discover.select_placeholder": "Auswählen",
"entry_actions.copy_link": "Link kopieren",
+ "entry_actions.exported_notify": "Artikel als PDF exportiert.",
+ "entry_actions.export_as_pdf": "Als PDF exportieren",
"entry_actions.failed_to_save_to_eagle": "Speichern in Eagle fehlgeschlagen.",
"entry_actions.failed_to_save_to_instapaper": "Speichern in Instapaper fehlgeschlagen.",
"entry_actions.failed_to_save_to_obsidian": "Speichern in Obsidian fehlgeschlagen",
diff --git a/apps/desktop/locales/app/en.json b/apps/desktop/locales/app/en.json
index 12d82f49e..f4f567110 100644
--- a/apps/desktop/locales/app/en.json
+++ b/apps/desktop/locales/app/en.json
@@ -108,6 +108,8 @@
"entry_actions.image_gallery": "Image Gallery",
"entry_actions.copied_notify": "{{which}} copied to clipboard.",
"entry_actions.copy_link": "Copy Link",
+ "entry_actions.exported_notify": "Exported article as PDF.",
+ "entry_actions.export_as_pdf": "Export as PDF",
"entry_actions.copy_title": "Copy Title",
"entry_actions.delete": "Delete",
"entry_actions.deleted": "Deleted.",
diff --git a/apps/desktop/locales/app/es.json b/apps/desktop/locales/app/es.json
index 686c08687..c299baf2a 100644
--- a/apps/desktop/locales/app/es.json
+++ b/apps/desktop/locales/app/es.json
@@ -15,6 +15,8 @@
"discover.rss_url": "RSS URL",
"discover.select_placeholder": "Seleccionar",
"entry_actions.copy_link": "Copiar enlace",
+ "entry_actions.exported_notify": "Artículo exportado como PDF.",
+ "entry_actions.export_as_pdf": "Exportar como PDF",
"entry_actions.failed_to_save_to_obsidian": "Error al guardar en Obsidian",
"entry_actions.mark_as_read": "Marcar como leído",
"entry_actions.mark_as_unread": "Marcar como no leído",
diff --git a/apps/desktop/locales/app/fi.json b/apps/desktop/locales/app/fi.json
index 9e4abfe47..baa90f112 100644
--- a/apps/desktop/locales/app/fi.json
+++ b/apps/desktop/locales/app/fi.json
@@ -15,6 +15,8 @@
"discover.rss_url": "RSS-URL",
"discover.select_placeholder": "Valitse",
"entry_actions.copy_link": "Kopioi linkki",
+ "entry_actions.exported_notify": "Artikkeli vietiin PDF-muodossa.",
+ "entry_actions.export_as_pdf": "Vie PDF:nä",
"entry_actions.failed_to_save_to_eagle": "Tallennus Eagleen epäonnistui.",
"entry_actions.failed_to_save_to_instapaper": "Tallennus Instapaperiin epäonnistui.",
"entry_actions.failed_to_save_to_readwise": "Tallennus Readwiseen epäonnistui.",
diff --git a/apps/desktop/locales/app/fr.json b/apps/desktop/locales/app/fr.json
index 81047be3d..d973e5cad 100644
--- a/apps/desktop/locales/app/fr.json
+++ b/apps/desktop/locales/app/fr.json
@@ -15,6 +15,8 @@
"discover.rss_url": "URL du RSS",
"discover.select_placeholder": "Sélectionner",
"entry_actions.copy_link": "Copier le lien",
+ "entry_actions.exported_notify": "Article exporté en PDF.",
+ "entry_actions.export_as_pdf": "Exporter en PDF",
"entry_actions.failed_to_save_to_eagle": "Échec de l'enregistrement sur Eagle.",
"entry_actions.failed_to_save_to_instapaper": "Échec de l'enregistrement sur Instapaper.",
"entry_actions.failed_to_save_to_readwise": "Échec de l'enregistrement sur Readwise.",
diff --git a/apps/desktop/locales/app/it.json b/apps/desktop/locales/app/it.json
index 03e47a391..a227a30f1 100644
--- a/apps/desktop/locales/app/it.json
+++ b/apps/desktop/locales/app/it.json
@@ -15,6 +15,8 @@
"discover.rss_url": "URL RSS",
"discover.select_placeholder": "Seleziona",
"entry_actions.copy_link": "Copia link",
+ "entry_actions.exported_notify": "Articolo esportato come PDF.",
+ "entry_actions.export_as_pdf": "Esporta come PDF",
"entry_actions.failed_to_save_to_eagle": "Salvataggio su Eagle non riuscito.",
"entry_actions.failed_to_save_to_instapaper": "Salvataggio su Instapaper non riuscito.",
"entry_actions.failed_to_save_to_readwise": "Salvataggio su Readwise non riuscito.",
diff --git a/apps/desktop/locales/app/ja.json b/apps/desktop/locales/app/ja.json
index 068f9bd71..d1073451e 100644
--- a/apps/desktop/locales/app/ja.json
+++ b/apps/desktop/locales/app/ja.json
@@ -107,6 +107,8 @@
"discover.target.lists": "リスト",
"entry_actions.copied_notify": "{{which}} をクリップボードにコピーしました。",
"entry_actions.copy_link": "リンクをコピー",
+ "entry_actions.exported_notify": "記事をPDFとしてエクスポートしました。",
+ "entry_actions.export_as_pdf": "PDFとしてエクスポート",
"entry_actions.copy_title": "タイトルをコピー",
"entry_actions.delete": "削除",
"entry_actions.deleted": "削除済み",
diff --git a/apps/desktop/locales/app/ko.json b/apps/desktop/locales/app/ko.json
index 5e98a327f..c93b82272 100644
--- a/apps/desktop/locales/app/ko.json
+++ b/apps/desktop/locales/app/ko.json
@@ -107,6 +107,8 @@
"discover.target.lists": "목록",
"entry_actions.copied_notify": "{{which}}이(가) 클립보드에 복사되었습니다",
"entry_actions.copy_link": "링크 복사",
+ "entry_actions.exported_notify": "PDF로 기사 내보내기 완료.",
+ "entry_actions.export_as_pdf": "PDF로 내보내기",
"entry_actions.copy_title": "제목 복사",
"entry_actions.delete": "삭제",
"entry_actions.deleted": "삭제됨",
diff --git a/apps/desktop/locales/app/pt.json b/apps/desktop/locales/app/pt.json
index 1ad2fd980..8cdd99d1c 100644
--- a/apps/desktop/locales/app/pt.json
+++ b/apps/desktop/locales/app/pt.json
@@ -15,6 +15,8 @@
"discover.rss_url": "RSS URL",
"discover.select_placeholder": "選択",
"entry_actions.copy_link": "リンクをコピー",
+ "entry_actions.exported_notify": "Artigo exportado como PDF.",
+ "entry_actions.export_as_pdf": "Exportar como PDF",
"entry_actions.failed_to_save_to_eagle": "Eagle への保存に失敗しました。",
"entry_actions.failed_to_save_to_instapaper": "Instapaper への保存に失敗しました。",
"entry_actions.failed_to_save_to_readwise": "Readwise への保存に失敗しました。",
diff --git a/apps/desktop/locales/app/ru.json b/apps/desktop/locales/app/ru.json
index 1481cc068..8f8f8f6b4 100644
--- a/apps/desktop/locales/app/ru.json
+++ b/apps/desktop/locales/app/ru.json
@@ -103,6 +103,8 @@
"discover.target.lists": "Списки",
"entry_actions.copied_notify": "{{which}} скопировано в буфер обмена.",
"entry_actions.copy_link": "Копировать ссылку",
+ "entry_actions.exported_notify": "Статья экспортирована в PDF.",
+ "entry_actions.export_as_pdf": "Экспортировать в PDF",
"entry_actions.copy_title": "Копировать заголовок",
"entry_actions.delete": "Удалить",
"entry_actions.deleted": "Удалено.",
diff --git a/apps/desktop/locales/app/tr.json b/apps/desktop/locales/app/tr.json
index 4ffe75fc7..726367e8c 100644
--- a/apps/desktop/locales/app/tr.json
+++ b/apps/desktop/locales/app/tr.json
@@ -28,6 +28,8 @@
"discover.target.label": "Arama hedefi",
"discover.target.lists": "Listeler",
"entry_actions.copy_link": "Bağlantıyı kopyala",
+ "entry_actions.exported_notify": "Makale PDF olarak dışa aktarıldı.",
+ "entry_actions.export_as_pdf": "PDF olarak dışa aktar",
"entry_actions.failed_to_save_to_eagle": "Eagle'a kaydetme başarısız oldu.",
"entry_actions.failed_to_save_to_instapaper": "Instapaper'a kaydetme başarısız oldu.",
"entry_actions.failed_to_save_to_readwise": "Readwise'a kaydetme başarısız oldu.",
diff --git a/apps/desktop/locales/app/zh-CN.json b/apps/desktop/locales/app/zh-CN.json
index e26fa4c0e..b94c9ba28 100644
--- a/apps/desktop/locales/app/zh-CN.json
+++ b/apps/desktop/locales/app/zh-CN.json
@@ -108,6 +108,8 @@
"entry_actions.image_gallery": "图片库",
"entry_actions.copied_notify": "{{which}}已复制到剪贴板。",
"entry_actions.copy_link": "复制链接",
+ "entry_actions.exported_notify": "文章已导出为 PDF。",
+ "entry_actions.export_as_pdf": "导出为 PDF",
"entry_actions.copy_title": "复制标题",
"entry_actions.delete": "删除",
"entry_actions.deleted": "已删除",
diff --git a/apps/desktop/locales/app/zh-HK.json b/apps/desktop/locales/app/zh-HK.json
index e2ea1d741..c4425cec6 100644
--- a/apps/desktop/locales/app/zh-HK.json
+++ b/apps/desktop/locales/app/zh-HK.json
@@ -108,6 +108,8 @@
"entry_actions.image_gallery": "圖片庫",
"entry_actions.copied_notify": "{{which}}已複製到剪貼簿",
"entry_actions.copy_link": "複製連結",
+ "entry_actions.exported_notify": "文章已匯出為 PDF。",
+ "entry_actions.export_as_pdf": "匯出為 PDF",
"entry_actions.copy_title": "複製標題",
"entry_actions.delete": "刪除",
"entry_actions.deleted": "已刪除",
diff --git a/apps/desktop/locales/app/zh-TW.json b/apps/desktop/locales/app/zh-TW.json
index d9ddca9b0..7490e9116 100644
--- a/apps/desktop/locales/app/zh-TW.json
+++ b/apps/desktop/locales/app/zh-TW.json
@@ -104,6 +104,8 @@
"discover.target.lists": "列表",
"entry_actions.copied_notify": "{{which}}已複製到剪貼簿",
"entry_actions.copy_link": "複製連結",
+ "entry_actions.exported_notify": "文章已匯出為 PDF。",
+ "entry_actions.export_as_pdf": "匯出為 PDF",
"entry_actions.copy_title": "複製標題",
"entry_actions.delete": "刪除",
"entry_actions.deleted": "已刪除。",
diff --git a/apps/desktop/src/renderer/src/hooks/biz/useEntryActions.tsx b/apps/desktop/src/renderer/src/hooks/biz/useEntryActions.tsx
index b92a58e80..3f2d2b4af 100644
--- a/apps/desktop/src/renderer/src/hooks/biz/useEntryActions.tsx
+++ b/apps/desktop/src/renderer/src/hooks/biz/useEntryActions.tsx
@@ -146,6 +146,10 @@ export const useEntryActions = ({ entryId, view }: { entryId: string; view?: Fee
hide: !entry?.entries.url,
shortcut: shortcuts.entry.copyLink.key,
},
+ {
+ id: COMMAND_ID.entry.exportAsPDF,
+ onClick: runCmdFn(COMMAND_ID.entry.exportAsPDF, [{ entryId }]),
+ },
{
id: COMMAND_ID.entry.openInBrowser,
onClick: runCmdFn(COMMAND_ID.entry.openInBrowser, [{ entryId }]),
diff --git a/apps/desktop/src/renderer/src/modules/command/commands/entry.tsx b/apps/desktop/src/renderer/src/modules/command/commands/entry.tsx
index 60d95a1d1..8aa3fc1f7 100644
--- a/apps/desktop/src/renderer/src/modules/command/commands/entry.tsx
+++ b/apps/desktop/src/renderer/src/modules/command/commands/entry.tsx
@@ -175,6 +175,25 @@ export const useRegisterEntryCommands = () => {
})
},
},
+ {
+ id: COMMAND_ID.entry.exportAsPDF,
+ label: t("entry_actions.export_as_pdf"),
+ icon: ,
+ run: ({ entryId }) => {
+ const entry = useEntryStore.getState().flatMapEntries[entryId]
+
+ if (!entry) {
+ toast.error("Failed to export as pdf: entry is not available", { duration: 3000 })
+ return
+ }
+
+ window.print()
+
+ toast(t("entry_actions.exported_notify"), {
+ duration: 1000,
+ })
+ },
+ },
{
id: COMMAND_ID.entry.copyTitle,
label: t("entry_actions.copy_title"),
diff --git a/apps/desktop/src/renderer/src/modules/command/commands/id.ts b/apps/desktop/src/renderer/src/modules/command/commands/id.ts
index ce5611051..dc68451b7 100644
--- a/apps/desktop/src/renderer/src/modules/command/commands/id.ts
+++ b/apps/desktop/src/renderer/src/modules/command/commands/id.ts
@@ -11,6 +11,7 @@ export const COMMAND_ID = {
read: "entry:read",
toggleAISummary: "entry:toggle-ai-summary",
toggleAITranslation: "entry:toggle-ai-translation",
+ exportAsPDF: "entry:export-as-pdf",
},
integration: {
saveToEagle: "integration:save-to-eagle",
diff --git a/apps/desktop/src/renderer/src/modules/command/commands/types.ts b/apps/desktop/src/renderer/src/modules/command/commands/types.ts
index dabd5a6fb..dd3d83653 100644
--- a/apps/desktop/src/renderer/src/modules/command/commands/types.ts
+++ b/apps/desktop/src/renderer/src/modules/command/commands/types.ts
@@ -25,6 +25,11 @@ export type CopyLinkCommand = Command<{
fn: (data: { entryId: string }) => void
}>
+export type ExportAsPDFCommand = Command<{
+ id: typeof COMMAND_ID.entry.exportAsPDF
+ fn: (data: { entryId: string }) => void
+}>
+
export type CopyTitleCommand = Command<{
id: typeof COMMAND_ID.entry.copyTitle
fn: (data: { entryId: string }) => void
@@ -65,6 +70,7 @@ export type EntryCommand =
| StarCommand
| DeleteCommand
| CopyLinkCommand
+ | ExportAsPDFCommand
| CopyTitleCommand
| OpenInBrowserCommand
| ViewSourceContentCommand
diff --git a/apps/desktop/src/renderer/src/modules/customize-toolbar/constant.ts b/apps/desktop/src/renderer/src/modules/customize-toolbar/constant.ts
index d92c4f85a..199091925 100644
--- a/apps/desktop/src/renderer/src/modules/customize-toolbar/constant.ts
+++ b/apps/desktop/src/renderer/src/modules/customize-toolbar/constant.ts
@@ -21,6 +21,7 @@ export const DEFAULT_ACTION_ORDER: ToolbarActionOrder = {
[
COMMAND_ID.entry.copyLink,
COMMAND_ID.entry.openInBrowser,
+ COMMAND_ID.entry.exportAsPDF,
COMMAND_ID.entry.read,
] as string[]
).includes(id),
diff --git a/apps/desktop/src/renderer/src/styles/main.css b/apps/desktop/src/renderer/src/styles/main.css
index 2df451951..0ca4475ed 100644
--- a/apps/desktop/src/renderer/src/styles/main.css
+++ b/apps/desktop/src/renderer/src/styles/main.css
@@ -2,3 +2,13 @@
@import "./additional.css";
@import "./scrollbar.css";
@import "./cursor.css";
+
+@media print {
+ * {
+ overflow: visible !important;
+ page-break-after: avoid;
+ page-break-before: avoid;
+ break-inside: avoid;
+ height: max-content;
+ }
+}
diff --git a/apps/mobile/src/icons/pdf_cute_re.tsx b/apps/mobile/src/icons/pdf_cute_re.tsx
new file mode 100644
index 000000000..fa13fd1b0
--- /dev/null
+++ b/apps/mobile/src/icons/pdf_cute_re.tsx
@@ -0,0 +1,25 @@
+import * as React from "react"
+import Svg, { Path } from "react-native-svg"
+
+interface PdfCuteReIconProps {
+ width?: number
+ height?: number
+ color?: string
+}
+
+export const PdfCuteReIcon = ({
+ width = 24,
+ height = 24,
+ color = "#10161F",
+}: PdfCuteReIconProps) => {
+ return (
+
+ )
+}
diff --git a/icons/mgc/pdf_cute_re.svg b/icons/mgc/pdf_cute_re.svg
new file mode 100644
index 000000000..cae867576
--- /dev/null
+++ b/icons/mgc/pdf_cute_re.svg
@@ -0,0 +1 @@
+
\ No newline at end of file