@link-assistant/web-capture 1.12.0 → 2.0.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 (119) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +2 -1
  3. package/bin/web-capture.js +5 -7
  4. package/package.json +32 -18
  5. package/src/archive.js +1 -2
  6. package/src/binary-download.js +13 -0
  7. package/src/docx.js +14 -11
  8. package/src/fetch.js +1 -2
  9. package/src/figures.js +2 -12
  10. package/src/gdocs-images.js +0 -1
  11. package/src/gdocs.js +0 -1
  12. package/src/github.js +0 -1
  13. package/src/lib.js +1 -2
  14. package/src/localize-images.js +2 -12
  15. package/src/markdown.js +0 -1
  16. package/src/shared-dialog.js +0 -1
  17. package/src/stream.js +0 -1
  18. package/src/transport.js +23 -5
  19. package/src/txt.js +0 -1
  20. package/.changeset/README.md +0 -8
  21. package/.changeset/config.json +0 -11
  22. package/.dockerignore +0 -6
  23. package/.jscpd.json +0 -19
  24. package/.lenv +0 -8
  25. package/.prettierignore +0 -8
  26. package/.prettierrc +0 -10
  27. package/Dockerfile +0 -52
  28. package/babel.config.cjs +0 -13
  29. package/docker-compose.yml +0 -11
  30. package/eslint.config.js +0 -112
  31. package/examples/js/capture_cache.js +0 -12
  32. package/examples/js/engine_comparison.js +0 -39
  33. package/examples/js/html_download.js +0 -23
  34. package/examples/js/image_download.js +0 -36
  35. package/examples/js/markdown_download.js +0 -23
  36. package/examples/js/playwright_example.js +0 -23
  37. package/examples/python/html_download.py +0 -15
  38. package/examples/python/image_download.py +0 -20
  39. package/examples/python/markdown_download.py +0 -15
  40. package/examples/python/playwright_example.py +0 -22
  41. package/jest.config.mjs +0 -20
  42. package/tests/ci/dependency-freshness.test.js +0 -74
  43. package/tests/ci/detect-code-changes.test.js +0 -174
  44. package/tests/ci/docker-install.test.js +0 -31
  45. package/tests/ci/rust-dockerfile.test.js +0 -54
  46. package/tests/ci/workflow-policy.test.js +0 -79
  47. package/tests/e2e/docker.test.js +0 -186
  48. package/tests/e2e/process.test.js +0 -215
  49. package/tests/fixtures/bold-coalesce-and-leakage.html +0 -27
  50. package/tests/fixtures/deepwiki/deepwiki-full-page.png +0 -0
  51. package/tests/fixtures/deepwiki/index.md +0 -1500
  52. package/tests/fixtures/deepwiki/part-1.md +0 -776
  53. package/tests/fixtures/habr-articles.js +0 -45
  54. package/tests/fixtures/heading-numbering.html +0 -19
  55. package/tests/fixtures/list-item-with-br.html +0 -8
  56. package/tests/fixtures/ol-continuous-numbering.html +0 -12
  57. package/tests/fixtures/paragraph-vs-line-break.html +0 -11
  58. package/tests/helpers/nock.js +0 -10
  59. package/tests/helpers/search-fixture.cjs +0 -17
  60. package/tests/helpers/temporary-directory.js +0 -12
  61. package/tests/integration/api-endpoints.test.js +0 -418
  62. package/tests/integration/archive-default-layout.test.js +0 -37
  63. package/tests/integration/browser-engines.test.js +0 -128
  64. package/tests/integration/browser-packaged-path.test.js +0 -45
  65. package/tests/integration/deepwiki-download.test.js +0 -144
  66. package/tests/integration/deepwiki-rendered-page.mock.test.js +0 -121
  67. package/tests/integration/formalai-contract.test.js +0 -214
  68. package/tests/integration/gdocs-public-doc.test.js +0 -315
  69. package/tests/integration/github-readme.test.js +0 -137
  70. package/tests/integration/google-drive-image.test.js +0 -246
  71. package/tests/integration/habr-article.test.js +0 -337
  72. package/tests/integration/search-endpoint.test.js +0 -88
  73. package/tests/integration/stackoverflow-download.test.js +0 -173
  74. package/tests/integration/wikipedia-download.test.js +0 -142
  75. package/tests/jest.setup.mjs +0 -7
  76. package/tests/mock/index.test.js +0 -225
  77. package/tests/unit/animation.test.js +0 -33
  78. package/tests/unit/batch.test.js +0 -114
  79. package/tests/unit/bold-coalesce-and-leakage.test.js +0 -54
  80. package/tests/unit/browser-launch-options.test.js +0 -42
  81. package/tests/unit/browser.test.js +0 -172
  82. package/tests/unit/cache.test.js +0 -182
  83. package/tests/unit/cli.test.js +0 -399
  84. package/tests/unit/convertGoogleDriveUrl.test.js +0 -89
  85. package/tests/unit/convertRelativeUrls.test.js +0 -34
  86. package/tests/unit/extract-images.test.js +0 -259
  87. package/tests/unit/fetch-html.test.js +0 -54
  88. package/tests/unit/figures.test.js +0 -74
  89. package/tests/unit/gdocs-export-headers.test.js +0 -28
  90. package/tests/unit/gdocs-preprocess.test.js +0 -36
  91. package/tests/unit/gdocs.test.js +0 -1490
  92. package/tests/unit/github.test.js +0 -156
  93. package/tests/unit/heading-image.test.js +0 -49
  94. package/tests/unit/heading-numbering.test.js +0 -28
  95. package/tests/unit/html2md-br-in-list-item.test.js +0 -23
  96. package/tests/unit/html2md-ol-numbering.test.js +0 -20
  97. package/tests/unit/html2md.test.js +0 -695
  98. package/tests/unit/image-mode-defaults.test.js +0 -54
  99. package/tests/unit/kreuzberg.test.js +0 -249
  100. package/tests/unit/latex.test.js +0 -123
  101. package/tests/unit/localize-images.test.js +0 -114
  102. package/tests/unit/markdown.test.js +0 -36
  103. package/tests/unit/metadata.test.js +0 -140
  104. package/tests/unit/package-runtime-dependencies.test.js +0 -74
  105. package/tests/unit/paragraph-vs-line-break.test.js +0 -56
  106. package/tests/unit/postprocess.test.js +0 -110
  107. package/tests/unit/proxy-headers.test.js +0 -100
  108. package/tests/unit/publish-verification.test.js +0 -57
  109. package/tests/unit/retry.test.js +0 -111
  110. package/tests/unit/search.test.js +0 -339
  111. package/tests/unit/shared-dialog.test.js +0 -173
  112. package/tests/unit/stackoverflow.test.js +0 -32
  113. package/tests/unit/stream.test.js +0 -85
  114. package/tests/unit/verify.test.js +0 -182
  115. package/tests/xpaste/xpaste-screenshot-markdown.mock.test.js +0 -375
  116. package/tests/xpaste/xpaste.e2e.test.js +0 -36
  117. package/tests/xpaste/xpaste.integration.test.js +0 -41
  118. package/tests/xpaste/xpaste.mock.test.js +0 -261
  119. package/tests/xpaste/xpaste.unit.test.js +0 -119
