@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.
Files changed (92) hide show
  1. package/build/src/lib/bundler.d.ts +1 -2
  2. package/build/src/lib/bundler.js.map +1 -1
  3. package/build/src/lib/replacement.d.ts +1 -2
  4. package/build/src/lib/replacement.js.map +1 -1
  5. package/build/src/lib/template.d.ts +13 -14
  6. package/build/src/lib/template.js +102 -37
  7. package/build/src/lib/template.js.map +1 -1
  8. package/build/src/lib/types/2d.d.ts +4 -5
  9. package/build/src/lib/types/boundingBox.d.ts +19 -0
  10. package/build/src/lib/types/boundingBox.js +3 -0
  11. package/build/src/lib/types/boundingBox.js.map +1 -0
  12. package/build/src/lib/types/containers.d.ts +13 -27
  13. package/build/src/lib/types/containers.js +3 -2
  14. package/build/src/lib/types/containers.js.map +1 -1
  15. package/build/src/lib/types/css.d.ts +4 -1
  16. package/build/src/lib/types/css.js +6 -3
  17. package/build/src/lib/types/css.js.map +1 -1
  18. package/build/src/lib/types/image.d.ts +17 -38
  19. package/build/src/lib/types/image.js +8 -2
  20. package/build/src/lib/types/image.js.map +1 -1
  21. package/build/src/lib/types/index.d.ts +3 -2
  22. package/build/src/lib/types/index.js +3 -2
  23. package/build/src/lib/types/index.js.map +1 -1
  24. package/build/src/lib/types/layer.d.ts +15 -0
  25. package/build/src/lib/types/layer.js +3 -0
  26. package/build/src/lib/types/layer.js.map +1 -0
  27. package/build/src/lib/types/position.d.ts +21 -0
  28. package/build/src/lib/types/position.js +42 -0
  29. package/build/src/lib/types/position.js.map +1 -0
  30. package/build/src/lib/types/scale.d.ts +9 -1
  31. package/build/src/lib/types/scale.js +2 -0
  32. package/build/src/lib/types/scale.js.map +1 -1
  33. package/build/src/lib/types/size.d.ts +4 -0
  34. package/build/src/lib/types/size.js +3 -0
  35. package/build/src/lib/types/size.js.map +1 -0
  36. package/build/src/lib/types/text.d.ts +29 -33
  37. package/build/src/lib/types/text.js +13 -4
  38. package/build/src/lib/types/text.js.map +1 -1
  39. package/build/src/lib/utils/buildFontString.d.ts +2 -2
  40. package/build/src/lib/utils/buildFontString.js.map +1 -1
  41. package/build/src/lib/utils/canvasToImage.d.ts +1 -1
  42. package/build/src/lib/utils/container.d.ts +4 -4
  43. package/build/src/lib/utils/container.js +52 -46
  44. package/build/src/lib/utils/container.js.map +1 -1
  45. package/build/src/lib/utils/drawBoundingBox.d.ts +1 -2
  46. package/build/src/lib/utils/drawBoundingBox.js +7 -47
  47. package/build/src/lib/utils/drawBoundingBox.js.map +1 -1
  48. package/build/src/lib/utils/htmlToImage.d.ts +3 -0
  49. package/build/src/lib/utils/htmlToImage.js +36 -0
  50. package/build/src/lib/utils/htmlToImage.js.map +1 -0
  51. package/build/src/lib/utils/index.d.ts +2 -1
  52. package/build/src/lib/utils/index.js +2 -1
  53. package/build/src/lib/utils/index.js.map +1 -1
  54. package/build/src/lib/utils/placeImage.d.ts +10 -5
  55. package/build/src/lib/utils/placeImage.js +25 -36
  56. package/build/src/lib/utils/placeImage.js.map +1 -1
  57. package/build/src/lib/utils/renderText.d.ts +3 -2
  58. package/build/src/lib/utils/renderText.js +12 -39
  59. package/build/src/lib/utils/renderText.js.map +1 -1
  60. package/build/src/lib/utils/toPx.d.ts +3 -0
  61. package/build/src/lib/utils/toPx.js +12 -0
  62. package/build/src/lib/utils/toPx.js.map +1 -0
  63. package/build/src/lib/utils/vNodeToImage.d.ts +4 -0
  64. package/build/src/lib/utils/vNodeToImage.js +36 -0
  65. package/build/src/lib/utils/vNodeToImage.js.map +1 -0
  66. package/build/src/test.js +55 -69
  67. package/build/src/test.js.map +1 -1
  68. package/package.json +6 -3
  69. package/roadmap.md +0 -1
  70. package/src/lib/bundler.ts +1 -2
  71. package/src/lib/replacement.ts +1 -2
  72. package/src/lib/template.ts +190 -68
  73. package/src/lib/types/boundingBox.ts +28 -0
  74. package/src/lib/types/containers.ts +55 -60
  75. package/src/lib/types/css.ts +32 -1
  76. package/src/lib/types/image.ts +32 -57
  77. package/src/lib/types/index.ts +3 -2
  78. package/src/lib/types/layer.ts +18 -0
  79. package/src/lib/types/scale.ts +11 -0
  80. package/src/lib/types/size.ts +4 -0
  81. package/src/lib/types/text.ts +47 -56
  82. package/src/lib/utils/buildFontString.ts +2 -2
  83. package/src/lib/utils/container.ts +118 -57
  84. package/src/lib/utils/drawBoundingBox.ts +19 -16
  85. package/src/lib/utils/htmlToImage.ts +24 -0
  86. package/src/lib/utils/index.ts +2 -1
  87. package/src/lib/utils/placeImage.ts +55 -58
  88. package/src/lib/utils/renderText.ts +19 -43
  89. package/src/lib/utils/toPx.ts +11 -0
  90. package/src/lib/types/2d.ts +0 -11
  91. package/src/lib/types/omitArgument.ts +0 -17
  92. package/src/lib/utils/canvasToImage.ts +0 -19
