@takazudo/zudo-image-tweaker 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1 -0
- package/LICENSE +21 -0
- package/README.md +57 -0
- package/dist/blurhash/index.d.ts +35 -0
- package/dist/blurhash/index.js +40 -0
- package/dist/browser/exif-orientation.d.ts +12 -0
- package/dist/browser/index.d.ts +7 -0
- package/dist/browser/index.js +160 -0
- package/dist/browser/orientation-semantics.d.ts +37 -0
- package/dist/browser/orientation.d.ts +25 -0
- package/dist/browser/prepare-upload.d.ts +100 -0
- package/dist/budget/index.d.ts +73 -0
- package/dist/budget/index.js +157 -0
- package/dist/calibrate/index.d.ts +129 -0
- package/dist/calibrate/index.js +206 -0
- package/dist/composite/index.d.ts +50 -0
- package/dist/composite/index.js +56 -0
- package/dist/exif/index.d.ts +41 -0
- package/dist/exif/index.js +100 -0
- package/dist/heif/index.d.ts +139 -0
- package/dist/heif/index.js +275 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +68 -0
- package/dist/ogp/index.d.ts +72 -0
- package/dist/ogp/index.js +117 -0
- package/dist/presets-PTxNoMdy.js +630 -0
- package/dist/product-photo/index.d.ts +50 -0
- package/dist/product-photo/index.js +189 -0
- package/dist/product-photo/shadow.d.ts +48 -0
- package/dist/run-BIjGA2Fu.js +22 -0
- package/dist/square/index.d.ts +98 -0
- package/dist/square/index.js +89 -0
- package/dist/variants/engine.d.ts +38 -0
- package/dist/variants/feature-detect.d.ts +8 -0
- package/dist/variants/hash-cache.d.ts +63 -0
- package/dist/variants/heic.d.ts +15 -0
- package/dist/variants/index.d.ts +5 -0
- package/dist/variants/index.js +19 -0
- package/dist/variants/presets.d.ts +18 -0
- package/dist/variants/repair.d.ts +28 -0
- package/dist/variants/run.d.ts +36 -0
- package/dist/variants/tags.d.ts +13 -0
- package/dist/variants/types.d.ts +208 -0
- package/package.json +126 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export interface RunResult {
|
|
2
|
+
stdout: string;
|
|
3
|
+
stderr: string;
|
|
4
|
+
}
|
|
5
|
+
export interface RunOptions {
|
|
6
|
+
/** Kill the subprocess if it hasn't exited after this many ms. @default 60000 */
|
|
7
|
+
timeoutMs?: number;
|
|
8
|
+
/**
|
|
9
|
+
* Signal used to kill a timed-out subprocess. @default 'SIGKILL' — a
|
|
10
|
+
* binary that installs a SIGTERM handler (or otherwise ignores it) would
|
|
11
|
+
* defeat the timeout under SIGTERM; SIGKILL cannot be caught or ignored,
|
|
12
|
+
* so the timeout stays a hard bound regardless of the target's own
|
|
13
|
+
* signal handling.
|
|
14
|
+
*/
|
|
15
|
+
killSignal?: NodeJS.Signals;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Thin `execFile` wrapper. Always invoked with an argument array (never a
|
|
19
|
+
* shell string), so paths carrying spaces or shell metacharacters pass
|
|
20
|
+
* through unmangled and there is no shell-injection surface. Isolated in
|
|
21
|
+
* its own module so tests can mock the single external-process seam.
|
|
22
|
+
*
|
|
23
|
+
* Every invocation carries a timeout (default 60s, see {@link RunOptions});
|
|
24
|
+
* a timed-out subprocess is killed and `execFile` rejects, which every
|
|
25
|
+
* caller already treats the same as any other non-ENOENT failure (see
|
|
26
|
+
* each module's existing null/fallback contract).
|
|
27
|
+
*/
|
|
28
|
+
export declare function run(command: string, args: string[], options?: RunOptions): Promise<RunResult>;
|
|
29
|
+
/**
|
|
30
|
+
* Resolve a caller-supplied path before it lands in an external binary's
|
|
31
|
+
* argv (issue #66), so a bare leading-dash relative filename (e.g.
|
|
32
|
+
* `-rf.jpg`) can never be parsed as an option flag by the invoked binary.
|
|
33
|
+
*/
|
|
34
|
+
export declare function resolveBinaryPath(inputPath: string): string;
|
|
35
|
+
/** True when the error is a "command not found" from execFile. */
|
|
36
|
+
export declare function isMissingBinaryError(error: unknown): boolean;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { TagParser } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Default filename-tag parser. A `__ogonly` suffix selects the OGP-only
|
|
4
|
+
* pipeline, `__og` selects full processing plus an OGP card, and anything
|
|
5
|
+
* else is a plain full-variant image. The directive suffix is stripped
|
|
6
|
+
* from the returned slug so outputs land in a clean directory name.
|
|
7
|
+
*/
|
|
8
|
+
export declare const defaultTagParser: TagParser;
|
|
9
|
+
/**
|
|
10
|
+
* Tag parser that disables all OGP dispatch: every file is a plain
|
|
11
|
+
* full-variant image keyed by its bare basename. Used by the photo preset.
|
|
12
|
+
*/
|
|
13
|
+
export declare const noTagParser: TagParser;
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import type { SmartOgpOptions } from '../ogp/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Default responsive-image widths. Kept in lockstep with the width/srcset
|
|
4
|
+
* contract the package documents ([600, 900, 1200, 1600, 2000]); a source
|
|
5
|
+
* whose own width is smaller never gets upscaled past it.
|
|
6
|
+
*/
|
|
7
|
+
export declare const DEFAULT_WIDTHS: number[];
|
|
8
|
+
export declare const DEFAULT_QUALITY = 85;
|
|
9
|
+
export declare const DEFAULT_FORMATS: string[];
|
|
10
|
+
export declare const DEFAULT_CONCURRENCY = 4;
|
|
11
|
+
export declare const DEFAULT_OGP_FILENAME = "ogp.jpg";
|
|
12
|
+
export declare const DEFAULT_CACHE_FILENAME = ".cache.json";
|
|
13
|
+
/** Which pipeline a single file runs through, chosen by the filename-tag parser. */
|
|
14
|
+
export type TagMode = 'full' | 'og' | 'ogonly';
|
|
15
|
+
/** The parsed result of a filename tag: the pipeline to run plus the identity slug. */
|
|
16
|
+
export interface ParsedTag {
|
|
17
|
+
mode: TagMode;
|
|
18
|
+
/** Directory name (under the output dir) this image's outputs are written into. */
|
|
19
|
+
slug: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Derive a {@link ParsedTag} from a source filename (basename, extension
|
|
23
|
+
* included). Fully replaceable so a caller can define their own tag
|
|
24
|
+
* vocabulary or disable tag dispatch entirely.
|
|
25
|
+
*/
|
|
26
|
+
export type TagParser = (filename: string) => ParsedTag;
|
|
27
|
+
/** Builds a variant's output filename from its width and format. */
|
|
28
|
+
export type OutputNameFn = (width: number, format: string) => string;
|
|
29
|
+
/**
|
|
30
|
+
* The per-image record handed to {@link ProcessOneConfig.onMetadata}. The
|
|
31
|
+
* engine itself never persists this anywhere — persistence (a DB, a JSON
|
|
32
|
+
* index, nothing at all) is entirely the caller's decision.
|
|
33
|
+
*/
|
|
34
|
+
export interface VariantMetadata {
|
|
35
|
+
/** Output directory name / stable identity key for this image. */
|
|
36
|
+
slug: string;
|
|
37
|
+
/** blurhash string, or null when encoding failed and no fallback was configured. */
|
|
38
|
+
blurhash: string | null;
|
|
39
|
+
/** Displayed (EXIF-oriented) width in pixels. */
|
|
40
|
+
width: number;
|
|
41
|
+
/** Displayed (EXIF-oriented) height in pixels. */
|
|
42
|
+
height: number;
|
|
43
|
+
/** height / width as a percentage, rounded to 2 dp (an intrinsic-ratio box value). */
|
|
44
|
+
aspectRatio: number;
|
|
45
|
+
/** Whether raster width variants were produced (false for animated-GIF passthrough). */
|
|
46
|
+
hasVariants: boolean;
|
|
47
|
+
/** Content hash of the source file, used for cache invalidation. */
|
|
48
|
+
hash: string;
|
|
49
|
+
/** ISO-8601 timestamp of when this record was produced. */
|
|
50
|
+
processedAt: string;
|
|
51
|
+
/** Source container format (extension, lowercased) when it isn't plain `webp`. */
|
|
52
|
+
originalFormat?: string;
|
|
53
|
+
}
|
|
54
|
+
export interface VariantOutput {
|
|
55
|
+
width: number;
|
|
56
|
+
format: string;
|
|
57
|
+
filename: string;
|
|
58
|
+
/** Absolute path to the written variant file. */
|
|
59
|
+
path: string;
|
|
60
|
+
size: number;
|
|
61
|
+
}
|
|
62
|
+
export interface OgpOutput {
|
|
63
|
+
filename: string;
|
|
64
|
+
path: string;
|
|
65
|
+
size: number;
|
|
66
|
+
method: 'landscape' | 'composite';
|
|
67
|
+
}
|
|
68
|
+
export type ItemStatus = 'processed' | 'skipped';
|
|
69
|
+
export interface ItemResult {
|
|
70
|
+
slug: string;
|
|
71
|
+
inputPath: string;
|
|
72
|
+
/** The per-image output directory (`config.outputDir` joined with the slug). */
|
|
73
|
+
outputDir: string;
|
|
74
|
+
status: ItemStatus;
|
|
75
|
+
/** Present when status is 'skipped'. */
|
|
76
|
+
reason?: 'cache-hit' | 'not-an-image';
|
|
77
|
+
mode: TagMode;
|
|
78
|
+
animated: boolean;
|
|
79
|
+
variants: VariantOutput[];
|
|
80
|
+
ogp: OgpOutput | null;
|
|
81
|
+
metadata: VariantMetadata | null;
|
|
82
|
+
}
|
|
83
|
+
export interface ProcessFailure {
|
|
84
|
+
inputPath: string;
|
|
85
|
+
slug: string;
|
|
86
|
+
/**
|
|
87
|
+
* Coarse pipeline stage the failure surfaced from, for triage. 'io' is
|
|
88
|
+
* pre-pipeline filesystem access (hashing the source, creating the output
|
|
89
|
+
* directory); 'unknown' is reserved for genuinely untagged errors (e.g. a
|
|
90
|
+
* throw from user-supplied callback code), not engine stages.
|
|
91
|
+
*/
|
|
92
|
+
stage: 'slug' | 'io' | 'heic' | 'probe' | 'variants' | 'ogp' | 'passthrough' | 'cache' | 'unknown';
|
|
93
|
+
error: string;
|
|
94
|
+
}
|
|
95
|
+
export interface ProcessSummary {
|
|
96
|
+
/** Successfully handled images (both freshly processed and cache-hit skips). */
|
|
97
|
+
results: ItemResult[];
|
|
98
|
+
/** One entry per file that threw; the run itself never throws for these. */
|
|
99
|
+
failed: ProcessFailure[];
|
|
100
|
+
/** Absolute paths of orphaned output directories removed (only when cleanup was opted into). */
|
|
101
|
+
removed: string[];
|
|
102
|
+
}
|
|
103
|
+
/** A single image to process, as accepted by {@link processOne}. */
|
|
104
|
+
export interface ImageEntry {
|
|
105
|
+
inputPath: string;
|
|
106
|
+
/** Pre-resolved tag; when omitted, `config.tagParser` derives it from the filename. */
|
|
107
|
+
tag?: ParsedTag;
|
|
108
|
+
}
|
|
109
|
+
export interface ProcessOneConfig {
|
|
110
|
+
/** Root directory the per-image slug directories are created under. Required. */
|
|
111
|
+
outputDir: string;
|
|
112
|
+
/** Responsive widths to emit. @default DEFAULT_WIDTHS */
|
|
113
|
+
widths?: number[];
|
|
114
|
+
/** Output formats per width. @default ['webp'] */
|
|
115
|
+
formats?: string[];
|
|
116
|
+
/** Encode quality (1-100) for variants and OGP. @default 85 */
|
|
117
|
+
quality?: number;
|
|
118
|
+
/** Names each variant file. @default `${width}w.${format}` */
|
|
119
|
+
outputName?: OutputNameFn;
|
|
120
|
+
/** OGP output filename within the slug directory. @default 'ogp.jpg' */
|
|
121
|
+
ogpFileName?: string;
|
|
122
|
+
/** Extra options forwarded to `/ogp`'s generateSmartOgp. */
|
|
123
|
+
ogpOptions?: SmartOgpOptions;
|
|
124
|
+
/** Cache sidecar filename within the slug directory. @default '.cache.json' */
|
|
125
|
+
cacheFileName?: string;
|
|
126
|
+
/** blurhash to record when encoding fails. No baked default — omit and the record's blurhash is null. */
|
|
127
|
+
fallbackBlurhash?: string;
|
|
128
|
+
/** Filename-tag parser. @default the `__og` / `__ogonly` parser */
|
|
129
|
+
tagParser?: TagParser;
|
|
130
|
+
/** Attempt to repair corrupt sources via magick/ffmpeg when available. @default true */
|
|
131
|
+
autoRepair?: boolean;
|
|
132
|
+
/**
|
|
133
|
+
* When corruption auto-repair runs (see {@link autoRepair}), first copy the
|
|
134
|
+
* untouched corrupt source to a sibling `<name>.corrupted.bak` so its
|
|
135
|
+
* original bytes can be inspected or recovered. A no-op unless `autoRepair`
|
|
136
|
+
* is on AND a repair is actually attempted; an existing `.bak` is never
|
|
137
|
+
* overwritten. The source file itself is never modified either way.
|
|
138
|
+
* @default false
|
|
139
|
+
*/
|
|
140
|
+
backupCorrupted?: boolean;
|
|
141
|
+
/**
|
|
142
|
+
* Bake EXIF orientation into pixels. The pipeline ALWAYS does this —
|
|
143
|
+
* the variant encode chain (and blurhash/OGP) auto-orient via sharp's
|
|
144
|
+
* `.rotate()`, and no output ever carries an EXIF orientation tag — so
|
|
145
|
+
* enabling this flag changes nothing (issue #29: it previously added
|
|
146
|
+
* only a redundant lossy pre-encode). Retained for API compatibility.
|
|
147
|
+
* See the `stripMetadata` behavior matrix for the full metadata
|
|
148
|
+
* semantics.
|
|
149
|
+
* @default false
|
|
150
|
+
*/
|
|
151
|
+
bakeExifOrientation?: boolean;
|
|
152
|
+
/**
|
|
153
|
+
* Strip ALL metadata — including the ICC profile — from the emitted
|
|
154
|
+
* variants.
|
|
155
|
+
*
|
|
156
|
+
* Behavior matrix for `stripMetadata` × `bakeExifOrientation` — what each
|
|
157
|
+
* combination means for the emitted variant files (issues #71, #29):
|
|
158
|
+
*
|
|
159
|
+
* | stripMetadata | bakeExifOrientation | EXIF | XMP | ICC profile | pixel orientation | colour handling |
|
|
160
|
+
* |---------------|---------------------|---------|---------|-------------|---------------------|------------------------------------------|
|
|
161
|
+
* | false | false | dropped | dropped | retained | baked (encode-time) | source-space pixels + profile carried |
|
|
162
|
+
* | false | true | dropped | dropped | retained | baked (encode-time) | source-space pixels + profile carried |
|
|
163
|
+
* | true | false | dropped | dropped | dropped | baked (encode-time) | pixels genuinely converted to sRGB first |
|
|
164
|
+
* | true | true | dropped | dropped | dropped | baked (encode-time) | pixels genuinely converted to sRGB first |
|
|
165
|
+
*
|
|
166
|
+
* Each variant is produced by exactly ONE encode of the source — no
|
|
167
|
+
* combination adds an intermediate re-encode, so `bakeExifOrientation`
|
|
168
|
+
* rows are byte-identical to their flagless counterparts.
|
|
169
|
+
*
|
|
170
|
+
* - EXIF and XMP are always dropped: sharp strips them on every encode
|
|
171
|
+
* unless explicitly asked to keep them, and this pipeline never asks.
|
|
172
|
+
* The EXIF orientation tag is therefore never emitted; instead the
|
|
173
|
+
* rotation/flip it describes is always physically baked into the
|
|
174
|
+
* pixels at encode time via the variant chain's `.rotate()`
|
|
175
|
+
* (blurhash and OGP auto-orient the same way on their own).
|
|
176
|
+
* - With `stripMetadata: false`, the ICC profile is retained via sharp's
|
|
177
|
+
* `keepIccProfile()`: pixel values stay in the source colour space and
|
|
178
|
+
* the profile carries through byte-identically, so a Display-P3 photo
|
|
179
|
+
* (every modern iPhone) keeps its full gamut and renders exactly as
|
|
180
|
+
* shot in any colour-managed viewer.
|
|
181
|
+
* - With `stripMetadata: true`, the profile is stripped strictly
|
|
182
|
+
* AFTER conversion, never instead of it: sharp 0.35.3's default
|
|
183
|
+
* pipeline honours the embedded input profile and genuinely converts
|
|
184
|
+
* the pixels to sRGB (verified pixel-level on a P3 fixture), so the
|
|
185
|
+
* untagged output renders correctly — at the cost of clipping
|
|
186
|
+
* wide-gamut colours to sRGB.
|
|
187
|
+
* @default false
|
|
188
|
+
*/
|
|
189
|
+
stripMetadata?: boolean;
|
|
190
|
+
/** Invoked (and awaited) with each produced/cache-hit VariantMetadata record. */
|
|
191
|
+
onMetadata?: (record: VariantMetadata) => void | Promise<void>;
|
|
192
|
+
/** Invoked (and awaited) once per failing file. The engine writes no report anywhere. */
|
|
193
|
+
onError?: (report: ProcessFailure) => void | Promise<void>;
|
|
194
|
+
}
|
|
195
|
+
export interface ProcessImagesConfig extends ProcessOneConfig {
|
|
196
|
+
/** Directory scanned for source images. Mutually usable with `files`. */
|
|
197
|
+
inputDir?: string;
|
|
198
|
+
/** Explicit list of source file paths, instead of (or in addition to) scanning inputDir. */
|
|
199
|
+
files?: string[];
|
|
200
|
+
/** Max images processed concurrently. @default 4 */
|
|
201
|
+
concurrency?: number;
|
|
202
|
+
/**
|
|
203
|
+
* Remove output slug directories that no longer correspond to any input.
|
|
204
|
+
* Opt-in, and only ever touches directories directly under `outputDir`.
|
|
205
|
+
* @default false
|
|
206
|
+
*/
|
|
207
|
+
cleanupOrphans?: boolean;
|
|
208
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@takazudo/zudo-image-tweaker",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "sharp-based image-tweaking toolkit: variants, HEIF conversion, OGP cards, byte-budget encoding, square crops, product-photo background removal, calibration, compositing, blurhash, EXIF, and browser upload prep.",
|
|
5
|
+
"private": false,
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"author": "Takeshi Takatsudo <takazudo@gmail.com> (https://github.com/Takazudo)",
|
|
9
|
+
"publishConfig": {
|
|
10
|
+
"access": "public"
|
|
11
|
+
},
|
|
12
|
+
"sideEffects": false,
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git+https://github.com/zudolab/zudo-image-tweaker.git",
|
|
16
|
+
"directory": "packages/zit"
|
|
17
|
+
},
|
|
18
|
+
"homepage": "https://github.com/zudolab/zudo-image-tweaker",
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/zudolab/zudo-image-tweaker/issues"
|
|
21
|
+
},
|
|
22
|
+
"main": "./dist/index.js",
|
|
23
|
+
"types": "./dist/index.d.ts",
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"import": "./dist/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./variants": {
|
|
30
|
+
"types": "./dist/variants/index.d.ts",
|
|
31
|
+
"import": "./dist/variants/index.js"
|
|
32
|
+
},
|
|
33
|
+
"./heif": {
|
|
34
|
+
"types": "./dist/heif/index.d.ts",
|
|
35
|
+
"import": "./dist/heif/index.js"
|
|
36
|
+
},
|
|
37
|
+
"./ogp": {
|
|
38
|
+
"types": "./dist/ogp/index.d.ts",
|
|
39
|
+
"import": "./dist/ogp/index.js"
|
|
40
|
+
},
|
|
41
|
+
"./budget": {
|
|
42
|
+
"types": "./dist/budget/index.d.ts",
|
|
43
|
+
"import": "./dist/budget/index.js"
|
|
44
|
+
},
|
|
45
|
+
"./square": {
|
|
46
|
+
"types": "./dist/square/index.d.ts",
|
|
47
|
+
"import": "./dist/square/index.js"
|
|
48
|
+
},
|
|
49
|
+
"./product-photo": {
|
|
50
|
+
"types": "./dist/product-photo/index.d.ts",
|
|
51
|
+
"import": "./dist/product-photo/index.js"
|
|
52
|
+
},
|
|
53
|
+
"./calibrate": {
|
|
54
|
+
"types": "./dist/calibrate/index.d.ts",
|
|
55
|
+
"import": "./dist/calibrate/index.js"
|
|
56
|
+
},
|
|
57
|
+
"./composite": {
|
|
58
|
+
"types": "./dist/composite/index.d.ts",
|
|
59
|
+
"import": "./dist/composite/index.js"
|
|
60
|
+
},
|
|
61
|
+
"./blurhash": {
|
|
62
|
+
"types": "./dist/blurhash/index.d.ts",
|
|
63
|
+
"import": "./dist/blurhash/index.js"
|
|
64
|
+
},
|
|
65
|
+
"./exif": {
|
|
66
|
+
"types": "./dist/exif/index.d.ts",
|
|
67
|
+
"import": "./dist/exif/index.js"
|
|
68
|
+
},
|
|
69
|
+
"./browser": {
|
|
70
|
+
"types": "./dist/browser/index.d.ts",
|
|
71
|
+
"import": "./dist/browser/index.js"
|
|
72
|
+
},
|
|
73
|
+
"./package.json": "./package.json"
|
|
74
|
+
},
|
|
75
|
+
"files": [
|
|
76
|
+
"dist",
|
|
77
|
+
"README.md",
|
|
78
|
+
"CHANGELOG.md",
|
|
79
|
+
"LICENSE"
|
|
80
|
+
],
|
|
81
|
+
"engines": {
|
|
82
|
+
"node": ">=22.12.0",
|
|
83
|
+
"pnpm": ">=11.0.0"
|
|
84
|
+
},
|
|
85
|
+
"scripts": {
|
|
86
|
+
"build": "vite build && tsc -p tsconfig.build.json",
|
|
87
|
+
"prepublishOnly": "pnpm build",
|
|
88
|
+
"test": "vitest run",
|
|
89
|
+
"test:watch": "vitest",
|
|
90
|
+
"typecheck": "tsc --noEmit"
|
|
91
|
+
},
|
|
92
|
+
"dependencies": {
|
|
93
|
+
"sharp": "^0.35.3",
|
|
94
|
+
"blurhash": "^2.0.5",
|
|
95
|
+
"xxhash-wasm": "^1.1.0",
|
|
96
|
+
"heic-decode": "^2.1.0"
|
|
97
|
+
},
|
|
98
|
+
"peerDependencies": {
|
|
99
|
+
"@imgly/background-removal-node": "^1.4.5",
|
|
100
|
+
"exifr": "^7.1.3",
|
|
101
|
+
"heic2any": "^0.0.4"
|
|
102
|
+
},
|
|
103
|
+
"peerDependenciesMeta": {
|
|
104
|
+
"@imgly/background-removal-node": {
|
|
105
|
+
"optional": true
|
|
106
|
+
},
|
|
107
|
+
"exifr": {
|
|
108
|
+
"optional": true
|
|
109
|
+
},
|
|
110
|
+
"heic2any": {
|
|
111
|
+
"optional": true
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
"devDependencies": {
|
|
115
|
+
"@arethetypeswrong/cli": "0.18.5",
|
|
116
|
+
"@imgly/background-removal-node": "^1.4.5",
|
|
117
|
+
"@types/node": "^22.0.0",
|
|
118
|
+
"exifr": "^7.1.3",
|
|
119
|
+
"heic2any": "^0.0.4",
|
|
120
|
+
"jsdom": "^25.0.0",
|
|
121
|
+
"publint": "0.3.21",
|
|
122
|
+
"typescript": "^5.6.0",
|
|
123
|
+
"vite": "^7.3.2",
|
|
124
|
+
"vitest": "^4.1.4"
|
|
125
|
+
}
|
|
126
|
+
}
|