retold-remote 0.0.22 → 0.0.25

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 (47) hide show
  1. package/css/retold-remote.css +87 -20
  2. package/docs/README.md +59 -11
  3. package/docs/_sidebar.md +1 -0
  4. package/docs/collections.md +30 -0
  5. package/docs/ebook-reader.md +75 -1
  6. package/docs/image-explorer.md +27 -1
  7. package/docs/server-setup.md +28 -18
  8. package/docs/stack-launcher.md +218 -0
  9. package/docs/ultravisor-integration.md +2 -0
  10. package/package.json +10 -7
  11. package/source/Pict-Application-RetoldRemote.js +2 -0
  12. package/source/RetoldRemote-ExtensionMaps.js +1 -1
  13. package/source/cli/RetoldRemote-Server-Setup.js +240 -2
  14. package/source/cli/RetoldRemote-Stack-Launcher.js +387 -0
  15. package/source/cli/RetoldRemote-Stack-Run.js +41 -0
  16. package/source/cli/commands/RetoldRemote-Command-Serve.js +129 -54
  17. package/source/providers/CollectionManager-AddItems.js +166 -0
  18. package/source/providers/Pict-Provider-GalleryNavigation.js +46 -0
  19. package/source/providers/keyboard-handlers/KeyHandler-ImageExplorer.js +5 -0
  20. package/source/providers/keyboard-handlers/KeyHandler-Viewer.js +23 -0
  21. package/source/server/RetoldRemote-CollectionExportService.js +696 -0
  22. package/source/server/RetoldRemote-CollectionService.js +5 -0
  23. package/source/server/RetoldRemote-EbookService.js +194 -3
  24. package/source/server/RetoldRemote-SubimageService.js +530 -0
  25. package/source/server/RetoldRemote-ToolDetector.js +50 -0
  26. package/source/server/RetoldRemote-UltravisorOperations.js +6 -6
  27. package/source/views/MediaViewer-EbookViewer.js +419 -1
  28. package/source/views/MediaViewer-PdfViewer.js +963 -0
  29. package/source/views/PictView-Remote-CollectionsPanel.js +166 -0
  30. package/source/views/PictView-Remote-ImageExplorer.js +606 -1
  31. package/source/views/PictView-Remote-ImageViewer.js +2 -2
  32. package/source/views/PictView-Remote-Layout.js +12 -0
  33. package/source/views/PictView-Remote-MediaViewer.js +83 -25
  34. package/source/views/PictView-Remote-SubimagesPanel.js +353 -0
  35. package/web-application/css/retold-remote.css +87 -20
  36. package/web-application/docs/README.md +59 -11
  37. package/web-application/docs/_sidebar.md +1 -0
  38. package/web-application/docs/collections.md +30 -0
  39. package/web-application/docs/ebook-reader.md +75 -1
  40. package/web-application/docs/image-explorer.md +27 -1
  41. package/web-application/docs/server-setup.md +28 -18
  42. package/web-application/docs/stack-launcher.md +218 -0
  43. package/web-application/docs/ultravisor-integration.md +2 -0
  44. package/web-application/retold-remote.js +399 -45
  45. package/web-application/retold-remote.js.map +1 -1
  46. package/web-application/retold-remote.min.js +13 -12
  47. package/web-application/retold-remote.min.js.map +1 -1
@@ -2263,26 +2263,7 @@ html, body
2263
2263
  {
2264
2264
  opacity: 1;
2265
2265
  }
2266
- .retold-remote-image-explore-btn
2267
- {
2268
- position: absolute;
2269
- bottom: 16px;
2270
- right: 16px;
2271
- background: rgba(40, 44, 52, 0.85);
2272
- color: #abb2bf;
2273
- border: 1px solid rgba(255, 255, 255, 0.15);
2274
- padding: 6px 14px;
2275
- border-radius: 6px;
2276
- font-size: 0.82rem;
2277
- cursor: pointer;
2278
- z-index: 20;
2279
- transition: background 0.2s, color 0.2s;
2280
- }
2281
- .retold-remote-image-explore-btn:hover
2282
- {
2283
- background: rgba(97, 175, 239, 0.3);
2284
- color: #fff;
2285
- }
2266
+ /* Explore button overlay styles removed — button moved to nav bar */
2286
2267
  .retold-remote-image-large-badge
