@page-scanner/cli 0.1.1 → 0.2.1

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 (55) hide show
  1. package/README.md +58 -4
  2. package/dist/api.d.ts +82 -2
  3. package/dist/api.d.ts.map +1 -1
  4. package/dist/api.js +147 -18
  5. package/dist/api.js.map +1 -1
  6. package/dist/batch.d.ts +60 -0
  7. package/dist/batch.d.ts.map +1 -0
  8. package/dist/batch.js +116 -0
  9. package/dist/batch.js.map +1 -0
  10. package/dist/cli/args.d.ts +27 -4
  11. package/dist/cli/args.d.ts.map +1 -1
  12. package/dist/cli/args.js +129 -10
  13. package/dist/cli/args.js.map +1 -1
  14. package/dist/cli/commands.d.ts +2 -0
  15. package/dist/cli/commands.d.ts.map +1 -1
  16. package/dist/cli/commands.js +170 -14
  17. package/dist/cli/commands.js.map +1 -1
  18. package/dist/daemon/rpc-server.d.ts.map +1 -1
  19. package/dist/daemon/rpc-server.js +17 -1
  20. package/dist/daemon/rpc-server.js.map +1 -1
  21. package/dist/diff/image.d.ts +42 -0
  22. package/dist/diff/image.d.ts.map +1 -0
  23. package/dist/diff/image.js +144 -0
  24. package/dist/diff/image.js.map +1 -0
  25. package/dist/diff/index.d.ts +46 -0
  26. package/dist/diff/index.d.ts.map +1 -0
  27. package/dist/diff/index.js +108 -0
  28. package/dist/diff/index.js.map +1 -0
  29. package/dist/diff/png.d.ts +12 -0
  30. package/dist/diff/png.d.ts.map +1 -0
  31. package/dist/diff/png.js +169 -0
  32. package/dist/diff/png.js.map +1 -0
  33. package/dist/diff/text.d.ts +54 -0
  34. package/dist/diff/text.d.ts.map +1 -0
  35. package/dist/diff/text.js +198 -0
  36. package/dist/diff/text.js.map +1 -0
  37. package/dist/index.d.ts +6 -3
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +6 -3
  40. package/dist/index.js.map +1 -1
  41. package/dist/output.d.ts +10 -0
  42. package/dist/output.d.ts.map +1 -1
  43. package/dist/output.js +24 -4
  44. package/dist/output.js.map +1 -1
  45. package/dist/protocol.d.ts +37 -2
  46. package/dist/protocol.d.ts.map +1 -1
  47. package/dist/protocol.js +23 -2
  48. package/dist/protocol.js.map +1 -1
  49. package/dist/verify.d.ts +31 -0
  50. package/dist/verify.d.ts.map +1 -0
  51. package/dist/verify.js +115 -0
  52. package/dist/verify.js.map +1 -0
  53. package/dist/version.d.ts +1 -1
  54. package/dist/version.js +1 -1
  55. package/package.json +3 -2
