@thi.ng/imago 0.1.0 → 0.2.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 +9 -1
- package/README.md +32 -1
- package/api.d.ts +17 -1
- package/package.json +7 -7
- package/path.d.ts +18 -6
- package/path.js +34 -4
- package/proc.d.ts +5 -1
- package/proc.js +15 -10
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
- **Last updated**: 2024-02-
|
|
3
|
+
- **Last updated**: 2024-02-22T23:15:26Z
|
|
4
4
|
- **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
|
|
5
5
|
|
|
6
6
|
All notable changes to this project will be documented in this file.
|
|
@@ -9,6 +9,14 @@ See [Conventional Commits](https://conventionalcommits.org/) for commit guidelin
|
|
|
9
9
|
**Note:** Unlisted _patch_ versions only involve non-code or otherwise excluded changes
|
|
10
10
|
and/or version bumps of transitive dependencies.
|
|
11
11
|
|
|
12
|
+
## [0.2.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/imago@0.2.0) (2024-02-22)
|
|
13
|
+
|
|
14
|
+
#### 🚀 Features
|
|
15
|
+
|
|
16
|
+
- add support for custom path part replacements ([b0419e1](https://github.com/thi-ng/umbrella/commit/b0419e1))
|
|
17
|
+
- add more path part replacements ([9f84a8a](https://github.com/thi-ng/umbrella/commit/9f84a8a))
|
|
18
|
+
- collect all output paths, update processImage() result ([a3ca52f](https://github.com/thi-ng/umbrella/commit/a3ca52f))
|
|
19
|
+
|
|
12
20
|
## [0.1.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/imago@0.1.0) (2024-02-22)
|
|
13
21
|
|
|
14
22
|
#### 🚀 Features
|
package/README.md
CHANGED
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
- [hsbl](#hsbl)
|
|
43
43
|
- [nest](#nest)
|
|
44
44
|
- [output](#output)
|
|
45
|
+
- [Templated output paths](#templated-output-paths)
|
|
45
46
|
- [resize](#resize)
|
|
46
47
|
- [rotate](#rotate)
|
|
47
48
|
- [Status](#status)
|
|
@@ -219,6 +220,36 @@ File output in any of these formats:
|
|
|
219
220
|
- tiff
|
|
220
221
|
- webp
|
|
221
222
|
|
|
223
|
+
#### Templated output paths
|
|
224
|
+
|
|
225
|
+
Output paths can contain `{id}`-templated parts which will be replaced/expanded.
|
|
226
|
+
The following built-in IDs are supported and custom IDs will be looked up via
|
|
227
|
+
the
|
|
228
|
+
[pathParts](https://docs.thi.ng/umbrella/imago/interfaces/ImgProcOpts.html#pathParts)
|
|
229
|
+
options provided to
|
|
230
|
+
[processImage()](https://docs.thi.ng/umbrella/imago/functions/processImage.html).
|
|
231
|
+
Any others will remain as is. Custom IDs take precedence over built-in ones.
|
|
232
|
+
|
|
233
|
+
- `name`: original base filename (w/o ext)
|
|
234
|
+
- `sha1`/`sha224`/`sha256`/`sha384`/`sha512`: truncated hash of output (8 chars)
|
|
235
|
+
- `w`: current image width
|
|
236
|
+
- `h`: current image height
|
|
237
|
+
- `date`: yyyyMMdd date format, e.g. 20240223
|
|
238
|
+
- `time`: HHmmss time format, e.g. 234459
|
|
239
|
+
- `year`: 4-digit year
|
|
240
|
+
- `month`: 2-digit month
|
|
241
|
+
- `week`: 2-digit week
|
|
242
|
+
- `day`: 2-digit day in month
|
|
243
|
+
- `hour`: 2-digit hour (24h system)
|
|
244
|
+
- `minute`: 2-digit minute
|
|
245
|
+
- `second`: 2-digit second
|
|
246
|
+
|
|
247
|
+
Output paths can contain sub-directories which will be automatically created
|
|
248
|
+
(relative to the [configured output
|
|
249
|
+
dir](https://docs.thi.ng/umbrella/imago/interfaces/ImgProcOpts.html#outDir)).
|
|
250
|
+
For example, the path template `{year}/{month}/{day}/{name}-{sha1}.jpg` might
|
|
251
|
+
get replaced to: `2024/02/22/test-123cafe4.jpg`...
|
|
252
|
+
|
|
222
253
|
### resize
|
|
223
254
|
|
|
224
255
|
Resizing image
|
|
@@ -250,7 +281,7 @@ For Node.js REPL:
|
|
|
250
281
|
const imago = await import("@thi.ng/imago");
|
|
251
282
|
```
|
|
252
283
|
|
|
253
|
-
Package sizes (brotli'd, pre-treeshake): ESM: 3.
|
|
284
|
+
Package sizes (brotli'd, pre-treeshake): ESM: 3.29 KB
|
|
254
285
|
|
|
255
286
|
## Dependencies
|
|
256
287
|
|
package/api.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import type { Fn3, Keys, TypedArray } from "@thi.ng/api";
|
|
2
3
|
import type { ILogger } from "@thi.ng/logger";
|
|
3
4
|
import type { AvifOptions, Blend, Exif, ExtendWith, FitEnum, GifOptions, Jp2Options, JpegOptions, JxlOptions, KernelEnum, Metadata, PngOptions, TiffOptions, TileOptions, WebpOptions } from "sharp";
|
|
4
5
|
export type Gravity = "c" | "e" | "n" | "ne" | "nw" | "s" | "se" | "sw" | "w";
|
|
@@ -147,6 +148,17 @@ export interface ImgProcOpts {
|
|
|
147
148
|
* Base directory for {@link output} steps
|
|
148
149
|
*/
|
|
149
150
|
outDir: string;
|
|
151
|
+
/**
|
|
152
|
+
* An object with custom output path replacements for {@link formatPath}. If
|
|
153
|
+
* a given replacement value is a function, it will be called with the
|
|
154
|
+
* current {@link ImgProcCtx}, the current {@link OutputSpec} (e.g. to
|
|
155
|
+
* obtain configured options) and the already serialized image as buffer.
|
|
156
|
+
*
|
|
157
|
+
* @remarks
|
|
158
|
+
* Replacement IDs in this object will take precedence over built-in
|
|
159
|
+
* replacement IDs, e.g. allowing to override `name`, `date` etc.
|
|
160
|
+
*/
|
|
161
|
+
pathParts: Record<string, Fn3<ImgProcCtx, OutputSpec, Buffer | TypedArray, string> | string>;
|
|
150
162
|
}
|
|
151
163
|
export interface ImgProcCtx {
|
|
152
164
|
path?: string;
|
|
@@ -155,6 +167,10 @@ export interface ImgProcCtx {
|
|
|
155
167
|
meta: Metadata;
|
|
156
168
|
logger: ILogger;
|
|
157
169
|
opts: Partial<ImgProcOpts>;
|
|
170
|
+
/**
|
|
171
|
+
* Paths of all exported images.
|
|
172
|
+
*/
|
|
173
|
+
outputs: string[];
|
|
158
174
|
}
|
|
159
175
|
export declare const GRAVITY_POSITION: Record<Gravity, string>;
|
|
160
176
|
export declare const GRAVITY_MAP: Record<Gravity, string>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/imago",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "JSON & API-based declarative and extensible image processing trees/pipelines",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -37,18 +37,18 @@
|
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@thi.ng/api": "^8.9.25",
|
|
39
39
|
"@thi.ng/checks": "^3.5.0",
|
|
40
|
-
"@thi.ng/date": "^2.
|
|
40
|
+
"@thi.ng/date": "^2.7.0",
|
|
41
41
|
"@thi.ng/defmulti": "^3.0.25",
|
|
42
42
|
"@thi.ng/errors": "^2.4.18",
|
|
43
|
-
"@thi.ng/file-io": "^1.3.
|
|
43
|
+
"@thi.ng/file-io": "^1.3.3",
|
|
44
44
|
"@thi.ng/logger": "^3.0.2",
|
|
45
|
-
"@thi.ng/pixel": "^6.1.
|
|
46
|
-
"@thi.ng/pixel-dither": "^1.1.
|
|
45
|
+
"@thi.ng/pixel": "^6.1.11",
|
|
46
|
+
"@thi.ng/pixel-dither": "^1.1.109",
|
|
47
47
|
"sharp": "^0.33.2"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@microsoft/api-extractor": "^7.40.1",
|
|
51
|
-
"@thi.ng/vectors": "^7.10.
|
|
51
|
+
"@thi.ng/vectors": "^7.10.11",
|
|
52
52
|
"esbuild": "^0.20.0",
|
|
53
53
|
"rimraf": "^5.0.5",
|
|
54
54
|
"typedoc": "^0.25.7",
|
|
@@ -121,5 +121,5 @@
|
|
|
121
121
|
"status": "alpha",
|
|
122
122
|
"year": 2024
|
|
123
123
|
},
|
|
124
|
-
"gitHead": "
|
|
124
|
+
"gitHead": "16f2b92b5410bd35dcde6c2971c8e62783ebc472\n"
|
|
125
125
|
}
|
package/path.d.ts
CHANGED
|
@@ -1,22 +1,34 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import type { TypedArray } from "@thi.ng/api";
|
|
3
|
-
import type { ImgProcCtx } from "./api.js";
|
|
3
|
+
import type { ImgProcCtx, OutputSpec } from "./api.js";
|
|
4
4
|
/**
|
|
5
5
|
* Expands/replaces all `{xyz}`-templated identifiers in given file path.
|
|
6
6
|
*
|
|
7
7
|
* @remarks
|
|
8
|
-
* The following IDs are supported
|
|
8
|
+
* The following built-in IDs are supported and custom IDs will be looked up via
|
|
9
|
+
* the {@link ImgProcOpts.pathParts} options provided to {@link processImage}.
|
|
10
|
+
* Any others will remain as is. Custom IDs take precedence over built-in ones.
|
|
9
11
|
*
|
|
10
|
-
* - date: yyyyMMdd
|
|
11
|
-
* - time: HHmmss
|
|
12
12
|
* - name: original base filename (w/o ext)
|
|
13
13
|
* - sha1/224/256/384/512: truncated hash of output
|
|
14
14
|
* - w: current width
|
|
15
15
|
* - h: current height
|
|
16
|
+
* - date: yyyyMMdd
|
|
17
|
+
* - time: HHmmss
|
|
18
|
+
* - year: 4-digit year
|
|
19
|
+
* - month: 2-digit month
|
|
20
|
+
* - week: 2-digit week
|
|
21
|
+
* - day: 2-digit day in month
|
|
22
|
+
* - hour: 2-digit hour (24h system)
|
|
23
|
+
* - minute: 2-digit minute
|
|
24
|
+
* - second: 2-digit second
|
|
25
|
+
*
|
|
26
|
+
* All date/time related values will be in UTC.
|
|
16
27
|
*
|
|
17
28
|
* @param path
|
|
18
|
-
* @param buf
|
|
19
29
|
* @param ctx
|
|
30
|
+
* @param spec
|
|
31
|
+
* @param buf
|
|
20
32
|
*/
|
|
21
|
-
export declare const formatPath: (path: string, buf: Buffer | TypedArray
|
|
33
|
+
export declare const formatPath: (path: string, ctx: ImgProcCtx, spec: OutputSpec, buf: Buffer | TypedArray) => string;
|
|
22
34
|
//# sourceMappingURL=path.d.ts.map
|
package/path.js
CHANGED
|
@@ -1,8 +1,24 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isFunction } from "@thi.ng/checks";
|
|
2
|
+
import {
|
|
3
|
+
FMT_HH,
|
|
4
|
+
FMT_HHmmss_ALT,
|
|
5
|
+
FMT_MM,
|
|
6
|
+
FMT_dd,
|
|
7
|
+
FMT_mm,
|
|
8
|
+
FMT_ss,
|
|
9
|
+
FMT_ww,
|
|
10
|
+
FMT_yyyy,
|
|
11
|
+
FMT_yyyyMMdd_ALT
|
|
12
|
+
} from "@thi.ng/date";
|
|
2
13
|
import { illegalArgs as unsupported } from "@thi.ng/errors";
|
|
3
14
|
import { createHash } from "node:crypto";
|
|
4
15
|
import { basename } from "node:path";
|
|
5
|
-
const
|
|
16
|
+
const _ = void 0;
|
|
17
|
+
const formatPath = (path, ctx, spec, buf) => path.replace(/\{(\w+)\}/g, (match, id) => {
|
|
18
|
+
const custom = ctx.opts.pathParts?.[id];
|
|
19
|
+
if (custom != null) {
|
|
20
|
+
return isFunction(custom) ? custom(ctx, spec, buf) : custom;
|
|
21
|
+
}
|
|
6
22
|
switch (id) {
|
|
7
23
|
case "name": {
|
|
8
24
|
!path && unsupported(
|
|
@@ -23,9 +39,23 @@ const formatPath = (path, buf, ctx) => path.replace(/\{(\w+)\}/g, (match, id) =>
|
|
|
23
39
|
case "h":
|
|
24
40
|
return String(ctx.size[1]);
|
|
25
41
|
case "date":
|
|
26
|
-
return FMT_yyyyMMdd_ALT();
|
|
42
|
+
return FMT_yyyyMMdd_ALT(_, true);
|
|
27
43
|
case "time":
|
|
28
|
-
return FMT_HHmmss_ALT();
|
|
44
|
+
return FMT_HHmmss_ALT(_, true);
|
|
45
|
+
case "year":
|
|
46
|
+
return FMT_yyyy(_, true);
|
|
47
|
+
case "month":
|
|
48
|
+
return FMT_MM(_, true);
|
|
49
|
+
case "week":
|
|
50
|
+
return FMT_ww(_, true);
|
|
51
|
+
case "day":
|
|
52
|
+
return FMT_dd(_, true);
|
|
53
|
+
case "hour":
|
|
54
|
+
return FMT_HH(_, true);
|
|
55
|
+
case "minute":
|
|
56
|
+
return FMT_mm(_, true);
|
|
57
|
+
case "second":
|
|
58
|
+
return FMT_ss(_, true);
|
|
29
59
|
}
|
|
30
60
|
return match;
|
|
31
61
|
});
|
package/proc.d.ts
CHANGED
|
@@ -2,7 +2,11 @@
|
|
|
2
2
|
import sharp, { type Sharp } from "sharp";
|
|
3
3
|
import { type CompLayer, type ImgProcCtx, type ImgProcOpts, type ProcSpec } from "./api.js";
|
|
4
4
|
export declare const LOGGER: import("@thi.ng/logger").ProxyLogger;
|
|
5
|
-
export declare const processImage: (src: string | Buffer | Sharp, procs: ProcSpec[], opts?: Partial<ImgProcOpts>, parentCtx?: ImgProcCtx) => Promise<
|
|
5
|
+
export declare const processImage: (src: string | Buffer | Sharp, procs: ProcSpec[], opts?: Partial<ImgProcOpts>, parentCtx?: ImgProcCtx) => Promise<{
|
|
6
|
+
img: sharp.Sharp;
|
|
7
|
+
meta: sharp.Metadata;
|
|
8
|
+
outputs: string[];
|
|
9
|
+
}>;
|
|
6
10
|
/**
|
|
7
11
|
* Extensible polymorphic function performing a single image processing step.
|
|
8
12
|
*
|
package/proc.js
CHANGED
|
@@ -51,7 +51,8 @@ const processImage = async (src, procs, opts = {}, parentCtx) => {
|
|
|
51
51
|
ensureSize(meta);
|
|
52
52
|
const ctx = {
|
|
53
53
|
path: isString(src) ? src : parentCtx?.path,
|
|
54
|
-
|
|
54
|
+
outputs: parentCtx ? parentCtx.outputs : [],
|
|
55
|
+
logger: opts.logger || LOGGER,
|
|
55
56
|
size: [meta.width, meta.height],
|
|
56
57
|
channels: meta.channels,
|
|
57
58
|
meta,
|
|
@@ -76,7 +77,7 @@ const processImage = async (src, procs, opts = {}, parentCtx) => {
|
|
|
76
77
|
}
|
|
77
78
|
});
|
|
78
79
|
}
|
|
79
|
-
return img;
|
|
80
|
+
return { img, meta, outputs: ctx.outputs };
|
|
80
81
|
};
|
|
81
82
|
const process = defmulti(
|
|
82
83
|
(spec) => spec.type,
|
|
@@ -227,11 +228,15 @@ const process = defmulti(
|
|
|
227
228
|
if (alpha)
|
|
228
229
|
output = output.ensureAlpha();
|
|
229
230
|
const { data, info } = await output.raw().toBuffer({ resolveWithObject: true });
|
|
230
|
-
const
|
|
231
|
-
|
|
231
|
+
const path2 = join(
|
|
232
|
+
outDir,
|
|
233
|
+
formatPath(opts.path, ctx, spec, data)
|
|
234
|
+
);
|
|
235
|
+
writeFile(path2, data, null, ctx.logger);
|
|
236
|
+
ctx.outputs.push(path2);
|
|
232
237
|
if (meta) {
|
|
233
238
|
writeJSON(
|
|
234
|
-
|
|
239
|
+
path2 + ".meta.json",
|
|
235
240
|
info,
|
|
236
241
|
void 0,
|
|
237
242
|
void 0,
|
|
@@ -281,12 +286,12 @@ const process = defmulti(
|
|
|
281
286
|
if (format)
|
|
282
287
|
output = output.toFormat(format);
|
|
283
288
|
const result = await output.toBuffer();
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
result
|
|
287
|
-
null,
|
|
288
|
-
ctx.logger
|
|
289
|
+
const path = join(
|
|
290
|
+
outDir,
|
|
291
|
+
formatPath(opts.path, ctx, spec, result)
|
|
289
292
|
);
|
|
293
|
+
writeFile(path, result, null, ctx.logger);
|
|
294
|
+
ctx.outputs.push(path);
|
|
290
295
|
return [input, false];
|
|
291
296
|
},
|
|
292
297
|
resize: async (spec, input, ctx) => {
|