screenitshot 0.5.0 → 0.7.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.
package/dist/cli.js CHANGED
@@ -1,50 +1,95 @@
1
1
  #!/usr/bin/env node
2
2
  import { Command } from 'commander';
3
- import { screenshot } from './index.js';
4
- import { readFile } from 'fs/promises';
5
- import { resolve, dirname } from 'path';
3
+ import { screenshot, detectFormat } from './index.js';
4
+ import { readFile, writeFile, access } from 'fs/promises';
5
+ import { resolve, dirname, basename, extname, join } from 'path';
6
6
  import { fileURLToPath } from 'url';
7
7
  const __filename = fileURLToPath(import.meta.url);
8
8
  const __dirname = dirname(__filename);
9
9
  const packageJson = JSON.parse(await readFile(resolve(__dirname, '../package.json'), 'utf-8'));
10
+ /**
11
+ * Generate a unique output path using macOS-style duplicate naming.
12
+ * If basePath exists, returns basePath with ' (1)', ' (2)', etc. suffix.
13
+ * Example: document.png -> document (1).png -> document (2).png
14
+ */
15
+ async function getUniqueOutputPath(basePath) {
16
+ try {
17
+ await access(basePath);
18
+ }
19
+ catch {
20
+ // File doesn't exist, use the base path
21
+ return basePath;
22
+ }
23
+ const dir = dirname(basePath);
24
+ const ext = extname(basePath);
25
+ const stem = basename(basePath, ext);
26
+ let counter = 1;
27
+ // eslint-disable-next-line no-constant-condition
28
+ while (true) {
29
+ const newPath = join(dir, `${stem} (${counter})${ext}`);
30
+ try {
31
+ await access(newPath);
32
+ counter++;
33
+ }
34
+ catch {
35
+ return newPath;
36
+ }
37
+ }
38
+ }
10
39
  const program = new Command();
11
40
  program
12
41
  .name('screenitshot')
13
42
  .description('Convert various file formats to high-quality screenshots')
14
43
  .version(packageJson.version)
15
44
  .argument('<input>', 'Input file path')
16
- .argument('[output]', 'Output image path')
17
45
  .option('-f, --format <format>', 'Output image format (png, jpeg, webp)', 'png')
18
- .option('-w, --width <width>', 'Viewport width', '1920')
19
- .option('-h, --height <height>', 'Viewport height', '1080')
46
+ .option('-w, --width <width>', 'Viewport width')
47
+ .option('-H, --height <height>', 'Viewport height')
20
48
  .option('-p, --page <page>', 'Page number for multi-page documents', '1')
