pdfdesk 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. pdfdesk-0.1.0/.gitignore +14 -0
  2. pdfdesk-0.1.0/LICENSE +21 -0
  3. pdfdesk-0.1.0/PKG-INFO +209 -0
  4. pdfdesk-0.1.0/README.md +188 -0
  5. pdfdesk-0.1.0/pdfdesk/__init__.py +3 -0
  6. pdfdesk-0.1.0/pdfdesk/__main__.py +3 -0
  7. pdfdesk-0.1.0/pdfdesk/cli.py +107 -0
  8. pdfdesk-0.1.0/prototype/app.js +683 -0
  9. pdfdesk-0.1.0/prototype/index.html +35 -0
  10. pdfdesk-0.1.0/prototype/styles.css +294 -0
  11. pdfdesk-0.1.0/prototype/vendor/fonts/OFL-ibmplexmono.txt +93 -0
  12. pdfdesk-0.1.0/prototype/vendor/fonts/OFL-ibmplexsans.txt +93 -0
  13. pdfdesk-0.1.0/prototype/vendor/fonts/OFL-sourceserif4.txt +93 -0
  14. pdfdesk-0.1.0/prototype/vendor/fonts/fonts.css +151 -0
  15. pdfdesk-0.1.0/prototype/vendor/fonts/ibm-plex-mono-400-latin-ext.woff2 +0 -0
  16. pdfdesk-0.1.0/prototype/vendor/fonts/ibm-plex-mono-400-latin.woff2 +0 -0
  17. pdfdesk-0.1.0/prototype/vendor/fonts/ibm-plex-mono-500-latin-ext.woff2 +0 -0
  18. pdfdesk-0.1.0/prototype/vendor/fonts/ibm-plex-mono-500-latin.woff2 +0 -0
  19. pdfdesk-0.1.0/prototype/vendor/fonts/ibm-plex-sans-400-latin-ext.woff2 +0 -0
  20. pdfdesk-0.1.0/prototype/vendor/fonts/ibm-plex-sans-400-latin.woff2 +0 -0
  21. pdfdesk-0.1.0/prototype/vendor/fonts/ibm-plex-sans-500-latin-ext.woff2 +0 -0
  22. pdfdesk-0.1.0/prototype/vendor/fonts/ibm-plex-sans-500-latin.woff2 +0 -0
  23. pdfdesk-0.1.0/prototype/vendor/fonts/ibm-plex-sans-600-latin-ext.woff2 +0 -0
  24. pdfdesk-0.1.0/prototype/vendor/fonts/ibm-plex-sans-600-latin.woff2 +0 -0
  25. pdfdesk-0.1.0/prototype/vendor/fonts/source-serif-4-400-latin-ext.woff2 +0 -0
  26. pdfdesk-0.1.0/prototype/vendor/fonts/source-serif-4-400-latin.woff2 +0 -0
  27. pdfdesk-0.1.0/prototype/vendor/fonts/source-serif-4-600-latin-ext.woff2 +0 -0
  28. pdfdesk-0.1.0/prototype/vendor/fonts/source-serif-4-600-latin.woff2 +0 -0
  29. pdfdesk-0.1.0/prototype/vendor/fonts/source-serif-4-700-latin-ext.woff2 +0 -0
  30. pdfdesk-0.1.0/prototype/vendor/fonts/source-serif-4-700-latin.woff2 +0 -0
  31. pdfdesk-0.1.0/prototype/vendor/pdfjs/LICENSE +177 -0
  32. pdfdesk-0.1.0/prototype/vendor/pdfjs/pdf.min.js +22 -0
  33. pdfdesk-0.1.0/prototype/vendor/pdfjs/pdf.worker.min.js +22 -0
  34. pdfdesk-0.1.0/pyproject.toml +45 -0
  35. pdfdesk-0.1.0/reference/README.md +20 -0
