@page-scanner/cli 0.1.1 → 0.2.0
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.
- package/README.md +53 -4
- package/dist/api.d.ts +82 -2
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +147 -18
- package/dist/api.js.map +1 -1
- package/dist/batch.d.ts +60 -0
- package/dist/batch.d.ts.map +1 -0
- package/dist/batch.js +116 -0
- package/dist/batch.js.map +1 -0
- package/dist/cli/args.d.ts +21 -4
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +94 -10
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/commands.d.ts +2 -0
- package/dist/cli/commands.d.ts.map +1 -1
- package/dist/cli/commands.js +143 -14
- package/dist/cli/commands.js.map +1 -1
- package/dist/daemon/rpc-server.d.ts.map +1 -1
- package/dist/daemon/rpc-server.js +17 -1
- package/dist/daemon/rpc-server.js.map +1 -1
- package/dist/diff/image.d.ts +42 -0
- package/dist/diff/image.d.ts.map +1 -0
- package/dist/diff/image.js +144 -0
- package/dist/diff/image.js.map +1 -0
- package/dist/diff/index.d.ts +46 -0
- package/dist/diff/index.d.ts.map +1 -0
- package/dist/diff/index.js +108 -0
- package/dist/diff/index.js.map +1 -0
- package/dist/diff/png.d.ts +12 -0
- package/dist/diff/png.d.ts.map +1 -0
- package/dist/diff/png.js +169 -0
- package/dist/diff/png.js.map +1 -0
- package/dist/diff/text.d.ts +54 -0
- package/dist/diff/text.d.ts.map +1 -0
- package/dist/diff/text.js +198 -0
- package/dist/diff/text.js.map +1 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/output.d.ts +10 -0
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +24 -4
- package/dist/output.js.map +1 -1
- package/dist/protocol.d.ts +37 -2
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +23 -2
- package/dist/protocol.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -73,10 +73,15 @@ 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
|
|
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]
|
|
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]
|
|
80
85
|
page-scanner serve [--daemon] [--idle <min>]
|
|
81
86
|
page-scanner stop
|
|
82
87
|
page-scanner --version | --help
|
|
@@ -90,10 +95,47 @@ and a directory otherwise, in which case the browser's suggested filename is use
|
|
|
90
95
|
Parent directories are created. A relative path is relative to **your** working directory, not the
|
|
91
96
|
daemon's, which is why the daemon hands the bytes back rather than writing them itself.
|
|
92
97
|
|
|
98
|
+
`--page-width` lays the page out at the width of a sheet before capturing it, the way a narrow
|
|
99
|
+
window would, so the PDF prints at 1:1 rather than being scaled down. `window`, the default, is
|
|
100
|
+
the width the browser has the page at. A 1280 px window on A4 is scaled to 55 %, which puts 16 px
|
|
101
|
+
body text at 6.5 pt; `--page-width a4` puts it at 12.
|
|
102
|
+
|
|
103
|
+
`--scheme` picks which of a page's two themes to capture, for a page that has both. `auto`, the
|
|
104
|
+
default, is whichever the browser is showing; `light` and `dark` force one. It applies to the PDF
|
|
105
|
+
as well as the preview, which is the point: Chrome prints every page in the light scheme unless it
|
|
106
|
+
is told otherwise, so without this a dark page produced a white PDF.
|
|
107
|
+
|
|
93
108
|
`--page-size` decides what a PDF is laid onto. `a4` and `letter` slice the capture across printable
|
|
94
109
|
sheets with a half-inch margin; `auto` is one page the exact size of the capture, which is not
|
|
95
110
|
printable and which Acrobat clamps past 200 inches.
|
|
96
111
|
|
|
112
|
+
`--url` more than once, or `--urls <file>` (one address to a line, `#` for a comment, `-` for
|
|
113
|
+
standard input), scans a list, one page at a time, into `--out`, which is then a directory. Each
|
|
114
|
+
path is printed as its file is written; a page that fails is reported on stderr and the rest carry
|
|
115
|
+
on, and the exit code is 1 if any failed. Up to 1,000 addresses a run.
|
|
116
|
+
|
|
117
|
+
`--name` names the file inside `--out`: `{n}` (the page's place in the list), `{host}`, `{name}`
|
|
118
|
+
(the browser's suggested name), `{date}`, `{time}` (when the run started) and `{ext}`, which is
|
|
119
|
+
added when left out. A `/` makes a subdirectory:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
page-scanner scan --urls reading.txt --out ~/Captures/ --name '{date}/{n}-{host}'
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
`--markdown beside` also writes the page's text as a `.md` next to the file, read from the page
|
|
126
|
+
itself rather than from the PDF, and prints its path on a second line; `--markdown only` writes the
|
|
127
|
+
`.md` alone. With `--json`, the result carries the title, address, capture time, language and
|
|
128
|
+
headings as `page`. Pictures are left out of the text.
|
|
129
|
+
|
|
130
|
+
`page-scanner diff <old> <new>` says what changed between two captures, with no browser: two
|
|
131
|
+
Markdown files (or two PDFs with the `.md` beside them) a passage at a time, printed as `diff -u`
|
|
132
|
+
prints it, or two PNGs pixel by pixel, writing the newer one with the changed regions outlined. It
|
|
133
|
+
exits 0 when nothing changed and 1 when something did.
|
|
134
|
+
|
|
135
|
+
There is no scheduler here: cron, launchd and Task Scheduler run the command at a time. Start the
|
|
136
|
+
daemon at login with `page-scanner serve --daemon --idle 0` so the extension is connected when the
|
|
137
|
+
schedule fires. The documentation has an example for each.
|
|
138
|
+
|
|
97
139
|
`--wait 0` means do not wait at all. Chrome retires the extension's service worker after about
|
|
98
140
|
thirty seconds of silence, so the default wait exists to cover the reconnect that follows.
|
|
99
141
|
|
|
@@ -140,6 +182,9 @@ a sentence naming the gap.
|
|
|
140
182
|
| 4 | not paired |
|
|
141
183
|
| 5 | the daemon would not start |
|
|
142
184
|
|
|
185
|
+
`diff` uses the codes the way `diff` itself does: `0` when the two captures are the same, `1` when
|
|
186
|
+
something changed, and `2` for anything it cannot compare.
|
|
187
|
+
|
|
143
188
|
## The daemon
|
|
144
189
|
|
|
145
190
|
The extension is the WebSocket **client**: nothing outside Chrome can open a connection into a
|
|
@@ -197,11 +242,14 @@ loopback port is reachable by everything running as you. So:
|
|
|
197
242
|
## Using it from Node
|
|
198
243
|
|
|
199
244
|
```js
|
|
200
|
-
import { scan, listTabs } from '@page-scanner/cli';
|
|
245
|
+
import { scan, scanMany, listTabs } from '@page-scanner/cli';
|
|
201
246
|
|
|
202
247
|
const { tabs } = await listTabs();
|
|
203
248
|
const result = await scan({ tabId: tabs[0].tabId, out: './out/', format: 'pdf' });
|
|
204
249
|
console.log(result.path, result.selectableText);
|
|
250
|
+
|
|
251
|
+
// A list, one page at a time, with a result for each.
|
|
252
|
+
const batch = await scanMany(['https://example.com/a', 'https://example.com/b'], { out: './out/' });
|
|
205
253
|
```
|
|
206
254
|
|
|
207
255
|
The package's main entry point does not load `ws`: the bridge runs in the daemon, which is a
|
|
@@ -215,7 +263,8 @@ the only one that pulls the WebSocket server in.
|
|
|
215
263
|
- `chrome.debugger` cannot attach while DevTools is open on the same tab. Close it, or scan a
|
|
216
264
|
different tab.
|
|
217
265
|
- 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`.
|
|
266
|
+
so in `truncated`. The extension's settings page can raise the height's limit to 120,000 or
|
|
267
|
+
240,000, and a scan from here follows it.
|
|
219
268
|
- One pairing per machine, shared by every browser profile that connects to it.
|
|
220
269
|
|
|
221
270
|
## 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":"AAQA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAiBjD,OAAO,KAAK,EACV,YAAY,EACZ,qBAAqB,EACrB,cAAc,EACd,iBAAiB,EAEjB,UAAU,EACV,UAAU,EACV,gBAAgB,EAChB,aAAa,EACb,aAAa,EACd,MAAM,eAAe,CAAC;AACvB,OAAO,EAAiB,UAAU,EAAE,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAG3D,MAAM,WAAW,aAAc,SAAQ,cAAc;IACnD,iFAAiF;IACjF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sEAAsE;IACtE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,WAAY,SAAQ,aAAa;IAChD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,QAAQ,CAAC,EAAE,UAAU,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,WAAW,CAAC,EAAE,qBAAqB,CAAC;IACpC,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,yEAAyE;IACzE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,uEAAuE;IACvE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,sFAAsF;AACtF,eAAO,MAAM,cAAc,uCAAwC,CAAC;AACpE,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3D,8CAA8C;AAC9C,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,qBAAqB;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,+DAA+D;IAC/D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,qFAAqF;IACrF,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC1B,gEAAgE;IAChE,cAAc,EAAE,OAAO,CAAC;IACxB,oEAAoE;IACpE,SAAS,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,sDAAsD;IACtD,IAAI,CAAC,EAAE,QAAQ,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,IAAI,EAAE,UAAU,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,2EAA2E;IAC3E,eAAe,EAAE,OAAO,CAAC;IACzB,MAAM,EAAE;QAAE,OAAO,EAAE,KAAK,CAAA;KAAE,GAAG;QAAE,OAAO,EAAE,IAAI,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9F,QAAQ,EAAE,gBAAgB,EAAE,CAAC;CAC9B;AAeD,MAAM,WAAW,UAAW,SAAQ,aAAa;IAC/C,UAAU,EAAE,MAAM,CAAC;IACnB,mFAAmF;IACnF,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAsB,IAAI,CACxB,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,cAAmB,GACjE,OAAO,CAAC,UAAU,CAAC,CAcrB;AAED,wBAAsB,YAAY,CAAC,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAK5F;AAED,iEAAiE;AACjE,wBAAsB,cAAc,CAClC,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAY/C;AAED,wBAAsB,QAAQ,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,UAAU,CAAC,CAY/E;AAaD;;;GAGG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,CAAC,EAClD,KAAK,EAAE,MAAM,GACZ,IAAI,CAkBN;AAkDD,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAwBpE;AAED,gEAAgE;AAChE,MAAM,MAAM,SAAS,GACjB,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG,UAAU,CAAC,GACxC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC;AAExF,MAAM,WAAW,WAAW;IAC1B,2DAA2D;IAC3D,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,OAAO,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC5D;AAED,MAAM,WAAW,YAAa,SAAQ,IAAI,CAAC,WAAW,EAAE,KAAK,GAAG,OAAO,CAAC;IACtE,6EAA6E;IAC7E,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACnD;AAED;;;;;GAKG;AACH,wBAAsB,QAAQ,CAC5B,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,WAAW,CAAC,CA6CtB;AAED,iGAAiG;AACjG,wBAAgB,UAAU,CACxB,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,CAAC,GACjD,IAAI,CASN;AA+BD,2EAA2E;AAC3E,wBAAsB,MAAM,IAAI,OAAO,CAAC,YAAY,CAAC,CA4BpD;AAED,OAAO,EAAE,UAAU,IAAI,IAAI,EAAE,CAAC"}
|
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
|
-
|
|
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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"}
|
package/dist/batch.d.ts
ADDED
|
@@ -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
|