@link-assistant/web-capture 1.7.2 → 1.7.3
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/CHANGELOG.md +6 -0
- package/bin/web-capture.js +21 -2
- package/package.json +1 -1
- package/tests/unit/cli.test.js +88 -4
package/CHANGELOG.md
CHANGED
package/bin/web-capture.js
CHANGED
|
@@ -16,6 +16,12 @@ const config = makeConfig({
|
|
|
16
16
|
.usage(
|
|
17
17
|
'web-capture - Capture web pages as HTML, Markdown, or PNG\n\nUsage:\n web-capture --serve [--port <port>] Start as API server\n web-capture <url> [options] Capture a URL to file/stdout'
|
|
18
18
|
)
|
|
19
|
+
.command('$0 [url]', 'Capture a URL or start the API server', (yargs) =>
|
|
20
|
+
yargs.positional('url', {
|
|
21
|
+
type: 'string',
|
|
22
|
+
description: 'URL to capture',
|
|
23
|
+
})
|
|
24
|
+
)
|
|
19
25
|
.option('serve', {
|
|
20
26
|
alias: 's',
|
|
21
27
|
type: 'boolean',
|
|
@@ -77,6 +83,7 @@ const config = makeConfig({
|
|
|
77
83
|
.option('output', {
|
|
78
84
|
alias: 'o',
|
|
79
85
|
type: 'string',
|
|
86
|
+
nargs: 1,
|
|
80
87
|
description:
|
|
81
88
|
'Output file path (default: stdout for text, auto-generated for images)',
|
|
82
89
|
})
|
|
@@ -232,6 +239,19 @@ const config = makeConfig({
|
|
|
232
239
|
},
|
|
233
240
|
});
|
|
234
241
|
|
|
242
|
+
function getUrlArgument() {
|
|
243
|
+
if (typeof config.url === 'string' && config.url.length > 0) {
|
|
244
|
+
return config.url;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const separatorIndex = process.argv.indexOf('--');
|
|
248
|
+
if (separatorIndex !== -1 && separatorIndex < process.argv.length - 1) {
|
|
249
|
+
return process.argv[separatorIndex + 1];
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return null;
|
|
253
|
+
}
|
|
254
|
+
|
|
235
255
|
async function startServer(port) {
|
|
236
256
|
// Import the Express app
|
|
237
257
|
const { app } = await import('../src/index.js');
|
|
@@ -824,8 +844,7 @@ async function captureUrl(url, options) {
|
|
|
824
844
|
}
|
|
825
845
|
|
|
826
846
|
async function main() {
|
|
827
|
-
|
|
828
|
-
const url = config._ && config._.length > 0 ? config._[0] : null;
|
|
847
|
+
const url = getUrlArgument();
|
|
829
848
|
|
|
830
849
|
if (config.serve) {
|
|
831
850
|
// Server mode
|
package/package.json
CHANGED
package/tests/unit/cli.test.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Unit tests for CLI argument parsing and functionality
|
|
2
2
|
import { spawn } from 'child_process';
|
|
3
|
+
import http from 'node:http';
|
|
3
4
|
import { fileURLToPath } from 'url';
|
|
4
5
|
import { dirname, resolve } from 'path';
|
|
5
6
|
|
|
@@ -33,6 +34,38 @@ function runCli(args, options = {}) {
|
|
|
33
34
|
});
|
|
34
35
|
}
|
|
35
36
|
|
|
37
|
+
function startFixtureServer() {
|
|
38
|
+
return new Promise((resolve, reject) => {
|
|
39
|
+
const server = http.createServer((req, res) => {
|
|
40
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
41
|
+
res.end(
|
|
42
|
+
'<!doctype html><html><body><h1>Issue 68</h1><p>Captured from positional URL.</p></body></html>'
|
|
43
|
+
);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
server.on('error', reject);
|
|
47
|
+
server.listen(0, '127.0.0.1', () => {
|
|
48
|
+
const { port } = server.address();
|
|
49
|
+
resolve({
|
|
50
|
+
server,
|
|
51
|
+
url: `http://127.0.0.1:${port}/article`,
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function stopFixtureServer(server) {
|
|
58
|
+
return new Promise((resolve, reject) => {
|
|
59
|
+
server.close((err) => {
|
|
60
|
+
if (err) {
|
|
61
|
+
reject(err);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
resolve();
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
36
69
|
describe('CLI', () => {
|
|
37
70
|
describe('--help', () => {
|
|
38
71
|
test('shows help message with --help flag', async () => {
|
|
@@ -78,12 +111,63 @@ describe('CLI', () => {
|
|
|
78
111
|
});
|
|
79
112
|
|
|
80
113
|
describe('URL validation', () => {
|
|
114
|
+
test('accepts a URL as a positional argument', async () => {
|
|
115
|
+
const { server, url } = await startFixtureServer();
|
|
116
|
+
|
|
117
|
+
try {
|
|
118
|
+
const result = await runCli([
|
|
119
|
+
url,
|
|
120
|
+
'--format',
|
|
121
|
+
'markdown',
|
|
122
|
+
'--output',
|
|
123
|
+
'-',
|
|
124
|
+
]);
|
|
125
|
+
|
|
126
|
+
expect(result.code).toBe(0);
|
|
127
|
+
expect(result.stderr).not.toContain('Unknown argument');
|
|
128
|
+
expect(result.stdout).toContain('Issue 68');
|
|
129
|
+
expect(result.stdout).toContain('Captured from positional URL.');
|
|
130
|
+
} finally {
|
|
131
|
+
await stopFixtureServer(server);
|
|
132
|
+
}
|
|
133
|
+
}, 15000);
|
|
134
|
+
|
|
135
|
+
test('accepts a URL after the -- argument separator', async () => {
|
|
136
|
+
const { server, url } = await startFixtureServer();
|
|
137
|
+
|
|
138
|
+
try {
|
|
139
|
+
const result = await runCli([
|
|
140
|
+
'--format',
|
|
141
|
+
'markdown',
|
|
142
|
+
'--output',
|
|
143
|
+
'-',
|
|
144
|
+
'--',
|
|
145
|
+
url,
|
|
146
|
+
]);
|
|
147
|
+
|
|
148
|
+
expect(result.code).toBe(0);
|
|
149
|
+
expect(result.stderr).not.toContain('Missing URL');
|
|
150
|
+
expect(result.stdout).toContain('Issue 68');
|
|
151
|
+
} finally {
|
|
152
|
+
await stopFixtureServer(server);
|
|
153
|
+
}
|
|
154
|
+
}, 15000);
|
|
155
|
+
|
|
156
|
+
test('rejects unknown options', async () => {
|
|
157
|
+
const result = await runCli([
|
|
158
|
+
'--unknown-option-for-issue-68',
|
|
159
|
+
'https://example.com',
|
|
160
|
+
]);
|
|
161
|
+
|
|
162
|
+
expect(result.code).toBe(1);
|
|
163
|
+
expect(result.stderr).toContain('Unknown argument');
|
|
164
|
+
});
|
|
165
|
+
|
|
81
166
|
test('rejects invalid URL', async () => {
|
|
82
|
-
const result = await runCli(['
|
|
83
|
-
// Should fail
|
|
167
|
+
const result = await runCli(['http://[invalid-url']);
|
|
168
|
+
// Should fail before trying to capture.
|
|
84
169
|
expect(result.code).toBe(1);
|
|
85
|
-
|
|
86
|
-
expect(result.stdout.length + result.stderr.length).toBeGreaterThan(0);
|
|
170
|
+
expect(result.stderr).toContain('Invalid URL');
|
|
87
171
|
}, 15000);
|
|
88
172
|
});
|
|
89
173
|
|