@@ -0,0 +1,14 @@
1
+ node_modules/
2
+ dist/
3
+ target/
4
+ .DS_Store
5
+ Thumbs.db
6
+ *.log
7
+ .env
8
+ # personal test PDFs
9
+ samples/*.pdf
10
+
11
+ # Python packaging
12
+ __pycache__/
13
+ *.egg-info/
14
+ .venv/
pdfdesk-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Subham
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
pdfdesk-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,209 @@
1
+ Metadata-Version: 2.5
2
+ Name: pdfdesk
3
+ Version: 0.1.0
4
+ Summary: Prototype: a local-first workspace for reading research papers, with a PDF reader, highlights, notes and reading-session history.
5
+ Project-URL: Homepage, https://github.com/shubham10divakar/pdfdesk
6
+ Project-URL: Source, https://github.com/shubham10divakar/pdfdesk
7
+ Project-URL: Issues, https://github.com/shubham10divakar/pdfdesk/issues
8
+ Project-URL: Roadmap, https://github.com/shubham10divakar/pdfdesk/blob/main/docs/roadmap.md
9
+ Author: Subham
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: local-first,notes,papers,pdf,reader,research
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Environment :: Web Environment
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Topic :: Scientific/Engineering
19
+ Requires-Python: >=3.9
20
+ Description-Content-Type: text/markdown
21
+
22
+ <div align="center">
23
+
24
+ # PDFDesk
25
+
26
+ ### Your reading desk for research papers.
27
+
28
+ **Library, PDF reader, highlights, notes, and a complete log of your reading, all in one window, all on your machine.**
29
+
30
+ [![PyPI](https://img.shields.io/pypi/v/pdfdesk?color=2f55d4&label=pypi)](https://pypi.org/project/pdfdesk/)
31
+ [![Downloads](https://static.pepy.tech/badge/pdfdesk)](https://pepy.tech/project/pdfdesk)
32
+ [![Downloads / month](https://img.shields.io/pypi/dm/pdfdesk?label=downloads%2Fmonth)](https://pypistats.org/packages/pdfdesk)
33
+ [![Python](https://img.shields.io/pypi/pyversions/pdfdesk)](https://pypi.org/project/pdfdesk/)
34
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green)](https://github.com/shubham10divakar/pdfdesk/blob/main/LICENSE)
35
+
36
+ ```bash
37
+ pip install pdfdesk && pdfdesk
38
+ ```
39
+
40
+ <img src="https://raw.githubusercontent.com/shubham10divakar/pdfdesk/main/docs/assets/overview.png" alt="PDFDesk overview: reading stats, continue reading, reading calendar, up next and revision queue" width="100%">
41
+
42
+ </div>
43
+
44
+ ---
45
+
46
+ ## Why PDFDesk
47
+
48
+ You read dozens of papers a month. A file manager tells you **where** a PDF lives. An annotation tool tells you **what** you marked. Neither tells you **how you read it**: when you opened it, how far you got, how long you actually spent, and what you concluded at the end of each sitting.
49
+
50
+ PDFDesk keeps that record for you. Every paper moves through a reading lifecycle, every sitting becomes a session, and every highlight and note links back to the page it came from. Months later you can see what you read and why it mattered.
51
+
52
+ <table>
53
+ <tr>
54
+ <td width="33%" valign="top">
55
+
56
+ ### 📚 Organise
57
+ A library that knows where each paper is in your reading, from *Inbox* to *Completed*.
58
+
59
+ </td>
60
+ <td width="33%" valign="top">
61
+
62
+ ### 🖍️ Read & annotate
63
+ A fast PDF reader with colour-coded highlights and Markdown notes that link to pages.
64
+
65
+ </td>
66
+ <td width="33%" valign="top">
67
+
68
+ ### 📈 Remember
69
+ Sessions, a reading calendar, streaks and a daily revision queue bring papers back.
70
+
71
+ </td>
72
+ </tr>
73
+ </table>
74
+
75
+ ---
76
+
77
+ ## Read with highlights that mean something
78
+
79
+ <img src="https://raw.githubusercontent.com/shubham10divakar/pdfdesk/main/docs/assets/reader-highlights.png" alt="PDFDesk reader with colour-coded highlights and the highlights panel" width="100%">
80
+
81
+ Select text on any page and pick a colour. Each colour has one job, so a page of highlights reads at a glance:
82
+
83
+ | | Colour | Meaning |
84
+ |---|---|---|
85
+ | 🟨 | Yellow | Key idea |
86
+ | 🟩 | Green | Method or result |
87
+ | 🟦 | Blue | Definition |
88
+ | 🟥 | Pink | Question or doubt |
89
+
90
+ - Add a comment to any highlight, and filter the panel by colour.
91
+ - Click a highlight in the panel to jump straight to it in the PDF.
92
+ - Highlights store the selected text as well as their position, so they stay put when you zoom.
93
+ - **Extract to notes** pulls every highlight into your notes, each with its page reference.
94
+
95
+ ## Notes that point back to the page
96
+
97
+ <img src="https://raw.githubusercontent.com/shubham10divakar/pdfdesk/main/docs/assets/reader-notes.png" alt="PDFDesk notes panel with Markdown and page links next to the PDF" width="100%">
98
+
99
+ - Write in **Markdown**: headings, bullets, quotes.
100
+ - Type `p. 12` anywhere and it becomes a link to page 12.
101
+ - **Cite p. N** drops in a reference to the page you're on.
102
+ - **Insert highlights** adds your highlights to the notes, each with its page.
103
+ - **Copy** exports the notes as Markdown, ready for your paper, wiki or Obsidian vault.
104
+ - Notes save automatically as you type.
105
+
106
+ ## A library that follows your reading
107
+
108
+ <img src="https://raw.githubusercontent.com/shubham10divakar/pdfdesk/main/docs/assets/library.png" alt="PDFDesk library with status, progress, last read and tags for each paper" width="100%">
109
+
110
+ Every paper has a place in the reading lifecycle:
111
+
112
+ **Inbox → Planned → Reading → Paused → Completed → Revisit**
113
+
114
+ - Opening a paper moves it to *Reading*. When you reach the last page, PDFDesk asks whether it's *Completed* or worth a *Revisit*.
115
+ - **Import** by button or drag and drop. Title, authors and page count come from the PDF itself.
116
+ - **Search** by title, author or tag from anywhere.
117
+ - **Tags** in the sidebar, with counts, for one-click filtering.
118
+ - See each paper's status, progress bar, pages read and when you last opened it.
119
+ - Set a **target page and date** ("finish section 3 by Friday") and it shows up in *Up next*.
120
+
121
+ ## Every session, recorded
122
+
123
+ PDFDesk logs each sitting with a paper on its own:
124
+
125
+ - **Active time only.** The clock pauses when the tab is hidden or you've been idle for 3 minutes, so your stats count reading, not open tabs.
126
+ - **Pages covered**: the first and last page you reached.
127
+ - **A takeaway**: an optional line on what you got out of the session.
128
+ - **Resume where you left off**: every paper reopens at your last page.
129
+ - **Bookmarks** for pages you'll come back to.
130
+
131
+ ## Your reading, at a glance
132
+
133
+ The overview turns your sessions into a picture of your reading:
134
+
135
+ - **Stats**: papers in your library, reading now, completed, time and pages this week.
136
+ - **Continue reading**: papers in progress, with a progress bar and a one-click resume.
137
+ - **Reading calendar**: a 17-week heatmap of your reading days, with your current streak and total hours.
138
+ - **Up next**: planned and paused papers, sorted by target date.
139
+ - **Revision queue**: highlights from finished papers come back each day, so ideas don't fade.
140
+ - **Reading log**: every session, newest first.
141
+
142
+ ## Easy on the eyes, day and night
143
+
144
+ <img src="https://raw.githubusercontent.com/shubham10divakar/pdfdesk/main/docs/assets/reader-dark.png" alt="PDFDesk reader in dark mode" width="100%">
145
+
146
+ Dark mode follows your system setting. Typography is set for long reading sessions: Source Serif 4 for titles and notes, IBM Plex Sans for the interface, IBM Plex Mono for numbers and page references.
147
+
148
+ ## Keyboard shortcuts
149
+
150
+ | Key | Action |
151
+ |---|---|
152
+ | `j` or `→` | Next page |
153
+ | `k` or `←` | Previous page |
154
+ | `b` | Bookmark this page |
155
+ | `Enter` in the page box | Jump to page |
156
+ | `Esc` | Close the highlight menu |
157
+
158
+ ---
159
+
160
+ ## Private by design
161
+
162
+ - 🔒 **Local-first.** Your PDFs, notes and history stay on your computer. No account, no cloud, no tracking.
163
+ - ✈️ **Works offline.** The PDF engine and fonts ship inside the package. Nothing loads from the internet.
164
+ - 🪶 **Lightweight.** One small package with **zero Python dependencies**. If you have Python 3.9+, you can run it.
165
+
166
+ ## Get started
167
+
168
+ ```bash
169
+ pip install pdfdesk
170
+ pdfdesk
171
+ ```
172
+
173
+ PDFDesk opens in your browser at **http://localhost:5173**. A few example papers are loaded so you can explore. Remove them from the sidebar when you're ready, then drop in your own PDFs.
174
+
175
+ ```bash
176
+ pdfdesk --no-browser # start without opening a browser window
177
+ pdfdesk --port 8080 # use another port
178
+ pdfdesk --version
179
+ ```
180
+
181
+ Upgrade any time with `pip install -U pdfdesk`.
182
+
183
+ > **Good to know:** in this version your library is stored in the browser you open PDFDesk in, for the address `localhost:5173`. Keep using the same browser and the default port and your library will be there every time. Uninstalling the package doesn't delete it.
184
+
185
+ ## What's coming
186
+
187
+ PDFDesk is at **0.1**, an early release. Next up:
188
+
189
+ - **Export and import** your whole library, PDFs included.
190
+ - **arXiv and DOI import**: paste an id and the title, authors, year and venue fill themselves in.
191
+ - **Full-text search** across notes and highlights.
192
+ - **PDF outline** in the sidebar, from the paper's table of contents.
193
+ - **PDFDesk 1.0** as a native desktop app (Tauri + SQLite), installed the same way, with `pip install -U pdfdesk`.
194
+ - Later: links between papers, spaced revision, weekly reading reports, Zotero import.
195
+
196
+ The full plan is in [docs/roadmap.md](https://github.com/shubham10divakar/pdfdesk/blob/main/docs/roadmap.md).
197
+
198
+ ## Contributing
199
+
200
+ Bug reports and ideas are welcome in [Issues](https://github.com/shubham10divakar/pdfdesk/issues). To work on the code, start with [DEVELOPMENT.md](https://github.com/shubham10divakar/pdfdesk/blob/main/DEVELOPMENT.md).
201
+
202
+ ## License
203
+
204
+ [MIT](https://github.com/shubham10divakar/pdfdesk/blob/main/LICENSE). Bundled third-party code keeps its own licence: [PDF.js](https://mozilla.github.io/pdf.js/) (Apache-2.0) and the Source Serif 4, IBM Plex Sans and IBM Plex Mono fonts (SIL Open Font License 1.1).
205
+
206
+ <div align="center">
207
+ <br>
208
+ <sub>Built for people who read papers for a living.</sub>
209
+ </div>
@@ -0,0 +1,188 @@
1
+ <div align="center">
2
+
3
+ # PDFDesk
4
+
5
+ ### Your reading desk for research papers.
6
+
7
+ **Library, PDF reader, highlights, notes, and a complete log of your reading, all in one window, all on your machine.**
8
+
9
+ [![PyPI](https://img.shields.io/pypi/v/pdfdesk?color=2f55d4&label=pypi)](https://pypi.org/project/pdfdesk/)
10
+ [![Downloads](https://static.pepy.tech/badge/pdfdesk)](https://pepy.tech/project/pdfdesk)
11
+ [![Downloads / month](https://img.shields.io/pypi/dm/pdfdesk?label=downloads%2Fmonth)](https://pypistats.org/packages/pdfdesk)
12
+ [![Python](https://img.shields.io/pypi/pyversions/pdfdesk)](https://pypi.org/project/pdfdesk/)
13
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green)](https://github.com/shubham10divakar/pdfdesk/blob/main/LICENSE)
14
+
15
+ ```bash
16
+ pip install pdfdesk && pdfdesk
17
+ ```
18
+
19
+ <img src="https://raw.githubusercontent.com/shubham10divakar/pdfdesk/main/docs/assets/overview.png" alt="PDFDesk overview: reading stats, continue reading, reading calendar, up next and revision queue" width="100%">
20
+
21
+ </div>
22
+
23
+ ---
24
+
25
+ ## Why PDFDesk
26
+
27
+ You read dozens of papers a month. A file manager tells you **where** a PDF lives. An annotation tool tells you **what** you marked. Neither tells you **how you read it**: when you opened it, how far you got, how long you actually spent, and what you concluded at the end of each sitting.
28
+
29
+ PDFDesk keeps that record for you. Every paper moves through a reading lifecycle, every sitting becomes a session, and every highlight and note links back to the page it came from. Months later you can see what you read and why it mattered.
30
+
31
+ <table>
32
+ <tr>
33
+ <td width="33%" valign="top">
34
+
35
+ ### 📚 Organise
36
+ A library that knows where each paper is in your reading, from *Inbox* to *Completed*.
37
+
38
+ </td>
39
+ <td width="33%" valign="top">
40
+
41
+ ### 🖍️ Read & annotate
42
+ A fast PDF reader with colour-coded highlights and Markdown notes that link to pages.
43
+
44
+ </td>
45
+ <td width="33%" valign="top">
46
+
47
+ ### 📈 Remember
48
+ Sessions, a reading calendar, streaks and a daily revision queue bring papers back.
49
+
50
+ </td>
51
+ </tr>
52
+ </table>
53
+
54
+ ---
55
+
56
+ ## Read with highlights that mean something
57
+
58
+ <img src="https://raw.githubusercontent.com/shubham10divakar/pdfdesk/main/docs/assets/reader-highlights.png" alt="PDFDesk reader with colour-coded highlights and the highlights panel" width="100%">
59
+
60
+ Select text on any page and pick a colour. Each colour has one job, so a page of highlights reads at a glance:
61
+
62
+ | | Colour | Meaning |
63
+ |---|---|---|
64
+ | 🟨 | Yellow | Key idea |
65
+ | 🟩 | Green | Method or result |
66
+ | 🟦 | Blue | Definition |
67
+ | 🟥 | Pink | Question or doubt |
68
+
69
+ - Add a comment to any highlight, and filter the panel by colour.
70
+ - Click a highlight in the panel to jump straight to it in the PDF.
71
+ - Highlights store the selected text as well as their position, so they stay put when you zoom.
72
+ - **Extract to notes** pulls every highlight into your notes, each with its page reference.
73
+
74
+ ## Notes that point back to the page
75
+
76
+ <img src="https://raw.githubusercontent.com/shubham10divakar/pdfdesk/main/docs/assets/reader-notes.png" alt="PDFDesk notes panel with Markdown and page links next to the PDF" width="100%">
77
+
78
+ - Write in **Markdown**: headings, bullets, quotes.
79
+ - Type `p. 12` anywhere and it becomes a link to page 12.
80
+ - **Cite p. N** drops in a reference to the page you're on.
81
+ - **Insert highlights** adds your highlights to the notes, each with its page.
82
+ - **Copy** exports the notes as Markdown, ready for your paper, wiki or Obsidian vault.
83
+ - Notes save automatically as you type.
84
+
85
+ ## A library that follows your reading
86
+
87
+ <img src="https://raw.githubusercontent.com/shubham10divakar/pdfdesk/main/docs/assets/library.png" alt="PDFDesk library with status, progress, last read and tags for each paper" width="100%">
88
+
89
+ Every paper has a place in the reading lifecycle:
90
+
91
+ **Inbox → Planned → Reading → Paused → Completed → Revisit**
92
+
93
+ - Opening a paper moves it to *Reading*. When you reach the last page, PDFDesk asks whether it's *Completed* or worth a *Revisit*.
94
+ - **Import** by button or drag and drop. Title, authors and page count come from the PDF itself.
95
+ - **Search** by title, author or tag from anywhere.
96
+ - **Tags** in the sidebar, with counts, for one-click filtering.
97
+ - See each paper's status, progress bar, pages read and when you last opened it.
98
+ - Set a **target page and date** ("finish section 3 by Friday") and it shows up in *Up next*.
99
+
100
+ ## Every session, recorded
101
+
102
+ PDFDesk logs each sitting with a paper on its own:
103
+
104
+ - **Active time only.** The clock pauses when the tab is hidden or you've been idle for 3 minutes, so your stats count reading, not open tabs.
105
+ - **Pages covered**: the first and last page you reached.
106
+ - **A takeaway**: an optional line on what you got out of the session.
107
+ - **Resume where you left off**: every paper reopens at your last page.
108
+ - **Bookmarks** for pages you'll come back to.
109
+
110
+ ## Your reading, at a glance
111
+
112
+ The overview turns your sessions into a picture of your reading:
113
+
114
+ - **Stats**: papers in your library, reading now, completed, time and pages this week.
115
+ - **Continue reading**: papers in progress, with a progress bar and a one-click resume.
116
+ - **Reading calendar**: a 17-week heatmap of your reading days, with your current streak and total hours.
117
+ - **Up next**: planned and paused papers, sorted by target date.
118
+ - **Revision queue**: highlights from finished papers come back each day, so ideas don't fade.
119
+ - **Reading log**: every session, newest first.
120
+
121
+ ## Easy on the eyes, day and night
122
+
123
+ <img src="https://raw.githubusercontent.com/shubham10divakar/pdfdesk/main/docs/assets/reader-dark.png" alt="PDFDesk reader in dark mode" width="100%">
124
+
125
+ Dark mode follows your system setting. Typography is set for long reading sessions: Source Serif 4 for titles and notes, IBM Plex Sans for the interface, IBM Plex Mono for numbers and page references.
126
+
127
+ ## Keyboard shortcuts
128
+
129
+ | Key | Action |
130
+ |---|---|
131
+ | `j` or `→` | Next page |
132
+ | `k` or `←` | Previous page |
133
+ | `b` | Bookmark this page |
134
+ | `Enter` in the page box | Jump to page |
135
+ | `Esc` | Close the highlight menu |
136
+
137
+ ---
138
+
139
+ ## Private by design
140
+
141
+ - 🔒 **Local-first.** Your PDFs, notes and history stay on your computer. No account, no cloud, no tracking.
142
+ - ✈️ **Works offline.** The PDF engine and fonts ship inside the package. Nothing loads from the internet.
143
+ - 🪶 **Lightweight.** One small package with **zero Python dependencies**. If you have Python 3.9+, you can run it.
144
+
145
+ ## Get started
146
+
147
+ ```bash
148
+ pip install pdfdesk
149
+ pdfdesk
150
+ ```
151
+
152
+ PDFDesk opens in your browser at **http://localhost:5173**. A few example papers are loaded so you can explore. Remove them from the sidebar when you're ready, then drop in your own PDFs.
153
+
154
+ ```bash
155
+ pdfdesk --no-browser # start without opening a browser window
156
+ pdfdesk --port 8080 # use another port
157
+ pdfdesk --version
158
+ ```
159
+
160
+ Upgrade any time with `pip install -U pdfdesk`.
161
+
162
+ > **Good to know:** in this version your library is stored in the browser you open PDFDesk in, for the address `localhost:5173`. Keep using the same browser and the default port and your library will be there every time. Uninstalling the package doesn't delete it.
163
+
164
+ ## What's coming
165
+
166
+ PDFDesk is at **0.1**, an early release. Next up:
167
+
168
+ - **Export and import** your whole library, PDFs included.
169
+ - **arXiv and DOI import**: paste an id and the title, authors, year and venue fill themselves in.
170
+ - **Full-text search** across notes and highlights.
171
+ - **PDF outline** in the sidebar, from the paper's table of contents.
172
+ - **PDFDesk 1.0** as a native desktop app (Tauri + SQLite), installed the same way, with `pip install -U pdfdesk`.
173
+ - Later: links between papers, spaced revision, weekly reading reports, Zotero import.
174
+
175
+ The full plan is in [docs/roadmap.md](https://github.com/shubham10divakar/pdfdesk/blob/main/docs/roadmap.md).
176
+
177
+ ## Contributing
178
+
179
+ Bug reports and ideas are welcome in [Issues](https://github.com/shubham10divakar/pdfdesk/issues). To work on the code, start with [DEVELOPMENT.md](https://github.com/shubham10divakar/pdfdesk/blob/main/DEVELOPMENT.md).
180
+
181
+ ## License
182
+
183
+ [MIT](https://github.com/shubham10divakar/pdfdesk/blob/main/LICENSE). Bundled third-party code keeps its own licence: [PDF.js](https://mozilla.github.io/pdf.js/) (Apache-2.0) and the Source Serif 4, IBM Plex Sans and IBM Plex Mono fonts (SIL Open Font License 1.1).
184
+
185
+ <div align="center">
186
+ <br>
187
+ <sub>Built for people who read papers for a living.</sub>
188
+ </div>
@@ -0,0 +1,3 @@
1
+ """PDFDesk: a local-first workspace for reading research papers."""
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1,3 @@
1
+ from pdfdesk.cli import main
2
+
3
+ raise SystemExit(main())
@@ -0,0 +1,107 @@
1
+ """`pdfdesk` command: serve the bundled browser app on localhost and open it."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import errno
7
+ import functools
8
+ import http.server
9
+ import socket
10
+ import sys
11
+ import threading
12
+ import webbrowser
13
+ from pathlib import Path
14
+
15
+ from pdfdesk import __version__
16
+
17
+ DEFAULT_PORT = 5173
18
+
19
+ # Windows can map .js to text/plain through the registry, which browsers refuse to run.
20
+ TYPES = {
21
+ ".html": "text/html; charset=utf-8",
22
+ ".js": "text/javascript; charset=utf-8",
23
+ ".mjs": "text/javascript; charset=utf-8",
24
+ ".css": "text/css; charset=utf-8",
25
+ ".json": "application/json; charset=utf-8",
26
+ ".svg": "image/svg+xml",
27
+ ".png": "image/png",
28
+ ".pdf": "application/pdf",
29
+ ".woff2": "font/woff2",
30
+ ".txt": "text/plain; charset=utf-8",
31
+ }
32
+
33
+
34
+ def static_dir() -> Path:
35
+ """The app files: bundled inside the wheel, or prototype/ when run from a checkout."""
36
+ bundled = Path(__file__).parent / "static"
37
+ if (bundled / "index.html").is_file():
38
+ return bundled
39
+ checkout = Path(__file__).parent.parent / "prototype"
40
+ if (checkout / "index.html").is_file():
41
+ return checkout
42
+ raise SystemExit("pdfdesk: app files are missing from this install. Reinstall with `pip install --force-reinstall pdfdesk`.")
43
+
44
+
45
+ class Handler(http.server.SimpleHTTPRequestHandler):
46
+ extensions_map = {**http.server.SimpleHTTPRequestHandler.extensions_map, **TYPES}
47
+
48
+ def end_headers(self) -> None:
49
+ # Revalidate every load, so an upgraded install never runs a stale app.js.
50
+ self.send_header("Cache-Control", "no-cache")
51
+ super().end_headers()
52
+
53
+ def log_message(self, format: str, *args) -> None: # quiet by default
54
+ if self.server.verbose: # type: ignore[attr-defined]
55
+ super().log_message(format, *args)
56
+
57
+
58
+ class Server(http.server.ThreadingHTTPServer):
59
+ # On Windows SO_REUSEADDR lets a second server bind the same port silently, so two copies would
60
+ # "run" at once. Claim the port exclusively there instead; elsewhere keep fast restarts.
61
+ allow_reuse_address = sys.platform != "win32"
62
+ daemon_threads = True
63
+
64
+ def server_bind(self) -> None:
65
+ if sys.platform == "win32" and hasattr(socket, "SO_EXCLUSIVEADDRUSE"):
66
+ self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_EXCLUSIVEADDRUSE, 1)
67
+ super().server_bind()
68
+
69
+
70
+ def main(argv: list[str] | None = None) -> int:
71
+ parser = argparse.ArgumentParser(
72
+ prog="pdfdesk",
73
+ description="Start PDFDesk on this computer and open it in your browser.",
74
+ )
75
+ parser.add_argument("--port", type=int, default=DEFAULT_PORT,
76
+ help=f"port to serve on (default {DEFAULT_PORT}). Your library is stored per port, so keep it the same.")
77
+ parser.add_argument("--no-browser", action="store_true", help="don't open a browser window")
78
+ parser.add_argument("--verbose", action="store_true", help="log every request")
79
+ parser.add_argument("--version", action="version", version=f"pdfdesk {__version__}")
80
+ args = parser.parse_args(argv)
81
+
82
+ handler = functools.partial(Handler, directory=str(static_dir()))
83
+ try:
84
+ server = Server(("127.0.0.1", args.port), handler)
85
+ except OSError as e:
86
+ if e.errno in (errno.EADDRINUSE, errno.EACCES) or getattr(e, "winerror", None) in (10048, 10013):
87
+ print(
88
+ f"pdfdesk: port {args.port} is already in use. PDFDesk may already be running at http://localhost:{args.port}\n"
89
+ "Your library is saved per port, so a different port starts with an empty library.\n"
90
+ "To use another port anyway: pdfdesk --port <number>",
91
+ file=sys.stderr,
92
+ )
93
+ return 1
94
+ raise
95
+ server.verbose = args.verbose # type: ignore[attr-defined]
96
+
97
+ url = f"http://localhost:{args.port}/"
98
+ print(f"PDFDesk {__version__} running at {url} (Ctrl+C to stop)")
99
+ if not args.no_browser:
100
+ threading.Timer(0.3, webbrowser.open, args=(url,)).start()
101
+ try:
102
+ server.serve_forever()
103
+ except KeyboardInterrupt:
104
+ print("\nStopped.")
105
+ finally:
106
+ server.server_close()
107
+ return 0