@@ -1,399 +0,0 @@
1
- // Unit tests for CLI argument parsing and functionality
2
- import { spawn } from 'child_process';
3
- import http from 'node:http';
4
- import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'fs';
5
- import { fileURLToPath } from 'url';
6
- import { dirname, join, resolve } from 'path';
7
- import packageJson from '../../package.json' with { type: 'json' };
8
-
9
- const __filename = fileURLToPath(import.meta.url);
10
- const __dirname = dirname(__filename);
11
- const cliPath = resolve(__dirname, '../../bin/web-capture.js');
12
- const searchFixturePath = resolve(__dirname, '../helpers/search-fixture.cjs');
13
-
14
- // Helper function to run CLI and capture output
15
- function runCli(args, options = {}) {
16
- return new Promise((resolve, reject) => {
17
- const proc = spawn(process.execPath, [cliPath, ...args], {
18
- cwd: options.cwd || dirname(cliPath),
19
- env: { ...process.env, ...options.env },
20
- });
21
-
22
- let stdout = '';
23
- let stderr = '';
24
-
25
- proc.stdout.on('data', (data) => {
26
- stdout += data.toString();
27
- });
28
- proc.stderr.on('data', (data) => {
29
- stderr += data.toString();
30
- });
31
-
32
- proc.on('close', (code) => {
33
- resolve({ code, stdout, stderr });
34
- });
35
-
36
- proc.on('error', reject);
37
- });
38
- }
39
-
40
- function startFixtureServer({
41
- body = '<!doctype html><html><body><h1>Issue 68</h1><p>Captured from positional URL.</p></body></html>',
42
- contentType = 'text/html; charset=utf-8',
43
- } = {}) {
44
- return new Promise((resolve, reject) => {
45
- const server = http.createServer((req, res) => {
46
- res.writeHead(200, {
47
- 'Content-Type': contentType,
48
- 'Content-Length': Buffer.byteLength(body),
49
- });
50
- res.end(body);
51
- });
52
-
53
- server.on('error', reject);
54
- server.listen(0, '127.0.0.1', () => {
55
- const { port } = server.address();
56
- resolve({
57
- server,
58
- url: `http://127.0.0.1:${port}/article`,
59
- });
60
- });
61
- });
62
- }
63
-
64
- function stopFixtureServer(server) {
65
- return new Promise((resolve, reject) => {
66
- server.close((err) => {
67
- if (err) {
68
- reject(err);
69
- return;
70
- }
71
- resolve();
72
- });
73
- });
74
- }
75
-
76
- describe('CLI', () => {
77
- describe('--help', () => {
78
- test('shows help message with --help flag', async () => {
79
- const result = await runCli(['--help']);
80
- expect(result.code).toBe(0);
81
- expect(result.stdout).toContain('web-capture');
82
- expect(result.stdout).toContain('Usage:');
83
- expect(result.stdout).toContain('--serve');
84
- expect(result.stdout).toContain('--format');
85
- expect(result.stdout).toContain('--output');
86
- expect(result.stdout).toContain('--engine');
87
- });
88
-
89
- test('shows help message with -h flag', async () => {
90
- const result = await runCli(['-h']);
91
- expect(result.code).toBe(0);
92
- expect(result.stdout).toContain('web-capture');
93
- expect(result.stdout).toContain('Usage:');
94
- });
95
-
96
- test('shows error and exits with code 1 when no arguments provided', async () => {
97
- const result = await runCli([]);
98
- expect(result.code).toBe(1);
99
- // With lino-arguments and yargs, error messages go to stderr
100
- expect(result.stderr).toContain('Error');
101
- });
102
- });
103
-
104
- describe('--version', () => {
105
- test('shows version with --version flag', async () => {
106
- const result = await runCli(['--version']);
107
- expect(result.code).toBe(0);
108
- // yargs outputs just the version number
109
- expect(result.stdout).toMatch(/\d+\.\d+\.\d+/);
110
- });
111
-
112
- test('shows version with -v flag', async () => {
113
- const result = await runCli(['-v']);
114
- expect(result.code).toBe(0);
115
- // yargs outputs just the version number
116
- expect(result.stdout).toMatch(/\d+\.\d+\.\d+/);
117
- });
118
-
119
- test('shows web-capture version when run from another npm project', async () => {
120
- const callerProjectDir = mkdtempSync(join(process.cwd(), 'caller-'));
121
- writeFileSync(
122
- join(callerProjectDir, 'package.json'),
123
- JSON.stringify({
124
- name: 'caller-project',
125
- version: '1.0.0',
126
- })
127
- );
128
-
129
- try {
130
- const result = await runCli(['--version'], { cwd: callerProjectDir });
131
-
132
- expect(result.code).toBe(0);
133
- expect(result.stdout.trim()).toBe(packageJson.version);
134
- } finally {
135
- rmSync(callerProjectDir, { recursive: true, force: true });
136
- }
137
- });
138
- });
139
-
140
- describe('URL validation', () => {
141
- test('accepts a URL as a positional argument', async () => {
142
- const { server, url } = await startFixtureServer();
143
-
144
- try {
145
- const result = await runCli([
146
- url,
147
- '--format',
148
- 'markdown',
149
- '--output',
150
- '-',
151
- ]);
152
-
153
- expect(result.code).toBe(0);
154
- expect(result.stderr).not.toContain('Unknown argument');
155
- expect(result.stdout).toContain('Issue 68');
156
- expect(result.stdout).toContain('Captured from positional URL.');
157
- } finally {
158
- await stopFixtureServer(server);
159
- }
160
- }, 15000);
161
-
162
- test('accepts a URL after the -- argument separator', async () => {
163
- const { server, url } = await startFixtureServer();
164
-
165
- try {
166
- const result = await runCli([
167
- '--format',
168
- 'markdown',
169
- '--output',
170
- '-',
171
- '--',
172
- url,
173
- ]);
174
-
175
- expect(result.code).toBe(0);
176
- expect(result.stderr).not.toContain('Missing URL');
177
- expect(result.stdout).toContain('Issue 68');
178
- } finally {
179
- await stopFixtureServer(server);
180
- }
181
- }, 15000);
182
-
183
- test('rejects unknown options', async () => {
184
- const result = await runCli([
185
- '--unknown-option-for-issue-68',
186
- 'https://example.com',
187
- ]);
188
-
189
- expect(result.code).toBe(1);
190
- expect(result.stderr).toContain('Unknown argument');
191
- });
192
-
193
- test('rejects invalid URL', async () => {
194
- const result = await runCli(['http://[invalid-url']);
195
- // Should fail before trying to capture.
196
- expect(result.code).toBe(1);
197
- expect(result.stderr).toContain('Invalid URL');
198
- }, 15000);
199
- });
200
-
201
- describe('format options', () => {
202
- test('accepts --format html', async () => {
203
- // Just test that the argument is accepted (actual fetch would fail without network)
204
- const result = await runCli(['--help']);
205
- expect(result.stdout).toContain('--format');
206
- expect(result.stdout).toContain('html');
207
- });
208
-
209
- test('accepts --format markdown', async () => {
210
- const result = await runCli(['--help']);
211
- expect(result.stdout).toContain('markdown');
212
- });
213
-
214
- test('accepts --format image', async () => {
215
- const result = await runCli(['--help']);
216
- expect(result.stdout).toContain('image');
217
- });
218
- });
219
-
220
- describe('engine options', () => {
221
- test('help shows engine options', async () => {
222
- const result = await runCli(['--help']);
223
- expect(result.stdout).toContain('--engine');
224
- expect(result.stdout).toContain('puppeteer');
225
- expect(result.stdout).toContain('playwright');
226
- });
227
-
228
- test('accepts --engine option', async () => {
229
- const result = await runCli(['--help']);
230
- expect(result.stdout).toContain('--engine');
231
- });
232
- });
233
-
234
- describe('server mode options', () => {
235
- test('help shows --serve option', async () => {
236
- const result = await runCli(['--help']);
237
- expect(result.stdout).toContain('--serve');
238
- expect(result.stdout).toContain('-s');
239
- });
240
-
241
- test('help shows --port option', async () => {
242
- const result = await runCli(['--help']);
243
- expect(result.stdout).toContain('--port');
244
- expect(result.stdout).toContain('-p');
245
- });
246
-
247
- test('help shows API endpoints', async () => {
248
- const result = await runCli(['--help']);
249
- expect(result.stdout).toContain('/html');
250
- expect(result.stdout).toContain('/markdown');
251
- expect(result.stdout).toContain('/image');
252
- expect(result.stdout).not.toContain('/gdocs');
253
- });
254
- });
255
-
256
- describe('output options', () => {
257
- test('help shows --output option', async () => {
258
- const result = await runCli(['--help']);
259
- expect(result.stdout).toContain('--output');
260
- expect(result.stdout).toContain('-o');
261
- });
262
- });
263
-
264
- describe('FormalAI-compatible CLI contract', () => {
265
- test('writes HTML, Markdown, and text captures to stdout with -o -', async () => {
266
- const { server, url } = await startFixtureServer({
267
- body: '<!doctype html><html><body><h1>FormalAI Fixture</h1><p>Stable CLI shape.</p></body></html>',
268
- });
269
-
270
- try {
271
- const html = await runCli([url, '--format', 'html', '--output', '-']);
272
- expect(html.code).toBe(0);
273
- expect(html.stdout).toContain('<h1>FormalAI Fixture</h1>');
274
-
275
- const markdown = await runCli([
276
- url,
277
- '--format',
278
- 'markdown',
279
- '--output',
280
- '-',
281
- ]);
282
- expect(markdown.code).toBe(0);
283
- expect(markdown.stdout).toContain('FormalAI Fixture');
284
- expect(markdown.stdout).toContain('Stable CLI shape.');
285
-
286
- const text = await runCli([url, '--format', 'txt', '--output', '-']);
287
- expect(text.code).toBe(0);
288
- expect(text.stdout).toContain('FormalAI Fixture');
289
- } finally {
290
- await stopFixtureServer(server);
291
- }
292
- }, 20000);
293
-
294
- test('writes archive captures as ZIP files for binary CLI consumers', async () => {
295
- const outputDir = mkdtempSync(join(process.cwd(), 'formalai-cli-'));
296
- const outputPath = join(outputDir, 'capture.zip');
297
- const { server, url } = await startFixtureServer({
298
- body: '<!doctype html><html><body><h1>FormalAI Archive</h1></body></html>',
299
- });
300
-
301
- try {
302
- const result = await runCli([
303
- url,
304
- '--archive',
305
- 'zip',
306
- '--output',
307
- outputPath,
308
- ]);
309
-
310
- expect(result.code).toBe(0);
311
- const zipBytes = readFileSync(outputPath);
312
- expect(zipBytes.length).toBeGreaterThan(50);
313
- expect(zipBytes[0]).toBe(0x50);
314
- expect(zipBytes[1]).toBe(0x4b);
315
- } finally {
316
- await stopFixtureServer(server);
317
- rmSync(outputDir, { recursive: true, force: true });
318
- }
319
- }, 20000);
320
-
321
- test('emits normalized search JSON from the search subcommand', async () => {
322
- const nodeOptions = [
323
- process.env.NODE_OPTIONS,
324
- `--require=${searchFixturePath}`,
325
- ]
326
- .filter(Boolean)
327
- .join(' ');
328
- const result = await runCli(
329
- ['search', 'formal-ai', '--provider', 'wikipedia', '--limit', '1'],
330
- {
331
- env: { NODE_OPTIONS: nodeOptions },
332
- }
333
- );
334
-
335
- expect(result.code).toBe(0);
336
- const body = JSON.parse(result.stdout);
337
- expect(body).toMatchObject({
338
- query: 'formal-ai',
339
- provider: 'wikipedia',
340
- captureMode: 'fetch',
341
- });
342
- expect(body.results).toEqual([
343
- {
344
- rank: 1,
345
- title: 'Formal methods',
346
- url: 'https://en.wikipedia.org/wiki/Formal_methods',
347
- snippet: 'the study of formal methods',
348
- },
349
- ]);
350
- expect(body.diagnostics).toMatchObject({
351
- status: 200,
352
- blockedByCors: false,
353
- blockedByCaptcha: false,
354
- });
355
- expect(body.diagnostics.sourceUrl).toContain('en.wikipedia.org');
356
- }, 20000);
357
-
358
- test('emits shared-dialog demo_memory from the shared-dialog subcommand', async () => {
359
- const fixturePath = resolve(
360
- __dirname,
361
- '../../../docs/case-studies/issue-141/raw-data/chatgpt-share-6a3825b9.html'
362
- );
363
- const body = readFileSync(fixturePath, 'utf-8');
364
- const { server, url } = await startFixtureServer({ body });
365
- const shareUrl = url.replace(
366
- '/article',
367
- '/share/6a3825b9-8de4-83ee-9c24-52fd1eb38d24'
368
- );
369
-
370
- try {
371
- const result = await runCli(
372
- [
373
- 'shared-dialog',
374
- shareUrl,
375
- '--format',
376
- 'demo-memory',
377
- '--output',
378
- '-',
379
- ],
380
- {
381
- cwd: resolve(__dirname, '../..'),
382
- }
383
- );
384
-
385
- expect(result.code).toBe(0);
386
- expect(result.stdout.startsWith('demo_memory')).toBe(true);
387
- expect(result.stdout).toContain('demo_memory');
388
- expect(result.stdout.match(/\n {2}event "/g)).toHaveLength(4);
389
- expect(result.stdout).toContain('role "user"');
390
- expect(result.stdout).toContain('role "assistant"');
391
- expect(result.stdout).toContain(
392
- 'conversationTitle "Infinite loop script"'
393
- );
394
- } finally {
395
- await stopFixtureServer(server);
396
- }
397
- }, 20000);
398
- });
399
- });
@@ -1,89 +0,0 @@
1
- import {
2
- convertGoogleDriveUrl,
3
- getGoogleDriveFileId,
4
- googleDriveImageTextForUrl,
5
- isGoogleDriveFileUrl,
6
- } from '../../src/lib.js';
7
-
8
- const FIRST_FILE_ID = '1Cxkx6-428EQAX0-eiaq66H829ohnPp7q';
9
- const SECOND_FILE_ID = '1fgJaftjv53xCN7vgiJOaQlbfWkUqPgyd';
10
-
11
- function directDownloadUrl(fileId) {
12
- return `https://drive.google.com/uc?export=download&id=${fileId}`;
13
- }
14
-
15
- describe('Google Drive URL helpers', () => {
16
- it.each([
17
- [
18
- 'issue URL with /view',
19
- `https://drive.google.com/file/d/${FIRST_FILE_ID}/view`,
20
- FIRST_FILE_ID,
21
- ],
22
- [
23
- 'issue URL without /view',
24
- `https://drive.google.com/file/d/${FIRST_FILE_ID}`,
25
- FIRST_FILE_ID,
26
- ],
27
- [
28
- 'second issue URL with /view',
29
- `https://drive.google.com/file/d/${SECOND_FILE_ID}/view`,
30
- SECOND_FILE_ID,
31
- ],
32
- [
33
- 'second issue URL without /view',
34
- `https://drive.google.com/file/d/${SECOND_FILE_ID}`,
35
- SECOND_FILE_ID,
36
- ],
37
- [
38
- 'open?id URL',
39
- `https://drive.google.com/open?id=${FIRST_FILE_ID}`,
40
- FIRST_FILE_ID,
41
- ],
42
- [
43
- 'direct uc URL',
44
- `https://drive.google.com/uc?export=download&id=${FIRST_FILE_ID}`,
45
- FIRST_FILE_ID,
46
- ],
47
- [
48
- 'redirected usercontent URL',
49
- `https://drive.usercontent.google.com/download?id=${FIRST_FILE_ID}&export=download`,
50
- FIRST_FILE_ID,
51
- ],
52
- ])('extracts and converts %s', (_name, input, fileId) => {
53
- expect(getGoogleDriveFileId(input)).toBe(fileId);
54
- expect(isGoogleDriveFileUrl(input)).toBe(true);
55
- expect(convertGoogleDriveUrl(input)).toBe(directDownloadUrl(fileId));
56
- });
57
-
58
- it('ignores non-Google Drive URLs and malformed Drive IDs', () => {
59
- const example = 'https://example.com/image.jpg';
60
- const malformed = 'https://drive.google.com/file/d/not%20valid/view';
61
-
62
- expect(getGoogleDriveFileId(example)).toBeNull();
63
- expect(isGoogleDriveFileUrl(example)).toBe(false);
64
- expect(convertGoogleDriveUrl(example)).toBe(example);
65
- expect(getGoogleDriveFileId(malformed)).toBeNull();
66
- expect(isGoogleDriveFileUrl(malformed)).toBe(false);
67
- expect(convertGoogleDriveUrl(malformed)).toBe(malformed);
68
- });
69
-
70
- it('keeps empty or missing inputs unchanged when converting', () => {
71
- expect(convertGoogleDriveUrl(null)).toBeNull();
72
- expect(convertGoogleDriveUrl(undefined)).toBeUndefined();
73
- expect(convertGoogleDriveUrl('')).toBe('');
74
- });
75
-
76
- it('renders text output with the original file URL and direct image URL', () => {
77
- const input = `https://drive.google.com/file/d/${FIRST_FILE_ID}/view`;
78
-
79
- expect(googleDriveImageTextForUrl(input)).toContain(
80
- `Original Google Drive file: ${input}`
81
- );
82
- expect(googleDriveImageTextForUrl(input)).toContain(
83
- `Image: ${directDownloadUrl(FIRST_FILE_ID)}`
84
- );
85
- expect(
86
- googleDriveImageTextForUrl('https://example.com/image.jpg')
87
- ).toBeNull();
88
- });
89
- });
@@ -1,34 +0,0 @@
1
- import { convertRelativeUrls } from '../../src/lib.js';
2
-
3
- describe('convertRelativeUrls', () => {
4
- const baseUrl = 'https://example.com/';
5
-
6
- it('should NOT inject runtimeHook if there are no <script> tags', () => {
7
- const html = `<!DOCTYPE html><html><head><title>Test</title></head><body><h1>Hello</h1><p>World</p></body></html>`;
8
- const result = convertRelativeUrls(html, baseUrl);
9
- // Should not inject the runtimeHook
10
- expect(result).not.toMatch(/MutationObserver/);
11
- expect(result).not.toMatch(/fixAllUrls/);
12
- expect(result).not.toMatch(/runtime JS hook/);
13
- // Should not add any <script> tag
14
- expect(result.match(/<script/gi)).toBeNull();
15
- });
16
-
17
- it('should inject runtimeHook if there is a <script> tag', () => {
18
- const html = `<!DOCTYPE html><html><head><title>Test</title><script src="foo.js"></script></head><body><h1>Hello</h1></body></html>`;
19
- const result = convertRelativeUrls(html, baseUrl);
20
- // Should inject the runtimeHook
21
- expect(result).toMatch(/MutationObserver/);
22
- expect(result).toMatch(/fixAllUrls/);
23
- // Should add a <script> tag for the hook
24
- expect((result.match(/<script/gi) || []).length).toBeGreaterThan(1);
25
- });
26
-
27
- it('should inject runtimeHook if there is an inline <script>', () => {
28
- const html = `<!DOCTYPE html><html><head><title>Test</title><script>console.log('hi');</script></head><body></body></html>`;
29
- const result = convertRelativeUrls(html, baseUrl);
30
- expect(result).toMatch(/MutationObserver/);
31
- expect(result).toMatch(/fixAllUrls/);
32
- expect((result.match(/<script/gi) || []).length).toBeGreaterThan(1);
33
- });
34
- });