package/README.md CHANGED
@@ -73,10 +73,16 @@ page-scanner pair [--port <n>] [--rotate] [--wait <s>=120] [--no-wait] [--js
73
73
  page-scanner status [--json]
74
74
  page-scanner browsers [--json]
75
75
  page-scanner tabs [--browser <id|label>] [--wait <s>=30] [--json]
76
- page-scanner scan (--url <u> | --tab <id>) [--window <id>] [--browser <id|label>]
76
+ page-scanner scan (--url <u>... | --urls <file|-> | --tab <id>) [--window <id>]
77
+ [--name <template>] [--markdown beside|only]
78
+ [--browser <id|label>]
77
79
  [--format pdf|png|jpeg=pdf] [--page-size auto|a4|letter=a4]
78
- [--quality <0-1>] [--video frame|blank] [--open-editor]
80
+ [--quality <0-1>] [--video frame|blank]
81
+ [--scheme auto|light|dark]
82
+ [--page-width window|a4|letter] [--open-editor]
79
83
  [--out <file|dir>] [--wait <s>=30] [--timeout <s>=120] [--json]
84
+ page-scanner diff <old> <new> [--out <file>] [--json]
85
+ page-scanner verify <file> [--record <file.integrity.json>] [--json]
80
86
  page-scanner serve [--daemon] [--idle <min>]
81
87
  page-scanner stop
82
88
  page-scanner --version | --help
@@ -90,10 +96,51 @@ and a directory otherwise, in which case the browser's suggested filename is use
90
96
  Parent directories are created. A relative path is relative to **your** working directory, not the
91
97
  daemon's, which is why the daemon hands the bytes back rather than writing them itself.
92
98
 
99
+ `--page-width` lays the page out at the width of a sheet before capturing it, the way a narrow
100
+ window would, so the PDF prints at 1:1 rather than being scaled down. `window`, the default, is
101
+ the width the browser has the page at. A 1280 px window on A4 is scaled to 55 %, which puts 16 px
102
+ body text at 6.5 pt; `--page-width a4` puts it at 12.
103
+
104
+ `--scheme` picks which of a page's two themes to capture, for a page that has both. `auto`, the
105
+ default, is whichever the browser is showing; `light` and `dark` force one. It applies to the PDF
106
+ as well as the preview, which is the point: Chrome prints every page in the light scheme unless it
107
+ is told otherwise, so without this a dark page produced a white PDF.
108
+
93
109
  `--page-size` decides what a PDF is laid onto. `a4` and `letter` slice the capture across printable
94
110
  sheets with a half-inch margin; `auto` is one page the exact size of the capture, which is not
95
111
  printable and which Acrobat clamps past 200 inches.
96
112
 
113
+ `--url` more than once, or `--urls <file>` (one address to a line, `#` for a comment, `-` for
114
+ standard input), scans a list, one page at a time, into `--out`, which is then a directory. Each
115
+ path is printed as its file is written; a page that fails is reported on stderr and the rest carry
116
+ on, and the exit code is 1 if any failed. Up to 1,000 addresses a run.
117
+
118
+ `--name` names the file inside `--out`: `{n}` (the page's place in the list), `{host}`, `{name}`
119
+ (the browser's suggested name), `{date}`, `{time}` (when the run started) and `{ext}`, which is
120
+ added when left out. A `/` makes a subdirectory:
121
+
122
+ ```bash
123
+ page-scanner scan --urls reading.txt --out ~/Captures/ --name '{date}/{n}-{host}'
124
+ ```
125
+
126
+ `--markdown beside` also writes the page's text as a `.md` next to the file, read from the page
127
+ itself rather than from the PDF, and prints its path on a second line; `--markdown only` writes the
128
+ `.md` alone. With `--json`, the result carries the title, address, capture time, language and
129
+ headings as `page`. Pictures are left out of the text.
130
+
131
+ `page-scanner diff <old> <new>` says what changed between two captures, with no browser: two
132
+ Markdown files (or two PDFs with the `.md` beside them) a passage at a time, printed as `diff -u`
133
+ prints it, or two PNGs pixel by pixel, writing the newer one with the changed regions outlined. It
134
+ exits 0 when nothing changed and 1 when something did.
135
+
136
+ `page-scanner verify <file>` checks a file against the integrity record the extension wrote beside
137
+ it: the SHA-256 and size, and the signature when there is one. It exits 0 when both hold and 1 when
138
+ either does not.
139
+
140
+ There is no scheduler here: cron, launchd and Task Scheduler run the command at a time. Start the
141
+ daemon at login with `page-scanner serve --daemon --idle 0` so the extension is connected when the
142
+ schedule fires. The documentation has an example for each.
143
+
97
144
  `--wait 0` means do not wait at all. Chrome retires the extension's service worker after about
98
145
  thirty seconds of silence, so the default wait exists to cover the reconnect that follows.
99
146
 
@@ -140,6 +187,9 @@ a sentence naming the gap.
140
187
  | 4 | not paired |
141
188
  | 5 | the daemon would not start |
142
189
 
190
+ `diff` uses the codes the way `diff` itself does: `0` when the two captures are the same, `1` when
191
+ something changed, and `2` for anything it cannot compare.
192
+
143
193
  ## The daemon
144
194
 
145
195
  The extension is the WebSocket **client**: nothing outside Chrome can open a connection into a
@@ -197,11 +247,14 @@ loopback port is reachable by everything running as you. So:
197
247
  ## Using it from Node
198
248
 
199
249
  ```js
200
- import { scan, listTabs } from '@page-scanner/cli';
250
+ import { scan, scanMany, listTabs } from '@page-scanner/cli';
201
251
 
202
252
  const { tabs } = await listTabs();
203
253
  const result = await scan({ tabId: tabs[0].tabId, out: './out/', format: 'pdf' });
204
254
  console.log(result.path, result.selectableText);
255
+
256
+ // A list, one page at a time, with a result for each.
257
+ const batch = await scanMany(['https://example.com/a', 'https://example.com/b'], { out: './out/' });
205
258
  ```
206
259
 
207
260
  The package's main entry point does not load `ws`: the bridge runs in the daemon, which is a
@@ -215,7 +268,8 @@ the only one that pulls the WebSocket server in.
215
268
  - `chrome.debugger` cannot attach while DevTools is open on the same tab. Close it, or scan a
216
269
  different tab.
217
270
  - A page larger than 60,000 CSS pixels on a side is captured up to that limit, and the result says
218
- so in `truncated`.
271
+ so in `truncated`. The extension's settings page can raise the height's limit to 120,000 or
272
+ 240,000, and a scan from here follows it.
219
273
  - One pairing per machine, shared by every browser profile that connects to it.
220
274
 
221
275
  ## Licence
package/dist/api.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import type { PairingConfig } from './config.js';
2
- import type { ExportFormatId, PageSizeId, TabSummary, TruncationReport, VideoHandling, WindowSummary } from './protocol.js';
2
+ import type { CaptureWidth, ColorSchemePreference, ExportFormatId, StructuredHeading, PageSizeId, TabSummary, TruncationReport, VideoHandling, WindowSummary } from './protocol.js';
3
3
  import { stopDaemon, type ConnectOptions } from './daemon/client.js';
4
4
  import type { ConnectedBrowser } from './bridge/server.js';
5
5
  export interface CommonOptions extends ConnectOptions {
@@ -16,16 +16,48 @@ export interface ScanOptions extends CommonOptions {
16
16
  pageSize?: PageSizeId;
17
17
  quality?: number;
18
18
  videoHandling?: VideoHandling;
19
+ colorScheme?: ColorSchemePreference;
20
+ captureWidth?: CaptureWidth;
19
21
  openEditor?: boolean;
20
22
  /** A file, or a directory to put the browser's suggested filename in. */
21
23
  out?: string;
24
+ /**
25
+ * The file's name inside `out` (or the working directory), as a template:
26
+ * `{n}`, `{host}`, `{name}`, `{date}`, `{time}`, `{ext}` (#59). Not with an
27
+ * `out` that names the file itself.
28
+ */
29
+ name?: string;
30
+ /**
31
+ * The page's text as Markdown (#61): `beside` writes a `.md` next to the
32
+ * file, `only` writes the `.md` and no file, `inline` puts the text in the
33
+ * result instead of on disk. Each also puts the page's title, address,
34
+ * capture time, language and headings in the result as `page`.
35
+ */
36
+ markdown?: MarkdownMode;
22
37
  /** What a relative `out` is relative to. Defaults to process.cwd(). */
23
38
  cwd?: string;
24
39
  /** How long to give the browser to produce the capture. */
25
40
  timeoutSeconds?: number;
26
41
  }
42
+ /** Where the page's text goes: beside the file, instead of it, or into the result. */
43
+ export declare const MARKDOWN_MODES: readonly ["beside", "only", "inline"];
44
+ export type MarkdownMode = (typeof MARKDOWN_MODES)[number];
45
+ /** The page as text, and what it is (#61). */
46
+ export interface PageText {
47
+ title: string;
48
+ url: string;
49
+ /** ISO 8601, UTC. */
50
+ capturedAt: string;
51
+ /** The page's own `lang`, or null when it names none. */
52
+ language: string | null;
53
+ headings: StructuredHeading[];
54
+ /** Where the Markdown was written, for `beside` and `only`. */
55
+ markdownPath?: string;
56
+ /** The Markdown itself, for `inline`. */
57
+ markdown?: string;
58
+ }
27
59
  export interface ScanResult {
28
- /** Absolute path of the file this wrote. */
60
+ /** Absolute path of the file this wrote: the `.md` itself for `markdown: 'only'`. */
29
61
  path: string;
30
62
  width: number;
31
63
  height: number;
@@ -36,6 +68,8 @@ export interface ScanResult {
36
68
  truncated: TruncationReport | null;
37
69
  browserId: string;
38
70
  fileName: string;
71
+ /** The page as text, when `markdown` asked for it. */
72
+ page?: PageText;
39
73
  }
40
74
  export interface TabsResult {
41
75
  browserId: string;
@@ -80,7 +114,53 @@ export declare function waitForBrowser(options?: CommonOptions): Promise<{
80
114
  label: string;
81
115
  }>;
82
116
  export declare function listTabs(options?: CommonOptions): Promise<TabsResult>;
117
+ /**
118
+ * Refuses a `--name` or an `--out` that cannot work for `files` files, before
119
+ * anything is asked of the daemon or the browser.
120
+ */
121
+ export declare function checkOutput(options: Pick<ScanOptions, 'out' | 'name' | 'cwd'>, files: number): void;
83
122
  export declare function scan(options: ScanOptions): Promise<ScanResult>;
123
+ /** One address of a batch: what it wrote, or why it did not. */
124
+ export type BatchItem = ({
125
+ url: string;
126
+ ok: true;
127
+ } & ScanResult) | {
128
+ url: string;
129
+ ok: false;
130
+ error: {
131
+ code: string;
132
+ message: string;
133
+ hint?: string;
134
+ };
135
+ };
136
+ export interface BatchResult {
137
+ /** One per address that was tried, in the list's order. */
138
+ results: BatchItem[];
139
+ written: number;
140
+ failed: number;
141
+ /**
142
+ * Set when a failure ended the batch early (no pairing, no browser, no
143
+ * daemon), so the addresses after `results` were not tried.
144
+ */
145
+ stopped?: {
146
+ code: string;
147
+ message: string;
148
+ hint?: string;
149
+ };
150
+ }
151
+ export interface BatchOptions extends Omit<ScanOptions, 'url' | 'tabId'> {
152
+ /** Called as each address finishes, for a caller that reports as it goes. */
153
+ onItem?: (item: BatchItem, index: number) => void;
154
+ }
155
+ /**
156
+ * Scans each address in turn and writes a file for each (#59). A page that
157
+ * fails is reported and the next one is scanned; a failure no later page
158
+ * could get past ends the batch. Files that two pages would give the same
159
+ * name are told apart with `-2`, `-3`.
160
+ */
161
+ export declare function scanMany(urls: readonly string[], options?: BatchOptions): Promise<BatchResult>;
162
+ /** What `scanMany` refuses before it starts: an empty or oversized list, or an unusable name. */
163
+ export declare function checkBatch(urls: readonly string[], options: Pick<ScanOptions, 'out' | 'name' | 'cwd'>): void;
84
164
  /** Everything `page-scanner status` reports, without starting a daemon. */
85
165
  export declare function status(): Promise<StatusReport>;
86
166
  export { stopDaemon as stop };
package/dist/api.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
package/dist/api.js CHANGED
@@ -6,12 +6,15 @@
6
6
  * the WebSocket server; `@page-scanner/cli/daemon` is the subpath that does.
7
7
  */
8
8
  import { ensureConfig, readConfig, configPath, configFileIsOwnerOnly } from './config.js';
9
- import { PAIR_COMMAND, PageScannerError } from './errors.js';
10
- import { resolveOutputPath, writeScanFile } from './output.js';
9
+ import { PAIR_COMMAND, PageScannerError, toPageScannerError } from './errors.js';
10
+ import { outputNamesAFile, resolveOutputPath, withExtension, writeScanFile, writeTextFile, } from './output.js';
11
+ import { MAX_BATCH_URLS, checkNameTemplate, endsTheBatch, fillNameTemplate, uniqueName, } from './batch.js';
11
12
  import { DEFAULT_PAGE_SIZE } from './protocol.js';
12
13
  import { connectDaemon, stopDaemon } from './daemon/client.js';
13
14
  import { readDaemonState } from './daemon/state.js';
14
15
  import { CLI_VERSION } from './version.js';
16
+ /** Where the page's text goes: beside the file, instead of it, or into the result. */
17
+ export const MARKDOWN_MODES = ['beside', 'only', 'inline'];
15
18
  function requirePairing() {
16
19
  const config = readConfig();
17
20
  if (!config.token) {
@@ -63,15 +66,151 @@ export async function listTabs(options = {}) {
63
66
  timeoutMs: waitMs,
64
67
  }, waitMs + 30_000);
65
68
  }
69
+ /**
70
+ * Refuses a `--name` or an `--out` that cannot work for `files` files, before
71
+ * anything is asked of the daemon or the browser.
72
+ */
73
+ export function checkOutput(options, files) {
74
+ if (options.name !== undefined)
75
+ checkNameTemplate(options.name);
76
+ if (options.out !== undefined && outputNamesAFile(options.out, options.cwd)) {
77
+ if (options.name !== undefined) {
78
+ throw new PageScannerError('BAD_REQUEST', `--out ${JSON.stringify(options.out)} names a file, so there is nothing for --name to name.`, 'Give --out a directory (end it with a slash if it does not exist yet).');
79
+ }
80
+ if (files > 1) {
81
+ throw new PageScannerError('BAD_REQUEST', `--out ${JSON.stringify(options.out)} names one file, and this scans ${files} pages.`, 'Give --out a directory (end it with a slash if it does not exist yet).');
82
+ }
83
+ }
84
+ }
85
+ /**
86
+ * Writes what the daemon answered to `target`, and the page's text where
87
+ * `markdown` says, and reports it. Nothing is written when the text was asked
88
+ * for and did not come: an extension from before #61 ignores the request and
89
+ * sends the file alone.
90
+ */
91
+ function deliver(answer, target, options) {
92
+ const mode = options.markdown;
93
+ if (mode !== undefined && !answer.structured) {
94
+ throw new PageScannerError('SCAN_FAILED', 'This version of Page Scanner in Chrome does not send the page’s text.', 'Update the extension (chrome://extensions, then Update), and scan again.');
95
+ }
96
+ const text = answer.structured;
97
+ const page = text && {
98
+ title: text.title,
99
+ url: text.url,
100
+ capturedAt: new Date(text.capturedAt).toISOString(),
101
+ language: text.language,
102
+ headings: text.headings,
103
+ };
104
+ if (mode === 'only' && text && page) {
105
+ writeTextFile(target, text.markdown);
106
+ page.markdownPath = target;
107
+ }
108
+ else {
109
+ writeScanFile(target, answer.bytesBase64);
110
+ if (mode === 'beside' && text && page) {
111
+ page.markdownPath = withExtension(target, 'md');
112
+ writeTextFile(page.markdownPath, text.markdown);
113
+ }
114
+ if (mode === 'inline' && text && page)
115
+ page.markdown = text.markdown;
116
+ }
117
+ return {
118
+ path: target,
119
+ width: answer.width,
120
+ height: answer.height,
121
+ mode: answer.mode,
122
+ selectableText: mode !== 'only' && answer.mode === 'vector' && (options.format ?? 'pdf') === 'pdf',
123
+ truncated: answer.truncated,
124
+ browserId: answer.browserId,
125
+ fileName: answer.fileName,
126
+ ...(page ? { page } : {}),
127
+ };
128
+ }
66
129
  export async function scan(options) {
67
130
  requirePairing();
68
131
  if ((options.url === undefined) === (options.tabId === undefined)) {
69
132
  throw new PageScannerError('BAD_REQUEST', 'Give exactly one of url and tabId.');
70
133
  }
134
+ checkOutput(options, 1);
135
+ const answer = await requestScan(options);
136
+ // The daemon hands back bytes, not a path. It may have been started hours
137
+ // ago from another directory; only this process knows what a relative
138
+ // `--out` means.
139
+ const name = options.name === undefined
140
+ ? answer.fileName
141
+ : fillNameTemplate(options.name, {
142
+ index: 1,
143
+ count: 1,
144
+ url: options.url ?? '',
145
+ suggested: answer.fileName,
146
+ startedAt: new Date(),
147
+ });
148
+ const target = resolveOutputPath(options.out, name, options.cwd);
149
+ return deliver(answer, target, options);
150
+ }
151
+ /**
152
+ * Scans each address in turn and writes a file for each (#59). A page that
153
+ * fails is reported and the next one is scanned; a failure no later page
154
+ * could get past ends the batch. Files that two pages would give the same
155
+ * name are told apart with `-2`, `-3`.
156
+ */
157
+ export async function scanMany(urls, options = {}) {
158
+ requirePairing();
159
+ checkBatch(urls, options);
160
+ const { onItem, ...scanOptions } = options;
161
+ const startedAt = new Date();
162
+ const taken = new Set();
163
+ const result = { results: [], written: 0, failed: 0 };
164
+ for (const [index, url] of urls.entries()) {
165
+ let item;
166
+ try {
167
+ const answer = await requestScan({ ...scanOptions, url });
168
+ const name = uniqueName(options.name === undefined
169
+ ? answer.fileName
170
+ : fillNameTemplate(options.name, {
171
+ index: index + 1,
172
+ count: urls.length,
173
+ url,
174
+ suggested: answer.fileName,
175
+ startedAt,
176
+ }), taken);
177
+ const target = resolveOutputPath(options.out, name, options.cwd);
178
+ item = { url, ok: true, ...deliver(answer, target, scanOptions) };
179
+ result.written += 1;
180
+ }
181
+ catch (thrown) {
182
+ const error = toPageScannerError(thrown);
183
+ const reason = {
184
+ code: error.code,
185
+ message: error.message,
186
+ ...(error.hint !== undefined ? { hint: error.hint } : {}),
187
+ };
188
+ if (endsTheBatch(error)) {
189
+ result.stopped = reason;
190
+ break;
191
+ }
192
+ item = { url, ok: false, error: reason };
193
+ result.failed += 1;
194
+ }
195
+ result.results.push(item);
196
+ onItem?.(item, index);
197
+ }
198
+ return result;
199
+ }
200
+ /** What `scanMany` refuses before it starts: an empty or oversized list, or an unusable name. */
201
+ export function checkBatch(urls, options) {
202
+ if (urls.length === 0)
203
+ throw new PageScannerError('BAD_REQUEST', 'The list has no addresses.');
204
+ if (urls.length > MAX_BATCH_URLS) {
205
+ throw new PageScannerError('BAD_REQUEST', `The list has ${urls.length} addresses; one run takes up to ${MAX_BATCH_URLS}.`);
206
+ }
207
+ checkOutput(options, urls.length);
208
+ }
209
+ async function requestScan(options) {
71
210
  const waitMs = Math.round((options.waitSeconds ?? 30) * 1000);
72
211
  const scanMs = Math.round((options.timeoutSeconds ?? 120) * 1000);
73
212
  const daemon = await connectDaemon(options);
74
- const answer = await daemon.call('scan', {
213
+ return daemon.call('scan', {
75
214
  ...(options.browser !== undefined ? { browserId: options.browser } : {}),
76
215
  ...(options.url !== undefined ? { url: options.url } : {}),
77
216
  ...(options.tabId !== undefined ? { tabId: options.tabId } : {}),
@@ -80,25 +219,15 @@ export async function scan(options) {
80
219
  pageSize: options.pageSize ?? DEFAULT_PAGE_SIZE,
81
220
  ...(options.quality !== undefined ? { quality: options.quality } : {}),
82
221
  ...(options.videoHandling !== undefined ? { videoHandling: options.videoHandling } : {}),
222
+ ...(options.colorScheme !== undefined ? { colorScheme: options.colorScheme } : {}),
223
+ ...(options.captureWidth !== undefined ? { captureWidth: options.captureWidth } : {}),
83
224
  ...(options.openEditor !== undefined ? { openEditor: options.openEditor } : {}),
225
+ ...(options.markdown !== undefined
226
+ ? { structured: options.markdown === 'only' ? 'only' : 'alongside' }
227
+ : {}),
84
228
  timeoutMs: waitMs,
85
229
  scanTimeoutMs: scanMs,
86
230
  }, waitMs + scanMs);
87
- // The daemon hands back bytes, not a path. It may have been started hours
88
- // ago from another directory; only this process knows what a relative
89
- // `--out` means.
90
- const target = resolveOutputPath(options.out, answer.fileName, options.cwd);
91
- writeScanFile(target, answer.bytesBase64);
92
- return {
93
- path: target,
94
- width: answer.width,
95
- height: answer.height,
96
- mode: answer.mode,
97
- selectableText: answer.mode === 'vector' && (options.format ?? 'pdf') === 'pdf',
98
- truncated: answer.truncated,
99
- browserId: answer.browserId,
100
- fileName: answer.fileName,
101
- };
102
231
  }
103
232
  /** Everything `page-scanner status` reports, without starting a daemon. */
104
233
  export async function status() {
package/dist/api.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Scanning a list of addresses in one go (#59), and naming what that writes.
3
+ *
4
+ * A batch is the single scan run once per address, in order, by the client:
5
+ * nothing about it crosses the bridge, so the extension and the wire contract
6
+ * are the same for one page or a hundred. One at a time on purpose. Each scan
7
+ * opens a tab and lays the page out at its full height, and several of those
8
+ * at once in the user's own Chrome is a machine that stops responding.
9
+ *
10
+ * Every file lands where the caller said, on their own disk. There is no
11
+ * record of what was captured anywhere else, which is what keeps this from
12
+ * becoming the capture history the product deliberately does not have.
13
+ */
14
+ import { PageScannerError } from './errors.js';
15
+ /** More than a morning's reading list; a longer one is split across runs. */
16
+ export declare const MAX_BATCH_URLS = 1000;
17
+ /** The placeholders a name template may use. */
18
+ export declare const NAME_FIELDS: readonly ["n", "host", "name", "date", "time", "ext"];
19
+ export type NameField = (typeof NAME_FIELDS)[number];
20
+ /**
21
+ * An address list as a file holds it: one to a line, blank lines and lines
22
+ * starting with `#` ignored, surrounding space trimmed.
23
+ */
24
+ export declare function readUrlList(text: string): string[];
25
+ /** Refuses a template that names a field there is no value for, before any page is scanned. */
26
+ export declare function checkNameTemplate(template: string): void;
27
+ export interface NameContext {
28
+ /** 1-based position in the list. */
29
+ index: number;
30
+ /** How many addresses the list has, which sets how wide {n} is. */
31
+ count: number;
32
+ url: string;
33
+ /** The name the browser suggested, e.g. `example-com-docs-20260923-1102.pdf`. */
34
+ suggested: string;
35
+ /** When the batch started, so every file of one run shares its date and time. */
36
+ startedAt: Date;
37
+ }
38
+ /**
39
+ * A template filled in for one page: `{n}` its place in the list, padded to
40
+ * the list's length, `{host}` the address's host with dots as hyphens,
41
+ * `{name}` the browser's suggested name without its extension, `{date}` and
42
+ * `{time}` when the batch started (local, `YYYYMMDD` and `HHMM`), `{ext}` the
43
+ * format's extension. A template without `{ext}` gets it on the end. A `/`
44
+ * makes a subdirectory of the output directory.
45
+ */
46
+ export declare function fillNameTemplate(template: string, context: NameContext): string;
47
+ /**
48
+ * The name again with `-2`, `-3` before its extension until it is one this
49
+ * batch has not written, so two pages that suggest the same name (the same
50
+ * site in the same minute) do not overwrite each other. Compared without
51
+ * regard to case, as macOS and Windows compare file names.
52
+ */
53
+ export declare function uniqueName(name: string, taken: Set<string>): string;
54
+ /**
55
+ * Whether a failure ends the whole batch rather than just its page: nothing
56
+ * paired, no browser to scan with, no daemon. Every later page would fail the
57
+ * same way, each after its own wait.
58
+ */
59
+ export declare function endsTheBatch(error: PageScannerError): boolean;
60
+ //# sourceMappingURL=batch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"batch.d.ts","sourceRoot":"","sources":["../src/batch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,6EAA6E;AAC7E,eAAO,MAAM,cAAc,OAAO,CAAC;AAEnC,gDAAgD;AAChD,eAAO,MAAM,WAAW,uDAAwD,CAAC;AACjF,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAIrD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAKlD;AAED,+FAA+F;AAC/F,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAmBxD;AAED,MAAM,WAAW,WAAW;IAC1B,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,iFAAiF;IACjF,SAAS,EAAE,MAAM,CAAC;IAClB,iFAAiF;IACjF,SAAS,EAAE,IAAI,CAAC;CACjB;AAkBD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,MAAM,CAqB/E;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,CAUnE;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAS7D"}
package/dist/batch.js ADDED
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Scanning a list of addresses in one go (#59), and naming what that writes.
3
+ *
4
+ * A batch is the single scan run once per address, in order, by the client:
5
+ * nothing about it crosses the bridge, so the extension and the wire contract
6
+ * are the same for one page or a hundred. One at a time on purpose. Each scan
7
+ * opens a tab and lays the page out at its full height, and several of those
8
+ * at once in the user's own Chrome is a machine that stops responding.
9
+ *
10
+ * Every file lands where the caller said, on their own disk. There is no
11
+ * record of what was captured anywhere else, which is what keeps this from
12
+ * becoming the capture history the product deliberately does not have.
13
+ */
14
+ import { PageScannerError } from './errors.js';
15
+ /** More than a morning's reading list; a longer one is split across runs. */
16
+ export const MAX_BATCH_URLS = 1000;
17
+ /** The placeholders a name template may use. */
18
+ export const NAME_FIELDS = ['n', 'host', 'name', 'date', 'time', 'ext'];
19
+ const PLACEHOLDER = /\{([^{}]*)\}/g;
20
+ /**
21
+ * An address list as a file holds it: one to a line, blank lines and lines
22
+ * starting with `#` ignored, surrounding space trimmed.
23
+ */
24
+ export function readUrlList(text) {
25
+ return text
26
+ .split(/\r?\n/)
27
+ .map((line) => line.trim())
28
+ .filter((line) => line !== '' && !line.startsWith('#'));
29
+ }
30
+ /** Refuses a template that names a field there is no value for, before any page is scanned. */
31
+ export function checkNameTemplate(template) {
32
+ if (template.trim() === '') {
33
+ throw new PageScannerError('BAD_REQUEST', '--name needs a value.');
34
+ }
35
+ for (const [, field] of template.matchAll(PLACEHOLDER)) {
36
+ if (!NAME_FIELDS.some((known) => known === field)) {
37
+ throw new PageScannerError('BAD_REQUEST', `--name has an unknown placeholder {${field}}.`, `The placeholders are ${NAME_FIELDS.map((known) => `{${known}}`).join(', ')}.`);
38
+ }
39
+ }
40
+ if (template.split(/[\\/]/).some((segment) => segment === '..')) {
41
+ throw new PageScannerError('BAD_REQUEST', '--name may not climb out of the output directory with "..".');
42
+ }
43
+ }
44
+ /** Windows refuses these in a file name, and a control character is trouble anywhere. */
45
+ // eslint-disable-next-line no-control-regex
46
+ const UNSAFE = /[<>:"|?*\u0000-\u001f]/g;
47
+ function pad(value, width) {
48
+ return String(value).padStart(width, '0');
49
+ }
50
+ function hostOf(url) {
51
+ try {
52
+ return new URL(url).hostname.replace(/^www\./, '').replace(/\./g, '-') || 'page';
53
+ }
54
+ catch {
55
+ return 'page';
56
+ }
57
+ }
58
+ /**
59
+ * A template filled in for one page: `{n}` its place in the list, padded to
60
+ * the list's length, `{host}` the address's host with dots as hyphens,
61
+ * `{name}` the browser's suggested name without its extension, `{date}` and
62
+ * `{time}` when the batch started (local, `YYYYMMDD` and `HHMM`), `{ext}` the
63
+ * format's extension. A template without `{ext}` gets it on the end. A `/`
64
+ * makes a subdirectory of the output directory.
65
+ */
66
+ export function fillNameTemplate(template, context) {
67
+ const dot = context.suggested.lastIndexOf('.');
68
+ const ext = dot > 0 ? context.suggested.slice(dot + 1) : '';
69
+ const at = context.startedAt;
70
+ const values = {
71
+ n: pad(context.index, String(context.count).length),
72
+ host: hostOf(context.url),
73
+ name: dot > 0 ? context.suggested.slice(0, dot) : context.suggested,
74
+ date: `${at.getFullYear()}${pad(at.getMonth() + 1, 2)}${pad(at.getDate(), 2)}`,
75
+ time: `${pad(at.getHours(), 2)}${pad(at.getMinutes(), 2)}`,
76
+ ext,
77
+ };
78
+ const filled = template.replace(PLACEHOLDER, (_, field) => values[field].replace(/[\\/]/g, '-'));
79
+ const named = template.includes('{ext}') || !ext ? filled : `${filled}.${ext}`;
80
+ return named
81
+ .split(/[\\/]/)
82
+ .map((segment) => segment.replace(UNSAFE, '-').trim())
83
+ .filter((segment) => segment !== '' && segment !== '.' && segment !== '..')
84
+ .join('/');
85
+ }
86
+ /**
87
+ * The name again with `-2`, `-3` before its extension until it is one this
88
+ * batch has not written, so two pages that suggest the same name (the same
89
+ * site in the same minute) do not overwrite each other. Compared without
90
+ * regard to case, as macOS and Windows compare file names.
91
+ */
92
+ export function uniqueName(name, taken) {
93
+ const dot = name.lastIndexOf('.');
94
+ const slash = name.lastIndexOf('/');
95
+ const cut = dot > slash + 1 ? dot : name.length;
96
+ let candidate = name;
97
+ for (let copy = 2; taken.has(candidate.toLowerCase()); copy++) {
98
+ candidate = `${name.slice(0, cut)}-${copy}${name.slice(cut)}`;
99
+ }
100
+ taken.add(candidate.toLowerCase());
101
+ return candidate;
102
+ }
103
+ /**
104
+ * Whether a failure ends the whole batch rather than just its page: nothing
105
+ * paired, no browser to scan with, no daemon. Every later page would fail the
106
+ * same way, each after its own wait.
107
+ */
108
+ export function endsTheBatch(error) {
109
+ return (error.code === 'NOT_PAIRED' ||
110
+ error.code === 'NO_BROWSER' ||
111
+ error.code === 'AMBIGUOUS_BROWSER' ||
112
+ error.code === 'UNKNOWN_BROWSER' ||
113
+ error.code === 'DAEMON_FAILED' ||
114
+ error.code === 'PORT_IN_USE');
115
+ }
116
+ //# sourceMappingURL=batch.js.map