21
- .action(async (input, output, options) => {
49
+ .action(async (input, options) => {
22
50
  try {
51
+ // Check input file exists and detect format
52
+ let inputData;
53
+ try {
54
+ inputData = await readFile(input);
55
+ }
56
+ catch {
57
+ console.error(`Error: Input file not found: ${input}`);
58
+ process.exit(1);
59
+ }
60
+ const inputFormat = await detectFormat(input);
61
+ if (inputFormat === 'unknown') {
62
+ console.error(`Error: Unsupported file format: ${input}`);
63
+ process.exit(1);
64
+ }
65
+ // Determine output path (same folder as input, with unique name)
66
+ const dir = dirname(input);
67
+ const stem = basename(input, extname(input));
68
+ const baseOutput = join(dir, `${stem}.${options.format}`);
69
+ const outputPath = await getUniqueOutputPath(baseOutput);
23
70
  console.log(`Converting ${input}...`);
24
- const result = await screenshot(input, {
25
- output,
71
+ const result = await screenshot(inputData, inputFormat, {
26
72
  format: options.format,
27
- width: parseInt(options.width),
28
- height: parseInt(options.height),
73
+ width: options.width ? parseInt(options.width) : undefined,
74
+ height: options.height ? parseInt(options.height) : undefined,
29
75
  page: parseInt(options.page),
76
+ fileName: basename(input),
30
77
  });
31
- console.log(`✓ Screenshot saved to ${result.path}`);
78
+ // Write output to file
79
+ await writeFile(outputPath, result.data);
80
+ console.log(`✓ Screenshot saved to ${outputPath}`);
81
+ console.log(` Renderer: ${result.renderer}`);
32
82
  console.log(` Format: ${result.format}`);
33
83
  console.log(` Size: ${result.width}x${result.height}`);
34
84
  }
35
85
  catch (error) {
36
86
  const err = error;
37
87
  // User-friendly error messages
38
- if (err.message.includes('ENOENT') || err.message.includes('no such file')) {
39
- console.error(`Error: Input file not found: ${input}`);
40
- }
41
- else if (err.message.includes('Unsupported file format')) {
88
+ if (err.message.includes('Unknown format')) {
42
89
  console.error(`Error: ${err.message}`);
43
- console.error('Supported formats: PDF');
44
90
  }
45
91
  else if (err.message.includes('No template available')) {
46
92
  console.error(`Error: Format not yet supported`);
47
- console.error('Currently supported: PDF');
48
93
  }
49
94
  else if (err.message.includes('page')) {
50
95
  console.error(`Error: Invalid page number or page not found`);
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"detector.d.ts","sourceRoot":"","sources":["../src/detector.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CA4BxE"}
1
+ {"version":3,"file":"detector.d.ts","sourceRoot":"","sources":["../src/detector.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAoHxE"}
package/dist/detector.js CHANGED
@@ -9,6 +9,94 @@ export async function detectFormat(filePath) {
9
9
  '.docx': 'docx',
10
10
  '.xlsx': 'xlsx',
11
11
  '.pptx': 'pptx',
12
+ '.md': 'md',
13
+ '.markdown': 'md',
14
+ '.html': 'html',
15
+ '.htm': 'html',
16
+ '.csv': 'csv',
17
+ '.tsv': 'csv',
18
+ '.rtf': 'rtf',
19
+ '.ipynb': 'ipynb',
20
+ '.tex': 'tex',
21
+ '.latex': 'tex',
22
+ // Source code extensions
23
+ '.js': 'code',
24
+ '.jsx': 'code',
25
+ '.ts': 'code',
26
+ '.tsx': 'code',
27
+ '.py': 'code',
28
+ '.rb': 'code',
29
+ '.java': 'code',
30
+ '.c': 'code',
31
+ '.cpp': 'code',
32
+ '.cc': 'code',
33
+ '.cxx': 'code',
34
+ '.h': 'code',
35
+ '.hpp': 'code',
36
+ '.cs': 'code',
37
+ '.go': 'code',
38
+ '.rs': 'code',
39
+ '.swift': 'code',
40
+ '.kt': 'code',
41
+ '.kts': 'code',
42
+ '.scala': 'code',
43
+ '.php': 'code',
44
+ '.sh': 'code',
45
+ '.bash': 'code',
46
+ '.zsh': 'code',
47
+ '.fish': 'code',
48
+ '.ps1': 'code',
49
+ '.sql': 'code',
50
+ '.json': 'code',
51
+ '.yaml': 'code',
52
+ '.yml': 'code',
53
+ '.xml': 'code',
54
+ '.css': 'code',
55
+ '.scss': 'code',
56
+ '.sass': 'code',
57
+ '.less': 'code',
58
+ '.vue': 'code',
59
+ '.svelte': 'code',
60
+ '.r': 'code',
61
+ '.lua': 'code',
62
+ '.perl': 'code',
63
+ '.pl': 'code',
64
+ '.ex': 'code',
65
+ '.exs': 'code',
66
+ '.erl': 'code',
67
+ '.hs': 'code',
68
+ '.ml': 'code',
69
+ '.fs': 'code',
70
+ '.fsx': 'code',
71
+ '.clj': 'code',
72
+ '.cljs': 'code',
73
+ '.dart': 'code',
74
+ '.zig': 'code',
75
+ '.nim': 'code',
76
+ '.v': 'code',
77
+ '.toml': 'code',
78
+ '.ini': 'code',
79
+ '.conf': 'code',
80
+ '.graphql': 'code',
81
+ '.gql': 'code',
82
+ '.proto': 'code',
83
+ '.tf': 'code',
84
+ '.hcl': 'code',
85
+ '.asm': 'code',
86
+ '.s': 'code',
87
+ '.diff': 'code',
88
+ '.patch': 'code',
89
+ '.mdx': 'code',
90
+ '.astro': 'code',
91
+ // URL file extension
92
+ '.url': 'url',
93
+ // Mermaid diagram extension
94
+ '.mmd': 'mmd',
95
+ '.mermaid': 'mmd',
96
+ // GeoJSON extension
97
+ '.geojson': 'geojson',
98
+ // GPX extension
99
+ '.gpx': 'gpx',
12
100
  };
13
101
  if (ext in extensionMap) {
14
102
  return extensionMap[ext];
@@ -1 +1 @@
1
- {"version":3,"file":"detector.js","sourceRoot":"","sources":["../src/detector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAG/B,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAAgB;IACjD,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IAE5C,kCAAkC;IAClC,MAAM,YAAY,GAA+B;QAC/C,MAAM,EAAE,KAAK;QACb,OAAO,EAAE,MAAM;QACf,OAAO,EAAE,MAAM;QACf,OAAO,EAAE,MAAM;QACf,OAAO,EAAE,MAAM;KAChB,CAAC;IAEF,IAAI,GAAG,IAAI,YAAY,EAAE,CAAC;QACxB,OAAO,YAAY,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAED,8BAA8B;IAC9B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACxC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAEjD,IAAI,KAAK,KAAK,UAAU;YAAE,OAAO,KAAK,CAAC,CAAE,OAAO;QAChD,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,KAAK,IAAI;YAAE,OAAO,MAAM,CAAC,CAAE,YAAY;IAC1E,CAAC;IAAC,MAAM,CAAC;QACP,qBAAqB;IACvB,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}
1
+ {"version":3,"file":"detector.js","sourceRoot":"","sources":["../src/detector.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,13 @@
1
1
  import type { ScreenshotOptions, ScreenshotResult } from './types.js';
2
- export { type ScreenshotOptions, type ScreenshotResult, type FileFormat } from './types.js';
3
- export declare function screenshot(inputPath: string, options?: ScreenshotOptions): Promise<ScreenshotResult>;
2
+ export { type ScreenshotOptions, type ScreenshotResult, type FileFormat, resolveFormat } from './types.js';
3
+ export { detectFormat } from './detector.js';
4
+ /**
5
+ * Convert input data to a screenshot image.
6
+ *
7
+ * @param input - Input data: Buffer for documents, or URL string for 'url' format
8
+ * @param inputFormat - Input format as slug (e.g., 'pdf') or MIME type (e.g., 'application/pdf')
9
+ * @param options - Optional screenshot options (format, width, height, page, fileName)
10
+ * @returns ScreenshotResult with image data buffer and dimensions
11
+ */
12
+ export declare function screenshot(input: Buffer | string, inputFormat: string, options?: ScreenshotOptions): Promise<ScreenshotResult>;
4
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEtE,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAE5F,wBAAsB,UAAU,CAC9B,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,gBAAgB,CAAC,CAS3B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGtE,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,KAAK,UAAU,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3G,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,KAAK,EAAE,MAAM,GAAG,MAAM,EACtB,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,gBAAgB,CAAC,CAK3B"}
package/dist/index.js CHANGED
@@ -1,11 +1,18 @@
1
- import { detectFormat } from './detector.js';
2
1
  import { Renderer } from './renderer.js';
3
- export async function screenshot(inputPath, options = {}) {
4
- const format = await detectFormat(inputPath);
5
- if (format === 'unknown') {
6
- throw new Error(`Unsupported file format: ${inputPath}`);
7
- }
2
+ import { resolveFormat } from './types.js';
3
+ export { resolveFormat } from './types.js';
4
+ export { detectFormat } from './detector.js';
5
+ /**
6
+ * Convert input data to a screenshot image.
7
+ *
8
+ * @param input - Input data: Buffer for documents, or URL string for 'url' format
9
+ * @param inputFormat - Input format as slug (e.g., 'pdf') or MIME type (e.g., 'application/pdf')
10
+ * @param options - Optional screenshot options (format, width, height, page, fileName)
11
+ * @returns ScreenshotResult with image data buffer and dimensions
12
+ */
13
+ export async function screenshot(input, inputFormat, options = {}) {
14
+ const format = resolveFormat(inputFormat);
8
15
  const renderer = new Renderer();
9
- return await renderer.render(inputPath, format, options);
16
+ return await renderer.render(input, format, options);
10
17
  }
11
18
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAKzC,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,SAAiB,EACjB,UAA6B,EAAE;IAE/B,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,SAAS,CAAC,CAAC;IAE7C,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,4BAA4B,SAAS,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAC;IAChC,OAAO,MAAM,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;AAC3D,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,OAAO,EAAkE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3G,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,KAAsB,EACtB,WAAmB,EACnB,UAA6B,EAAE;IAE/B,MAAM,MAAM,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;IAE1C,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAC;IAChC,OAAO,MAAM,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;AACvD,CAAC"}
@@ -2,6 +2,6 @@ import type { FileFormat, ScreenshotOptions, ScreenshotResult } from './types.js
2
2
  export declare class Renderer {
3
3
  private getTemplatePath;
4
4
  private injectDataIntoPage;
5
- render(inputPath: string, format: FileFormat, options?: ScreenshotOptions): Promise<ScreenshotResult>;
5
+ render(input: Buffer | string, format: FileFormat, options?: ScreenshotOptions): Promise<ScreenshotResult>;
6
6
  }
7
7
  //# sourceMappingURL=renderer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAKlF,qBAAa,QAAQ;IACnB,OAAO,CAAC,eAAe;YAiBT,kBAAkB;IAa1B,MAAM,CACV,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,UAAU,EAClB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,gBAAgB,CAAC;CAmH7B"}
1
+ {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAKlF,qBAAa,QAAQ;IACnB,OAAO,CAAC,eAAe;YA4BT,kBAAkB;IAe1B,MAAM,CACV,KAAK,EAAE,MAAM,GAAG,MAAM,EACtB,MAAM,EAAE,UAAU,EAClB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,gBAAgB,CAAC;CA6J7B"}
package/dist/renderer.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import { chromium } from 'playwright';
2
- import { readFile } from 'fs/promises';
3
2
  import { resolve, dirname } from 'path';
4
3
  import { fileURLToPath } from 'url';
5
4
  const __filename = fileURLToPath(import.meta.url);
@@ -12,6 +11,17 @@ export class Renderer {
12
11
  docx: resolve(__dirname, '../templates/docx.html'),
13
12
  xlsx: resolve(__dirname, '../templates/xlsx.html'),
14
13
  pptx: resolve(__dirname, '../templates/pptx.html'),
14
+ md: resolve(__dirname, '../templates/md.html'),
15
+ html: resolve(__dirname, '../templates/html.html'),
16
+ csv: resolve(__dirname, '../templates/csv.html'),
17
+ rtf: resolve(__dirname, '../templates/rtf.html'),
18
+ ipynb: resolve(__dirname, '../templates/ipynb.html'),
19
+ tex: resolve(__dirname, '../templates/tex.html'),
20
+ code: resolve(__dirname, '../templates/code.html'),
21
+ url: resolve(__dirname, '../templates/url.html'),
22
+ mmd: resolve(__dirname, '../templates/mmd.html'),
23
+ geojson: resolve(__dirname, '../templates/geojson.html'),
24
+ gpx: resolve(__dirname, '../templates/gpx.html'),
15
25
  unknown: '',
16
26
  };
17
27
  const path = templateMap[format];
@@ -20,21 +30,21 @@ export class Renderer {
20
30
  }
21
31
  return path;
22
32
  }
23
- async injectDataIntoPage(page, fileBase64, pageNumber = 1) {
33
+ async injectDataIntoPage(page, fileBase64, pageNumber = 1, fileName = '') {
24
34
  // Inject data into page globals before template loads
25
- await page.addInitScript(({ fileBase64: fb64, pageNum }) => {
35
+ await page.addInitScript(({ fileBase64: fb64, pageNum, fName }) => {
26
36
  // Override the placeholder values
27
37
  globalThis.fileBase64 = fb64;
28
38
  globalThis.pageNumber = pageNum;
29
- }, { fileBase64, pageNum: pageNumber });
39
+ globalThis.fileName = fName;
40
+ }, { fileBase64, pageNum: pageNumber, fName: fileName });
30
41
  }
31
- async render(inputPath, format, options = {}) {
32
- const { output, format: imageFormat = 'png', width, height, page: pageNumber = 1, } = options;
42
+ async render(input, format, options = {}) {
43
+ const { format: imageFormat = 'png', width, height, page: pageNumber = 1, fileName = '', } = options;
33
44
  // Use small initial viewport - content will determine final size
34
45
  // For formats like XLSX, large viewport causes table to expand to fill it
35
46
  const initialWidth = width || 800;
36
47
  const initialHeight = height || 600;
37
- const outputPath = output || inputPath.replace(/\.[^.]+$/, `.${imageFormat}`);
38
48
  // Launch browser
39
49
  const browser = await chromium.launch({
40
50
  headless: true,
@@ -46,15 +56,46 @@ export class Renderer {
46
56
  viewport: { width: initialWidth, height: initialHeight },
47
57
  deviceScaleFactor,
48
58
  });
49
- // Read and encode file as base64
50
- const fileData = await readFile(inputPath);
51
- const fileBase64 = fileData.toString('base64');
59
+ // Special handling for URL format - navigate directly to the URL
60
+ if (format === 'url') {
61
+ // Input should be URL string (or buffer containing URL)
62
+ const url = Buffer.isBuffer(input)
63
+ ? input.toString('utf-8').trim()
64
+ : input.trim();
65
+ // Set a reasonable viewport for webpage screenshots
66
+ const webWidth = width || 1280;
67
+ const webHeight = height || 800;
68
+ await page.setViewportSize({ width: webWidth, height: webHeight });
69
+ // Navigate to URL and wait for network idle
70
+ await page.goto(url, { waitUntil: 'networkidle' });
71
+ // Take screenshot to buffer
72
+ const screenshotData = await page.screenshot({
73
+ type: imageFormat,
74
+ fullPage: false,
75
+ });
76
+ await browser.close();
77
+ return {
78
+ data: screenshotData,
79
+ format: imageFormat,
80
+ width: webWidth * deviceScaleFactor,
81
+ height: webHeight * deviceScaleFactor,
82
+ renderer: format,
83
+ };
84
+ }
85
+ // Encode input as base64
86
+ let fileBase64;
87
+ if (Buffer.isBuffer(input)) {
88
+ fileBase64 = input.toString('base64');
89
+ }
90
+ else {
91
+ // String input for non-URL formats is treated as text content
92
+ fileBase64 = Buffer.from(input, 'utf-8').toString('base64');
93
+ }
52
94
  // Inject data before loading template
53
- await this.injectDataIntoPage(page, fileBase64, pageNumber);
95
+ await this.injectDataIntoPage(page, fileBase64, pageNumber, fileName);
54
96
  // Load template
55
97
  const templatePath = this.getTemplatePath(format);
56
98
  await page.goto(`file://${templatePath}`);
57
- // Wait for render complete and get metadata
58
99
  const metadata = await page.evaluate(async () => {
59
100
  const renderComplete = globalThis.renderComplete;
60
101
  if (!renderComplete) {
@@ -66,6 +107,7 @@ export class Renderer {
66
107
  // Check if we need to clip (for EPUB content cropping)
67
108
  const clipX = metadata.clipX;
68
109
  const clipY = metadata.clipY;
110
+ let screenshotData;
69
111
  if (clipX !== undefined && clipY !== undefined) {
70
112
  // Resize viewport to ensure clip area is fully visible
71
113
  const requiredWidth = clipX + metadata.width;
@@ -77,8 +119,7 @@ export class Renderer {
77
119
  // Wait for layout to stabilize
78
120
  await page.waitForTimeout(100);
79
121
  // Use clip to capture just the content area
80
- await page.screenshot({
81
- path: outputPath,
122
+ screenshotData = await page.screenshot({
82
123
  type: imageFormat,
83
124
  clip: {
84
125
  x: clipX,
@@ -97,8 +138,7 @@ export class Renderer {
97
138
  // Wait for layout to stabilize after viewport resize
98
139
  await page.waitForTimeout(100);
99
140
  // Take screenshot at exact rendered size
100
- await page.screenshot({
101
- path: outputPath,
141
+ screenshotData = await page.screenshot({
102
142
  type: imageFormat,
103
143
  fullPage: false,
104
144
  });
@@ -108,10 +148,11 @@ export class Renderer {
108
148
  const actualWidth = metadata.width * deviceScaleFactor;
109
149
  const actualHeight = metadata.height * deviceScaleFactor;
110
150
  return {
111
- path: outputPath,
151
+ data: screenshotData,
112
152
  format: imageFormat,
113
153
  width: actualWidth,
114
154
  height: actualHeight,
155
+ renderer: format,
115
156
  };
116
157
  }
117
158
  catch (error) {
@@ -1 +1 @@
1
- {"version":3,"file":"renderer.js","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"renderer.js","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAa,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAGpC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC,MAAM,OAAO,QAAQ;IACX,eAAe,CAAC,MAAkB;QACxC,MAAM,WAAW,GAA+B;YAC9C,GAAG,EAAE,OAAO,CAAC,SAAS,EAAE,uBAAuB,CAAC;YAChD,IAAI,EAAE,OAAO,CAAC,SAAS,EAAE,wBAAwB,CAAC;YAClD,IAAI,EAAE,OAAO,CAAC,SAAS,EAAE,wBAAwB,CAAC;YAClD,IAAI,EAAE,OAAO,CAAC,SAAS,EAAE,wBAAwB,CAAC;YAClD,IAAI,EAAE,OAAO,CAAC,SAAS,EAAE,wBAAwB,CAAC;YAClD,EAAE,EAAE,OAAO,CAAC,SAAS,EAAE,sBAAsB,CAAC;YAC9C,IAAI,EAAE,OAAO,CAAC,SAAS,EAAE,wBAAwB,CAAC;YAClD,GAAG,EAAE,OAAO,CAAC,SAAS,EAAE,uBAAuB,CAAC;YAChD,GAAG,EAAE,OAAO,CAAC,SAAS,EAAE,uBAAuB,CAAC;YAChD,KAAK,EAAE,OAAO,CAAC,SAAS,EAAE,yBAAyB,CAAC;YACpD,GAAG,EAAE,OAAO,CAAC,SAAS,EAAE,uBAAuB,CAAC;YAChD,IAAI,EAAE,OAAO,CAAC,SAAS,EAAE,wBAAwB,CAAC;YAClD,GAAG,EAAE,OAAO,CAAC,SAAS,EAAE,uBAAuB,CAAC;YAChD,GAAG,EAAE,OAAO,CAAC,SAAS,EAAE,uBAAuB,CAAC;YAChD,OAAO,EAAE,OAAO,CAAC,SAAS,EAAE,2BAA2B,CAAC;YACxD,GAAG,EAAE,OAAO,CAAC,SAAS,EAAE,uBAAuB,CAAC;YAChD,OAAO,EAAE,EAAE;SACZ,CAAC;QAEF,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;QACjC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,qCAAqC,MAAM,EAAE,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,KAAK,CAAC,kBAAkB,CAC9B,IAAU,EACV,UAAkB,EAClB,aAAqB,CAAC,EACtB,WAAmB,EAAE;QAErB,sDAAsD;QACtD,MAAM,IAAI,CAAC,aAAa,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAA0D,EAAE,EAAE;YACxH,kCAAkC;YACjC,UAAiD,CAAC,UAAU,GAAG,IAAI,CAAC;YACpE,UAAiD,CAAC,UAAU,GAAG,OAAO,CAAC;YACvE,UAAiD,CAAC,QAAQ,GAAG,KAAK,CAAC;QACtE,CAAC,EAAE,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,KAAK,CAAC,MAAM,CACV,KAAsB,EACtB,MAAkB,EAClB,UAA6B,EAAE;QAE/B,MAAM,EACJ,MAAM,EAAE,WAAW,GAAG,KAAK,EAC3B,KAAK,EACL,MAAM,EACN,IAAI,EAAE,UAAU,GAAG,CAAC,EACpB,QAAQ,GAAG,EAAE,GACd,GAAG,OAAO,CAAC;QAEZ,iEAAiE;QACjE,0EAA0E;QAC1E,MAAM,YAAY,GAAG,KAAK,IAAI,GAAG,CAAC;QAClC,MAAM,aAAa,GAAG,MAAM,IAAI,GAAG,CAAC;QAEpC,iBAAiB;QACjB,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC;YACpC,QAAQ,EAAE,IAAI;SACf,CAAC,CAAC;QAEH,IAAI,CAAC;YACH,yEAAyE;YACzE,MAAM,iBAAiB,GAAG,CAAC,CAAC;YAE5B,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC;gBACjC,QAAQ,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE;gBACxD,iBAAiB;aAClB,CAAC,CAAC;YAEH,iEAAiE;YACjE,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;gBACrB,wDAAwD;gBACxD,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;oBAChC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE;oBAChC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;gBAEjB,oDAAoD;gBACpD,MAAM,QAAQ,GAAG,KAAK,IAAI,IAAI,CAAC;gBAC/B,MAAM,SAAS,GAAG,MAAM,IAAI,GAAG,CAAC;gBAChC,MAAM,IAAI,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;gBAEnE,4CAA4C;gBAC5C,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC,CAAC;gBAEnD,4BAA4B;gBAC5B,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC;oBAC3C,IAAI,EAAE,WAA6B;oBACnC,QAAQ,EAAE,KAAK;iBAChB,CAAC,CAAC;gBAEH,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;gBAEtB,OAAO;oBACL,IAAI,EAAE,cAAc;oBACpB,MAAM,EAAE,WAAW;oBACnB,KAAK,EAAE,QAAQ,GAAG,iBAAiB;oBACnC,MAAM,EAAE,SAAS,GAAG,iBAAiB;oBACrC,QAAQ,EAAE,MAAM;iBACjB,CAAC;YACJ,CAAC;YAED,yBAAyB;YACzB,IAAI,UAAkB,CAAC;YACvB,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC3B,UAAU,GAAG,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACxC,CAAC;iBAAM,CAAC;gBACN,8DAA8D;gBAC9D,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAC9D,CAAC;YAED,sCAAsC;YACtC,MAAM,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;YAEtE,gBAAgB;YAChB,MAAM,YAAY,GAAG,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;YAClD,MAAM,IAAI,CAAC,IAAI,CAAC,UAAU,YAAY,EAAE,CAAC,CAAC;YAS1C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE;gBAC9C,MAAM,cAAc,GAAI,UAAiD,CAAC,cAAmD,CAAC;gBAE9H,IAAI,CAAC,cAAc,EAAE,CAAC;oBACpB,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;gBACrD,CAAC;gBAED,oCAAoC;gBACpC,OAAO,MAAM,cAAc,CAAC;YAC9B,CAAC,CAAC,CAAC;YAEH,uDAAuD;YACvD,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;YAC7B,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;YAE7B,IAAI,cAAsB,CAAC;YAE3B,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBAC/C,uDAAuD;gBACvD,MAAM,aAAa,GAAG,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC;gBAC7C,MAAM,cAAc,GAAG,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC;gBAC/C,MAAM,IAAI,CAAC,eAAe,CAAC;oBACzB,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,YAAY,CAAC;oBAC5C,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,aAAa,CAAC;iBAChD,CAAC,CAAC;gBAEH,+BAA+B;gBAC/B,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;gBAE/B,4CAA4C;gBAC5C,cAAc,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC;oBACrC,IAAI,EAAE,WAA6B;oBACnC,IAAI,EAAE;wBACJ,CAAC,EAAE,KAAK;wBACR,CAAC,EAAE,KAAK;wBACR,KAAK,EAAE,QAAQ,CAAC,KAAK;wBACrB,MAAM,EAAE,QAAQ,CAAC,MAAM;qBACxB;iBACF,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,mDAAmD;gBACnD,MAAM,IAAI,CAAC,eAAe,CAAC;oBACzB,KAAK,EAAE,QAAQ,CAAC,KAAK;oBACrB,MAAM,EAAE,QAAQ,CAAC,MAAM;iBACxB,CAAC,CAAC;gBAEH,qDAAqD;gBACrD,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;gBAE/B,yCAAyC;gBACzC,cAAc,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC;oBACrC,IAAI,EAAE,WAA6B;oBACnC,QAAQ,EAAE,KAAK;iBAChB,CAAC,CAAC;YACL,CAAC;YAED,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;YAEtB,oDAAoD;YACpD,MAAM,WAAW,GAAG,QAAQ,CAAC,KAAK,GAAG,iBAAiB,CAAC;YACvD,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,GAAG,iBAAiB,CAAC;YAEzD,OAAO;gBACL,IAAI,EAAE,cAAc;gBACpB,MAAM,EAAE,WAAW;gBACnB,KAAK,EAAE,WAAW;gBAClB,MAAM,EAAE,YAAY;gBACpB,QAAQ,EAAE,MAAM;aACjB,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;YACtB,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;CACF"}
package/dist/types.d.ts CHANGED
@@ -1,15 +1,16 @@
1
1
  export interface ScreenshotOptions {
2
- output?: string;
3
2
  format?: 'png' | 'jpeg' | 'webp';
4
3
  width?: number;
5
4
  height?: number;
6
5
  page?: number;
6
+ fileName?: string;
7
7
  }
8
8
  export interface ScreenshotResult {
9
- path: string;
9
+ data: Buffer;
10
10
  format: string;
11
11
  width: number;
12
12
  height: number;
13
+ renderer: string;
13
14
  }
14
15
  export interface RenderMetadata {
15
16
  width: number;
@@ -18,5 +19,11 @@ export interface RenderMetadata {
18
19
  pageNumber: number;
19
20
  scale: number;
20
21
  }
21
- export type FileFormat = 'pdf' | 'epub' | 'docx' | 'xlsx' | 'pptx' | 'unknown';
22
+ export type FileFormat = 'pdf' | 'epub' | 'docx' | 'xlsx' | 'pptx' | 'md' | 'html' | 'csv' | 'rtf' | 'ipynb' | 'tex' | 'code' | 'url' | 'mmd' | 'geojson' | 'gpx' | 'unknown';
23
+ export declare const MIME_TO_FORMAT: Record<string, FileFormat>;
24
+ export declare const SLUG_TO_FORMAT: Record<string, FileFormat>;
25
+ /**
26
+ * Resolve a format string (MIME type or slug) to a FileFormat.
27
+ */
28
+ export declare function resolveFormat(formatStr: string): FileFormat;
22
29
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;IACjC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,SAAS,GAAG,KAAK,GAAG,SAAS,CAAC;AAG9K,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAgBrD,CAAC;AAGF,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAsBrD,CAAC;AAEF;;GAEG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,CAa3D"}
package/dist/types.js CHANGED
@@ -1,2 +1,58 @@
1
- export {};
1
+ // Mapping from MIME types to FileFormat
2
+ export const MIME_TO_FORMAT = {
3
+ 'application/pdf': 'pdf',
4
+ 'application/epub+zip': 'epub',
5
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'docx',
6
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'xlsx',
7
+ 'application/vnd.openxmlformats-officedocument.presentationml.presentation': 'pptx',
8
+ 'text/markdown': 'md',
9
+ 'text/html': 'html',
10
+ 'text/csv': 'csv',
11
+ 'application/rtf': 'rtf',
12
+ 'text/rtf': 'rtf',
13
+ 'application/x-ipynb+json': 'ipynb',
14
+ 'application/x-tex': 'tex',
15
+ 'text/x-tex': 'tex',
16
+ 'application/geo+json': 'geojson',
17
+ 'application/gpx+xml': 'gpx',
18
+ };
19
+ // Mapping from slug names to FileFormat
20
+ export const SLUG_TO_FORMAT = {
21
+ 'pdf': 'pdf',
22
+ 'epub': 'epub',
23
+ 'docx': 'docx',
24
+ 'xlsx': 'xlsx',
25
+ 'pptx': 'pptx',
26
+ 'md': 'md',
27
+ 'markdown': 'md',
28
+ 'html': 'html',
29
+ 'htm': 'html',
30
+ 'csv': 'csv',
31
+ 'rtf': 'rtf',
32
+ 'ipynb': 'ipynb',
33
+ 'jupyter': 'ipynb',
34
+ 'tex': 'tex',
35
+ 'latex': 'tex',
36
+ 'code': 'code',
37
+ 'url': 'url',
38
+ 'mmd': 'mmd',
39
+ 'mermaid': 'mmd',
40
+ 'geojson': 'geojson',
41
+ 'gpx': 'gpx',
42
+ };
43
+ /**
44
+ * Resolve a format string (MIME type or slug) to a FileFormat.
45
+ */
46
+ export function resolveFormat(formatStr) {
47
+ // Try slug first (more common)
48
+ const lowerFormat = formatStr.toLowerCase();
49
+ if (lowerFormat in SLUG_TO_FORMAT) {
50
+ return SLUG_TO_FORMAT[lowerFormat];
51
+ }
52
+ // Try MIME type
53
+ if (formatStr in MIME_TO_FORMAT) {
54
+ return MIME_TO_FORMAT[formatStr];
55
+ }
56
+ throw new Error(`Unknown format: ${formatStr}. Use a slug (e.g., 'pdf') or MIME type (e.g., 'application/pdf')`);
57
+ }
2
58
  //# sourceMappingURL=types.js.map
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AA0BA,wCAAwC;AACxC,MAAM,CAAC,MAAM,cAAc,GAA+B;IACxD,iBAAiB,EAAE,KAAK;IACxB,sBAAsB,EAAE,MAAM;IAC9B,yEAAyE,EAAE,MAAM;IACjF,mEAAmE,EAAE,MAAM;IAC3E,2EAA2E,EAAE,MAAM;IACnF,eAAe,EAAE,IAAI;IACrB,WAAW,EAAE,MAAM;IACnB,UAAU,EAAE,KAAK;IACjB,iBAAiB,EAAE,KAAK;IACxB,UAAU,EAAE,KAAK;IACjB,0BAA0B,EAAE,OAAO;IACnC,mBAAmB,EAAE,KAAK;IAC1B,YAAY,EAAE,KAAK;IACnB,sBAAsB,EAAE,SAAS;IACjC,qBAAqB,EAAE,KAAK;CAC7B,CAAC;AAEF,wCAAwC;AACxC,MAAM,CAAC,MAAM,cAAc,GAA+B;IACxD,KAAK,EAAE,KAAK;IACZ,MAAM,EAAE,MAAM;IACd,MAAM,EAAE,MAAM;IACd,MAAM,EAAE,MAAM;IACd,MAAM,EAAE,MAAM;IACd,IAAI,EAAE,IAAI;IACV,UAAU,EAAE,IAAI;IAChB,MAAM,EAAE,MAAM;IACd,KAAK,EAAE,MAAM;IACb,KAAK,EAAE,KAAK;IACZ,KAAK,EAAE,KAAK;IACZ,OAAO,EAAE,OAAO;IAChB,SAAS,EAAE,OAAO;IAClB,KAAK,EAAE,KAAK;IACZ,OAAO,EAAE,KAAK;IACd,MAAM,EAAE,MAAM;IACd,KAAK,EAAE,KAAK;IACZ,KAAK,EAAE,KAAK;IACZ,SAAS,EAAE,KAAK;IAChB,SAAS,EAAE,SAAS;IACpB,KAAK,EAAE,KAAK;CACb,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,SAAiB;IAC7C,+BAA+B;IAC/B,MAAM,WAAW,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC;IAC5C,IAAI,WAAW,IAAI,cAAc,EAAE,CAAC;QAClC,OAAO,cAAc,CAAC,WAAW,CAAC,CAAC;IACrC,CAAC;IAED,gBAAgB;IAChB,IAAI,SAAS,IAAI,cAAc,EAAE,CAAC;QAChC,OAAO,cAAc,CAAC,SAAS,CAAC,CAAC;IACnC,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,mBAAmB,SAAS,mEAAmE,CAAC,CAAC;AACnH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "screenitshot",
3
- "version": "0.5.0",
3
+ "version": "0.7.1",
4
4
  "description": "Convert various file formats to high-quality screenshots",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -10,7 +10,7 @@
10
10
  "type": "module",
11
11
  "scripts": {
12
12
  "build": "tsc && npm run copy-templates",
13
- "copy-templates": "mkdir -p templates && cp ../render/dist/pdf.html ../render/dist/docx.html ../render/dist/xlsx.html ../render/dist/pptx.html ../render/dist/epub.html templates/",
13
+ "copy-templates": "mkdir -p templates && cp ../render/dist/*.html templates/",
14
14
  "dev": "tsc --watch",
15
15
  "start": "npm run build && node dist/cli.js",
16
16
  "lint": "eslint \"src/**/*.ts\"",
package/src/cli.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { Command } from 'commander';
4
- import { screenshot } from './index.js';
5
- import { readFile } from 'fs/promises';
6
- import { resolve, dirname } from 'path';
4
+ import { screenshot, detectFormat } from './index.js';
5
+ import { readFile, writeFile, access } from 'fs/promises';
6
+ import { resolve, dirname, basename, extname, join } from 'path';
7
7
  import { fileURLToPath } from 'url';
8
8
 
9
9
  const __filename = fileURLToPath(import.meta.url);
@@ -13,6 +13,36 @@ const packageJson = JSON.parse(
13
13
  await readFile(resolve(__dirname, '../package.json'), 'utf-8')
14
14
  );
15
15
 
16
+ /**
17
+ * Generate a unique output path using macOS-style duplicate naming.
18
+ * If basePath exists, returns basePath with ' (1)', ' (2)', etc. suffix.
19
+ * Example: document.png -> document (1).png -> document (2).png
20
+ */
21
+ async function getUniqueOutputPath(basePath: string): Promise<string> {
22
+ try {
23
+ await access(basePath);
24
+ } catch {
25
+ // File doesn't exist, use the base path
26
+ return basePath;
27
+ }
28
+
29
+ const dir = dirname(basePath);
30
+ const ext = extname(basePath);
31
+ const stem = basename(basePath, ext);
32
+
33
+ let counter = 1;
34
+ // eslint-disable-next-line no-constant-condition
35
+ while (true) {
36
+ const newPath = join(dir, `${stem} (${counter})${ext}`);
37
+ try {
38
+ await access(newPath);
39
+ counter++;
40
+ } catch {
41
+ return newPath;
42
+ }
43
+ }
44
+ }
45
+
16
46
  const program = new Command();
17
47
 
18
48
  program
@@ -20,38 +50,58 @@ program
20
50
  .description('Convert various file formats to high-quality screenshots')
21
51
  .version(packageJson.version)
22
52
  .argument('<input>', 'Input file path')
23
- .argument('[output]', 'Output image path')
24
53
  .option('-f, --format <format>', 'Output image format (png, jpeg, webp)', 'png')
25
- .option('-w, --width <width>', 'Viewport width', '1920')
26
- .option('-h, --height <height>', 'Viewport height', '1080')
54
+ .option('-w, --width <width>', 'Viewport width')
55
+ .option('-H, --height <height>', 'Viewport height')
27
56
  .option('-p, --page <page>', 'Page number for multi-page documents', '1')
28
- .action(async (input: string, output: string | undefined, options: any) => {
57
+ .action(async (input: string, options: { format: 'png' | 'jpeg' | 'webp'; width?: string; height?: string; page: string }) => {
29
58
  try {
59
+ // Check input file exists and detect format
60
+ let inputData: Buffer;
61
+ try {
62
+ inputData = await readFile(input);
63
+ } catch {
64
+ console.error(`Error: Input file not found: ${input}`);
65
+ process.exit(1);
66
+ }
67
+
68
+ const inputFormat = await detectFormat(input);
69
+ if (inputFormat === 'unknown') {
70
+ console.error(`Error: Unsupported file format: ${input}`);
71
+ process.exit(1);
72
+ }
73
+
74
+ // Determine output path (same folder as input, with unique name)
75
+ const dir = dirname(input);
76
+ const stem = basename(input, extname(input));
77
+ const baseOutput = join(dir, `${stem}.${options.format}`);
78
+ const outputPath = await getUniqueOutputPath(baseOutput);
79
+
30
80
  console.log(`Converting ${input}...`);
31
81
 
32
- const result = await screenshot(input, {
33
- output,
82
+ const result = await screenshot(inputData, inputFormat, {
34
83
  format: options.format,
35
- width: parseInt(options.width),
36
- height: parseInt(options.height),
84
+ width: options.width ? parseInt(options.width) : undefined,
85
+ height: options.height ? parseInt(options.height) : undefined,
37
86
  page: parseInt(options.page),
87
+ fileName: basename(input),
38
88
  });
39
89
 
40
- console.log(`✓ Screenshot saved to ${result.path}`);
90
+ // Write output to file
91
+ await writeFile(outputPath, result.data);
92
+
93
+ console.log(`✓ Screenshot saved to ${outputPath}`);
94
+ console.log(` Renderer: ${result.renderer}`);
41
95
  console.log(` Format: ${result.format}`);
42
96
  console.log(` Size: ${result.width}x${result.height}`);
43
97
  } catch (error) {
44
98
  const err = error as Error;
45
99
 
46
100
  // User-friendly error messages
47
- if (err.message.includes('ENOENT') || err.message.includes('no such file')) {
48
- console.error(`Error: Input file not found: ${input}`);
49
- } else if (err.message.includes('Unsupported file format')) {
101
+ if (err.message.includes('Unknown format')) {
50
102
  console.error(`Error: ${err.message}`);
51
- console.error('Supported formats: PDF');
52
103
  } else if (err.message.includes('No template available')) {
53
104
  console.error(`Error: Format not yet supported`);
54
- console.error('Currently supported: PDF');
55
105
  } else if (err.message.includes('page')) {
56
106
  console.error(`Error: Invalid page number or page not found`);
57
107
  // Show stack trace in debug mode
package/src/detector.ts CHANGED
@@ -12,6 +12,94 @@ export async function detectFormat(filePath: string): Promise<FileFormat> {
12
12
  '.docx': 'docx',
13
13
  '.xlsx': 'xlsx',
14
14
  '.pptx': 'pptx',
15
+ '.md': 'md',
16
+ '.markdown': 'md',
17
+ '.html': 'html',
18
+ '.htm': 'html',
19
+ '.csv': 'csv',
20
+ '.tsv': 'csv',
21
+ '.rtf': 'rtf',
22
+ '.ipynb': 'ipynb',
23
+ '.tex': 'tex',
24
+ '.latex': 'tex',
25
+ // Source code extensions
26
+ '.js': 'code',
27
+ '.jsx': 'code',
28
+ '.ts': 'code',
29
+ '.tsx': 'code',
30
+ '.py': 'code',
31
+ '.rb': 'code',
32
+ '.java': 'code',
33
+ '.c': 'code',
34
+ '.cpp': 'code',
35
+ '.cc': 'code',
36
+ '.cxx': 'code',
37
+ '.h': 'code',
38
+ '.hpp': 'code',
39
+ '.cs': 'code',
40
+ '.go': 'code',
41
+ '.rs': 'code',
42
+ '.swift': 'code',
43
+ '.kt': 'code',
44
+ '.kts': 'code',
45
+ '.scala': 'code',
46
+ '.php': 'code',
47
+ '.sh': 'code',
48
+ '.bash': 'code',
49
+ '.zsh': 'code',
50
+ '.fish': 'code',
51
+ '.ps1': 'code',
52
+ '.sql': 'code',
53
+ '.json': 'code',
54
+ '.yaml': 'code',
55
+ '.yml': 'code',
56
+ '.xml': 'code',
57
+ '.css': 'code',
58
+ '.scss': 'code',
59
+ '.sass': 'code',
60
+ '.less': 'code',
61
+ '.vue': 'code',
62
+ '.svelte': 'code',
63
+ '.r': 'code',
64
+ '.lua': 'code',
65
+ '.perl': 'code',
66
+ '.pl': 'code',
67
+ '.ex': 'code',
68
+ '.exs': 'code',
69
+ '.erl': 'code',
70
+ '.hs': 'code',
71
+ '.ml': 'code',
72
+ '.fs': 'code',
73
+ '.fsx': 'code',
74
+ '.clj': 'code',
75
+ '.cljs': 'code',
76
+ '.dart': 'code',
77
+ '.zig': 'code',
78
+ '.nim': 'code',
79
+ '.v': 'code',
80
+ '.toml': 'code',
81
+ '.ini': 'code',
82
+ '.conf': 'code',
83
+ '.graphql': 'code',
84
+ '.gql': 'code',
85
+ '.proto': 'code',
86
+ '.tf': 'code',
87
+ '.hcl': 'code',
88
+ '.asm': 'code',
89
+ '.s': 'code',
90
+ '.diff': 'code',
91
+ '.patch': 'code',
92
+ '.mdx': 'code',
93
+ '.astro': 'code',
94
+ // URL file extension
95
+ '.url': 'url',
96
+ // Mermaid diagram extension
97
+ '.mmd': 'mmd',
98
+ '.mermaid': 'mmd',
99
+ // GeoJSON extension
100
+ '.geojson': 'geojson',
101
+ // GPX extension
102
+ '.gpx': 'gpx',
15
103
  };
16
104
 
17
105
  if (ext in extensionMap) {
package/src/index.ts CHANGED
@@ -1,19 +1,25 @@
1
- import { detectFormat } from './detector.js';
2
1
  import { Renderer } from './renderer.js';
3
2
  import type { ScreenshotOptions, ScreenshotResult } from './types.js';
3
+ import { resolveFormat } from './types.js';
4
4
 
5
- export { type ScreenshotOptions, type ScreenshotResult, type FileFormat } from './types.js';
5
+ export { type ScreenshotOptions, type ScreenshotResult, type FileFormat, resolveFormat } from './types.js';
6
+ export { detectFormat } from './detector.js';
6
7
 
8
+ /**
9
+ * Convert input data to a screenshot image.
10
+ *
11
+ * @param input - Input data: Buffer for documents, or URL string for 'url' format
12
+ * @param inputFormat - Input format as slug (e.g., 'pdf') or MIME type (e.g., 'application/pdf')
13
+ * @param options - Optional screenshot options (format, width, height, page, fileName)
14
+ * @returns ScreenshotResult with image data buffer and dimensions
15
+ */
7
16
  export async function screenshot(
8
- inputPath: string,
17
+ input: Buffer | string,
18
+ inputFormat: string,
9
19
  options: ScreenshotOptions = {}
10
20
  ): Promise<ScreenshotResult> {
11
- const format = await detectFormat(inputPath);
12
-
13
- if (format === 'unknown') {
14
- throw new Error(`Unsupported file format: ${inputPath}`);
15
- }
21
+ const format = resolveFormat(inputFormat);
16
22
 
17
23
  const renderer = new Renderer();
18
- return await renderer.render(inputPath, format, options);
24
+ return await renderer.render(input, format, options);
19
25
  }
package/src/renderer.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { chromium, type Page } from 'playwright';
2
- import { readFile } from 'fs/promises';
3
2
  import { resolve, dirname } from 'path';
4
3
  import { fileURLToPath } from 'url';
5
4
  import type { FileFormat, ScreenshotOptions, ScreenshotResult } from './types.js';
@@ -15,6 +14,17 @@ export class Renderer {
15
14
  docx: resolve(__dirname, '../templates/docx.html'),
16
15
  xlsx: resolve(__dirname, '../templates/xlsx.html'),
17
16
  pptx: resolve(__dirname, '../templates/pptx.html'),
17
+ md: resolve(__dirname, '../templates/md.html'),
18
+ html: resolve(__dirname, '../templates/html.html'),
19
+ csv: resolve(__dirname, '../templates/csv.html'),
20
+ rtf: resolve(__dirname, '../templates/rtf.html'),
21
+ ipynb: resolve(__dirname, '../templates/ipynb.html'),
22
+ tex: resolve(__dirname, '../templates/tex.html'),
23
+ code: resolve(__dirname, '../templates/code.html'),
24
+ url: resolve(__dirname, '../templates/url.html'),
25
+ mmd: resolve(__dirname, '../templates/mmd.html'),
26
+ geojson: resolve(__dirname, '../templates/geojson.html'),
27
+ gpx: resolve(__dirname, '../templates/gpx.html'),
18
28
  unknown: '',
19
29
  };
20
30
 
@@ -28,27 +38,29 @@ export class Renderer {
28
38
  private async injectDataIntoPage(
29
39
  page: Page,
30
40
  fileBase64: string,
31
- pageNumber: number = 1
41
+ pageNumber: number = 1,
42
+ fileName: string = ''
32
43
  ): Promise<void> {
33
44
  // Inject data into page globals before template loads
34
- await page.addInitScript(({ fileBase64: fb64, pageNum }: { fileBase64: string; pageNum: number }) => {
45
+ await page.addInitScript(({ fileBase64: fb64, pageNum, fName }: { fileBase64: string; pageNum: number; fName: string }) => {
35
46
  // Override the placeholder values
36
- (globalThis as any).fileBase64 = fb64;
37
- (globalThis as any).pageNumber = pageNum;
38
- }, { fileBase64, pageNum: pageNumber });
47
+ (globalThis as unknown as Record<string, unknown>).fileBase64 = fb64;
48
+ (globalThis as unknown as Record<string, unknown>).pageNumber = pageNum;
49
+ (globalThis as unknown as Record<string, unknown>).fileName = fName;
50
+ }, { fileBase64, pageNum: pageNumber, fName: fileName });
39
51
  }
40
52
 
41
53
  async render(
42
- inputPath: string,
54
+ input: Buffer | string,
43
55
  format: FileFormat,
44
56
  options: ScreenshotOptions = {}
45
57
  ): Promise<ScreenshotResult> {
46
58
  const {
47
- output,
48
59
  format: imageFormat = 'png',
49
60
  width,
50
61
  height,
51
62
  page: pageNumber = 1,
63
+ fileName = '',
52
64
  } = options;
53
65
 
54
66
  // Use small initial viewport - content will determine final size
@@ -56,8 +68,6 @@ export class Renderer {
56
68
  const initialWidth = width || 800;
57
69
  const initialHeight = height || 600;
58
70
 
59
- const outputPath = output || inputPath.replace(/\.[^.]+$/, `.${imageFormat}`);
60
-
61
71
  // Launch browser
62
72
  const browser = await chromium.launch({
63
73
  headless: true,
@@ -72,20 +82,63 @@ export class Renderer {
72
82
  deviceScaleFactor,
73
83
  });
74
84
 
75
- // Read and encode file as base64
76
- const fileData = await readFile(inputPath);
77
- const fileBase64 = fileData.toString('base64');
85
+ // Special handling for URL format - navigate directly to the URL
86
+ if (format === 'url') {
87
+ // Input should be URL string (or buffer containing URL)
88
+ const url = Buffer.isBuffer(input)
89
+ ? input.toString('utf-8').trim()
90
+ : input.trim();
91
+
92
+ // Set a reasonable viewport for webpage screenshots
93
+ const webWidth = width || 1280;
94
+ const webHeight = height || 800;
95
+ await page.setViewportSize({ width: webWidth, height: webHeight });
96
+
97
+ // Navigate to URL and wait for network idle
98
+ await page.goto(url, { waitUntil: 'networkidle' });
99
+
100
+ // Take screenshot to buffer
101
+ const screenshotData = await page.screenshot({
102
+ type: imageFormat as 'png' | 'jpeg',
103
+ fullPage: false,
104
+ });
105
+
106
+ await browser.close();
107
+
108
+ return {
109
+ data: screenshotData,
110
+ format: imageFormat,
111
+ width: webWidth * deviceScaleFactor,
112
+ height: webHeight * deviceScaleFactor,
113
+ renderer: format,
114
+ };
115
+ }
116
+
117
+ // Encode input as base64
118
+ let fileBase64: string;
119
+ if (Buffer.isBuffer(input)) {
120
+ fileBase64 = input.toString('base64');
121
+ } else {
122
+ // String input for non-URL formats is treated as text content
123
+ fileBase64 = Buffer.from(input, 'utf-8').toString('base64');
124
+ }
78
125
 
79
126
  // Inject data before loading template
80
- await this.injectDataIntoPage(page, fileBase64, pageNumber);
127
+ await this.injectDataIntoPage(page, fileBase64, pageNumber, fileName);
81
128
 
82
129
  // Load template
83
130
  const templatePath = this.getTemplatePath(format);
84
131
  await page.goto(`file://${templatePath}`);
85
132
 
86
133
  // Wait for render complete and get metadata
134
+ interface PageMetadata {
135
+ width: number;
136
+ height: number;
137
+ clipX?: number;
138
+ clipY?: number;
139
+ }
87
140
  const metadata = await page.evaluate(async () => {
88
- const renderComplete = (globalThis as any).renderComplete;
141
+ const renderComplete = (globalThis as unknown as Record<string, unknown>).renderComplete as Promise<PageMetadata> | undefined;
89
142
 
90
143
  if (!renderComplete) {
91
144
  throw new Error('window.renderComplete not found');
@@ -96,8 +149,10 @@ export class Renderer {
96
149
  });
97
150
 
98
151
  // Check if we need to clip (for EPUB content cropping)
99
- const clipX = (metadata as any).clipX;
100
- const clipY = (metadata as any).clipY;
152
+ const clipX = metadata.clipX;
153
+ const clipY = metadata.clipY;
154
+
155
+ let screenshotData: Buffer;
101
156
 
102
157
  if (clipX !== undefined && clipY !== undefined) {
103
158
  // Resize viewport to ensure clip area is fully visible
@@ -112,8 +167,7 @@ export class Renderer {
112
167
  await page.waitForTimeout(100);
113
168
 
114
169
  // Use clip to capture just the content area
115
- await page.screenshot({
116
- path: outputPath,
170
+ screenshotData = await page.screenshot({
117
171
  type: imageFormat as 'png' | 'jpeg',
118
172
  clip: {
119
173
  x: clipX,
@@ -133,8 +187,7 @@ export class Renderer {
133
187
  await page.waitForTimeout(100);
134
188
 
135
189
  // Take screenshot at exact rendered size
136
- await page.screenshot({
137
- path: outputPath,
190
+ screenshotData = await page.screenshot({
138
191
  type: imageFormat as 'png' | 'jpeg',
139
192
  fullPage: false,
140
193
  });
@@ -147,10 +200,11 @@ export class Renderer {
147
200
  const actualHeight = metadata.height * deviceScaleFactor;
148
201
 
149
202
  return {
150
- path: outputPath,
203
+ data: screenshotData,
151
204
  format: imageFormat,
152
205
  width: actualWidth,
153
206
  height: actualHeight,
207
+ renderer: format,
154
208
  };
155
209
  } catch (error) {
156
210
  await browser.close();
package/src/types.ts CHANGED
@@ -1,16 +1,17 @@
1
1
  export interface ScreenshotOptions {
2
- output?: string;
3
2
  format?: 'png' | 'jpeg' | 'webp';
4
3
  width?: number;
5
4
  height?: number;
6
5
  page?: number;
6
+ fileName?: string;
7
7
  }
8
8
 
9
9
  export interface ScreenshotResult {
10
- path: string;
10
+ data: Buffer;
11
11
  format: string;
12
12
  width: number;
13
13
  height: number;
14
+ renderer: string;
14
15
  }
15
16
 
16
17
  export interface RenderMetadata {
@@ -21,4 +22,66 @@ export interface RenderMetadata {
21
22
  scale: number;
22
23
  }
23
24
 
24
- export type FileFormat = 'pdf' | 'epub' | 'docx' | 'xlsx' | 'pptx' | 'unknown';
25
+ export type FileFormat = 'pdf' | 'epub' | 'docx' | 'xlsx' | 'pptx' | 'md' | 'html' | 'csv' | 'rtf' | 'ipynb' | 'tex' | 'code' | 'url' | 'mmd' | 'geojson' | 'gpx' | 'unknown';
26
+
27
+ // Mapping from MIME types to FileFormat
28
+ export const MIME_TO_FORMAT: Record<string, FileFormat> = {
29
+ 'application/pdf': 'pdf',
30
+ 'application/epub+zip': 'epub',
31
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'docx',
32
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'xlsx',
33
+ 'application/vnd.openxmlformats-officedocument.presentationml.presentation': 'pptx',
34
+ 'text/markdown': 'md',
35
+ 'text/html': 'html',
36
+ 'text/csv': 'csv',
37
+ 'application/rtf': 'rtf',
38
+ 'text/rtf': 'rtf',
39
+ 'application/x-ipynb+json': 'ipynb',
40
+ 'application/x-tex': 'tex',
41
+ 'text/x-tex': 'tex',
42
+ 'application/geo+json': 'geojson',
43
+ 'application/gpx+xml': 'gpx',
44
+ };
45
+
46
+ // Mapping from slug names to FileFormat
47
+ export const SLUG_TO_FORMAT: Record<string, FileFormat> = {
48
+ 'pdf': 'pdf',
49
+ 'epub': 'epub',
50
+ 'docx': 'docx',
51
+ 'xlsx': 'xlsx',
52
+ 'pptx': 'pptx',
53
+ 'md': 'md',
54
+ 'markdown': 'md',
55
+ 'html': 'html',
56
+ 'htm': 'html',
57
+ 'csv': 'csv',
58
+ 'rtf': 'rtf',
59
+ 'ipynb': 'ipynb',
60
+ 'jupyter': 'ipynb',
61
+ 'tex': 'tex',
62
+ 'latex': 'tex',
63
+ 'code': 'code',
64
+ 'url': 'url',
65
+ 'mmd': 'mmd',
66
+ 'mermaid': 'mmd',
67
+ 'geojson': 'geojson',
68
+ 'gpx': 'gpx',
69
+ };
70
+
71
+ /**
72
+ * Resolve a format string (MIME type or slug) to a FileFormat.
73
+ */
74
+ export function resolveFormat(formatStr: string): FileFormat {
75
+ // Try slug first (more common)
76
+ const lowerFormat = formatStr.toLowerCase();
77
+ if (lowerFormat in SLUG_TO_FORMAT) {
78
+ return SLUG_TO_FORMAT[lowerFormat];
79
+ }
80
+
81
+ // Try MIME type
82
+ if (formatStr in MIME_TO_FORMAT) {
83
+ return MIME_TO_FORMAT[formatStr];
84
+ }
85
+
86
+ throw new Error(`Unknown format: ${formatStr}. Use a slug (e.g., 'pdf') or MIME type (e.g., 'application/pdf')`);
87
+ }