@@ -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 { hboxPackingFn, vboxPackingFn } from './utils/container';
14
- import { DirectionContainerOptions, PackingFn } from './types/containers';
15
- import { BoundingBox } from './types/2d';
16
- import { renderText } from './utils';
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
- return packingFn(this.shadowBackground(), images);
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
- position: BoundingBox,
117
- options?: DirectionContainerOptions,
118
- ): this => this.container(imagesFn, hboxPackingFn(position, options));
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
- position: BoundingBox,
123
- options?: DirectionContainerOptions,
124
- ): this => this.container(imagesFn, vboxPackingFn(position, options));
125
-
126
- image = ({
127
- key,
128
- path,
129
- position,
130
- options,
131
- }: ImageLayerProps<EntryType>): this =>
132
- this.layer(async (entry, { debugMode, width, height }) => {
133
- const imagePath =
134
- path ??
135
- (options?.pathFn ? options.pathFn(entry[key]) : entry[key]);
136
- const image = await this.loadImage(imagePath, options);
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
- position,
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(position, {
147
- width,
148
- height,
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
- loadImage = async (
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 = ({ key, position, options }: TextLayerProps<EntryType>): this =>
171
- this.layer(async (entry, { debugMode, width, height }) => {
172
- const text = entry[key] as string;
173
- const fontFamily =
174
- options?.font?.family ?? this.defaultFontFamily ?? 'Arial';
175
- return renderText(
176
- text,
177
- position,
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
- width,
180
- height,
181
- },
182
- { ...options, font: { ...options?.font, family: fontFamily } },
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
- return Promise.all(
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
- // TODO: Ledger of actions applied to the image like a logging feed
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 { Alignment, ImageType, ScaleMode } from './image';
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 const DEFAULT_CONTAINER_OPTIONS: Required<ContainerOptions> = {
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 ContainerOptions = {
11
- /**
12
- * Setting a non-default value for justify will cause the alignment to be ignored.
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
- // TODO: all required
45
- export const DEFAULT_DIRECTION_CONTAINER_OPTIONS: DirectionContainerOptions = {
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
- * Same as CSS justify-content property
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
- export type GridContainerOptions = ContainerOptions & {
63
- rows?: number;
64
- cols?: number;
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
- * Defines what is considered the main direction of the container.
68
- * -> `rows` - the items would be placed to fill each row before starting the next
69
- * -> `cols` - the items would be placed to fill each col before starting the next
70
- *
71
- * Defaults to `rows`
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
- export type PackingFn = (background: ImageType, images: Array<ImageType>) => Promise<ImageType>;
68
+ export type PackingFn = (
69
+ box: BoundingBox,
70
+ background: ImageType,
71
+ images: Array<ImageType>,
72
+ ) => Promise<ImageType>;
@@ -1 +1,32 @@
1
- export const toPx = (value: number): string => `${value}px`;
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
+ };
@@ -1,66 +1,41 @@
1
1
  import { JimpInstance } from 'jimp';
2
- import { BoundingBox, Point, Size } from './2d';
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 ImageLayerProps<EntryType> = (
7
- | {
8
- key: keyof EntryType;
9
- path?: undefined;
10
- }
11
- | {
12
- key?: undefined;
13
- path: string;
14
- }
15
- ) & {
16
- position: ImagePosition;
17
- options?: ImageLayerOptions;
18
- };
19
-
20
- export type ImageLayerOptions = {
21
- assetsPath?: string;
22
- pathFn?: (path: string) => string;
23
- // TODO:
24
- // processorFn?: (entry: EntryType, image: ImageType) => Promise<ImageType>;
25
- };
26
-
27
- export type ImagePosition = ImageAlignmentProps & ScaleProps & BoundingBox;
28
-
29
- export type ImageAlignmentProps = {
30
- /**
31
- * Overridden by xAlignment and/or yAlignment if provided.
32
- * default `center`
33
- */
34
- alignment?: Alignment;
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
- };
@@ -1,9 +1,10 @@
1
- export * from './2d';
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
+ };
@@ -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';
@@ -0,0 +1,4 @@
1
+ export type Size = {
2
+ width: number;
3
+ height: number;
4
+ };