@hellkite/pipkin 0.5.1 → 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/template.d.ts +10 -8
- package/build/src/lib/template.js +51 -18
- package/build/src/lib/template.js.map +1 -1
- package/build/src/lib/types/containers.d.ts +11 -22
- package/build/src/lib/types/containers.js +3 -1
- package/build/src/lib/types/containers.js.map +1 -1
- package/build/src/lib/types/image.d.ts +5 -12
- package/build/src/lib/types/image.js +2 -0
- package/build/src/lib/types/image.js.map +1 -1
- package/build/src/lib/types/index.d.ts +1 -0
- package/build/src/lib/types/index.js +1 -0
- 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/text.d.ts +23 -27
- 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/container.d.ts +4 -3
- package/build/src/lib/utils/container.js +41 -4
- package/build/src/lib/utils/container.js.map +1 -1
- package/build/src/lib/utils/drawBoundingBox.js.map +1 -1
- package/build/src/lib/utils/htmlToImage.js +1 -1
- package/build/src/lib/utils/htmlToImage.js.map +1 -1
- package/build/src/lib/utils/placeImage.d.ts +4 -3
- package/build/src/lib/utils/placeImage.js +22 -28
- package/build/src/lib/utils/placeImage.js.map +1 -1
- package/build/src/lib/utils/renderText.d.ts +2 -1
- package/build/src/lib/utils/renderText.js +8 -10
- package/build/src/lib/utils/renderText.js.map +1 -1
- package/build/src/test.js +14 -5
- package/build/src/test.js.map +1 -1
- package/package.json +4 -1
- package/roadmap.md +0 -1
- package/src/lib/template.ts +127 -29
- package/src/lib/types/containers.ts +52 -46
- package/src/lib/types/image.ts +21 -29
- package/src/lib/types/index.ts +1 -0
- package/src/lib/types/layer.ts +18 -0
- package/src/lib/types/text.ts +44 -49
- package/src/lib/utils/buildFontString.ts +2 -2
- package/src/lib/utils/container.ts +102 -9
- package/src/lib/utils/drawBoundingBox.ts +12 -9
- package/src/lib/utils/htmlToImage.ts +1 -1
- package/src/lib/utils/placeImage.ts +8 -10
- package/src/lib/utils/renderText.ts +13 -20
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { ImageLayerOptions, ImageType, BoundingBox } from '../types';
|
|
2
|
-
|
|
2
|
+
import { RequiredDeep } from 'type-fest';
|
|
3
|
+
type PlaceImageProps<EntryType extends Record<string, string>> = {
|
|
3
4
|
image: ImageType;
|
|
4
5
|
box: BoundingBox;
|
|
5
6
|
backgroundSize: {
|
|
6
7
|
width: number;
|
|
7
8
|
height: number;
|
|
8
9
|
};
|
|
9
|
-
options: ImageLayerOptions
|
|
10
|
+
options: RequiredDeep<ImageLayerOptions<EntryType>>;
|
|
10
11
|
};
|
|
11
|
-
export declare
|
|
12
|
+
export declare const placeImage: <EntryType extends Record<string, string>>({ image, box, backgroundSize, options, }: PlaceImageProps<EntryType>) => Promise<ImageType>;
|
|
12
13
|
export {};
|
|
@@ -8,37 +8,31 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
-
};
|
|
14
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.placeImage =
|
|
12
|
+
exports.placeImage = void 0;
|
|
16
13
|
const virtual_dom_1 = require("virtual-dom");
|
|
17
14
|
const toPx_1 = require("./toPx");
|
|
18
15
|
const types_1 = require("../types");
|
|
19
|
-
const lodash_merge_1 = __importDefault(require("lodash.merge"));
|
|
20
16
|
const htmlToImage_1 = require("./htmlToImage");
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
});
|
|
43
|
-
}
|
|
17
|
+
const placeImage = (_a) => __awaiter(void 0, [_a], void 0, function* ({ image, box, backgroundSize, options, }) {
|
|
18
|
+
const imageBase64 = yield image.getBase64('image/png');
|
|
19
|
+
const objectFit = types_1.SCALE_MODE_TO_OBJECT_FIT[options.scale];
|
|
20
|
+
const document = (0, virtual_dom_1.h)('div', {
|
|
21
|
+
style: Object.assign({ display: 'flex', position: 'absolute', scale: 1, justifyContent: options.justifyContent, alignItems: options.alignItems }, (0, toPx_1.boundingBoxToPx)(box)),
|
|
22
|
+
}, [
|
|
23
|
+
(0, virtual_dom_1.h)('img', {
|
|
24
|
+
style: {
|
|
25
|
+
objectFit,
|
|
26
|
+
flex: '1 1 auto',
|
|
27
|
+
minWidth: 0,
|
|
28
|
+
minHeight: 0,
|
|
29
|
+
maxWidth: '100%',
|
|
30
|
+
maxHeight: '100%',
|
|
31
|
+
},
|
|
32
|
+
src: imageBase64,
|
|
33
|
+
}, []),
|
|
34
|
+
]);
|
|
35
|
+
return (0, htmlToImage_1.htmlToImage)(document, backgroundSize);
|
|
36
|
+
});
|
|
37
|
+
exports.placeImage = placeImage;
|
|
44
38
|
//# sourceMappingURL=placeImage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"placeImage.js","sourceRoot":"","sources":["../../../../src/lib/utils/placeImage.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"placeImage.js","sourceRoot":"","sources":["../../../../src/lib/utils/placeImage.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6CAAgC;AAChC,iCAAyC;AACzC,oCAKkB;AAClB,+CAA4C;AAUrC,MAAM,UAAU,GAAG,KAKyB,EAAE,4CALsB,EACvE,KAAK,EACL,GAAG,EACH,cAAc,EACd,OAAO,GACkB;IACzB,MAAM,WAAW,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IACvD,MAAM,SAAS,GAAG,gCAAwB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAE1D,MAAM,QAAQ,GAAG,IAAA,eAAC,EACd,KAAK,EACL;QACI,KAAK,kBACD,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,UAAU,EACpB,KAAK,EAAE,CAAC,EAER,cAAc,EAAE,OAAO,CAAC,cAAc,EACtC,UAAU,EAAE,OAAO,CAAC,UAAU,IAE3B,IAAA,sBAAe,EAAC,GAAG,CAAC,CAC1B;KACJ,EACD;QACI,IAAA,eAAC,EACG,KAAK,EACL;YACI,KAAK,EAAE;gBACH,SAAS;gBACT,IAAI,EAAE,UAAU;gBAChB,QAAQ,EAAE,CAAC;gBACX,SAAS,EAAE,CAAC;gBACZ,QAAQ,EAAE,MAAM;gBAChB,SAAS,EAAE,MAAM;aACpB;YACD,GAAG,EAAE,WAAW;SACnB,EACD,EAAE,CACL;KACJ,CACJ,CAAC;IAEF,OAAO,IAAA,yBAAW,EAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;AACjD,CAAC,CAAA,CAAA;AA3CY,QAAA,UAAU,cA2CtB"}
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
import { ImageType, BoundingBox, Size, TextLayerOptions } from '../types';
|
|
2
|
-
|
|
2
|
+
import { RequiredDeep } from 'type-fest';
|
|
3
|
+
export declare const renderText: <EntryType extends Record<string, string>>(text: string, box: BoundingBox, backgroundSize: Size, options: RequiredDeep<TextLayerOptions<EntryType>>) => Promise<ImageType>;
|
|
@@ -11,13 +11,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.renderText = void 0;
|
|
13
13
|
const virtual_dom_1 = require("virtual-dom");
|
|
14
|
-
const types_1 = require("../types");
|
|
15
14
|
const toPx_1 = require("./toPx");
|
|
16
15
|
const htmlToImage_1 = require("./htmlToImage");
|
|
17
16
|
const renderText = (text, box, backgroundSize, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
18
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
19
17
|
let textChildren = [text];
|
|
20
|
-
for (const [word, image] of Object.entries(
|
|
18
|
+
for (const [word, image] of Object.entries(options.replacement)) {
|
|
21
19
|
const regex = new RegExp(word, 'gi');
|
|
22
20
|
const imageBase64 = yield image.getBase64('image/png');
|
|
23
21
|
let tmpChildren = [];
|
|
@@ -32,7 +30,7 @@ const renderText = (text, box, backgroundSize, options) => __awaiter(void 0, voi
|
|
|
32
30
|
style: {
|
|
33
31
|
display: 'inline',
|
|
34
32
|
verticalAlign: 'middle',
|
|
35
|
-
height: (0, toPx_1.toPx)(
|
|
33
|
+
height: (0, toPx_1.toPx)(options.font.size),
|
|
36
34
|
width: 'auto',
|
|
37
35
|
},
|
|
38
36
|
src: imageBase64,
|
|
@@ -44,18 +42,18 @@ const renderText = (text, box, backgroundSize, options) => __awaiter(void 0, voi
|
|
|
44
42
|
textChildren = tmpChildren;
|
|
45
43
|
}
|
|
46
44
|
const document = (0, virtual_dom_1.h)('div', {
|
|
47
|
-
style: Object.assign({ display: 'flex', overflow: 'visible', position: 'absolute', justifyContent:
|
|
45
|
+
style: Object.assign({ display: 'flex', overflow: 'visible', position: 'absolute', justifyContent: options.justifyContent, alignItems: options.alignItems }, (0, toPx_1.boundingBoxToPx)(box)),
|
|
48
46
|
}, [
|
|
49
47
|
(0, virtual_dom_1.h)('div', {
|
|
50
48
|
style: {
|
|
51
49
|
overflow: 'visible',
|
|
52
50
|
overflowWrap: 'word-wrap',
|
|
53
51
|
whiteSpace: 'normal',
|
|
54
|
-
color: options
|
|
55
|
-
fontFamily:
|
|
56
|
-
fontSize:
|
|
57
|
-
fontStyle:
|
|
58
|
-
fontWeight:
|
|
52
|
+
color: options.color,
|
|
53
|
+
fontFamily: options.font.family,
|
|
54
|
+
fontSize: options.font.size,
|
|
55
|
+
fontStyle: options.font.italic ? 'italic' : undefined,
|
|
56
|
+
fontWeight: options.font.bold ? 'bold' : undefined,
|
|
59
57
|
},
|
|
60
58
|
}, textChildren),
|
|
61
59
|
]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderText.js","sourceRoot":"","sources":["../../../../src/lib/utils/renderText.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6CAAuC;
|
|
1
|
+
{"version":3,"file":"renderText.js","sourceRoot":"","sources":["../../../../src/lib/utils/renderText.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,6CAAuC;AAEvC,iCAA+C;AAC/C,+CAA4C;AAGrC,MAAM,UAAU,GAAG,CACtB,IAAY,EACZ,GAAgB,EAChB,cAAoB,EACpB,OAAkD,EAChC,EAAE;IACpB,IAAI,YAAY,GAA0B,CAAC,IAAI,CAAC,CAAC;IACjD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;QAC9D,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACrC,MAAM,WAAW,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;QAEvD,IAAI,WAAW,GAA0B,EAAE,CAAC;QAC5C,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;YACrC,IAAI,OAAO,WAAW,KAAK,QAAQ,EAAE,CAAC;gBAClC,SAAS;YACb,CAAC;YAED,MAAM,KAAK,GAAI,WAAsB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACnD,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;gBAChD,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;oBACZ,WAAW,CAAC,IAAI,CACZ,IAAA,eAAC,EACG,KAAK,EACL;wBACI,KAAK,EAAE;4BACH,OAAO,EAAE,QAAQ;4BACjB,aAAa,EAAE,QAAQ;4BACvB,MAAM,EAAE,IAAA,WAAI,EAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;4BAC/B,KAAK,EAAE,MAAM;yBAChB;wBACD,GAAG,EAAE,WAAW;qBACnB,EACD,EAAE,CACL,CACJ,CAAC;gBACN,CAAC;gBACD,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;YACnC,CAAC;QACL,CAAC;QAED,YAAY,GAAG,WAAW,CAAC;IAC/B,CAAC;IAED,MAAM,QAAQ,GAAG,IAAA,eAAC,EACd,KAAK,EACL;QACI,KAAK,kBACD,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,SAAS,EACnB,QAAQ,EAAE,UAAU,EAEpB,cAAc,EAAE,OAAO,CAAC,cAAc,EACtC,UAAU,EAAE,OAAO,CAAC,UAAU,IAE3B,IAAA,sBAAe,EAAC,GAAG,CAAC,CAC1B;KACJ,EACD;QACI,IAAA,eAAC,EACG,KAAK,EACL;YACI,KAAK,EAAE;gBACH,QAAQ,EAAE,SAAS;gBACnB,YAAY,EAAE,WAAW;gBACzB,UAAU,EAAE,QAAQ;gBAEpB,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM;gBAC/B,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI;gBAC3B,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;gBACrD,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;aACrD;SACJ,EACD,YAAY,CACf;KACJ,CACJ,CAAC;IAEF,OAAO,IAAA,yBAAW,EAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;AACjD,CAAC,CAAA,CAAC;AA/EW,QAAA,UAAU,cA+ErB"}
|
package/build/src/test.js
CHANGED
|
@@ -17,8 +17,9 @@ const lib_1 = require("./lib");
|
|
|
17
17
|
const result = yield lib_1.Template.new({
|
|
18
18
|
defaultFontFamily: 'branela',
|
|
19
19
|
defaultAssetsPath: 'assets',
|
|
20
|
+
color: 0xC3C3C3FF,
|
|
20
21
|
})
|
|
21
|
-
.text({ key: '
|
|
22
|
+
.text({ key: 'title' }, {
|
|
22
23
|
left: 25,
|
|
23
24
|
top: 25,
|
|
24
25
|
width: 700,
|
|
@@ -40,6 +41,7 @@ const lib_1 = require("./lib");
|
|
|
40
41
|
size: 38,
|
|
41
42
|
},
|
|
42
43
|
color: 'purple',
|
|
44
|
+
skip: (entry) => entry.title.toLowerCase() === 'luigi'
|
|
43
45
|
})
|
|
44
46
|
.font('assets/branela.otf', 'branela')
|
|
45
47
|
.image({ pathFn: entry => `${entry.title.toLowerCase()}.png` }, { left: 25, top: 225, width: 700, height: 700 }, {
|
|
@@ -76,14 +78,21 @@ const lib_1 = require("./lib");
|
|
|
76
78
|
scale: 'stretch',
|
|
77
79
|
gap: 50,
|
|
78
80
|
})
|
|
79
|
-
.
|
|
81
|
+
.grid(() => Promise.resolve([
|
|
82
|
+
luigi.clone(), luigi.clone(), luigi.clone(),
|
|
83
|
+
luigi.clone(), luigi.clone(), luigi.clone(),
|
|
84
|
+
luigi.clone(), luigi.clone(), luigi.clone(),
|
|
85
|
+
]), {
|
|
80
86
|
left: 300,
|
|
81
87
|
top: 325,
|
|
82
|
-
width:
|
|
88
|
+
width: 400,
|
|
83
89
|
height: 600,
|
|
84
90
|
}, {
|
|
85
|
-
scale: '
|
|
86
|
-
gap:
|
|
91
|
+
scale: 'stretch',
|
|
92
|
+
gap: 10,
|
|
93
|
+
alignItems: 'flex-start',
|
|
94
|
+
justifyContent: 'flex-start',
|
|
95
|
+
skip: true,
|
|
87
96
|
})
|
|
88
97
|
.debug()
|
|
89
98
|
.fromCsv('assets/data.csv', {
|
package/build/src/test.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test.js","sourceRoot":"","sources":["../../src/test.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,+BAA4B;AAC5B,+BAAkE;AASlE,CAAC,GAAS,EAAE;IACR,MAAM,QAAQ,GAAG,CAAC,MAAM,WAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAc,CAAC;IACvE,MAAM,KAAK,GAAG,CAAC,MAAM,WAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAc,CAAC;IACjE,MAAM,MAAM,GAAG,MAAM,cAAQ,CAAC,GAAG,CAAe;QAC5C,iBAAiB,EAAE,SAAS;QAC5B,iBAAiB,EAAE,QAAQ;
|
|
1
|
+
{"version":3,"file":"test.js","sourceRoot":"","sources":["../../src/test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hellkite/pipkin",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"description": "Library for board game card generation",
|
|
5
5
|
"main": "build/src/index.js",
|
|
6
6
|
"types": "build/src/index.d.ts",
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"canvas": "^3.1.0",
|
|
19
19
|
"jimp": "^1.6.0",
|
|
20
20
|
"lodash.camelcase": "^4.3.0",
|
|
21
|
+
"lodash.chunk": "^4.2.0",
|
|
21
22
|
"lodash.concat": "^4.5.0",
|
|
22
23
|
"lodash.merge": "^4.6.2",
|
|
23
24
|
"node-html-to-image": "^5.0.0",
|
|
@@ -27,12 +28,14 @@
|
|
|
27
28
|
},
|
|
28
29
|
"devDependencies": {
|
|
29
30
|
"@types/lodash.camelcase": "^4.3.9",
|
|
31
|
+
"@types/lodash.chunk": "^4.2.9",
|
|
30
32
|
"@types/lodash.concat": "^4.5.9",
|
|
31
33
|
"@types/lodash.merge": "^4.6.9",
|
|
32
34
|
"@types/node": "^22.7.5",
|
|
33
35
|
"@types/papaparse": "^5.3.15",
|
|
34
36
|
"@types/virtual-dom": "^2.1.4",
|
|
35
37
|
"gts": "^6.0.2",
|
|
38
|
+
"type-fest": "^4.40.0",
|
|
36
39
|
"typescript": "^5.6.3"
|
|
37
40
|
}
|
|
38
41
|
}
|
package/roadmap.md
CHANGED
package/src/lib/template.ts
CHANGED
|
@@ -5,8 +5,35 @@ import camelCase from 'lodash.camelcase';
|
|
|
5
5
|
import concat from 'lodash.concat';
|
|
6
6
|
import { registerFont } from 'canvas';
|
|
7
7
|
import path from 'path';
|
|
8
|
-
import {
|
|
9
|
-
|
|
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';
|
|
10
37
|
|
|
11
38
|
type RequiredTemplateOptions = {
|
|
12
39
|
height: number;
|
|
@@ -34,7 +61,7 @@ export type LayerFnContext = {
|
|
|
34
61
|
export type LayerFn<EntryType> = (
|
|
35
62
|
entry: EntryType,
|
|
36
63
|
context: LayerFnContext,
|
|
37
|
-
) => Promise<ImageType>;
|
|
64
|
+
) => Promise<ImageType | undefined>;
|
|
38
65
|
|
|
39
66
|
export type TemplateLayerFn<EntryType extends Record<string, string>> = (
|
|
40
67
|
template: Template<EntryType>,
|
|
@@ -99,40 +126,81 @@ export class Template<EntryType extends Record<string, string>> {
|
|
|
99
126
|
return template.render(entry);
|
|
100
127
|
});
|
|
101
128
|
|
|
102
|
-
// TODO: logic for rendering debug helpers
|
|
103
129
|
container = (
|
|
104
130
|
imagesFn: (entry: EntryType) => Promise<Array<ImageType>>,
|
|
131
|
+
box: BoundingBox,
|
|
105
132
|
packingFn: PackingFn,
|
|
133
|
+
options?: ContainerOptions<EntryType>,
|
|
106
134
|
): this =>
|
|
107
|
-
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
|
+
|
|
108
145
|
const images = await imagesFn(entry);
|
|
109
|
-
|
|
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;
|
|
110
162
|
});
|
|
111
163
|
|
|
112
164
|
hbox = (
|
|
113
165
|
imagesFn: (entry: EntryType) => Promise<Array<ImageType>>,
|
|
114
166
|
box: BoundingBox,
|
|
115
|
-
options?: DirectionContainerOptions
|
|
116
|
-
): this => this.container(imagesFn, hboxPackingFn(
|
|
167
|
+
options?: DirectionContainerOptions<EntryType>,
|
|
168
|
+
): this => this.container(imagesFn, box, hboxPackingFn(options), options);
|
|
117
169
|
|
|
118
170
|
vbox = (
|
|
119
171
|
imagesFn: (entry: EntryType) => Promise<Array<ImageType>>,
|
|
120
172
|
box: BoundingBox,
|
|
121
|
-
options?: DirectionContainerOptions
|
|
122
|
-
): this => this.container(imagesFn, vboxPackingFn(
|
|
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);
|
|
123
181
|
|
|
124
182
|
image = (
|
|
125
183
|
ref: ImageRef<EntryType>,
|
|
126
184
|
box: BoundingBox,
|
|
127
|
-
options: ImageLayerOptions
|
|
185
|
+
options: ImageLayerOptions<EntryType>,
|
|
128
186
|
): this =>
|
|
129
187
|
this.layer(async (entry, { debugMode }) => {
|
|
130
|
-
const
|
|
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
|
+
}
|
|
197
|
+
|
|
198
|
+
const image = await this.pathFromImageRef(entry, ref, mergedOptions);
|
|
131
199
|
const result = await placeImage({
|
|
132
200
|
image,
|
|
133
201
|
box,
|
|
134
202
|
backgroundSize: this.backgroundSize,
|
|
135
|
-
options,
|
|
203
|
+
options: mergedOptions,
|
|
136
204
|
});
|
|
137
205
|
|
|
138
206
|
// debug mode
|
|
@@ -154,16 +222,41 @@ export class Template<EntryType extends Record<string, string>> {
|
|
|
154
222
|
text = (
|
|
155
223
|
ref: TextRef<EntryType>,
|
|
156
224
|
box: BoundingBox,
|
|
157
|
-
options?: TextLayerOptions
|
|
225
|
+
options?: TextLayerOptions<EntryType>,
|
|
158
226
|
): this =>
|
|
159
227
|
this.layer(async (entry, { debugMode }) => {
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
228
|
+
const mergedOptions = merge(
|
|
229
|
+
{},
|
|
230
|
+
DEFAULT_TEXT_LAYER_OPTIONS,
|
|
231
|
+
{
|
|
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,
|
|
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;
|
|
167
260
|
});
|
|
168
261
|
|
|
169
262
|
font(path: fs.PathLike, name: string): this {
|
|
@@ -179,13 +272,14 @@ export class Template<EntryType extends Record<string, string>> {
|
|
|
179
272
|
}
|
|
180
273
|
|
|
181
274
|
private async renderLayers(entry: EntryType): Promise<Array<ImageType>> {
|
|
182
|
-
|
|
275
|
+
const results = await Promise.all(
|
|
183
276
|
this.layers.map(layerFn =>
|
|
184
277
|
layerFn(entry, {
|
|
185
278
|
debugMode: this.debugMode,
|
|
186
279
|
}),
|
|
187
280
|
),
|
|
188
281
|
);
|
|
282
|
+
return results.filter(result => !!result);
|
|
189
283
|
}
|
|
190
284
|
|
|
191
285
|
async render(
|
|
@@ -258,12 +352,11 @@ export class Template<EntryType extends Record<string, string>> {
|
|
|
258
352
|
private pathFromImageRef = async (
|
|
259
353
|
entry: EntryType,
|
|
260
354
|
ref: ImageRef<EntryType>,
|
|
261
|
-
options: ImageLayerOptions
|
|
355
|
+
options: RequiredDeep<ImageLayerOptions<EntryType>>,
|
|
262
356
|
): Promise<ImageType> => {
|
|
263
|
-
const assetsPath = options?.assetsPath ?? this.defaultAssetsPath;
|
|
264
357
|
const pathSegments = [];
|
|
265
|
-
if (assetsPath) {
|
|
266
|
-
pathSegments.push(assetsPath);
|
|
358
|
+
if (options.assetsPath) {
|
|
359
|
+
pathSegments.push(options.assetsPath);
|
|
267
360
|
}
|
|
268
361
|
|
|
269
362
|
if ('buffer' in ref) {
|
|
@@ -283,7 +376,7 @@ export class Template<EntryType extends Record<string, string>> {
|
|
|
283
376
|
}
|
|
284
377
|
};
|
|
285
378
|
|
|
286
|
-
private
|
|
379
|
+
private textFromTextRef = (
|
|
287
380
|
entry: EntryType,
|
|
288
381
|
ref: TextRef<EntryType>,
|
|
289
382
|
): string => {
|
|
@@ -297,6 +390,11 @@ export class Template<EntryType extends Record<string, string>> {
|
|
|
297
390
|
throw new Error('Unknown TextRef variant');
|
|
298
391
|
}
|
|
299
392
|
};
|
|
300
|
-
}
|
|
301
393
|
|
|
302
|
-
|
|
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
|
+
}
|
|
@@ -1,66 +1,72 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RequiredDeep } from 'type-fest';
|
|
2
|
+
import { BoundingBox } from './boundingBox';
|
|
2
3
|
import { ImageType } from './image';
|
|
3
4
|
import { ScaleMode } from './scale';
|
|
5
|
+
import { LayerOptions } from './layer';
|
|
4
6
|
|
|
5
|
-
export type ContainerOptions =
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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;
|
|
12
16
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
*/
|
|
19
|
-
gap?: number;
|
|
17
|
+
/**
|
|
18
|
+
* Defaults to `none`
|
|
19
|
+
*/
|
|
20
|
+
scale?: ScaleMode;
|
|
21
|
+
};
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
*
|
|
25
|
-
* Defaults to `center`
|
|
26
|
-
*/
|
|
27
|
-
alignItems?: AlignItems;
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Defaults to `none`
|
|
31
|
-
*/
|
|
32
|
-
scale?: ScaleMode;
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
export const DEFAULT_CONTAINER_OPTIONS: Required<ContainerOptions> = {
|
|
23
|
+
export const DEFAULT_CONTAINER_OPTIONS: RequiredDeep<
|
|
24
|
+
ContainerOptions<Record<string, string>>
|
|
25
|
+
> = {
|
|
36
26
|
gap: 0,
|
|
37
27
|
justifyContent: 'normal',
|
|
38
28
|
alignItems: 'center',
|
|
39
29
|
scale: 'none',
|
|
30
|
+
skip: false,
|
|
40
31
|
};
|
|
41
32
|
|
|
42
|
-
export type DirectionContainerOptions
|
|
33
|
+
export type DirectionContainerOptions<
|
|
34
|
+
EntryType extends Record<string, string>,
|
|
35
|
+
> = ContainerOptions<EntryType> & {
|
|
43
36
|
reversed?: boolean;
|
|
44
37
|
};
|
|
45
38
|
|
|
46
|
-
export const DEFAULT_DIRECTION_CONTAINER_OPTIONS:
|
|
39
|
+
export const DEFAULT_DIRECTION_CONTAINER_OPTIONS: RequiredDeep<
|
|
40
|
+
DirectionContainerOptions<Record<string, string>>
|
|
41
|
+
> = {
|
|
47
42
|
...DEFAULT_CONTAINER_OPTIONS,
|
|
48
43
|
reversed: false,
|
|
49
|
-
}
|
|
44
|
+
};
|
|
50
45
|
|
|
51
|
-
export type GridContainerOptions
|
|
52
|
-
|
|
53
|
-
|
|
46
|
+
export type GridContainerOptions<EntryType extends Record<string, string>> =
|
|
47
|
+
ContainerOptions<EntryType> & {
|
|
48
|
+
size?: number;
|
|
54
49
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
};
|
|
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
|
+
};
|
|
64
59
|
|
|
60
|
+
export const DEFAULT_GRID_CONTAINER_OPTIONS: RequiredDeep<
|
|
61
|
+
GridContainerOptions<Record<string, string>>
|
|
62
|
+
> = {
|
|
63
|
+
...DEFAULT_CONTAINER_OPTIONS,
|
|
64
|
+
size: 3,
|
|
65
|
+
direction: 'rows',
|
|
66
|
+
};
|
|
65
67
|
|
|
66
|
-
export type PackingFn = (
|
|
68
|
+
export type PackingFn = (
|
|
69
|
+
box: BoundingBox,
|
|
70
|
+
background: ImageType,
|
|
71
|
+
images: Array<ImageType>,
|
|
72
|
+
) => Promise<ImageType>;
|