@gheop/tojiru 0.1.2 → 0.3.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 +38 -2
- package/dist/cli.js +54 -3
- package/dist/cli.js.map +1 -1
- package/dist/convert.js +2 -2
- package/dist/convert.js.map +1 -1
- package/dist/extractors/cb7.js +1 -1
- package/dist/extractors/cb7.js.map +1 -1
- package/dist/extractors/cbr.js +1 -1
- package/dist/extractors/cbr.js.map +1 -1
- package/dist/extractors/cbz.js +1 -1
- package/dist/extractors/cbz.js.map +1 -1
- package/dist/extractors/djvu.js +2 -1
- package/dist/extractors/djvu.js.map +1 -1
- package/dist/extractors/pdf.js +38 -4
- package/dist/extractors/pdf.js.map +1 -1
- package/dist/pages.js +2 -1
- package/dist/pages.js.map +1 -1
- package/dist/serve.js +74 -0
- package/dist/serve.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -66,13 +66,32 @@ sudo dnf install poppler-utils djvulibre p7zip
|
|
|
66
66
|
|
|
67
67
|
```bash
|
|
68
68
|
tojiru <input> [options]
|
|
69
|
+
tojiru serve <dir> [options]
|
|
69
70
|
```
|
|
70
71
|
|
|
72
|
+
Generation shows per-page progress on stderr (e.g. `Converting 12/30`).
|
|
73
|
+
|
|
74
|
+
### Convert options
|
|
75
|
+
|
|
71
76
|
| Option | Description |
|
|
72
77
|
|---|---|
|
|
73
78
|
| `-o, --out <dir>` | Output folder (default: the input name without extension) |
|
|
74
79
|
| `-t, --title <title>` | Document title shown in the reader |
|
|
75
80
|
| `-f, --force` | Overwrite a non-empty output folder |
|
|
81
|
+
| `--serve` | Start a preview server on the output folder after converting |
|
|
82
|
+
|
|
83
|
+
### Preview server
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
tojiru serve out/ # serve an existing bundle
|
|
87
|
+
tojiru serve out/ -p 9000 # on a custom port
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
| Option | Description |
|
|
91
|
+
|---|---|
|
|
92
|
+
| `-p, --port <n>` | Port to listen on (default: 8000; auto-increments on EADDRINUSE) |
|
|
93
|
+
|
|
94
|
+
The server uses Node built-ins only — no extra dependencies. It opens the browser automatically (best-effort).
|
|
76
95
|
|
|
77
96
|
Examples:
|
|
78
97
|
|
|
@@ -80,9 +99,14 @@ Examples:
|
|
|
80
99
|
tojiru novel.pdf --out reader/ --title "My Novel"
|
|
81
100
|
tojiru comic.cbz --out comic/
|
|
82
101
|
tojiru scan.djvu --out book/ --force
|
|
83
|
-
```
|
|
84
102
|
|
|
85
|
-
|
|
103
|
+
# preview immediately after converting
|
|
104
|
+
tojiru novel.pdf --out reader/ --serve
|
|
105
|
+
|
|
106
|
+
# or convert first, serve later
|
|
107
|
+
tojiru novel.pdf --out reader/
|
|
108
|
+
tojiru serve reader/
|
|
109
|
+
```
|
|
86
110
|
|
|
87
111
|
## Where it shines (and where it doesn't)
|
|
88
112
|
|
|
@@ -110,6 +134,18 @@ MIT — see [LICENSE](LICENSE).
|
|
|
110
134
|
|
|
111
135
|
## Changelog
|
|
112
136
|
|
|
137
|
+
### v0.3.0 — Smaller PDF bundles (2026-06-26)
|
|
138
|
+
|
|
139
|
+
- Vector PDF page coordinates are rounded to 2 decimals — ~25% smaller pages, no visible change
|
|
140
|
+
- Image-only PDF pages (scans, comic PDFs) are auto-detected and rendered as WebP instead of SVG-wrapped bitmaps — e.g. a comic PDF dropped from ×34 to ×2.7
|
|
141
|
+
|
|
142
|
+
### v0.2.0 — Preview server and progress (2026-06-25)
|
|
143
|
+
|
|
144
|
+
- Built-in `tojiru serve <dir>` command previews a bundle locally — uses Node built-ins only, no extra install needed
|
|
145
|
+
- `--serve` flag on the convert command starts the server immediately after generating
|
|
146
|
+
- Per-page progress shown on stderr during generation (`Converting i/N`, `Processing i/N`)
|
|
147
|
+
- Browser opens automatically after `serve` / `--serve` (best-effort, swallows errors)
|
|
148
|
+
|
|
113
149
|
### v0.1.2 — Version reporting (2026-06-25)
|
|
114
150
|
|
|
115
151
|
- `tojiru --version` now reads the version from `package.json`, so it always matches the published version
|
package/dist/cli.js
CHANGED
|
@@ -2,18 +2,31 @@
|
|
|
2
2
|
import { readdir } from 'node:fs/promises';
|
|
3
3
|
import { basename } from 'node:path';
|
|
4
4
|
import { existsSync } from 'node:fs';
|
|
5
|
+
import { spawn } from 'node:child_process';
|
|
5
6
|
import { Command } from 'commander';
|
|
6
7
|
import { VERSION } from './version.js';
|
|
7
8
|
import { convert } from './convert.js';
|
|
9
|
+
import { serve } from './serve.js';
|
|
10
|
+
function openBrowser(url) {
|
|
11
|
+
const cmd = process.platform === 'darwin' ? 'open' : 'xdg-open';
|
|
12
|
+
try {
|
|
13
|
+
spawn(cmd, [url], { detached: true, stdio: 'ignore' }).unref();
|
|
14
|
+
}
|
|
15
|
+
catch { /* best-effort */ }
|
|
16
|
+
}
|
|
8
17
|
const program = new Command();
|
|
9
18
|
program
|
|
10
19
|
.name('tojiru')
|
|
11
20
|
.description('Turn a fixed-page document into a static web reader')
|
|
12
|
-
.version(VERSION)
|
|
13
|
-
|
|
21
|
+
.version(VERSION);
|
|
22
|
+
// Default convert command — runs when no subcommand matches
|
|
23
|
+
program
|
|
24
|
+
.command('convert <input>', { isDefault: true })
|
|
25
|
+
.description('Convert a document to a static web reader')
|
|
14
26
|
.option('-o, --out <dir>', 'output folder')
|
|
15
27
|
.option('-t, --title <title>', 'document title')
|
|
16
28
|
.option('-f, --force', 'overwrite a non-empty output folder')
|
|
29
|
+
.option('--serve', 'start a preview server after converting')
|
|
17
30
|
.action(async (input, opts) => {
|
|
18
31
|
try {
|
|
19
32
|
if (!existsSync(input))
|
|
@@ -22,8 +35,46 @@ program
|
|
|
22
35
|
if (existsSync(outDir) && (await readdir(outDir)).length > 0 && !opts.force) {
|
|
23
36
|
throw new Error(`Folder ${outDir} is not empty. Use --force to overwrite.`);
|
|
24
37
|
}
|
|
25
|
-
const
|
|
38
|
+
const isTTY = process.stderr.isTTY === true;
|
|
39
|
+
const onProgress = isTTY
|
|
40
|
+
? (done, total, label) => {
|
|
41
|
+
process.stderr.write(`\r${label} ${done}/${total}`);
|
|
42
|
+
}
|
|
43
|
+
: undefined;
|
|
44
|
+
const r = await convert(input, { outDir, title: opts.title, onProgress });
|
|
45
|
+
// Clear progress line before success message
|
|
46
|
+
if (isTTY)
|
|
47
|
+
process.stderr.write('\x1b[2K\r');
|
|
26
48
|
console.log(`✓ ${r.pageCount} pages → ${r.outDir}/`);
|
|
49
|
+
if (opts.serve) {
|
|
50
|
+
const server = await serve(outDir);
|
|
51
|
+
process.stderr.write(`Serving ${outDir} at ${server.url}\n`);
|
|
52
|
+
openBrowser(server.url);
|
|
53
|
+
// Keep running — http server holds the event loop open
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
process.stderr.write(` Preview: tojiru serve ${outDir}\n`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
catch (e) {
|
|
60
|
+
console.error(`Error: ${e.message}`);
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
// Serve subcommand
|
|
65
|
+
program
|
|
66
|
+
.command('serve <dir>')
|
|
67
|
+
.description('Serve a tojiru bundle for browser preview')
|
|
68
|
+
.option('-p, --port <n>', 'port to listen on', '8000')
|
|
69
|
+
.action(async (dir, opts) => {
|
|
70
|
+
try {
|
|
71
|
+
if (!existsSync(dir))
|
|
72
|
+
throw new Error(`Directory not found: ${dir}`);
|
|
73
|
+
const port = opts.port ? parseInt(opts.port, 10) : 8000;
|
|
74
|
+
const server = await serve(dir, port);
|
|
75
|
+
process.stderr.write(`Serving ${dir} at ${server.url}\n`);
|
|
76
|
+
openBrowser(server.url);
|
|
77
|
+
// Keep running — Ctrl+C exits
|
|
27
78
|
}
|
|
28
79
|
catch (e) {
|
|
29
80
|
console.error(`Error: ${e.message}`);
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/convert.js
CHANGED
|
@@ -19,12 +19,12 @@ export async function convert(input, opts) {
|
|
|
19
19
|
}
|
|
20
20
|
const work = await mkdtemp(join(tmpdir(), 'tojiru-'));
|
|
21
21
|
try {
|
|
22
|
-
const doc = await extractor.extract(input, work);
|
|
22
|
+
const doc = await extractor.extract(input, work, opts.onProgress);
|
|
23
23
|
if (opts.title)
|
|
24
24
|
doc.title = opts.title;
|
|
25
25
|
if (doc.pages.length === 0)
|
|
26
26
|
throw new Error('No pages extracted.');
|
|
27
|
-
const pages = await processPages(doc, opts.outDir);
|
|
27
|
+
const pages = await processPages(doc, opts.outDir, {}, opts.onProgress);
|
|
28
28
|
await writeFolder(buildManifest(doc.title, doc.kind, pages), opts.outDir);
|
|
29
29
|
return { outDir: opts.outDir, pageCount: doc.pages.length };
|
|
30
30
|
}
|
package/dist/convert.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convert.js","sourceRoot":"","sources":["../src/convert.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAGhD,MAAM,UAAU,GAAgB,CAAC,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"convert.js","sourceRoot":"","sources":["../src/convert.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAGhD,MAAM,UAAU,GAAgB,CAAC,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,CAAC,CAAA;AAavG,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,KAAa,EAAE,IAAoB;IAC/D,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,CAAA;IACpC,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAA;IACzD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,6BAA6B,IAAI,EAAE,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAA;IACrF,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,SAAS,CAAC,CAAC,CAAA;IACrD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,CAAA;QACjE,IAAI,IAAI,CAAC,KAAK;YAAE,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAA;QACtC,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAA;QAClE,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,UAAU,CAAC,CAAA;QACvE,MAAM,WAAW,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;QACzE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,CAAA;IAC7D,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;IAClD,CAAC;AACH,CAAC"}
|
package/dist/extractors/cb7.js
CHANGED
|
@@ -7,7 +7,7 @@ import { isImage, naturalCompare, imageDims } from './images.js';
|
|
|
7
7
|
export const cb7Extractor = {
|
|
8
8
|
name: 'cb7',
|
|
9
9
|
async canHandle(file) { return (await detectKind(file)) === 'cb7'; },
|
|
10
|
-
async extract(file, workdir) {
|
|
10
|
+
async extract(file, workdir, _onProgress) {
|
|
11
11
|
if (!(await hasBinary('7z')))
|
|
12
12
|
throw new Error('7z not found. Install p7zip (package p7zip / p7zip-full).');
|
|
13
13
|
await mkdir(workdir, { recursive: true });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cb7.js","sourceRoot":"","sources":["../../src/extractors/cb7.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEnD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAA;AAC/B,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAEhE,MAAM,CAAC,MAAM,YAAY,GAAc;IACrC,IAAI,EAAE,KAAK;IACX,KAAK,CAAC,SAAS,CAAC,IAAI,IAAI,OAAO,CAAC,MAAM,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,CAAA,CAAC,CAAC;IACnE,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO;
|
|
1
|
+
{"version":3,"file":"cb7.js","sourceRoot":"","sources":["../../src/extractors/cb7.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEnD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAA;AAC/B,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAEhE,MAAM,CAAC,MAAM,YAAY,GAAc;IACrC,IAAI,EAAE,KAAK;IACX,KAAK,CAAC,SAAS,CAAC,IAAI,IAAI,OAAO,CAAC,MAAM,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,CAAA,CAAC,CAAC;IACnE,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,WAAwB;QACnD,IAAI,CAAC,CAAC,MAAM,SAAS,CAAC,IAAI,CAAC,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAA;QAC1G,MAAM,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QACzC,8EAA8E;QAC9E,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,OAAO,EAAE,EAAE,IAAI,CAAC,CAAC,CAAA;QAClD,MAAM,KAAK,GAAG,CAAC,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAA;QACxG,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAA;QACrE,MAAM,KAAK,GAAiB,EAAE,CAAA;QAC9B,KAAK,MAAM,CAAC,IAAI,KAAK;YAAE,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;QAC5F,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;IACrE,CAAC;CACF,CAAA"}
|
package/dist/extractors/cbr.js
CHANGED
|
@@ -6,7 +6,7 @@ import { isImage, naturalCompare, imageDims } from './images.js';
|
|
|
6
6
|
export const cbrExtractor = {
|
|
7
7
|
name: 'cbr',
|
|
8
8
|
async canHandle(file) { return (await detectKind(file)) === 'cbr'; },
|
|
9
|
-
async extract(file, workdir) {
|
|
9
|
+
async extract(file, workdir, _onProgress) {
|
|
10
10
|
await mkdir(workdir, { recursive: true });
|
|
11
11
|
// filenameTransform strips any directory component so that entries with
|
|
12
12
|
// `../` or absolute paths cannot escape workdir (zip-slip defence).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cbr.js","sourceRoot":"","sources":["../../src/extractors/cbr.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AACnD,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAA;AAEvD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAEhE,MAAM,CAAC,MAAM,YAAY,GAAc;IACrC,IAAI,EAAE,KAAK;IACX,KAAK,CAAC,SAAS,CAAC,IAAI,IAAI,OAAO,CAAC,MAAM,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,CAAA,CAAC,CAAC;IACnE,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO;
|
|
1
|
+
{"version":3,"file":"cbr.js","sourceRoot":"","sources":["../../src/extractors/cbr.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AACnD,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAA;AAEvD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAEhE,MAAM,CAAC,MAAM,YAAY,GAAc;IACrC,IAAI,EAAE,KAAK;IACX,KAAK,CAAC,SAAS,CAAC,IAAI,IAAI,OAAO,CAAC,MAAM,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,CAAA,CAAC,CAAC;IACnE,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,WAAwB;QACnD,MAAM,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QACzC,wEAAwE;QACxE,oEAAoE;QACpE,MAAM,SAAS,GAAG,MAAM,uBAAuB,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,iBAAiB,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACrI,uDAAuD;QACvD,MAAM,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC,OAAO,EAAE,CAAA;QACrC,6DAA6D;QAC7D,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC,6CAA6C,CAAC,CAAC;QAExE,MAAM,KAAK,GAAa,EAAE,CAAA;QAC1B,KAAK,UAAU,IAAI,CAAC,CAAS;YAC3B,KAAK,MAAM,CAAC,IAAI,MAAM,OAAO,CAAC,CAAC,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;gBAC1D,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAA;gBACzB,IAAI,CAAC,CAAC,WAAW,EAAE;oBAAE,MAAM,IAAI,CAAC,CAAC,CAAC,CAAA;qBAC7B,IAAI,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;oBAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACzC,CAAC;QACH,CAAC;QACD,MAAM,IAAI,CAAC,OAAO,CAAC,CAAA;QACnB,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QAC9D,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAA;QACrE,MAAM,KAAK,GAAiB,EAAE,CAAA;QAC9B,KAAK,MAAM,CAAC,IAAI,KAAK;YAAE,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;QAC5F,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;IACrE,CAAC;CACF,CAAA"}
|
package/dist/extractors/cbz.js
CHANGED
|
@@ -42,7 +42,7 @@ function extractAll(zip, workdir) {
|
|
|
42
42
|
export const cbzExtractor = {
|
|
43
43
|
name: 'cbz',
|
|
44
44
|
async canHandle(file) { return (await detectKind(file)) === 'cbz'; },
|
|
45
|
-
async extract(file, workdir) {
|
|
45
|
+
async extract(file, workdir, _onProgress) {
|
|
46
46
|
await mkdir(workdir, { recursive: true });
|
|
47
47
|
const zip = await openZip(file);
|
|
48
48
|
const files = (await extractAll(zip, workdir)).sort((a, b) => naturalCompare(basename(a), basename(b)));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cbz.js","sourceRoot":"","sources":["../../src/extractors/cbz.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAA;AAC3C,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AACxC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAC/C,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAEhE,SAAS,OAAO,CAAC,IAAY;IAC3B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;IACjH,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,8EAA8E;AAC9E,SAAS,UAAU,CAAC,GAAkB,EAAE,OAAe;IACrD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,GAAG,GAAa,EAAE,CAAA;QACxB,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAkB,EAAE,EAAE;YACrC,MAAM,IAAI,GAAI,KAAK,CAAC,QAA8B,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;YACnE,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;gBAAC,GAAG,CAAC,SAAS,EAAE,CAAC;gBAAC,OAAM;YAAC,CAAC;YACrE,GAAG,CAAC,cAAc,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE;gBAC1C,IAAI,GAAG;oBAAE,OAAO,MAAM,CAAC,GAAG,CAAC,CAAA;gBAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAA;gBAC1C,IAAI,CAAC;oBAAC,MAAM,QAAQ,CAAC,EAAE,EAAE,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC;oBAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBAAC,GAAG,CAAC,SAAS,EAAE,CAAA;gBAAC,CAAC;gBACpF,OAAO,CAAC,EAAE,CAAC;oBAAC,MAAM,CAAC,CAAC,CAAC,CAAA;gBAAC,CAAC;YACzB,CAAC,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;QACF,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAA;QACjC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QACvB,GAAG,CAAC,SAAS,EAAE,CAAA;IACjB,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,YAAY,GAAc;IACrC,IAAI,EAAE,KAAK;IACX,KAAK,CAAC,SAAS,CAAC,IAAI,IAAI,OAAO,CAAC,MAAM,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,CAAA,CAAC,CAAC;IACnE,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO;
|
|
1
|
+
{"version":3,"file":"cbz.js","sourceRoot":"","sources":["../../src/extractors/cbz.ts"],"names":[],"mappings":"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"}
|
package/dist/extractors/djvu.js
CHANGED
|
@@ -15,7 +15,7 @@ async function pageCount(file) {
|
|
|
15
15
|
export const djvuExtractor = {
|
|
16
16
|
name: 'djvu',
|
|
17
17
|
async canHandle(file) { return (await detectKind(file)) === 'djvu'; },
|
|
18
|
-
async extract(file, workdir) {
|
|
18
|
+
async extract(file, workdir, onProgress) {
|
|
19
19
|
if (!(await hasBinary('ddjvu')) || !(await hasBinary('djvused'))) {
|
|
20
20
|
throw new Error('djvulibre not found. Install djvulibre (ddjvu, djvused).');
|
|
21
21
|
}
|
|
@@ -32,6 +32,7 @@ export const djvuExtractor = {
|
|
|
32
32
|
// which bloats and degrades text edges on bitonal content.
|
|
33
33
|
await sharp(tiff).webp({ lossless: true, effort: 6 }).toFile(webp);
|
|
34
34
|
pages.push({ type: 'raster', imagePath: webp, ...(await imageDims(webp)) });
|
|
35
|
+
onProgress?.(i, count, 'Converting');
|
|
35
36
|
}
|
|
36
37
|
return { title: basename(file, extname(file)), kind: 'djvu', pages };
|
|
37
38
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"djvu.js","sourceRoot":"","sources":["../../src/extractors/djvu.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AACxC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AACnD,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAA;AAC/B,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAEvC,KAAK,UAAU,SAAS,CAAC,IAAY;IACnC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAA;IAC1D,MAAM,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAA;IACrC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAA;IACnF,OAAO,CAAC,CAAA;AACV,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAc;IACtC,IAAI,EAAE,MAAM;IACZ,KAAK,CAAC,SAAS,CAAC,IAAI,IAAI,OAAO,CAAC,MAAM,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK,MAAM,CAAA,CAAC,CAAC;IACpE,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO;
|
|
1
|
+
{"version":3,"file":"djvu.js","sourceRoot":"","sources":["../../src/extractors/djvu.ts"],"names":[],"mappings":"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"}
|
package/dist/extractors/pdf.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { readFile } from 'node:fs/promises';
|
|
1
|
+
import { readFile, unlink, writeFile } from 'node:fs/promises';
|
|
2
2
|
import { basename, extname, join } from 'node:path';
|
|
3
3
|
import { detectKind } from './detect.js';
|
|
4
4
|
import { findPdfConverter } from '../tools.js';
|
|
5
5
|
import { run } from '../run.js';
|
|
6
|
+
import sharp from 'sharp';
|
|
7
|
+
import { imageDims } from './images.js';
|
|
6
8
|
function pad(n, width) {
|
|
7
9
|
return String(n).padStart(width, '0');
|
|
8
10
|
}
|
|
@@ -33,12 +35,25 @@ function viewBox(svg) {
|
|
|
33
35
|
return { w: Math.round(Number(w[1])), h: Math.round(Number(h[1])) };
|
|
34
36
|
throw new Error('SVG has no usable dimensions');
|
|
35
37
|
}
|
|
38
|
+
// Rounds floats with ≥3 decimal places to `decimals` places.
|
|
39
|
+
// Integers and short floats (≤2 decimals) are unchanged.
|
|
40
|
+
// Safe for glyph outlines and <use> positions at 2 decimals (0.01 pt precision).
|
|
41
|
+
export function roundCoords(svg, decimals = 2) {
|
|
42
|
+
return svg.replace(/-?\d+\.\d{3,}/g, (m) => String(Number(parseFloat(m).toFixed(decimals))));
|
|
43
|
+
}
|
|
44
|
+
// A page is raster-dominated when pdftocairo wrapped a full-page bitmap in SVG:
|
|
45
|
+
// at least one <image> element and fewer than 50 <use> elements (vector glyphs).
|
|
46
|
+
function isRasterDominated(svg) {
|
|
47
|
+
const imageCount = (svg.match(/<image/g) ?? []).length;
|
|
48
|
+
const useCount = (svg.match(/<use/g) ?? []).length;
|
|
49
|
+
return imageCount >= 1 && useCount < 50;
|
|
50
|
+
}
|
|
36
51
|
export const pdfExtractor = {
|
|
37
52
|
name: 'pdf',
|
|
38
53
|
async canHandle(file) {
|
|
39
54
|
return (await detectKind(file)) === 'pdf';
|
|
40
55
|
},
|
|
41
|
-
async extract(file, workdir) {
|
|
56
|
+
async extract(file, workdir, onProgress) {
|
|
42
57
|
const conv = await findPdfConverter();
|
|
43
58
|
if (!conv) {
|
|
44
59
|
throw new Error('No PDF converter found. Install poppler (pdftocairo) or mupdf (mutool).');
|
|
@@ -47,7 +62,8 @@ export const pdfExtractor = {
|
|
|
47
62
|
const width = Math.max(4, String(count).length);
|
|
48
63
|
const pages = [];
|
|
49
64
|
for (let i = 1; i <= count; i++) {
|
|
50
|
-
const
|
|
65
|
+
const stem = pad(i, width);
|
|
66
|
+
const svgPath = join(workdir, `${stem}.svg`);
|
|
51
67
|
if (conv === 'pdftocairo') {
|
|
52
68
|
await run('pdftocairo', ['-svg', '-f', String(i), '-l', String(i), file, svgPath]);
|
|
53
69
|
}
|
|
@@ -55,7 +71,25 @@ export const pdfExtractor = {
|
|
|
55
71
|
await run('mutool', ['draw', '-F', 'svg', '-o', svgPath, file, String(i)]);
|
|
56
72
|
}
|
|
57
73
|
const svg = await readFile(svgPath, 'utf8');
|
|
58
|
-
|
|
74
|
+
if (conv === 'pdftocairo' && isRasterDominated(svg)) {
|
|
75
|
+
// Full-page bitmap wrapped in SVG: re-render to a raster image, encode it
|
|
76
|
+
// as WebP (far smaller than the lossless PNG render), and drop the SVG.
|
|
77
|
+
const stemPath = join(workdir, stem);
|
|
78
|
+
await run('pdftocairo', ['-png', '-singlefile', '-r', '150', '-f', String(i), '-l', String(i), file, stemPath]);
|
|
79
|
+
const pngPath = `${stemPath}.png`;
|
|
80
|
+
const webpPath = `${stemPath}.webp`;
|
|
81
|
+
await sharp(pngPath).webp({ quality: 82, effort: 6 }).toFile(webpPath);
|
|
82
|
+
await unlink(svgPath);
|
|
83
|
+
await unlink(pngPath);
|
|
84
|
+
pages.push({ type: 'raster', imagePath: webpPath, ...(await imageDims(webpPath)) });
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
// Vector page: round coordinates to shrink SVG, then store.
|
|
88
|
+
const rounded = roundCoords(svg);
|
|
89
|
+
await writeFile(svgPath, rounded, 'utf8');
|
|
90
|
+
pages.push({ type: 'vector', svgPath, ...viewBox(rounded) });
|
|
91
|
+
}
|
|
92
|
+
onProgress?.(i, count, 'Converting');
|
|
59
93
|
}
|
|
60
94
|
return {
|
|
61
95
|
title: basename(file, extname(file)),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pdf.js","sourceRoot":"","sources":["../../src/extractors/pdf.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"pdf.js","sourceRoot":"","sources":["../../src/extractors/pdf.ts"],"names":[],"mappings":"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"}
|
package/dist/pages.js
CHANGED
|
@@ -2,7 +2,7 @@ import { mkdir, readFile, writeFile, copyFile } from 'node:fs/promises';
|
|
|
2
2
|
import { gzipSync } from 'node:zlib';
|
|
3
3
|
import { basename, join } from 'node:path';
|
|
4
4
|
import sharp from 'sharp';
|
|
5
|
-
export async function processPages(doc, outDir, opts = {}) {
|
|
5
|
+
export async function processPages(doc, outDir, opts = {}, onProgress) {
|
|
6
6
|
const thumbWidth = opts.thumbWidth ?? 150;
|
|
7
7
|
const width = Math.max(4, String(doc.pages.length).length);
|
|
8
8
|
await mkdir(join(outDir, 'pages'), { recursive: true });
|
|
@@ -27,6 +27,7 @@ export async function processPages(doc, outDir, opts = {}) {
|
|
|
27
27
|
await sharp(page.imagePath).resize({ width: thumbWidth }).webp().toFile(join(outDir, thumb));
|
|
28
28
|
out.push({ n, type: 'raster', w: page.w, h: page.h, file, thumb });
|
|
29
29
|
}
|
|
30
|
+
onProgress?.(i + 1, doc.pages.length, 'Processing');
|
|
30
31
|
}
|
|
31
32
|
return out;
|
|
32
33
|
}
|
package/dist/pages.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pages.js","sourceRoot":"","sources":["../src/pages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AACvE,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AACpC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAC1C,OAAO,KAAK,MAAM,OAAO,CAAA;AAYzB,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,GAAa,EACb,MAAc,EACd,OAAgC,EAAE;
|
|
1
|
+
{"version":3,"file":"pages.js","sourceRoot":"","sources":["../src/pages.ts"],"names":[],"mappings":"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"}
|
package/dist/serve.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { createServer } from 'node:http';
|
|
2
|
+
import { createReadStream, existsSync, statSync } from 'node:fs';
|
|
3
|
+
import { join, resolve as resolvePath, extname } from 'node:path';
|
|
4
|
+
const CONTENT_TYPES = {
|
|
5
|
+
'.html': 'text/html',
|
|
6
|
+
'.css': 'text/css',
|
|
7
|
+
'.js': 'text/javascript',
|
|
8
|
+
'.json': 'application/json',
|
|
9
|
+
'.svg': 'image/svg+xml',
|
|
10
|
+
'.svgz': 'application/octet-stream',
|
|
11
|
+
'.webp': 'image/webp',
|
|
12
|
+
'.jpg': 'image/jpeg',
|
|
13
|
+
'.jpeg': 'image/jpeg',
|
|
14
|
+
'.png': 'image/png',
|
|
15
|
+
'.gif': 'image/gif',
|
|
16
|
+
};
|
|
17
|
+
export async function serve(dir, port = 8000) {
|
|
18
|
+
const absDir = resolvePath(dir);
|
|
19
|
+
function handler(req, res) {
|
|
20
|
+
const urlPath = req.url?.split('?')[0] ?? '/';
|
|
21
|
+
const safePath = urlPath === '/' ? '/index.html' : urlPath;
|
|
22
|
+
let decoded;
|
|
23
|
+
try {
|
|
24
|
+
decoded = decodeURIComponent(safePath);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
res.writeHead(400);
|
|
28
|
+
res.end();
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const abs = resolvePath(join(absDir, decoded));
|
|
32
|
+
// Path traversal check: the resolved path must be inside absDir
|
|
33
|
+
if (!abs.startsWith(absDir + '/')) {
|
|
34
|
+
res.writeHead(404);
|
|
35
|
+
res.end();
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (!existsSync(abs) || statSync(abs).isDirectory()) {
|
|
39
|
+
res.writeHead(404);
|
|
40
|
+
res.end();
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const ext = extname(abs).toLowerCase();
|
|
44
|
+
const ct = CONTENT_TYPES[ext] ?? 'application/octet-stream';
|
|
45
|
+
res.writeHead(200, { 'Content-Type': ct });
|
|
46
|
+
createReadStream(abs).pipe(res);
|
|
47
|
+
}
|
|
48
|
+
return new Promise((resolveFn, rejectFn) => {
|
|
49
|
+
let currentPort = port;
|
|
50
|
+
function tryListen() {
|
|
51
|
+
const server = createServer(handler);
|
|
52
|
+
server.listen(currentPort, '127.0.0.1');
|
|
53
|
+
server.on('listening', () => {
|
|
54
|
+
const url = `http://localhost:${currentPort}`;
|
|
55
|
+
resolveFn({ url, close: () => server.close() });
|
|
56
|
+
});
|
|
57
|
+
server.on('error', (err) => {
|
|
58
|
+
if (err.code === 'EADDRINUSE' && currentPort < 8020) {
|
|
59
|
+
currentPort++;
|
|
60
|
+
server.removeAllListeners();
|
|
61
|
+
tryListen();
|
|
62
|
+
}
|
|
63
|
+
else if (err.code === 'EADDRINUSE') {
|
|
64
|
+
rejectFn(new Error('No free port found in 8000–8020'));
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
rejectFn(err);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
tryListen();
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=serve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve.js","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"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"}
|