@hellkite/pipkin 0.5.0 → 0.5.2
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/build/src/lib/bundler.d.ts +1 -2
- package/build/src/lib/bundler.js.map +1 -1
- package/build/src/lib/replacement.d.ts +1 -2
- package/build/src/lib/replacement.js.map +1 -1
- package/build/src/lib/template.d.ts +13 -14
- package/build/src/lib/template.js +102 -37
- package/build/src/lib/template.js.map +1 -1
- package/build/src/lib/types/2d.d.ts +4 -5
- package/build/src/lib/types/boundingBox.d.ts +19 -0
- package/build/src/lib/types/boundingBox.js +3 -0
- package/build/src/lib/types/boundingBox.js.map +1 -0
- package/build/src/lib/types/containers.d.ts +13 -27
- package/build/src/lib/types/containers.js +3 -2
- package/build/src/lib/types/containers.js.map +1 -1
- package/build/src/lib/types/css.d.ts +4 -1
- package/build/src/lib/types/css.js +6 -3
- package/build/src/lib/types/css.js.map +1 -1
- package/build/src/lib/types/image.d.ts +17 -38
- package/build/src/lib/types/image.js +8 -2
- package/build/src/lib/types/image.js.map +1 -1
- package/build/src/lib/types/index.d.ts +3 -2
- package/build/src/lib/types/index.js +3 -2
- package/build/src/lib/types/index.js.map +1 -1
- package/build/src/lib/types/layer.d.ts +15 -0
- package/build/src/lib/types/layer.js +3 -0
- package/build/src/lib/types/layer.js.map +1 -0
- package/build/src/lib/types/position.d.ts +21 -0
- package/build/src/lib/types/position.js +42 -0
- package/build/src/lib/types/position.js.map +1 -0
- package/build/src/lib/types/scale.d.ts +9 -1
- package/build/src/lib/types/scale.js +2 -0
- package/build/src/lib/types/scale.js.map +1 -1
- package/build/src/lib/types/size.d.ts +4 -0
- package/build/src/lib/types/size.js +3 -0
- package/build/src/lib/types/size.js.map +1 -0
- package/build/src/lib/types/text.d.ts +29 -33
- package/build/src/lib/types/text.js +13 -4
- package/build/src/lib/types/text.js.map +1 -1
- package/build/src/lib/utils/buildFontString.d.ts +2 -2
- package/build/src/lib/utils/buildFontString.js.map +1 -1
- package/build/src/lib/utils/canvasToImage.d.ts +1 -1
- package/build/src/lib/utils/container.d.ts +4 -4
- package/build/src/lib/utils/container.js +52 -46
- package/build/src/lib/utils/container.js.map +1 -1
- package/build/src/lib/utils/drawBoundingBox.d.ts +1 -2
- package/build/src/lib/utils/drawBoundingBox.js +7 -47
- package/build/src/lib/utils/drawBoundingBox.js.map +1 -1
- package/build/src/lib/utils/htmlToImage.d.ts +3 -0
- package/build/src/lib/utils/htmlToImage.js +36 -0
- package/build/src/lib/utils/htmlToImage.js.map +1 -0
- package/build/src/lib/utils/index.d.ts +2 -1
- package/build/src/lib/utils/index.js +2 -1
- package/build/src/lib/utils/index.js.map +1 -1
- package/build/src/lib/utils/placeImage.d.ts +10 -5
- package/build/src/lib/utils/placeImage.js +25 -36
- package/build/src/lib/utils/placeImage.js.map +1 -1
- package/build/src/lib/utils/renderText.d.ts +3 -2
- package/build/src/lib/utils/renderText.js +12 -39
- package/build/src/lib/utils/renderText.js.map +1 -1
- package/build/src/lib/utils/toPx.d.ts +3 -0
- package/build/src/lib/utils/toPx.js +12 -0
- package/build/src/lib/utils/toPx.js.map +1 -0
- package/build/src/lib/utils/vNodeToImage.d.ts +4 -0
- package/build/src/lib/utils/vNodeToImage.js +36 -0
- package/build/src/lib/utils/vNodeToImage.js.map +1 -0
- package/build/src/test.js +55 -69
- package/build/src/test.js.map +1 -1
- package/package.json +6 -3
- package/roadmap.md +0 -1
- package/src/lib/bundler.ts +1 -2
- package/src/lib/replacement.ts +1 -2
- package/src/lib/template.ts +190 -68
- package/src/lib/types/boundingBox.ts +28 -0
- package/src/lib/types/containers.ts +55 -60
- package/src/lib/types/css.ts +32 -1
- package/src/lib/types/image.ts +32 -57
- package/src/lib/types/index.ts +3 -2
- package/src/lib/types/layer.ts +18 -0
- package/src/lib/types/scale.ts +11 -0
- package/src/lib/types/size.ts +4 -0
- package/src/lib/types/text.ts +47 -56
- package/src/lib/utils/buildFontString.ts +2 -2
- package/src/lib/utils/container.ts +118 -57
- package/src/lib/utils/drawBoundingBox.ts +19 -16
- package/src/lib/utils/htmlToImage.ts +24 -0
- package/src/lib/utils/index.ts +2 -1
- package/src/lib/utils/placeImage.ts +55 -58
- package/src/lib/utils/renderText.ts +19 -43
- package/src/lib/utils/toPx.ts +11 -0
- package/src/lib/types/2d.ts +0 -11
- package/src/lib/types/omitArgument.ts +0 -17
- package/src/lib/utils/canvasToImage.ts +0 -19
package/src/lib/template.ts
CHANGED
|
@@ -2,18 +2,38 @@ import * as fs from 'fs';
|
|
|
2
2
|
import { parse as parseCsv } from 'papaparse';
|
|
3
3
|
import { Jimp, rgbaToInt } from 'jimp';
|
|
4
4
|
import camelCase from 'lodash.camelcase';
|
|
5
|
-
import { placeImage } from './utils/placeImage';
|
|
6
|
-
import { drawBoundingBox } from './utils/drawBoundingBox';
|
|
7
|
-
import { ImageType, ImageLayerOptions, ImageLayerProps } from './types/image';
|
|
8
|
-
import { TextLayerProps } from './types/text';
|
|
9
|
-
import { RenderOptions } from './types/render';
|
|
10
5
|
import concat from 'lodash.concat';
|
|
11
6
|
import { registerFont } from 'canvas';
|
|
12
7
|
import path from 'path';
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
8
|
+
import {
|
|
9
|
+
drawBoundingBox,
|
|
10
|
+
gridPackingFn,
|
|
11
|
+
hboxPackingFn,
|
|
12
|
+
placeImage,
|
|
13
|
+
renderText,
|
|
14
|
+
vboxPackingFn,
|
|
15
|
+
} from './utils';
|
|
16
|
+
import {
|
|
17
|
+
DirectionContainerOptions,
|
|
18
|
+
ImageLayerOptions,
|
|
19
|
+
ImageRef,
|
|
20
|
+
ImageType,
|
|
21
|
+
PackingFn,
|
|
22
|
+
BoundingBox,
|
|
23
|
+
RenderOptions,
|
|
24
|
+
Size,
|
|
25
|
+
TextLayerOptions,
|
|
26
|
+
TextRef,
|
|
27
|
+
GridContainerOptions,
|
|
28
|
+
DEFAULT_TEXT_LAYER_OPTIONS,
|
|
29
|
+
FontOptions,
|
|
30
|
+
DEFAULT_IMAGE_LAYER_OPTIONS,
|
|
31
|
+
LayerOptions,
|
|
32
|
+
ContainerOptions,
|
|
33
|
+
DEFAULT_CONTAINER_OPTIONS,
|
|
34
|
+
} from './types';
|
|
35
|
+
import merge from 'lodash.merge';
|
|
36
|
+
import { RequiredDeep } from 'type-fest';
|
|
17
37
|
|
|
18
38
|
type RequiredTemplateOptions = {
|
|
19
39
|
height: number;
|
|
@@ -35,15 +55,13 @@ const DEFAULT_TEMPLATE_OPTIONS: RequiredTemplateOptions = {
|
|
|
35
55
|
};
|
|
36
56
|
|
|
37
57
|
export type LayerFnContext = {
|
|
38
|
-
width: number;
|
|
39
|
-
height: number;
|
|
40
58
|
debugMode: boolean;
|
|
41
59
|
};
|
|
42
60
|
|
|
43
61
|
export type LayerFn<EntryType> = (
|
|
44
62
|
entry: EntryType,
|
|
45
63
|
context: LayerFnContext,
|
|
46
|
-
) => Promise<ImageType>;
|
|
64
|
+
) => Promise<ImageType | undefined>;
|
|
47
65
|
|
|
48
66
|
export type TemplateLayerFn<EntryType extends Record<string, string>> = (
|
|
49
67
|
template: Template<EntryType>,
|
|
@@ -90,6 +108,13 @@ export class Template<EntryType extends Record<string, string>> {
|
|
|
90
108
|
});
|
|
91
109
|
}
|
|
92
110
|
|
|
111
|
+
private get backgroundSize(): Size {
|
|
112
|
+
return {
|
|
113
|
+
width: this.background.width,
|
|
114
|
+
height: this.background.height,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
93
118
|
layer(fn: LayerFn<EntryType>): this {
|
|
94
119
|
this.layers.push(fn);
|
|
95
120
|
return this;
|
|
@@ -101,86 +126,137 @@ export class Template<EntryType extends Record<string, string>> {
|
|
|
101
126
|
return template.render(entry);
|
|
102
127
|
});
|
|
103
128
|
|
|
104
|
-
// TODO: logic for rendering debug helpers
|
|
105
129
|
container = (
|
|
106
130
|
imagesFn: (entry: EntryType) => Promise<Array<ImageType>>,
|
|
131
|
+
box: BoundingBox,
|
|
107
132
|
packingFn: PackingFn,
|
|
133
|
+
options?: ContainerOptions<EntryType>,
|
|
108
134
|
): this =>
|
|
109
|
-
this.layer(async (entry: EntryType) => {
|
|
135
|
+
this.layer(async (entry: EntryType, { debugMode }) => {
|
|
136
|
+
const mergedOptions: RequiredDeep<ContainerOptions<EntryType>>= merge(
|
|
137
|
+
{},
|
|
138
|
+
DEFAULT_CONTAINER_OPTIONS,
|
|
139
|
+
options,
|
|
140
|
+
);
|
|
141
|
+
if (this.shouldSkipLayerForEntry(entry, mergedOptions)) {
|
|
142
|
+
return undefined;
|
|
143
|
+
}
|
|
144
|
+
|
|
110
145
|
const images = await imagesFn(entry);
|
|
111
|
-
|
|
146
|
+
const result = await packingFn(
|
|
147
|
+
box,
|
|
148
|
+
this.shadowBackground(),
|
|
149
|
+
images,
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
// debug mode
|
|
153
|
+
if (debugMode) {
|
|
154
|
+
const debugImage = await drawBoundingBox(
|
|
155
|
+
box,
|
|
156
|
+
this.backgroundSize,
|
|
157
|
+
);
|
|
158
|
+
return debugImage.composite(result);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return result;
|
|
112
162
|
});
|
|
113
163
|
|
|
114
164
|
hbox = (
|
|
115
165
|
imagesFn: (entry: EntryType) => Promise<Array<ImageType>>,
|
|
116
|
-
|
|
117
|
-
options?: DirectionContainerOptions
|
|
118
|
-
): this => this.container(imagesFn, hboxPackingFn(
|
|
166
|
+
box: BoundingBox,
|
|
167
|
+
options?: DirectionContainerOptions<EntryType>,
|
|
168
|
+
): this => this.container(imagesFn, box, hboxPackingFn(options), options);
|
|
119
169
|
|
|
120
170
|
vbox = (
|
|
121
171
|
imagesFn: (entry: EntryType) => Promise<Array<ImageType>>,
|
|
122
|
-
|
|
123
|
-
options?: DirectionContainerOptions
|
|
124
|
-
): this => this.container(imagesFn, vboxPackingFn(
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
172
|
+
box: BoundingBox,
|
|
173
|
+
options?: DirectionContainerOptions<EntryType>,
|
|
174
|
+
): this => this.container(imagesFn, box, vboxPackingFn(options), options);
|
|
175
|
+
|
|
176
|
+
grid = (
|
|
177
|
+
imagesFn: (entry: EntryType) => Promise<Array<ImageType>>,
|
|
178
|
+
box: BoundingBox,
|
|
179
|
+
options?: GridContainerOptions<EntryType>,
|
|
180
|
+
): this => this.container(imagesFn, box, gridPackingFn(options), options);
|
|
181
|
+
|
|
182
|
+
image = (
|
|
183
|
+
ref: ImageRef<EntryType>,
|
|
184
|
+
box: BoundingBox,
|
|
185
|
+
options: ImageLayerOptions<EntryType>,
|
|
186
|
+
): this =>
|
|
187
|
+
this.layer(async (entry, { debugMode }) => {
|
|
188
|
+
const mergedOptions: RequiredDeep<ImageLayerOptions<EntryType>>= merge(
|
|
189
|
+
{},
|
|
190
|
+
DEFAULT_IMAGE_LAYER_OPTIONS,
|
|
191
|
+
{ assetsPath: this.defaultAssetsPath },
|
|
192
|
+
options,
|
|
193
|
+
);
|
|
194
|
+
if (this.shouldSkipLayerForEntry(entry, mergedOptions)) {
|
|
195
|
+
return undefined;
|
|
196
|
+
}
|
|
137
197
|
|
|
198
|
+
const image = await this.pathFromImageRef(entry, ref, mergedOptions);
|
|
138
199
|
const result = await placeImage({
|
|
139
|
-
background: this.shadowBackground(),
|
|
140
200
|
image,
|
|
141
|
-
|
|
201
|
+
box,
|
|
202
|
+
backgroundSize: this.backgroundSize,
|
|
203
|
+
options: mergedOptions,
|
|
142
204
|
});
|
|
143
205
|
|
|
144
206
|
// debug mode
|
|
145
207
|
if (debugMode) {
|
|
146
|
-
const debugImage = await drawBoundingBox(
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
208
|
+
const debugImage = await drawBoundingBox(
|
|
209
|
+
box,
|
|
210
|
+
this.backgroundSize,
|
|
211
|
+
);
|
|
150
212
|
return debugImage.composite(result);
|
|
151
213
|
}
|
|
152
214
|
|
|
153
215
|
return result;
|
|
154
216
|
});
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
imagePath: string,
|
|
158
|
-
options?: ImageLayerOptions,
|
|
159
|
-
): Promise<ImageType> => {
|
|
160
|
-
const assetsPath = options?.assetsPath ?? this.defaultAssetsPath;
|
|
161
|
-
const imageCompletePath = assetsPath
|
|
162
|
-
? path.join(assetsPath, imagePath)
|
|
163
|
-
: imagePath;
|
|
164
|
-
const image = (await Jimp.read(
|
|
165
|
-
imageCompletePath,
|
|
166
|
-
)) as unknown as ImageType;
|
|
217
|
+
loadImage = async (imagePath: string | Buffer): Promise<ImageType> => {
|
|
218
|
+
const image = (await Jimp.read(imagePath)) as unknown as ImageType;
|
|
167
219
|
return image;
|
|
168
220
|
};
|
|
169
221
|
|
|
170
|
-
text = (
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
222
|
+
text = (
|
|
223
|
+
ref: TextRef<EntryType>,
|
|
224
|
+
box: BoundingBox,
|
|
225
|
+
options?: TextLayerOptions<EntryType>,
|
|
226
|
+
): this =>
|
|
227
|
+
this.layer(async (entry, { debugMode }) => {
|
|
228
|
+
const mergedOptions = merge(
|
|
229
|
+
{},
|
|
230
|
+
DEFAULT_TEXT_LAYER_OPTIONS,
|
|
178
231
|
{
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
232
|
+
font: {
|
|
233
|
+
family: this.defaultFontFamily,
|
|
234
|
+
},
|
|
235
|
+
} as FontOptions,
|
|
236
|
+
options,
|
|
237
|
+
);
|
|
238
|
+
if (this.shouldSkipLayerForEntry(entry, mergedOptions)) {
|
|
239
|
+
return undefined;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const text = this.textFromTextRef(entry, ref);
|
|
243
|
+
const result = await renderText(
|
|
244
|
+
text,
|
|
245
|
+
box,
|
|
246
|
+
this.backgroundSize,
|
|
247
|
+
mergedOptions,
|
|
183
248
|
);
|
|
249
|
+
|
|
250
|
+
// debug mode
|
|
251
|
+
if (debugMode) {
|
|
252
|
+
const debugImage = await drawBoundingBox(
|
|
253
|
+
box,
|
|
254
|
+
this.backgroundSize,
|
|
255
|
+
);
|
|
256
|
+
return debugImage.composite(result);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return result;
|
|
184
260
|
});
|
|
185
261
|
|
|
186
262
|
font(path: fs.PathLike, name: string): this {
|
|
@@ -196,15 +272,14 @@ export class Template<EntryType extends Record<string, string>> {
|
|
|
196
272
|
}
|
|
197
273
|
|
|
198
274
|
private async renderLayers(entry: EntryType): Promise<Array<ImageType>> {
|
|
199
|
-
|
|
275
|
+
const results = await Promise.all(
|
|
200
276
|
this.layers.map(layerFn =>
|
|
201
277
|
layerFn(entry, {
|
|
202
278
|
debugMode: this.debugMode,
|
|
203
|
-
width: this.background.width,
|
|
204
|
-
height: this.background.height,
|
|
205
279
|
}),
|
|
206
280
|
),
|
|
207
281
|
);
|
|
282
|
+
return results.filter(result => !!result);
|
|
208
283
|
}
|
|
209
284
|
|
|
210
285
|
async render(
|
|
@@ -273,6 +348,53 @@ export class Template<EntryType extends Record<string, string>> {
|
|
|
273
348
|
}
|
|
274
349
|
});
|
|
275
350
|
}
|
|
276
|
-
}
|
|
277
351
|
|
|
278
|
-
|
|
352
|
+
private pathFromImageRef = async (
|
|
353
|
+
entry: EntryType,
|
|
354
|
+
ref: ImageRef<EntryType>,
|
|
355
|
+
options: RequiredDeep<ImageLayerOptions<EntryType>>,
|
|
356
|
+
): Promise<ImageType> => {
|
|
357
|
+
const pathSegments = [];
|
|
358
|
+
if (options.assetsPath) {
|
|
359
|
+
pathSegments.push(options.assetsPath);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
if ('buffer' in ref) {
|
|
363
|
+
return this.loadImage(ref.buffer);
|
|
364
|
+
} else if ('path' in ref) {
|
|
365
|
+
return this.loadImage(path.join(...pathSegments, ref.path));
|
|
366
|
+
} else if ('absolutePath' in ref) {
|
|
367
|
+
return this.loadImage(ref.absolutePath);
|
|
368
|
+
} else if ('key' in ref) {
|
|
369
|
+
const fileName = entry[ref.key];
|
|
370
|
+
return this.loadImage(path.join(...pathSegments, fileName));
|
|
371
|
+
} else if ('pathFn' in ref) {
|
|
372
|
+
const fileName = ref.pathFn(entry);
|
|
373
|
+
return this.loadImage(path.join(...pathSegments, fileName));
|
|
374
|
+
} else {
|
|
375
|
+
throw new Error('Unknown ImageRef variant');
|
|
376
|
+
}
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
private textFromTextRef = (
|
|
380
|
+
entry: EntryType,
|
|
381
|
+
ref: TextRef<EntryType>,
|
|
382
|
+
): string => {
|
|
383
|
+
if ('key' in ref) {
|
|
384
|
+
return entry[ref.key];
|
|
385
|
+
} else if ('text' in ref) {
|
|
386
|
+
return ref.text;
|
|
387
|
+
} else if ('textFn' in ref) {
|
|
388
|
+
return ref.textFn(entry);
|
|
389
|
+
} else {
|
|
390
|
+
throw new Error('Unknown TextRef variant');
|
|
391
|
+
}
|
|
392
|
+
};
|
|
393
|
+
|
|
394
|
+
private shouldSkipLayerForEntry = (entry: EntryType, options: LayerOptions<EntryType>): boolean => {
|
|
395
|
+
if (typeof options.skip === 'function') {
|
|
396
|
+
return options.skip(entry);
|
|
397
|
+
}
|
|
398
|
+
return options.skip ?? false;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export type BoundingBox = (
|
|
2
|
+
| {
|
|
3
|
+
top: number;
|
|
4
|
+
height: number;
|
|
5
|
+
}
|
|
6
|
+
| {
|
|
7
|
+
bottom: number;
|
|
8
|
+
height: number;
|
|
9
|
+
}
|
|
10
|
+
| {
|
|
11
|
+
top: number;
|
|
12
|
+
bottom: number;
|
|
13
|
+
}
|
|
14
|
+
) &
|
|
15
|
+
(
|
|
16
|
+
| {
|
|
17
|
+
left: number;
|
|
18
|
+
width: number;
|
|
19
|
+
}
|
|
20
|
+
| {
|
|
21
|
+
right: number;
|
|
22
|
+
width: number;
|
|
23
|
+
}
|
|
24
|
+
| {
|
|
25
|
+
left: number;
|
|
26
|
+
right: number;
|
|
27
|
+
}
|
|
28
|
+
);
|
|
@@ -1,77 +1,72 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RequiredDeep } from 'type-fest';
|
|
2
|
+
import { BoundingBox } from './boundingBox';
|
|
3
|
+
import { ImageType } from './image';
|
|
4
|
+
import { ScaleMode } from './scale';
|
|
5
|
+
import { LayerOptions } from './layer';
|
|
2
6
|
|
|
3
|
-
export
|
|
7
|
+
export type ContainerOptions<EntryType extends Record<string, string>> =
|
|
8
|
+
LayerOptions<EntryType> & {
|
|
9
|
+
/**
|
|
10
|
+
* This is treated as a minimum length of an unit of space
|
|
11
|
+
* between two items, but it can grow larger than it
|
|
12
|
+
*
|
|
13
|
+
* Defaults to 0
|
|
14
|
+
*/
|
|
15
|
+
gap?: number;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Defaults to `none`
|
|
19
|
+
*/
|
|
20
|
+
scale?: ScaleMode;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const DEFAULT_CONTAINER_OPTIONS: RequiredDeep<
|
|
24
|
+
ContainerOptions<Record<string, string>>
|
|
25
|
+
> = {
|
|
4
26
|
gap: 0,
|
|
5
27
|
justifyContent: 'normal',
|
|
6
28
|
alignItems: 'center',
|
|
7
29
|
scale: 'none',
|
|
30
|
+
skip: false,
|
|
8
31
|
};
|
|
9
32
|
|
|
10
|
-
export type
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
*
|
|
14
|
-
* Defaults to `normal`
|
|
15
|
-
*/
|
|
16
|
-
justifyContent?: ContainerJustifyContent;
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* This is treated as a minimum length of an unit of space
|
|
20
|
-
* between two items, but it can grow larger than it
|
|
21
|
-
*
|
|
22
|
-
* Defaults to 0
|
|
23
|
-
*/
|
|
24
|
-
gap?: number;
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Defines how the items should be placed
|
|
28
|
-
* across the secondary direction of the container
|
|
29
|
-
*
|
|
30
|
-
* Defaults to `center`
|
|
31
|
-
*/
|
|
32
|
-
alignItems?: Alignment;
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Defaults to `none`
|
|
36
|
-
*/
|
|
37
|
-
scale?: ScaleMode;
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
export type DirectionContainerOptions = ContainerOptions & {
|
|
33
|
+
export type DirectionContainerOptions<
|
|
34
|
+
EntryType extends Record<string, string>,
|
|
35
|
+
> = ContainerOptions<EntryType> & {
|
|
41
36
|
reversed?: boolean;
|
|
42
37
|
};
|
|
43
38
|
|
|
44
|
-
|
|
45
|
-
|
|
39
|
+
export const DEFAULT_DIRECTION_CONTAINER_OPTIONS: RequiredDeep<
|
|
40
|
+
DirectionContainerOptions<Record<string, string>>
|
|
41
|
+
> = {
|
|
46
42
|
...DEFAULT_CONTAINER_OPTIONS,
|
|
47
43
|
reversed: false,
|
|
48
|
-
}
|
|
44
|
+
};
|
|
49
45
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
type ContainerJustifyContent =
|
|
54
|
-
| 'flex-start'
|
|
55
|
-
| 'flex-end'
|
|
56
|
-
| 'center'
|
|
57
|
-
| 'space-evenly'
|
|
58
|
-
| 'space-between'
|
|
59
|
-
| 'space-around'
|
|
60
|
-
| 'normal';
|
|
46
|
+
export type GridContainerOptions<EntryType extends Record<string, string>> =
|
|
47
|
+
ContainerOptions<EntryType> & {
|
|
48
|
+
size?: number;
|
|
61
49
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
50
|
+
/**
|
|
51
|
+
* Defines what is considered the main direction of the container.
|
|
52
|
+
* -> `rows` - the items would be placed to fill each row before starting the next
|
|
53
|
+
* -> `cols` - the items would be placed to fill each col before starting the next
|
|
54
|
+
*
|
|
55
|
+
* Defaults to `rows`
|
|
56
|
+
*/
|
|
57
|
+
direction?: 'rows' | 'cols';
|
|
58
|
+
};
|
|
65
59
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
*/
|
|
73
|
-
direction?: 'rows' | 'cols';
|
|
60
|
+
export const DEFAULT_GRID_CONTAINER_OPTIONS: RequiredDeep<
|
|
61
|
+
GridContainerOptions<Record<string, string>>
|
|
62
|
+
> = {
|
|
63
|
+
...DEFAULT_CONTAINER_OPTIONS,
|
|
64
|
+
size: 3,
|
|
65
|
+
direction: 'rows',
|
|
74
66
|
};
|
|
75
67
|
|
|
76
|
-
|
|
77
|
-
|
|
68
|
+
export type PackingFn = (
|
|
69
|
+
box: BoundingBox,
|
|
70
|
+
background: ImageType,
|
|
71
|
+
images: Array<ImageType>,
|
|
72
|
+
) => Promise<ImageType>;
|
package/src/lib/types/css.ts
CHANGED
|
@@ -1 +1,32 @@
|
|
|
1
|
-
|
|
1
|
+
import { ScaleMode } from './scale';
|
|
2
|
+
|
|
3
|
+
export type JustifyContent =
|
|
4
|
+
| 'flex-start'
|
|
5
|
+
| 'flex-end'
|
|
6
|
+
| 'center'
|
|
7
|
+
| 'space-evenly'
|
|
8
|
+
| 'space-between'
|
|
9
|
+
| 'space-around'
|
|
10
|
+
| 'normal';
|
|
11
|
+
|
|
12
|
+
export type AlignItems =
|
|
13
|
+
| 'normal'
|
|
14
|
+
| 'stretch'
|
|
15
|
+
| 'center'
|
|
16
|
+
| 'start'
|
|
17
|
+
| 'end'
|
|
18
|
+
| 'flex-start'
|
|
19
|
+
| 'flex-end'
|
|
20
|
+
| 'self-start'
|
|
21
|
+
| 'self-end'
|
|
22
|
+
| 'baseline'
|
|
23
|
+
| 'first baseline'
|
|
24
|
+
| 'last baseline'
|
|
25
|
+
| 'safe center'
|
|
26
|
+
| 'unsafe center';
|
|
27
|
+
|
|
28
|
+
export const SCALE_MODE_TO_OBJECT_FIT: Record<ScaleMode, string> = {
|
|
29
|
+
'keep-ratio': 'contain',
|
|
30
|
+
stretch: 'fill',
|
|
31
|
+
none: 'none',
|
|
32
|
+
};
|
package/src/lib/types/image.ts
CHANGED
|
@@ -1,66 +1,41 @@
|
|
|
1
1
|
import { JimpInstance } from 'jimp';
|
|
2
|
-
import {
|
|
2
|
+
import { ScaleMode } from './scale';
|
|
3
|
+
import { LayerOptions } from './layer';
|
|
4
|
+
import { RequiredDeep } from 'type-fest';
|
|
3
5
|
|
|
4
6
|
export type ImageType = JimpInstance;
|
|
5
7
|
|
|
6
|
-
export type
|
|
7
|
-
| {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
| {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
export
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* default `center`
|
|
37
|
-
*/
|
|
38
|
-
xAlignment?: Alignment;
|
|
39
|
-
/**
|
|
40
|
-
* default `center`
|
|
41
|
-
*/
|
|
42
|
-
yAlignment?: Alignment;
|
|
8
|
+
export type ImageRef<EntryType extends Record<string, string>> =
|
|
9
|
+
| { buffer: Buffer }
|
|
10
|
+
| { path: string }
|
|
11
|
+
| { absolutePath: string }
|
|
12
|
+
| { key: keyof EntryType }
|
|
13
|
+
| { pathFn: (entry: EntryType) => string };
|
|
14
|
+
|
|
15
|
+
export type ImageLayerOptions<EntryType extends Record<string, string>> =
|
|
16
|
+
LayerOptions<EntryType> & {
|
|
17
|
+
/**
|
|
18
|
+
* Base path for the assets. Overrides the more global property of the template `defaultAssetsPath`.
|
|
19
|
+
*/
|
|
20
|
+
assetsPath?: string;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Defaults to `none`
|
|
24
|
+
*/
|
|
25
|
+
scale?: ScaleMode;
|
|
26
|
+
|
|
27
|
+
// TODO:
|
|
28
|
+
// processorFn?: (entry: EntryType, image: ImageType) => Promise<ImageType>;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const DEFAULT_IMAGE_LAYER_OPTIONS: RequiredDeep<ImageLayerOptions<Record<string, string>>> = {
|
|
32
|
+
justifyContent: 'center',
|
|
33
|
+
alignItems: 'center',
|
|
34
|
+
scale: 'none',
|
|
35
|
+
skip: false,
|
|
36
|
+
assetsPath: ''
|
|
43
37
|
};
|
|
44
38
|
|
|
45
39
|
export type Alignment = 'start' | 'center' | 'end';
|
|
46
40
|
|
|
47
41
|
export const DEFAULT_IMAGE_ALIGNMENT: Alignment = 'center';
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Behavior of the content around a space
|
|
51
|
-
* that is bigger or smaller than necessary
|
|
52
|
-
* -> `none`: no scaling
|
|
53
|
-
* -> `keep-ration`: scale while preserving aspect ration
|
|
54
|
-
* -> `stretch`: scale without preserving aspect ration
|
|
55
|
-
*/
|
|
56
|
-
// TODO: Could be extended with 'x-stretch' and 'y-stretch'
|
|
57
|
-
export type ScaleMode = 'none' | 'keep-ratio' | 'stretch';
|
|
58
|
-
|
|
59
|
-
export const DEFAULT_SCALE_MODE: ScaleMode = 'none';
|
|
60
|
-
|
|
61
|
-
export type ScaleProps = {
|
|
62
|
-
/**
|
|
63
|
-
* Defaults to `none`
|
|
64
|
-
*/
|
|
65
|
-
scale?: ScaleMode;
|
|
66
|
-
};
|
package/src/lib/types/index.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
export * from './
|
|
1
|
+
export * from './size';
|
|
2
2
|
export * from './containers';
|
|
3
3
|
export * from './image';
|
|
4
|
-
export * from './omitArgument';
|
|
5
4
|
export * from './render';
|
|
6
5
|
export * from './replacement';
|
|
7
6
|
export * from './scale';
|
|
8
7
|
export * from './text';
|
|
8
|
+
export * from './boundingBox';
|
|
9
9
|
export * from './css';
|
|
10
|
+
export * from './layer';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { JustifyContent, AlignItems } from "./css";
|
|
2
|
+
|
|
3
|
+
export type LayerOptions<EntryType extends Record<string, string>> = {
|
|
4
|
+
/**
|
|
5
|
+
* default `center`
|
|
6
|
+
*/
|
|
7
|
+
justifyContent?: JustifyContent;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* default `center`
|
|
11
|
+
*/
|
|
12
|
+
alignItems?: AlignItems;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Decides if a layer should be rendered or not for a certain entry
|
|
16
|
+
*/
|
|
17
|
+
skip?: boolean | ((entry: EntryType) => boolean);
|
|
18
|
+
};
|
package/src/lib/types/scale.ts
CHANGED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Behavior of the content around a space
|
|
3
|
+
* that is bigger or smaller than necessary
|
|
4
|
+
* -> `none`: no scaling
|
|
5
|
+
* -> `keep-ration`: scale while preserving aspect ration
|
|
6
|
+
* -> `stretch`: scale without preserving aspect ration
|
|
7
|
+
*/
|
|
8
|
+
// TODO: Could be extended with 'x-stretch' and 'y-stretch'
|
|
9
|
+
export type ScaleMode = 'none' | 'keep-ratio' | 'stretch';
|
|
10
|
+
|
|
11
|
+
export const DEFAULT_SCALE_MODE: ScaleMode = 'none';
|