@macrulez/devtoolz 0.2.0 → 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.
Files changed (80) hide show
  1. package/README.md +131 -8
  2. package/dist/cli.js +265 -8
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/case-check/report.js +8 -6
  5. package/dist/commands/case-check/report.js.map +1 -1
  6. package/dist/commands/circular-imports/report.js +11 -12
  7. package/dist/commands/circular-imports/report.js.map +1 -1
  8. package/dist/commands/console-strip/report.js +9 -7
  9. package/dist/commands/console-strip/report.js.map +1 -1
  10. package/dist/commands/dead-exports/report.js +6 -4
  11. package/dist/commands/dead-exports/report.js.map +1 -1
  12. package/dist/commands/empty-catch/report.js +5 -3
  13. package/dist/commands/empty-catch/report.js.map +1 -1
  14. package/dist/commands/exports-doctor/report.js +7 -5
  15. package/dist/commands/exports-doctor/report.js.map +1 -1
  16. package/dist/commands/full-check/report.d.ts +3 -0
  17. package/dist/commands/full-check/report.js +55 -0
  18. package/dist/commands/full-check/report.js.map +1 -0
  19. package/dist/commands/full-check/run.d.ts +32 -0
  20. package/dist/commands/full-check/run.js +251 -0
  21. package/dist/commands/full-check/run.js.map +1 -0
  22. package/dist/commands/image-hash/cache.d.ts +14 -0
  23. package/dist/commands/image-hash/cache.js +40 -0
  24. package/dist/commands/image-hash/cache.js.map +1 -0
  25. package/dist/commands/image-hash/core.d.ts +56 -0
  26. package/dist/commands/image-hash/core.js +293 -0
  27. package/dist/commands/image-hash/core.js.map +1 -0
  28. package/dist/commands/image-hash/hash.d.ts +19 -0
  29. package/dist/commands/image-hash/hash.js +97 -0
  30. package/dist/commands/image-hash/hash.js.map +1 -0
  31. package/dist/commands/image-hash/report.d.ts +3 -0
  32. package/dist/commands/image-hash/report.js +94 -0
  33. package/dist/commands/image-hash/report.js.map +1 -0
  34. package/dist/commands/image-hash/run.d.ts +60 -0
  35. package/dist/commands/image-hash/run.js +315 -0
  36. package/dist/commands/image-hash/run.js.map +1 -0
  37. package/dist/commands/image-hash/sharp-loader.d.ts +59 -0
  38. package/dist/commands/image-hash/sharp-loader.js +79 -0
  39. package/dist/commands/image-hash/sharp-loader.js.map +1 -0
  40. package/dist/commands/orphan-tests/report.js +7 -5
  41. package/dist/commands/orphan-tests/report.js.map +1 -1
  42. package/dist/commands/readme-check/report.js +7 -5
  43. package/dist/commands/readme-check/report.js.map +1 -1
  44. package/dist/commands/scripts-check/report.js +7 -5
  45. package/dist/commands/scripts-check/report.js.map +1 -1
  46. package/dist/commands/stale-ts-ignore/report.js +7 -5
  47. package/dist/commands/stale-ts-ignore/report.js.map +1 -1
  48. package/dist/commands/strip-comments/report.js +6 -4
  49. package/dist/commands/strip-comments/report.js.map +1 -1
  50. package/dist/commands/todo-report/report.js +7 -5
  51. package/dist/commands/todo-report/report.js.map +1 -1
  52. package/dist/commands/unused-deps/report.js +7 -5
  53. package/dist/commands/unused-deps/report.js.map +1 -1
  54. package/dist/format/colors.d.ts +4 -0
  55. package/dist/format/colors.js +4 -3
  56. package/dist/format/colors.js.map +1 -1
  57. package/dist/format/diff-render.js +2 -2
  58. package/dist/format/diff-render.js.map +1 -1
  59. package/dist/format/file-list.d.ts +1 -9
  60. package/dist/format/file-list.js +5 -16
  61. package/dist/format/file-list.js.map +1 -1
  62. package/dist/format/findings-list.d.ts +1 -8
  63. package/dist/format/findings-list.js +5 -14
  64. package/dist/format/findings-list.js.map +1 -1
  65. package/dist/format/style.d.ts +20 -0
  66. package/dist/format/style.js +36 -0
  67. package/dist/format/style.js.map +1 -0
  68. package/dist/format/table.d.ts +8 -0
  69. package/dist/format/table.js +44 -0
  70. package/dist/format/table.js.map +1 -0
  71. package/dist/format/vibes.d.ts +4 -1
  72. package/dist/format/vibes.js +25 -10
  73. package/dist/format/vibes.js.map +1 -1
  74. package/dist/index.d.ts +7 -0
  75. package/dist/index.js +4 -0
  76. package/dist/index.js.map +1 -1
  77. package/dist/utils/walk.d.ts +2 -0
  78. package/dist/utils/walk.js +4 -3
  79. package/dist/utils/walk.js.map +1 -1
  80. package/package.json +4 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core.js","sourceRoot":"","sources":["../../../src/commands/image-hash/core.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { type Components, type HashType } from './core.js';