2287
2268
  {
2288
2269
  position: absolute;
@@ -2480,6 +2461,75 @@ html, body
2480
2461
  text-align: center;
2481
2462
  color: var(--retold-text-secondary);
2482
2463
  }
2464
+ /* Subimage region overlays */
2465
+ .retold-remote-iex-region-overlay
2466
+ {
2467
+ border: 2px solid rgba(229, 192, 123, 0.85);
2468
+ background: rgba(229, 192, 123, 0.08);
2469
+ pointer-events: none;
2470
+ position: relative;
2471
+ }
2472
+ /* Subimages sidebar panel */
2473
+ .retold-remote-subimages-panel
2474
+ {
2475
+ overflow-y: auto;
2476
+ height: 100%;
2477
+ }
2478
+ .retold-remote-subimages-item
2479
+ {
2480
+ display: flex;
2481
+ align-items: center;
2482
+ justify-content: space-between;
2483
+ padding: 6px 10px;
2484
+ border-bottom: 1px solid var(--retold-border);
2485
+ cursor: default;
2486
+ transition: background 0.15s;
2487
+ }
2488
+ .retold-remote-subimages-item:hover
2489
+ {
2490
+ background: rgba(255, 255, 255, 0.04);
2491
+ }
2492
+ .retold-remote-subimages-item-info
2493
+ {
2494
+ flex: 1;
2495
+ min-width: 0;
2496
+ overflow: hidden;
2497
+ }
2498
+ .retold-remote-subimages-item-label
2499
+ {
2500
+ font-size: 0.82rem;
2501
+ color: var(--retold-text);
2502
+ white-space: nowrap;
2503
+ overflow: hidden;
2504
+ text-overflow: ellipsis;
2505
+ }
2506
+ .retold-remote-subimages-item-dims
2507
+ {
2508
+ font-size: 0.7rem;
2509
+ color: var(--retold-text-dim);
2510
+ margin-top: 1px;
2511
+ }
2512
+ .retold-remote-subimages-item-actions
2513
+ {
2514
+ display: flex;
2515
+ gap: 2px;
2516
+ margin-left: 6px;
2517
+ flex-shrink: 0;
2518
+ }
2519
+ .retold-remote-subimages-item-actions button
2520
+ {
2521
+ background: transparent;
2522
+ border: 1px solid var(--retold-border);
2523
+ border-radius: 3px;
2524
+ color: var(--retold-text-dim);
2525
+ cursor: pointer;
2526
+ transition: color 0.15s, border-color 0.15s;
2527
+ }
2528
+ .retold-remote-subimages-item-actions button:hover
2529
+ {
2530
+ color: var(--retold-text);
2531
+ border-color: var(--retold-accent);
2532
+ }
2483
2533
 
2484
2534
  /* ============================================================
2485
2535
  AudioExplorer
@@ -3515,6 +3565,23 @@ html, body
3515
3565
  border-color: var(--retold-accent);
3516
3566
  color: var(--retold-text-primary);
3517
3567
  }
3568
+ .retold-remote-collections-export-btn
3569
+ {
3570
+ padding: 3px 8px;
3571
+ border: 1px solid var(--retold-border);
3572
+ border-radius: 3px;
3573
+ background: transparent;
3574
+ color: var(--retold-text-muted);
3575
+ font-size: 0.72rem;
3576
+ cursor: pointer;
3577
+ font-family: inherit;
3578
+ margin-left: auto;
3579
+ }
3580
+ .retold-remote-collections-export-btn:hover
3581
+ {
3582
+ border-color: var(--retold-accent);
3583
+ color: var(--retold-text-primary);
3584
+ }
3518
3585
  /* ---- Item rows ---- */
3519
3586
  .retold-remote-collection-item