2
+ import type { SharpFactory } from './sharp-loader.js';
3
+ export interface ComputeOptions {
4
+ types: HashType[];
5
+ size: number;
6
+ components: Components;
7
+ maxPixels?: number;
8
+ }
9
+ export interface ComputedHashes {
10
+ width: number;
11
+ height: number;
12
+ blurhash?: string;
13
+ thumbhash?: string;
14
+ color?: string;
15
+ preview?: string;
16
+ }
17
+ export declare function dominantColor(rgba: ArrayLike<number>): string | undefined;
18
+ export declare function friendlyMessage(error: unknown, maxPixels: number | undefined): string;
19
+ export declare function computeHashes(sharp: SharpFactory, input: string | Uint8Array, options: ComputeOptions): Promise<ComputedHashes>;
@@ -0,0 +1,97 @@
1
+ import { encode as encodeBlurhash } from 'blurhash';
2
+ import { rgbaToThumbHash, thumbHashToRGBA } from 'thumbhash';
3
+ import { resolveComponents } from './core.js';
4
+ export function dominantColor(rgba) {
5
+ const buckets = new Map();
6
+ for (let i = 0; i + 3 < rgba.length; i += 4) {
7
+ if (rgba[i + 3] < 128)
8
+ continue;
9
+ const r = rgba[i];
10
+ const g = rgba[i + 1];
11
+ const b = rgba[i + 2];
12
+ const key = ((r >> 4) << 8) | ((g >> 4) << 4) | (b >> 4);
13
+ const bucket = buckets.get(key);
14
+ if (bucket) {
15
+ bucket.count++;
16
+ bucket.r += r;
17
+ bucket.g += g;
18
+ bucket.b += b;
19
+ }
20
+ else {
21
+ buckets.set(key, { count: 1, r, g, b });
22
+ }
23
+ }
24
+ let best;
25
+ for (const bucket of buckets.values()) {
26
+ if (!best || bucket.count > best.count)
27
+ best = bucket;
28
+ }
29
+ if (!best)
30
+ return undefined;
31
+ const hex = (sum) => Math.round(sum / best.count)
32
+ .toString(16)
33
+ .padStart(2, '0');
34
+ return `#${hex(best.r)}${hex(best.g)}${hex(best.b)}`;
35
+ }
36
+ export function friendlyMessage(error, maxPixels) {
37
+ const message = error instanceof Error ? error.message : String(error);
38
+ if (/pixel limit/i.test(message)) {
39
+ const limit = maxPixels === undefined ? 'the default limit' : `${maxPixels} pixels`;
40
+ return `image is larger than ${limit} — raise it with --max-pixels (0 removes the limit)`;
41
+ }
42
+ if (/unsupported image format|corrupt header|bad seek|not a known file format/i.test(message)) {
43
+ return 'not a readable image — the file is corrupt or in an unsupported format';
44
+ }
45
+ if (/premature end|truncated|VipsJpeg|VipsPng|end of stream/i.test(message)) {
46
+ return 'the image file is truncated or damaged';
47
+ }
48
+ return message;
49
+ }
50
+ export async function computeHashes(sharp, input, options) {
51
+ const inputOptions = { failOn: 'truncated' };
52
+ if (options.maxPixels !== undefined) {
53
+ inputOptions.limitInputPixels = options.maxPixels === 0 ? false : options.maxPixels;
54
+ }
55
+ const metadata = await sharp(input, inputOptions).metadata();
56
+ const swapped = (metadata.orientation ?? 1) >= 5;
57
+ const width = (swapped ? metadata.height : metadata.width) ?? 0;
58
+ const height = (swapped ? metadata.width : metadata.height) ?? 0;
59
+ const { data, info } = await sharp(input, inputOptions)
60
+ .rotate()
61
+ .resize({ width: options.size, height: options.size, fit: 'inside', withoutEnlargement: true })
62
+ .toColourspace('srgb')
63
+ .ensureAlpha()
64
+ .raw()
65
+ .toBuffer({ resolveWithObject: true });
66
+ const result = {
67
+ width: width || info.width,
68
+ height: height || info.height,
69
+ };
70
+ if (options.types.includes('blurhash')) {
71
+ const components = resolveComponents(options.components, info.width, info.height);
72
+ result.blurhash = encodeBlurhash(new Uint8ClampedArray(data), info.width, info.height, components.x, components.y);
73
+ }
74
+ const needsThumbhash = options.types.includes('thumbhash') || options.types.includes('preview');
75
+ if (needsThumbhash) {
76
+ const hash = rgbaToThumbHash(info.width, info.height, data);
77
+ if (options.types.includes('thumbhash')) {
78
+ result.thumbhash = Buffer.from(hash).toString('base64');
79
+ }
80
+ if (options.types.includes('preview')) {
81
+ const decoded = thumbHashToRGBA(hash);
82
+ const png = await sharp(decoded.rgba, {
83
+ raw: { width: decoded.w, height: decoded.h, channels: 4 },
84
+ })
85
+ .png({ compressionLevel: 9 })
86
+ .toBuffer();
87
+ result.preview = `data:image/png;base64,${Buffer.from(png).toString('base64')}`;
88
+ }
89
+ }
90
+ if (options.types.includes('color')) {
91
+ const color = dominantColor(data);
92
+ if (color !== undefined)
93
+ result.color = color;
94
+ }
95
+ return result;
96
+ }
97
+ //# sourceMappingURL=hash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hash.js","sourceRoot":"","sources":["../../../src/commands/image-hash/hash.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { type VibesOptions } from '../../format/vibes.js';
2
+ import type { ImageHashReport } from './run.js';
3
+ export declare function renderImageHashReport(report: ImageHashReport, options?: VibesOptions): string;
@@ -0,0 +1,94 @@
1
+ import { banner } from '../../format/vibes.js';
2
+ import { createStyle } from '../../format/style.js';
3
+ import { renderTable } from '../../format/table.js';
4
+ import { ALL_TYPES } from './core.js';
5
+ const TYPE_LABEL = {
6
+ blurhash: 'BlurHash',
7
+ thumbhash: 'ThumbHash',
8
+ color: 'Color',
9
+ preview: 'Preview',
10
+ };
11
+ const PREVIEW_CELL_WIDTH = 28;
12
+ function hashTypesIn(report) {
13
+ return ALL_TYPES.filter((type) => report.entries.some((entry) => entry[type] !== undefined));
14
+ }
15
+ function cellText(type, value) {
16
+ if (value === undefined)
17
+ return '';
18
+ if (type === 'preview' && value.length > PREVIEW_CELL_WIDTH) {
19
+ return `${value.slice(0, PREVIEW_CELL_WIDTH - 1)}…`;
20
+ }
21
+ return value;
22
+ }
23
+ function imageHashTable(report, options) {
24
+ const s = createStyle(options);
25
+ const types = hashTypesIn(report);
26
+ const typeStyle = {
27
+ blurhash: s.name,
28
+ thumbhash: s.accent,
29
+ color: s.value,
30
+ preview: s.tag,
31
+ };
32
+ const columns = [
33
+ { header: 'File', shrink: true, style: s.path },
34
+ { header: 'Size', align: 'right', style: s.tag },
35
+ ...types.map((type) => ({ header: TYPE_LABEL[type], style: typeStyle[type] })),
36
+ ];
37
+ const rows = report.entries.map((entry) => [
38
+ entry.file,
39
+ `${entry.width}×${entry.height}`,
40
+ ...types.map((type) => cellText(type, entry[type])),
41
+ ]);
42
+ return renderTable(columns, rows, options);
43
+ }
44
+ export function renderImageHashReport(report, options = {}) {
45
+ const s = createStyle(options);
46
+ const lines = [];
47
+ const isClean = report.errors.length === 0 && report.outdated.length === 0;
48
+ if (options.quiet && isClean)
49
+ return '';
50
+ if (!options.quiet && !options.plain)
51
+ lines.push(banner(options), '');
52
+ if (report.dryRun && report.entries.length > 0) {
53
+ lines.push(...imageHashTable(report, options), '');
54
+ }
55
+ const count = report.entries.length;
56
+ const cachedNote = report.cached > 0 ? `, ${report.cached} from the cache` : '';
57
+ lines.push(s.info(`Hashed ${count} image${count === 1 ? '' : 's'}${cachedNote}.`));
58
+ if (report.check) {
59
+ if (report.outdated.length === 0) {
60
+ lines.push('', s.success(`All ${report.checked} output file${report.checked === 1 ? ' is' : 's are'} up to date.`));
61
+ }
62
+ else {
63
+ lines.push('', s.problem(`${report.outdated.length} of ${report.checked} output file${report.checked === 1 ? '' : 's'} out of date:`));
64
+ for (const item of report.outdated) {
65
+ const reason = item.reason === 'missing' ? 'missing' : 'differs from the images';
66
+ lines.push(` ${s.path(item.file)} ${s.muted('—')} ${s.error(reason)}`);
67
+ }
68
+ lines.push('', s.hint('(regenerate them by running the same command without --check)'));
69
+ }
70
+ }
71
+ if (report.written.length > 0) {
72
+ const verb = report.dryRun ? 'Would write' : 'Wrote';
73
+ const heading = `${verb} ${report.written.length} file${report.written.length === 1 ? '' : 's'}:`;
74
+ lines.push('', report.dryRun ? s.heading(heading) : s.success(heading));
75
+ for (const file of report.written)
76
+ lines.push(` ${s.path(file)}`);
77
+ }
78
+ if (report.pruned > 0) {
79
+ lines.push('', s.info(`Removed ${report.pruned} entr${report.pruned === 1 ? 'y' : 'ies'} whose image no longer exists.`));
80
+ }
81
+ if (report.dryRun) {
82
+ lines.push('', s.hint(report.written.length > 0
83
+ ? '(dry run — nothing written; drop --dry-run to write the files)'
84
+ : '(dry run — nothing written)'));
85
+ }
86
+ if (report.errors.length > 0) {
87
+ lines.push('', s.problem(`${report.errors.length} problem${report.errors.length === 1 ? '' : 's'}:`));
88
+ for (const error of report.errors) {
89
+ lines.push(` ${s.path(error.file)} ${s.muted('—')} ${s.error(error.message)}`);
90
+ }
91
+ }
92
+ return lines.join('\n');
93
+ }
94
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../../../src/commands/image-hash/report.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ import { type Components, type HashEntry, type HashType, type OutputFormat } from './core.js';
2
+ import { type SharpFactory } from './sharp-loader.js';
3
+ export interface ImageHashProgress {
4
+ done: number;
5
+ total: number;
6
+ cached: number;
7
+ }
8
+ export interface ImageHashRunOptions {
9
+ paths: string[];
10
+ cwd: string;
11
+ types: HashType[];
12
+ recursive?: boolean;
13
+ extensions?: string[];
14
+ ignoreGlobs?: string[];
15
+ respectGitignore?: boolean;
16
+ components?: Components;
17
+ size?: number;
18
+ maxPixels?: number;
19
+ format?: OutputFormat;
20
+ exportName?: string;
21
+ out?: string;
22
+ perFile?: boolean;
23
+ outDir?: string;
24
+ suffix?: string;
25
+ outExtension?: string;
26
+ keyBase?: string;
27
+ keyPrefix?: string;
28
+ cache?: string;
29
+ update?: boolean;
30
+ prune?: boolean;
31
+ check?: boolean;
32
+ concurrency?: number;
33
+ assumeYes?: boolean;
34
+ dryRun?: boolean;
35
+ sharp?: SharpFactory;
36
+ onProgress?: (progress: ImageHashProgress) => void;
37
+ }
38
+ export interface ImageHashError {
39
+ file: string;
40
+ message: string;
41
+ }
42
+ export interface OutdatedOutput {
43
+ file: string;
44
+ reason: 'missing' | 'changed';
45
+ }
46
+ export interface ImageHashReport {
47
+ filesScanned: number;
48
+ entries: HashEntry[];
49
+ written: string[];
50
+ errors: ImageHashError[];
51
+ stdout: string | null;
52
+ dryRun: boolean;
53
+ check: boolean;
54
+ checked: number;
55
+ outdated: OutdatedOutput[];
56
+ cached: number;
57
+ pruned: number;
58
+ exitCode: number;
59
+ }
60
+ export declare function runImageHash(options: ImageHashRunOptions): Promise<ImageHashReport>;
@@ -0,0 +1,315 @@
1
+ import { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
2
+ import { basename, dirname, join, relative, resolve } from 'node:path';
3
+ import { walk } from '../../utils/walk.js';
4
+ import { ALL_TYPES, DEFAULT_BLURHASH_COMPONENTS, DEFAULT_EXPORT_NAME, DEFAULT_IMAGE_EXTENSIONS, DEFAULT_SAMPLE_SIZE, ImageHashUsageError, componentsLabel, formatAggregate, formatPerFile, isUrl, normalizeOutExtension, orderTypes, outputFileName, parseAggregate, splitPathArguments, validateExportName, validateSuffix, withUpperCaseVariants, } from './core.js';
5
+ import { cacheHit, emptyCache, loadCache, saveCache } from './cache.js';
6
+ import { computeHashes, friendlyMessage } from './hash.js';
7
+ import { loadSharp } from './sharp-loader.js';
8
+ const DOWNLOAD_TIMEOUT_MS = 30000;
9
+ const MAX_DOWNLOAD_BYTES = 100 * 1024 * 1024;
10
+ function toPosix(path) {
11
+ return path.split('\\').join('/');
12
+ }
13
+ function urlBaseName(url) {
14
+ try {
15
+ const name = basename(decodeURIComponent(new URL(url).pathname));
16
+ return name === '' ? 'image' : name;
17
+ }
18
+ catch {
19
+ return 'image';
20
+ }
21
+ }
22
+ function collectImages(options, errors) {
23
+ const extensions = withUpperCaseVariants(options.extensions ?? DEFAULT_IMAGE_EXTENSIONS);
24
+ const images = [];
25
+ const seen = new Set();
26
+ for (const input of splitPathArguments(options.paths)) {
27
+ if (isUrl(input)) {
28
+ if (!seen.has(input)) {
29
+ seen.add(input);
30
+ images.push({ abs: input, root: '', url: true });
31
+ }
32
+ continue;
33
+ }
34
+ const abs = resolve(options.cwd, input);
35
+ const stat = statSync(abs, { throwIfNoEntry: false });
36
+ if (!stat) {
37
+ errors.push({ file: input, message: 'path does not exist' });
38
+ continue;
39
+ }
40
+ const root = stat.isDirectory() ? abs : dirname(abs);
41
+ const found = walk([abs], {
42
+ cwd: options.cwd,
43
+ extensions,
44
+ ignoreGlobs: options.ignoreGlobs ?? [],
45
+ recursive: options.recursive ?? false,
46
+ ...(options.respectGitignore !== undefined
47
+ ? { respectGitignore: options.respectGitignore }
48
+ : {}),
49
+ });
50
+ for (const file of found) {
51
+ if (seen.has(file))
52
+ continue;
53
+ seen.add(file);
54
+ images.push({ abs: file, root, url: false });
55
+ }
56
+ }
57
+ return images.sort((a, b) => a.abs.localeCompare(b.abs));
58
+ }
59
+ async function fetchImage(url) {
60
+ const response = await fetch(url, { signal: AbortSignal.timeout(DOWNLOAD_TIMEOUT_MS) }).catch((error) => {
61
+ const cause = error.cause;
62
+ const reason = cause?.code ??
63
+ cause?.errors?.[0]?.code ??
64
+ (error instanceof Error ? error.message : String(error));
65
+ throw new Error(`download failed: ${reason}`);
66
+ });
67
+ if (!response.ok)
68
+ throw new Error(`download failed: HTTP ${response.status}`);
69
+ const bytes = new Uint8Array(await response.arrayBuffer());
70
+ if (bytes.length > MAX_DOWNLOAD_BYTES)
71
+ throw new Error('download is larger than 100 MB');
72
+ return bytes;
73
+ }
74
+ async function mapWithConcurrency(items, limit, task) {
75
+ const results = new Array(items.length);
76
+ let next = 0;
77
+ const workers = Array.from({ length: Math.max(1, Math.min(limit, items.length)) }, async () => {
78
+ while (next < items.length) {
79
+ const index = next++;
80
+ results[index] = await task(items[index]);
81
+ }
82
+ });
83
+ await Promise.all(workers);
84
+ return results;
85
+ }
86
+ function writeText(path, content) {
87
+ mkdirSync(dirname(path), { recursive: true });
88
+ writeFileSync(path, content);
89
+ }
90
+ function normalizeNewlines(text) {
91
+ return text.replace(/\r\n/g, '\n');
92
+ }
93
+ function pick(computed, key, types) {
94
+ const entry = { file: key, width: computed.width, height: computed.height };
95
+ for (const type of types) {
96
+ const value = computed[type];
97
+ if (value !== undefined)
98
+ entry[type] = value;
99
+ }
100
+ return entry;
101
+ }
102
+ function validate(options, perFile) {
103
+ if (options.out !== undefined && perFile) {
104
+ throw new ImageHashUsageError('--out cannot be combined with --per-file or --out-dir');
105
+ }
106
+ if (options.check) {
107
+ if (options.out === undefined && !perFile) {
108
+ throw new ImageHashUsageError('--check needs the output to compare against: pass -o, --per-file or --out-dir');
109
+ }
110
+ if (options.dryRun)
111
+ throw new ImageHashUsageError('--check cannot be combined with --dry-run');
112
+ if (options.update)
113
+ throw new ImageHashUsageError('--check cannot be combined with --update');
114
+ }
115
+ if (options.update && (options.out === undefined || perFile)) {
116
+ throw new ImageHashUsageError('--update merges into the single file given with -o');
117
+ }
118
+ if (options.prune && !options.update) {
119
+ throw new ImageHashUsageError('--prune only makes sense together with --update');
120
+ }
121
+ }
122
+ export async function runImageHash(options) {
123
+ const format = options.format ?? 'json';
124
+ const exportName = validateExportName(options.exportName ?? DEFAULT_EXPORT_NAME);
125
+ const perFile = Boolean(options.perFile) || options.outDir !== undefined;
126
+ const dryRun = Boolean(options.dryRun);
127
+ const check = Boolean(options.check);
128
+ validate(options, perFile);
129
+ const suffix = validateSuffix(options.suffix, options.types, format);
130
+ const outExtension = normalizeOutExtension(options.outExtension, format);
131
+ const size = options.size ?? DEFAULT_SAMPLE_SIZE;
132
+ const components = options.components ?? DEFAULT_BLURHASH_COMPONENTS;
133
+ const params = `${size}|${componentsLabel(components)}`;
134
+ const keyBase = resolve(options.cwd, options.keyBase ?? '.');
135
+ const keyPrefix = options.keyPrefix ?? '';
136
+ const keyOf = (source) => source.url ? source.abs : `${keyPrefix}${toPosix(relative(keyBase, source.abs))}`;
137
+ const errors = [];
138
+ const images = collectImages(options, errors);
139
+ const cachePath = options.cache !== undefined ? resolve(options.cwd, options.cache) : null;
140
+ const cache = cachePath ? loadCache(cachePath) : emptyCache();
141
+ const newRecords = {};
142
+ let sharpPromise = null;
143
+ const loadConfiguredSharp = async () => {
144
+ const loaded = options.sharp ??
145
+ (await loadSharp({ assumeYes: options.assumeYes ?? false, cwd: options.cwd }));
146
+ loaded.cache?.(false);
147
+ return loaded;
148
+ };
149
+ const getSharp = () => {
150
+ if (!sharpPromise)
151
+ sharpPromise = loadConfiguredSharp();
152
+ return sharpPromise;
153
+ };
154
+ const computeOptions = {
155
+ types: options.types,
156
+ size,
157
+ components,
158
+ ...(options.maxPixels !== undefined ? { maxPixels: options.maxPixels } : {}),
159
+ };
160
+ let done = 0;
161
+ let cached = 0;
162
+ const total = images.length;
163
+ const entries = [];
164
+ const sources = new Map();
165
+ const results = await mapWithConcurrency(images, options.concurrency ?? 4, async (image) => {
166
+ const key = keyOf(image);
167
+ const display = image.url ? image.abs : toPosix(relative(options.cwd, image.abs));
168
+ try {
169
+ let computed;
170
+ if (image.url) {
171
+ const bytes = await fetchImage(image.abs);
172
+ computed = await computeHashes(await getSharp(), bytes, computeOptions);
173
+ }
174
+ else {
175
+ const stat = statSync(image.abs);
176
+ const sig = `${stat.mtimeMs}:${stat.size}`;
177
+ const cacheKey = toPosix(relative(options.cwd, image.abs));
178
+ const previous = cache.files[cacheKey];
179
+ const hit = cachePath ? cacheHit(previous, sig, params, options.types) : null;
180
+ if (hit) {
181
+ computed = hit;
182
+ cached++;
183
+ }
184
+ else {
185
+ computed = await computeHashes(await getSharp(), image.abs, computeOptions);
186
+ const base = previous && previous.sig === sig && previous.params === params ? previous : {};
187
+ newRecords[cacheKey] = { ...base, ...computed, sig, params };
188
+ }
189
+ }
190
+ return { image, entry: pick(computed, key, options.types) };
191
+ }
192
+ catch (error) {
193
+ return { image, error: { file: display, message: friendlyMessage(error, options.maxPixels) } };
194
+ }
195
+ finally {
196
+ done++;
197
+ options.onProgress?.({ done, total, cached });
198
+ }
199
+ });
200
+ for (const result of results) {
201
+ if ('entry' in result) {
202
+ entries.push(result.entry);
203
+ sources.set(result.entry.file, result.image);
204
+ }
205
+ else {
206
+ errors.push(result.error);
207
+ }
208
+ }
209
+ entries.sort((a, b) => a.file.localeCompare(b.file));
210
+ const outputs = [];
211
+ let stdout = null;
212
+ let pruned = 0;
213
+ if (perFile) {
214
+ const claimed = new Set();
215
+ const outDirAbs = options.outDir !== undefined ? resolve(options.cwd, options.outDir) : null;
216
+ for (const entry of entries) {
217
+ const source = sources.get(entry.file);
218
+ if (source.url && outDirAbs === null) {
219
+ errors.push({
220
+ file: entry.file,
221
+ message: 'a URL input needs --out-dir for its output file',
222
+ });
223
+ continue;
224
+ }
225
+ const targetDir = source.url
226
+ ? outDirAbs
227
+ : outDirAbs !== null
228
+ ? join(outDirAbs, relative(source.root, dirname(source.abs)))
229
+ : dirname(source.abs);
230
+ const imageName = source.url ? urlBaseName(source.abs) : source.abs;
231
+ for (const unit of formatPerFile(entry, options.types, format)) {
232
+ const target = join(targetDir, outputFileName(imageName, suffix, unit.token, outExtension));
233
+ if (claimed.has(target)) {
234
+ errors.push({ file: entry.file, message: `output ${target} is already taken` });
235
+ continue;
236
+ }
237
+ claimed.add(target);
238
+ outputs.push({ path: target, content: unit.content });
239
+ }
240
+ }
241
+ }
242
+ else {
243
+ let outputEntries = entries;
244
+ if (options.update) {
245
+ const target = resolve(options.cwd, options.out);
246
+ const existing = existsSync(target)
247
+ ? parseAggregate(readFileSync(target, 'utf8'), format)
248
+ : [];
249
+ const merged = new Map(existing.map((entry) => [entry.file, entry]));
250
+ const freshKeys = new Set(entries.map((entry) => entry.file));
251
+ for (const entry of entries)
252
+ merged.set(entry.file, { ...merged.get(entry.file), ...entry });
253
+ if (options.prune) {
254
+ for (const key of [...merged.keys()]) {
255
+ if (freshKeys.has(key) || isUrl(key))
256
+ continue;
257
+ const local = key.startsWith(keyPrefix) ? key.slice(keyPrefix.length) : key;
258
+ if (!existsSync(resolve(keyBase, local))) {
259
+ merged.delete(key);
260
+ pruned++;
261
+ }
262
+ }
263
+ }
264
+ outputEntries = [...merged.values()].sort((a, b) => a.file.localeCompare(b.file));
265
+ }
266
+ const outputTypes = options.update
267
+ ? orderTypes([
268
+ ...options.types,
269
+ ...outputEntries.flatMap((entry) => ALL_TYPES.filter((type) => entry[type] !== undefined)),
270
+ ])
271
+ : options.types;
272
+ const content = formatAggregate(outputEntries, outputTypes, format, exportName);
273
+ if (options.out !== undefined) {
274
+ outputs.push({ path: resolve(options.cwd, options.out), content });
275
+ }
276
+ else if (!dryRun && !check) {
277
+ stdout = content;
278
+ }
279
+ }
280
+ const written = [];
281
+ const outdated = [];
282
+ for (const output of outputs) {
283
+ const display = toPosix(relative(options.cwd, output.path));
284
+ if (check) {
285
+ if (!existsSync(output.path)) {
286
+ outdated.push({ file: display, reason: 'missing' });
287
+ }
288
+ else if (normalizeNewlines(readFileSync(output.path, 'utf8')) !== normalizeNewlines(output.content)) {
289
+ outdated.push({ file: display, reason: 'changed' });
290
+ }
291
+ continue;
292
+ }
293
+ if (!dryRun)
294
+ writeText(output.path, output.content);
295
+ written.push(display);
296
+ }
297
+ if (cachePath && !dryRun && !check && Object.keys(newRecords).length > 0) {
298
+ saveCache(cachePath, { version: 1, files: { ...cache.files, ...newRecords } });
299
+ }
300
+ return {
301
+ filesScanned: images.length,
302
+ entries,
303
+ written,
304
+ errors,
305
+ stdout,
306
+ dryRun,
307
+ check,
308
+ checked: check ? outputs.length : 0,
309
+ outdated,
310
+ cached,
311
+ pruned,
312
+ exitCode: errors.length > 0 || outdated.length > 0 ? 1 : 0,
313
+ };
314
+ }
315
+ //# sourceMappingURL=run.js.map