3520
3587
  {
package/docs/README.md CHANGED
@@ -4,10 +4,18 @@ A browser-based media server and NAS file explorer. Point it at a folder and bro
4
4
 
5
5
  ## Quick Start
6
6
 
7
+ Just the media browser:
8
+
7
9
  ```bash
8
10
  npx retold-remote serve /path/to/media
9
11
  ```
10
12
 
13
+ The full stack (Retold Remote + embedded Orator-Conversion + child Ultravisor):
14
+
15
+ ```bash
16
+ retold-stack /path/to/media
17
+ ```
18
+
11
19
  Or with Docker:
12
20
 
13
21
  ```bash
@@ -17,17 +25,24 @@ docker run -p 8086:8086 -v /path/to/media:/media retold-remote
17
25
 
18
26
  Then open `http://localhost:8086` in a browser.
19
27
 
28
+ See [Stack Launcher](stack-launcher.md) for what `retold-stack` does and how the XDG-style data paths work.
29
+
20
30
  ## Features
21
31
 
22
32
  - **Gallery browser** with grid and list views, thumbnail generation, and lazy loading
23
33
  - **Image viewer** with three fit modes, 0.25x-8x zoom, and EXIF orientation support
24
34
  - **Video viewer** with action menu, in-browser playback, VLC streaming, and frame explorer
25
35
  - **Audio viewer** with waveform visualization, selection-based playback, and segment extraction
26
- - **eBook reader** for EPUB and MOBI with table of contents and page navigation
36
+ - **eBook reader** for EPUB and MOBI with table of contents, page navigation, text selection capture, and visual region selection
37
+ - **PDF viewer** with full pdf.js rendering, page navigation, text layer selection, and visual region selection
38
+ - **Document conversion** for DOC, DOCX, RTF, ODT, WPD, ODP, PPT(X), ODS, XLS(X) — converted to PDF on the fly via Orator-Conversion + LibreOffice
27
39
  - **Code/text viewer** with syntax highlighting for 30+ languages
28
- - **PDF viewer** via native browser rendering
29
40
  - **Archive browsing** into zip, 7z, rar, tar.gz, cbz, and cbr files as virtual folders
30
41
  - **Filtering and sorting** by media type, extension, file size, date, and text search (with regex)
42
+ - **Subimage regions** — draw labeled rectangles on images, ebook pages, and PDF pages; persisted per file
43
+ - **Collections & Export** — bookmark files, image crops, video clips, audio clips, and document regions; export the whole collection to a folder with proper file cutting
44
+ - **Stack mode** — single command launches Ultravisor coordinator + Retold Remote + embedded Orator-Conversion with sane XDG data paths
45
+ - **Ultravisor offload** — heavy work (frame extraction, waveforms, conversions) dispatched to a beacon worker on a faster machine
31
46
  - **15 themes** from greyscale to retro and cyberpunk
32
47
  - **Full keyboard navigation** across every mode
33
48
  - **Media type override** to force any file open as image, video, audio, or text (keys 1-4)
@@ -40,14 +55,16 @@ Then open `http://localhost:8086` in a browser.
40
55
  | Document | Contents |
41
56
  |----------|----------|
42
57
  | [Server Setup and Docker](server-setup.md) | Installation, CLI options, environment variables, configuration, Docker |
58
+ | [Stack Launcher](stack-launcher.md) | `retold-stack` and `--stack` flag, XDG paths, child process orchestration |
59
+ | [Ultravisor Integration](ultravisor-integration.md) | Offloading heavy media processing to a beacon worker |
43
60
  | [Image Viewer](image-viewer.md) | Fit modes, zoom, keyboard shortcuts, mouse interactions |
44
61
  | [Video Viewer](video-viewer.md) | Action menu, in-browser playback, VLC streaming |
45
62
  | [Audio Viewer](audio-viewer.md) | HTML5 playback, autoplay, VLC streaming |
46
- | [eBook Reader](ebook-reader.md) | EPUB/MOBI support, table of contents, page navigation |
47
- | [Image Explorer](image-explorer.md) | Deep-zoom with OpenSeadragon, DZI tiling, coordinate display |
63
+ | [eBook Reader](ebook-reader.md) | EPUB/MOBI support, TOC, page nav, text/region selection |
64
+ | [Image Explorer](image-explorer.md) | Deep-zoom with OpenSeadragon, DZI tiling, region selection |
48
65
  | [Video Explorer](video-explorer.md) | Frame grid, timeline, range selection, clip extraction |
49
66
  | [Audio Explorer](audio-explorer.md) | Waveform visualization, selection, zoom, segment playback |
50
- | [Collections](collections.md) | Bookmarks, favorites, quick-add, item types, operation plans |
67
+ | [Collections](collections.md) | Bookmarks, favorites, quick-add, item types, operation plans, export |
51
68
  | [File Metadata](metadata.md) | Info overlay, sidebar metadata, EXIF/GPS, ffprobe, explorer info bars |
52
69
 
53
70
  ## Keyboard Shortcuts (All Modes)
@@ -158,11 +175,24 @@ In the frame preview overlay:
158
175
  | `+` / `=` | Zoom in |
159
176
  | `-` | Zoom out |
160
177
  | `0` | Reset zoom |
161
- | `a` | Quick-add to collection |
178
+ | `s` | Toggle region selection mode (draw rectangles) |
179
+ | `a` | Quick-add to collection (current region if selected) |
162
180
  | `b` | Toggle collection panel |
163
181
  | `h` | Toggle favorite |
164
182
  | `Esc` | Back to viewer |
165
183
 
184
+ ### Document Viewer (PDF / EPUB)
185
+
186
+ | Key | Action |
187
+ |-----|--------|
188
+ | `s` | Toggle visual region selection mode |
189
+ | `a` | Quick-add document region to collection |
190
+ | `Esc` | Back to gallery |
191
+
192
+ In the PDF viewer, page navigation buttons and a page input are in the controls bar. The text layer supports native browser text selection — use the **Save Selection** button to capture selected text as a labeled region.
193
+
194
+ In the EPUB reader, the controls bar exposes **Save Selection** (captures the selected text + CFI) and **Select Region** (draws a rectangle over the rendered page).
195
+
166
196
  ### Sidebar (F9)
167
197
 
168
198
  | Key | Action |
@@ -184,7 +214,9 @@ mp4, webm, mov, mkv, avi, wmv, flv, m4v, ogv, mpg, mpeg, mpe, mpv, m2v, ts, mts,
184
214
  mp3, wav, ogg, flac, aac, m4a, wma, oga
185
215
 
186
216
  ### Documents
187
- pdf, epub, mobi
217
+ pdf, epub, mobi, doc, docx, rtf, odt, wpd, wps, pages, odp, ppt, pptx, ods, xls, xlsx
218
+
219
+ Documents beyond pdf/epub/mobi are converted to PDF on the fly via the embedded Orator-Conversion service (requires LibreOffice or Calibre on the server).
188
220
 
189
221
  ### Archives
190
222
  zip, 7z, rar, tar, tar.gz, tar.bz2, tar.xz, tgz, cbz, cbr
@@ -204,13 +236,16 @@ These external tools enhance functionality when available on the server:
204
236
 
205
237
  | Tool | Feature |
206
238
  |------|---------|
207
- | **sharp** (npm) | Fast image thumbnail generation |
239
+ | **sharp** (npm) | Fast image thumbnail generation, region cropping |
208
240
  | **ImageMagick** | Fallback image thumbnails |
209
- | **ffmpeg** | Video thumbnails, frame extraction, audio waveforms |
241
+ | **ffmpeg** | Video thumbnails, frame extraction, audio waveforms, clip cutting |
210
242
  | **ffprobe** | Media metadata (duration, resolution, codec) |
211
243
  | **7-Zip** (7z) | Archive browsing for rar, 7z, tar.* formats |
212
244
  | **VLC** | External video streaming |
213
- | **ebook-convert** (Calibre) | MOBI to EPUB conversion |
245
+ | **audiowaveform** (BBC) | Faster audio waveform peak generation |
246
+ | **ebook-convert** (Calibre) | MOBI/AZW to EPUB conversion (and PDF fallback for documents) |
247
+ | **LibreOffice** (`soffice`) | DOC/DOCX/RTF/ODT/WPD/PPT(X)/XLS(X) to PDF conversion |
248
+ | **pdftk** + **pdftoppm** (poppler) | PDF page extraction and rendering (used by Orator-Conversion) |
214
249
 
215
250
  Without these tools the application still works -- images serve directly, videos play in-browser, and zip/cbz archives use native extraction.
216
251
 
@@ -231,7 +266,20 @@ Without these tools the application still works -- images serve directly, videos
231
266
  | GET | `/api/media/audio-waveform?path=&peaks=` | Audio waveform peak data |
232
267
  | GET | `/api/media/audio-segment?path=&start=&end=` | Extract audio segment |
233
268
  | GET | `/api/media/ebook-convert?path=` | Convert MOBI to EPUB |
234
- | GET | `/api/media/ebook/:cacheKey/:filename` | Serve converted ebook |
269
+ | GET | `/api/media/doc-convert?path=` | Convert DOC/DOCX/RTF/ODT/WPD/etc. to PDF |
270
+ | GET | `/api/media/ebook/:cacheKey/:filename` | Serve converted ebook or PDF |
271
+ | GET | `/api/media/pdf-text?path=&page=` | Extract text from a PDF page |
272
+ | GET | `/api/media/subimage-regions?path=` | List labeled regions for an image, ebook, or PDF |
273
+ | POST | `/api/media/subimage-regions` | Add a labeled region (visual or text-selection) |
274
+ | PUT | `/api/media/subimage-regions/:id` | Update a region's label or coordinates |
275
+ | DELETE | `/api/media/subimage-regions/:id?path=` | Remove a labeled region |
276
+ | GET | `/api/collections` | List all collections |
277
+ | POST | `/api/collections/:guid/items` | Add items to a collection |
278
+ | POST | `/api/collections/:guid/export` | Export collection to a folder (cuts clips, crops images) |
279
+ | POST | `/api/conversion/1.0/doc-to-pdf` | Convert any document buffer to PDF (via Orator-Conversion) |
280
+ | POST | `/api/conversion/1.0/pdf-to-page-png/:Page` | Render a PDF page as PNG |
281
+ | POST | `/api/conversion/1.0/pdf-to-page-jpg/:Page/:LongSidePixels` | Render and resize a PDF page as JPEG |
282
+ | POST | `/api/conversion/1.0/image/resize` | Resize an image |
235
283
  | POST | `/api/media/open` | Open file in external player (VLC) |
236
284
 
237
285
  ## License
package/docs/_sidebar.md CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  - Getting Started
4
4
  - [Server Setup & Docker](server-setup.md)
5
+ - [Stack Launcher](stack-launcher.md)
5
6
  - [Ultravisor Integration](ultravisor-integration.md)
6
7
  - [Ultravisor Beacon Tool Setup](ultravisor-configuration.md)
7
8
 
@@ -16,6 +16,11 @@ Press `a` in any mode to add the current item to a collection. If a collection i
16
16
  | Video explorer | Video frame | Path, timestamp, cached frame image |
17
17
  | Video explorer (with selection) | Video clip | Path, start time, end time |
18
18
  | Audio explorer (with selection) | Audio clip | Path, start time, end time |
19
+ | Image explorer (with active region) | Image crop | Path, X, Y, Width, Height in original pixels |
20
+ | PDF viewer (with text selection) | Document region (text) | Path, page number, selected text |
21
+ | PDF viewer (with visual region) | Document region (visual) | Path, page number, X/Y/Width/Height in PDF units |
22
+ | EPUB reader (with text selection) | Document region (text) | Path, CFI, spine index, chapter title, selected text |
23
+ | EPUB reader (with visual region) | Document region (visual) | Path, X/Y/Width/Height in container coordinates |
19
24
 
20
25
  ### Folder Choice
21
26
 
@@ -136,11 +141,35 @@ Pending item destinations can be edited inline by clicking the destination path.
136
141
  | `a` | Gallery, viewer, all explorers | Quick-add current item to collection |
137
142
  | `s` | Video explorer | Add selected range as video clip |
138
143
  | `s` | Audio explorer | Save audio snippet to collection |
144
+ | `s` | Image explorer | Toggle region selection mode |
145
+ | `s` | Document viewer (PDF/EPUB) | Toggle visual region selection mode |
139
146
  | `[` | Video explorer | Set selection start at current frame |
140
147
  | `]` | Video explorer | Set selection end at current frame |
141
148
  | `b` | All modes | Toggle collection panel |
142
149
  | `h` | All modes | Toggle favorite |
143
150
 
151
+ ## Export
152
+
153
+ Collections can be exported to a folder within the content root. Each item is processed according to its type:
154
+
155
+ | Item Type | Export Behavior |
156
+ |-----------|----------------|
157
+ | `file` / `subfile` | Copied directly to the destination |
158
+ | `image-crop` | Cropped via sharp at the original resolution |
159
+ | `video-clip` | Extracted via `ffmpeg -ss -t -c copy` |
160
+ | `video-frame` | Extracted via `ffmpeg -ss -vframes 1` |
161
+ | `audio-clip` | Extracted via `ffmpeg -ss -t -vn` |
162
+ | `document-region` (text) | Written as a `.txt` file with the captured text and source metadata |
163
+ | `document-region` (visual) | Metadata file describing the page and region |
164
+ | `folder` | Copied recursively |
165
+ | `folder-contents` | Files copied flat into the destination |
166
+
167
+ Exported files are named `{sortOrder}_{label}.{ext}` so the order is preserved on disk.
168
+
169
+ To export, click the **⇩ Export** button in the collection detail header. You will be prompted for a destination path (relative to the content root).
170
+
171
+ The export endpoint is restricted to paths within the content root for safety — paths containing `..` or absolute paths are rejected.
172
+
144
173
  ## Data Storage
145
174
 
146
175
  Collections are stored server-side as Bibliograph records. Each collection is a JSON document containing the collection metadata and its items array. The favorites collection uses a well-known GUID and is created automatically.
@@ -160,3 +189,4 @@ Client-side state (which collection is open, panel width, last-used collection)
160
189
  | PUT | `/api/collections/:guid/reorder` | Reorder items (manual sort) |
161
190
  | POST | `/api/collections/copy-items` | Copy items between collections |
162
191
  | POST | `/api/collections/:guid/execute` | Execute pending operations (operation plans) |
192
+ | POST | `/api/collections/:guid/export` | Export the collection to a folder within the content root |
@@ -79,12 +79,86 @@ RUN apt-get update && apt-get install -y calibre && rm -rf /var/lib/apt/lists/*
79
79
 
80
80
  ## PDF Files
81
81
 
82
- PDF files are rendered using the browser's native PDF viewer in an iframe. No additional tools or libraries are required. The browser provides its own controls for page navigation, zoom, and search.
82
+ PDF files are rendered using a full **pdf.js** canvas pipeline. The library is loaded from CDN on first use; no server-side dependencies are required for basic display.
83
+
84
+ ### Page Navigation
85
+
86
+ The controls bar exposes:
87
+
88
+ - **← Prev** / **Next →** — page navigation
89
+ - **Page input** — type a page number and press Enter to jump
90
+ - **Zoom In / Out / Fit** — adjust scale (0.25x – 5x)
91
+
92
+ ### Text Selection
93
+
94
+ PDF.js renders an invisible text layer over the canvas, so native browser text selection works. Drag to select text, then click **💾 Save Selection** to capture it as a labeled region.
95
+
96
+ The capture stores: page number, selected text, optional label.
97
+
98
+ ### Visual Region Selection
99
+
100
+ Click **✂ Select Region** to enter visual selection mode. A crosshair cursor appears over the page canvas. Drag a rectangle, release, and a label input appears in the controls bar.
101
+
102
+ The capture stores: page number, X/Y/Width/Height in PDF units (so the region remaps correctly at any zoom level), optional label.
103
+
104
+ ### Server-Side Text Extraction
105
+
106
+ `GET /api/media/pdf-text?path=<file>&page=<num>` returns the extracted text for a specific page (via pdf-parse). This is useful for search indexing or for when you want the full text without selecting it manually.
107
+
108
+ ## Convertible Document Formats
109
+
110
+ Beyond PDF/EPUB/MOBI, the viewer also handles `.doc`, `.docx`, `.rtf`, `.odt`, `.wpd`, `.wps`, `.pages`, `.odp`, `.ppt`, `.pptx`, `.ods`, `.xls`, and `.xlsx` files. These are converted to PDF on the fly via the embedded **Orator-Conversion** service, then displayed in the same pdf.js viewer.
111
+
112
+ ### Conversion Pipeline
113
+
114
+ 1. The browser opens a convertible document
115
+ 2. Retold Remote shows a "Converting document to PDF..." spinner
116
+ 3. The server calls `GET /api/media/doc-convert?path=<file>` which delegates to `orator-conversion`'s `doc-to-pdf` custom converter
117
+ 4. The converter pipes the file through LibreOffice headless (`soffice --headless --convert-to pdf`)
118
+ 5. Falls back to Calibre's `ebook-convert` if LibreOffice is unavailable
119
+ 6. The resulting PDF is cached in the same Parime cache as ebooks (separate `manifest-pdf.json`)
120
+ 7. The browser loads the PDF in the standard pdf.js viewer with full text and region selection
121
+
122
+ Conversion results are cached per file (keyed by path + mtime), so reopening the same document is instant after the first conversion.
123
+
124
+ ### Required Tools
125
+
126
+ | Tool | Use |
127
+ |------|-----|
128
+ | **LibreOffice** (`soffice`) | Best fidelity for Word, RTF, ODT, WordPerfect, PowerPoint, Excel |
129
+ | **Calibre** (`ebook-convert`) | Fallback for documents LibreOffice can't handle |
130
+
131
+ Install at least one of them on the server. On macOS: `brew install --cask libreoffice` or `brew install calibre`.
132
+
133
+ ## eBook Selection Features
134
+
135
+ The EPUB reader supports the same labeled-region capture pattern as PDF and image viewers.
136
+
137
+ ### Save Text Selection
138
+
139
+ 1. Select text in the rendered EPUB content (works through the epub.js iframe via `getContents()`)
140
+ 2. Click **💾 Save Selection** in the controls bar
141
+ 3. Enter a label and save
142
+
143
+ The capture stores:
144
+
145
+ - **CFI** (Canonical Fragment Identifier) — exact location for re-navigating later
146
+ - **Spine index** — which section of the book
147
+ - **Chapter title** — best-effort lookup from the TOC
148
+ - **Selected text** — the actual highlighted prose
149
+
150
+ Click a saved text selection in the **Regions** sidebar tab to navigate back to its exact location via `rendition.display(cfi)`.
151
+
152
+ ### Visual Region Selection
153
+
154
+ Click **✂ Select Region** to overlay a transparent crosshair on the rendered page. Drag a rectangle to capture a visual area. The capture stores X/Y/Width/Height plus the viewport dimensions at capture time (so coordinates can be remapped if the window is resized later).
83
155
 
84
156
  ## Limitations
85
157
 
86
158
  - MOBI conversion requires Calibre's `ebook-convert` on the server
159
+ - Document conversion (DOC, DOCX, RTF, etc.) requires LibreOffice or Calibre on the server
87
160
  - DRM-protected ebooks cannot be read
88
161
  - Complex EPUB layouts (fixed-layout EPUBs, heavy CSS) may not render perfectly
89
162
  - The reader uses single-page mode only (no two-page spreads)
90
163
  - Page numbers shown in the UI correspond to the reflowed content, not the original book pagination
164
+ - EPUB visual region coordinates are container-relative; they remap reasonably at different window sizes but are not perfectly stable across major layout reflows
@@ -51,11 +51,37 @@ If Sharp is not available on the server, the image loads directly regardless of
51
51
  | `+` / `=` | Zoom in (1.5x) |
52
52
  | `-` | Zoom out (1.5x) |
53
53
  | `0` | Reset to home zoom (fit to view) |
54
- | `a` | Quick-add to active collection |
54
+ | `s` | Toggle region selection mode |
55
+ | `a` | Quick-add to active collection (current region if one is selected) |
55
56
  | `b` | Toggle collection panel |
56
57
  | `h` | Toggle favorite |
57
58
  | `Esc` | Back to image viewer |
58
59
 
60
+ ## Subimage Regions
61
+
62
+ Press `s` (or click the **✂ Select** button in the header) to enter region selection mode. The cursor changes to a crosshair and OpenSeadragon's drag-to-pan is temporarily disabled.
63
+
64
+ Drag a rectangle on the image. On release, an inline label input appears in the controls bar — type a name and hit Enter. The region is saved with these coordinates:
65
+
66
+ - **X, Y** — top-left corner in original image pixels
67
+ - **Width, Height** — dimensions in original image pixels
68
+
69
+ Saved regions render as gold-bordered overlays with floating label badges. They persist per file via the SubimageService and appear in the **Regions** sidebar tab.
70
+
71
+ ### Region Actions
72
+
73
+ From the **Regions** sidebar tab you can:
74
+
75
+ - 🔍 **Navigate** — zoom the explorer to the saved region (`viewport.fitBounds(imageRect)`)
76
+ - ➕ **Add to Collection** — saves as an `image-crop` collection item with the original-pixel `CropRegion`
77
+ - 🗑️ **Delete** — removes the region
78
+
79
+ ### Multiple Regions
80
+
81
+ You can save unlimited labeled regions per image. They never lose resolution because the coordinates are stored in the original image pixel space, not in viewport pixels. When the collection is exported, each region is cropped at full resolution via `sharp.extract()`.
82
+
83
+ This same labeling pattern works on CBZ/CBR comic pages (each page is a regular image inside an archive — no special handling needed) and is the foundation for the document region system in the EPUB and PDF viewers.
84
+
59
85
  ## Coordinate Display
60
86
 
61
87
  In DZI tile mode, the info bar shows the pixel coordinates of the point under the cursor in real time (e.g., "(4096, 3072)"). This updates as the mouse moves across the canvas and reflects the actual pixel position in the original full-resolution image.
@@ -21,31 +21,31 @@ The build step bundles the client-side JavaScript with Quackage and copies asset
21
21
 
22
22
  ## Running the Server
23
23
 
24
- ### CLI Command
24
+ ### CLI Commands
25
25
 
26
- ```bash
27
- retold-remote serve [content-path] [options]
28
- ```
29
-
30
- Or using the short alias:
26
+ There are three bin entries provided by the `retold-remote` package:
31
27
 
32
28
  ```bash
33
- rr serve /path/to/media
29
+ retold-remote serve [content-path] [options] # full form
30
+ rr serve [content-path] [options] # short alias
31
+ retold-stack [content-path] [options] # convenience: serve --stack
34
32
  ```
35
33
 
36
34
  If `content-path` is omitted, the current directory is served.
37
35
 
36
+ The `retold-stack` shortcut auto-injects `serve --stack`, which spawns Ultravisor as a child process and uses XDG-style data paths. See [Stack Launcher](stack-launcher.md) for the full story.
37
+
38
38
  ### Options
39
39
 
40
40
  | Flag | Description | Default |
41
41
  |------|-------------|---------|
42
42
  | `-p, --port [port]` | Port to listen on | Random 7000-7999 |
43
- | `-H, --hashed-filenames` | Enable hashed filename mode (hides real paths from browser) | Off |
44
- | `-c, --cache-path [path]` | Root cache directory | `./dist/retold-cache/` |
45
- | `--cache-thumbnails [path]` | Override thumbnail cache location | `<cache-root>/thumbnails/` |
46
- | `--cache-archives [path]` | Override archive extraction cache | `<cache-root>/archives/` |
47
- | `--cache-video-frames [path]` | Override video frame cache | `<cache-root>/video-frames/` |
48
- | `--cache-audio-waveforms [path]` | Override audio waveform cache | `<cache-root>/audio-waveforms/` |
43
+ | `--no-hash` | Disable hashed filename mode (use plain paths in URLs) | Hashing on |
44
+ | `-c, --cache-path [path]` | Root cache directory | `./dist/retold-cache/` (or `~/.cache/retold-remote/` in stack mode) |
45
+ | `--cache-server [url]` | URL of a remote Parime cache server | None |
46
+ | `-u, --ultravisor [url]` | Connect to an Ultravisor mesh; URL defaults to `http://localhost:54321` if omitted | None |
47
+ | `--stack` | Spawn Ultravisor as a child process and connect to it. Uses XDG-style data paths under `~/.local/share` and `~/.cache`. See [Stack Launcher](stack-launcher.md) | Off |
48
+ | `-l, --logfile [path]` | Write logs to a file (auto-generates timestamped name if path omitted) | Console only |
49
49
 
50
50
  ### Direct Node.js
51
51
 
@@ -65,20 +65,30 @@ Default port is `8086` when using `server.js` directly.
65
65
  ### Examples
66
66
 
67
67
  ```bash
68
- # Serve current directory on port 8086
69
- node server.js
68
+ # Serve current directory on a random port
69
+ retold-remote serve
70
70
 
71
71
  # Serve a specific folder
72
- node server.js /mnt/nas/media
72
+ retold-remote serve /mnt/nas/media
73
73
 
74
74
  # CLI with custom port
75
75
  retold-remote serve /mnt/nas/media -p 3000
76
76
 
77
- # Hashed filenames for privacy
78
- retold-remote serve /mnt/nas/media -H
77
+ # Plain paths in URLs (disable hashing)
78
+ retold-remote serve /mnt/nas/media --no-hash
79
79
 
80
80
  # Custom cache location (useful for Docker volumes)
81
81
  retold-remote serve /media -c /cache
82
+
83
+ # Connect to an existing Ultravisor mesh
84
+ retold-remote serve /media -u http://192.168.1.100:54321
85
+
86
+ # Full stack: spawn Ultravisor as a child process, embed Orator-Conversion,
87
+ # use XDG paths (~/.local/share/ultravisor, ~/.cache/retold-remote)
88
+ retold-stack /mnt/nas/media
89
+
90
+ # Same thing via the explicit flag
91
+ retold-remote serve --stack /mnt/nas/media
82
92
  ```
83
93
 
84
94
  ## Configuration