@koda-sl/baker-cli 0.395.0-dev.f8ecbaa42 → 0.395.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/README.md +243 -132
- package/canvas/static-ad-composition/index.html +3 -154
- package/canvas/static-ad-composition/meta.json +1 -1
- package/dist/{chunk-AOVFDDVW.js → chunk-BRIJ4OWT.js} +14 -2
- package/dist/{chunk-AOVFDDVW.js.map → chunk-BRIJ4OWT.js.map} +1 -1
- package/dist/{chunk-NEZ3NAJV.js → chunk-EEHNRAFA.js} +4 -4
- package/dist/{chunk-Q3LMLQAI.js → chunk-LHJ5IXBN.js} +3963 -2664
- package/dist/chunk-LHJ5IXBN.js.map +1 -0
- package/dist/{chunk-OKE2QJSJ.js → chunk-Q7RQ3H6Y.js} +3 -3
- package/dist/{chunk-T2UNK5BW.js → chunk-QP7637HG.js} +3 -3
- package/dist/{chunk-QIQ57EIA.js → chunk-ZWMATKNS.js} +2 -2
- package/dist/cli.js +11599 -11312
- package/dist/cli.js.map +1 -1
- package/dist/{client-EQOSDYJL.js → client-4P6U75EX.js} +4 -4
- package/dist/engine/index.d.ts +175 -120
- package/dist/engine/index.js +3 -3
- package/dist/{env-ANKM47IJ.js → env-LJHSZSNA.js} +2 -2
- package/dist/{output-NR4EJQDV.js → output-HVBFJX4I.js} +5 -5
- package/dist/{shared-SLCDVV45.js → shared-7ZEF4DIX.js} +6 -6
- package/package.json +2 -1
- package/dist/chunk-Q3LMLQAI.js.map +0 -1
- /package/dist/{chunk-NEZ3NAJV.js.map → chunk-EEHNRAFA.js.map} +0 -0
- /package/dist/{chunk-OKE2QJSJ.js.map → chunk-Q7RQ3H6Y.js.map} +0 -0
- /package/dist/{chunk-T2UNK5BW.js.map → chunk-QP7637HG.js.map} +0 -0
- /package/dist/{chunk-QIQ57EIA.js.map → chunk-ZWMATKNS.js.map} +0 -0
- /package/dist/{client-EQOSDYJL.js.map → client-4P6U75EX.js.map} +0 -0
- /package/dist/{env-ANKM47IJ.js.map → env-LJHSZSNA.js.map} +0 -0
- /package/dist/{output-NR4EJQDV.js.map → output-HVBFJX4I.js.map} +0 -0
- /package/dist/{shared-SLCDVV45.js.map → shared-7ZEF4DIX.js.map} +0 -0
|
@@ -20,18 +20,10 @@
|
|
|
20
20
|
.block { font-family: 'AdBody', 'Helvetica Neue', Arial, sans-serif; overflow-wrap: break-word; text-wrap: pretty; }
|
|
21
21
|
.block.headline, .block.subheadline, .block.cta { font-family: 'AdHeadline', 'AdBody', 'Helvetica Neue', Arial, sans-serif; }
|
|
22
22
|
.block.headline { text-wrap: balance; letter-spacing: -0.01em; }
|
|
23
|
-
.fill { display: inline-block; line-height: 1.1; padding: 0.5em 1.2em;
|
|
23
|
+
.fill { display: inline-block; line-height: 1.1; padding: 0.5em 1.2em; }
|
|
24
24
|
.fill.highlight { padding: 0.12em 0.4em; box-decoration-break: clone; -webkit-box-decoration-break: clone; }
|
|
25
25
|
.fill.sticker { transform: rotate(-3deg); }
|
|
26
|
-
.fill.outline { background: transparent !important; border: 0.09em solid currentColor; }
|
|
27
26
|
.logo { display: block; width: auto; object-fit: contain; }
|
|
28
|
-
.shape { position: absolute; pointer-events: none; }
|
|
29
|
-
.shape svg { display: block; height: 100%; width: auto; }
|
|
30
|
-
.shape.chrome { display: flex; align-items: center; justify-content: space-between; }
|
|
31
|
-
.chrome-back { display: flex; align-items: center; gap: 0.2em; font-family: 'AdBody', 'Helvetica Neue', Arial, sans-serif; }
|
|
32
|
-
.chrome-more { display: flex; align-items: center; justify-content: center; border-radius: 999px; }
|
|
33
|
-
.block.mark { display: flex; align-items: flex-start; gap: 0.45em; }
|
|
34
|
-
.block.mark svg { flex: none; width: 1.05em; height: 1.05em; margin-top: 0.1em; }
|
|
35
27
|
</style>
|
|
36
28
|
</head>
|
|
37
29
|
<body>
|
|
@@ -130,8 +122,6 @@
|
|
|
130
122
|
el.style.minHeight = ((at.y[1] - at.y[0]) / 100) * H + "px";
|
|
131
123
|
el.style.justifyContent = "center";
|
|
132
124
|
el.style.gap = 1.2 * U + "px";
|
|
133
|
-
// A card's lines keep off its edges.
|
|
134
|
-
if (g.inset) el.style.padding = 2.6 * U + "px " + 3.2 * U + "px";
|
|
135
125
|
// Copy rewritten for our brand runs longer than the source's: allow some growth
|
|
136
126
|
// past the region before the type shrinks.
|
|
137
127
|
el.dataset.max = String(((at.y[1] - at.y[0]) / 100) * H * 1.35);
|
|
@@ -156,91 +146,6 @@
|
|
|
156
146
|
else el.insertBefore(img, el.firstChild);
|
|
157
147
|
}
|
|
158
148
|
|
|
159
|
-
// The structures of a text-only ad, each at its layout region's box on this format:
|
|
160
|
-
// cards and panels, dividers, icons and an app's chrome. Drawn before the copy, under it.
|
|
161
|
-
var ICON_PATHS = {
|
|
162
|
-
check: '<path d="M5 12.5l4.5 4.5L19 7.5" fill="none" stroke="C" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>',
|
|
163
|
-
cross: '<path d="M6.5 6.5l11 11M17.5 6.5l-11 11" fill="none" stroke="C" stroke-width="3" stroke-linecap="round"/>',
|
|
164
|
-
dots: '<circle cx="5" cy="12" r="2" fill="C"/><circle cx="12" cy="12" r="2" fill="C"/><circle cx="19" cy="12" r="2" fill="C"/>',
|
|
165
|
-
chevron_left: '<path d="M15 4.5L7.5 12 15 19.5" fill="none" stroke="C" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round"/>',
|
|
166
|
-
arrow_right: '<path d="M4 12h15M13 6l6 6-6 6" fill="none" stroke="C" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round"/>',
|
|
167
|
-
star: '<path d="M12 3l2.7 5.6 6.1.9-4.4 4.3 1 6.1L12 17l-5.4 2.9 1-6.1-4.4-4.3 6.1-.9z" fill="C"/>',
|
|
168
|
-
heart: '<path d="M12 20s-7-4.4-7-10a4 4 0 017-2.6A4 4 0 0119 10c0 5.6-7 10-7 10z" fill="C"/>',
|
|
169
|
-
};
|
|
170
|
-
function icon(name, color) {
|
|
171
|
-
var path = ICON_PATHS[name] || "";
|
|
172
|
-
return '<svg viewBox="0 0 24 24" aria-hidden="true">' + path.split('"C"').join('"' + color + '"') + "</svg>";
|
|
173
|
-
}
|
|
174
|
-
var SHAPE_RADIUS = { pill: "999px", rounded: 2.4 * U + "px", square: "0" };
|
|
175
|
-
function addShape(s) {
|
|
176
|
-
var at = s.at && s.at[FRAME.format];
|
|
177
|
-
if (!at) return;
|
|
178
|
-
var left = (at.x[0] / 100) * W;
|
|
179
|
-
var top = (at.y[0] / 100) * H;
|
|
180
|
-
var width = ((at.x[1] - at.x[0]) / 100) * W;
|
|
181
|
-
var height = ((at.y[1] - at.y[0]) / 100) * H;
|
|
182
|
-
var el = document.createElement("div");
|
|
183
|
-
el.className = "shape " + s.kind;
|
|
184
|
-
el.setAttribute("data-layout-ignore", "");
|
|
185
|
-
el.style.left = left + "px";
|
|
186
|
-
el.style.top = top + "px";
|
|
187
|
-
el.style.width = width + "px";
|
|
188
|
-
el.style.height = height + "px";
|
|
189
|
-
if (s.kind === "box") {
|
|
190
|
-
el.style.background = s.fill || "transparent";
|
|
191
|
-
if (s.border) el.style.border = Math.max(2, 0.28 * U) + "px solid " + s.border;
|
|
192
|
-
el.style.borderRadius = SHAPE_RADIUS[s.radius] || SHAPE_RADIUS.rounded;
|
|
193
|
-
if (s.shadow) el.style.boxShadow = "0 " + 0.8 * U + "px " + 2.6 * U + "px rgba(0,0,0,0.18)";
|
|
194
|
-
} else if (s.kind === "rule") {
|
|
195
|
-
var thick = Math.max(2, 0.32 * U);
|
|
196
|
-
el.style.background = s.color;
|
|
197
|
-
if (width >= height) {
|
|
198
|
-
el.style.top = top + height / 2 - thick / 2 + "px";
|
|
199
|
-
el.style.height = thick + "px";
|
|
200
|
-
} else {
|
|
201
|
-
el.style.left = left + width / 2 - thick / 2 + "px";
|
|
202
|
-
el.style.width = thick + "px";
|
|
203
|
-
}
|
|
204
|
-
} else if (s.kind === "icon") {
|
|
205
|
-
el.style.display = "flex";
|
|
206
|
-
el.style.justifyContent = "center";
|
|
207
|
-
el.style.alignItems = "center";
|
|
208
|
-
if (s.ring) {
|
|
209
|
-
// A circled icon (a note's "more" button): the ring is as tall as the region.
|
|
210
|
-
var ring = Math.min(width, height);
|
|
211
|
-
var circle = document.createElement("div");
|
|
212
|
-
circle.className = "chrome-more";
|
|
213
|
-
circle.style.width = ring + "px";
|
|
214
|
-
circle.style.height = ring + "px";
|
|
215
|
-
circle.style.border = Math.max(2, ring * 0.07) + "px solid " + s.color;
|
|
216
|
-
circle.innerHTML = '<span style="display:block;height:' + ring * 0.6 + 'px">' + icon(s.icon, s.color) + "</span>";
|
|
217
|
-
el.appendChild(circle);
|
|
218
|
-
} else {
|
|
219
|
-
el.innerHTML = icon(s.icon, s.color);
|
|
220
|
-
}
|
|
221
|
-
} else if (s.kind === "chrome") {
|
|
222
|
-
var size = Math.min(height * 0.62, 5 * U);
|
|
223
|
-
var back = document.createElement("div");
|
|
224
|
-
back.className = "chrome-back";
|
|
225
|
-
if (!facesStaged) back.style.fontFamily = FALLBACK_FACE;
|
|
226
|
-
back.style.color = s.color;
|
|
227
|
-
back.style.fontSize = size + "px";
|
|
228
|
-
back.innerHTML = '<span style="display:block;height:1.1em">' + icon("chevron_left", s.color) + "</span>";
|
|
229
|
-
var label = document.createElement("span");
|
|
230
|
-
label.textContent = s.label;
|
|
231
|
-
back.appendChild(label);
|
|
232
|
-
var more = document.createElement("div");
|
|
233
|
-
more.className = "chrome-more";
|
|
234
|
-
more.style.width = size * 1.35 + "px";
|
|
235
|
-
more.style.height = size * 1.35 + "px";
|
|
236
|
-
more.style.border = Math.max(2, size * 0.09) + "px solid " + s.color;
|
|
237
|
-
more.innerHTML = '<span style="display:block;height:' + size * 0.8 + 'px">' + icon("dots", s.color) + "</span>";
|
|
238
|
-
el.appendChild(back);
|
|
239
|
-
if (s.more) el.appendChild(more);
|
|
240
|
-
}
|
|
241
|
-
root.appendChild(el);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
149
|
function addBlock(b) {
|
|
245
150
|
var el = document.createElement("div");
|
|
246
151
|
el.className = "block " + b.role;
|
|
@@ -249,11 +154,6 @@
|
|
|
249
154
|
el.dataset.base = String(size);
|
|
250
155
|
el.style.fontSize = size * U + "px";
|
|
251
156
|
el.style.fontWeight = String(WEIGHT[b.weight] || (b.role === "cta" ? 700 : 400));
|
|
252
|
-
// A staged face is one weight, so a line prompt.json sets bold (a bold paragraph, a
|
|
253
|
-
// sign-off) is drawn in the heavy face whatever its role.
|
|
254
|
-
if (facesStaged && WEIGHT[b.weight] >= 600) {
|
|
255
|
-
el.style.fontFamily = "'AdHeadline', 'AdBody', 'Helvetica Neue', Arial, sans-serif";
|
|
256
|
-
}
|
|
257
157
|
el.style.lineHeight = b.role === "headline" ? "1.04" : "1.22";
|
|
258
158
|
el.style.textTransform = CASE[b.case] || "none";
|
|
259
159
|
el.style.textAlign = b.align || "center";
|
|
@@ -269,29 +169,15 @@
|
|
|
269
169
|
fill.style.background = t.background || (AD.cta && AD.cta.background) || "#111111";
|
|
270
170
|
fill.style.color = t.color || (AD.cta && AD.cta.color) || "#ffffff";
|
|
271
171
|
fill.style.borderRadius = RADIUS[t.shape] || RADIUS.rounded;
|
|
272
|
-
if (t.outline) fill.classList.add("outline");
|
|
273
172
|
el.appendChild(fill);
|
|
274
173
|
} else {
|
|
275
|
-
|
|
276
|
-
// A tick or cross list item: the mark in its own colour, then the line.
|
|
277
|
-
el.classList.add("mark");
|
|
278
|
-
el.innerHTML = icon(t.mark, t.color);
|
|
279
|
-
var words = document.createElement("span");
|
|
280
|
-
words.textContent = text;
|
|
281
|
-
el.appendChild(words);
|
|
282
|
-
} else {
|
|
283
|
-
el.textContent = text;
|
|
284
|
-
}
|
|
174
|
+
el.textContent = text;
|
|
285
175
|
el.style.color = ink;
|
|
286
176
|
if (t.kind === "underline") {
|
|
287
177
|
el.style.textDecoration = "underline";
|
|
288
178
|
el.style.textDecorationThickness = "0.08em";
|
|
289
179
|
el.style.textUnderlineOffset = "0.18em";
|
|
290
180
|
}
|
|
291
|
-
if (t.kind === "strike") {
|
|
292
|
-
el.style.textDecoration = "line-through";
|
|
293
|
-
el.style.textDecorationThickness = "0.08em";
|
|
294
|
-
}
|
|
295
181
|
var dark = (luma(ink) || 255) < 110;
|
|
296
182
|
el.dataset.dark = dark ? "1" : "0";
|
|
297
183
|
if (hasPlate) el.style.textShadow = dark ? "0 1px 10px rgba(255,255,255,0.35)" : "0 2px 14px rgba(0,0,0,0.45)";
|
|
@@ -300,7 +186,6 @@
|
|
|
300
186
|
}
|
|
301
187
|
|
|
302
188
|
var drawCopy = FRAME.draw_copy !== false;
|
|
303
|
-
(hasPlate ? [] : AD.shapes || []).forEach(addShape);
|
|
304
189
|
(drawCopy ? AD.copy || [] : []).forEach(addBlock);
|
|
305
190
|
if (AD.logo) addLogo(AD.logo);
|
|
306
191
|
|
|
@@ -313,9 +198,7 @@
|
|
|
313
198
|
// layout is written.
|
|
314
199
|
function fit(el) {
|
|
315
200
|
var max = Number(el.dataset.max);
|
|
316
|
-
|
|
317
|
-
var pad = getComputedStyle(el);
|
|
318
|
-
var width = el.getBoundingClientRect().width - parseFloat(pad.paddingLeft) - parseFloat(pad.paddingRight);
|
|
201
|
+
var width = el.getBoundingClientRect().width;
|
|
319
202
|
var scale = 1;
|
|
320
203
|
for (var i = 0; i < 40; i++) {
|
|
321
204
|
var tooTall = el.scrollHeight > max;
|
|
@@ -326,42 +209,10 @@
|
|
|
326
209
|
scale *= 0.94;
|
|
327
210
|
Array.prototype.forEach.call(el.querySelectorAll(".block"), function (c) {
|
|
328
211
|
c.style.fontSize = Number(c.dataset.base) * U * scale + "px";
|
|
329
|
-
c.dataset.scale = String(scale);
|
|
330
212
|
});
|
|
331
213
|
}
|
|
332
214
|
}
|
|
333
215
|
|
|
334
|
-
// A region's copy may run past its box, but never into the next region down the same
|
|
335
|
-
// column: the room it has ends where that one starts.
|
|
336
|
-
function keepClearOfNext(el) {
|
|
337
|
-
var r = el.getBoundingClientRect();
|
|
338
|
-
var room = Infinity;
|
|
339
|
-
Array.prototype.forEach.call(root.querySelectorAll(".group.placed"), function (other) {
|
|
340
|
-
if (other === el) return;
|
|
341
|
-
var q = other.getBoundingClientRect();
|
|
342
|
-
var sameColumn = Math.min(r.right, q.right) - Math.max(r.left, q.left) > 0;
|
|
343
|
-
if (sameColumn && q.top > r.top + 1) room = Math.min(room, q.top - r.top - 0.8 * U);
|
|
344
|
-
});
|
|
345
|
-
// Two regions the format already stacks on each other are left as they are: holding
|
|
346
|
-
// one to less than its own box would only shrink its type to nothing.
|
|
347
|
-
if (room === Infinity || room < parseFloat(el.style.minHeight)) return;
|
|
348
|
-
el.dataset.max = String(Math.min(Number(el.dataset.max), room));
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
// Lines set at one size in prompt.json stay one size in the ad: every one is drawn at
|
|
352
|
-
// the smallest scale any of them needed to fit.
|
|
353
|
-
function evenSizes() {
|
|
354
|
-
var least = {};
|
|
355
|
-
var blocks = Array.prototype.slice.call(root.querySelectorAll(".block"));
|
|
356
|
-
blocks.forEach(function (b) {
|
|
357
|
-
var s = Number(b.dataset.scale || 1);
|
|
358
|
-
least[b.dataset.base] = Math.min(least[b.dataset.base] || 1, s);
|
|
359
|
-
});
|
|
360
|
-
blocks.forEach(function (b) {
|
|
361
|
-
b.style.fontSize = Number(b.dataset.base) * U * least[b.dataset.base] + "px";
|
|
362
|
-
});
|
|
363
|
-
}
|
|
364
|
-
|
|
365
216
|
// A soft scrim behind a band of light type over the picture (or a light one behind
|
|
366
217
|
// dark type), so copy with no position of its own reads on any plate. Copy placed
|
|
367
218
|
// by the layout sits on the calm area the plate kept for it.
|
|
@@ -392,9 +243,7 @@
|
|
|
392
243
|
|
|
393
244
|
var ready = document.fonts && document.fonts.ready ? document.fonts.ready : Promise.resolve();
|
|
394
245
|
ready.then(function () {
|
|
395
|
-
Array.prototype.forEach.call(root.querySelectorAll(".group.placed"), keepClearOfNext);
|
|
396
246
|
containers().forEach(fit);
|
|
397
|
-
evenSizes();
|
|
398
247
|
["top", "bottom"].forEach(scrim);
|
|
399
248
|
root.setAttribute("data-ready", "1");
|
|
400
249
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "static-ad",
|
|
3
|
-
"title": "Static ad: the picture (or
|
|
3
|
+
"title": "Static ad: the picture (or the brand colours) with what the concept holds drawn on top",
|
|
4
4
|
"description": "Written by `baker canvas scaffold-static-ad`, one copy per delivered format. Draws only what prompt.compose.json (derived from prompt.json) holds: each line of copy where the source layout placed it, set the way the reference set it (plain, underlined, with an arrow, as a button or sticker), in the staged fonts, and the logo file only when the concept shows one. The plate is the image model's clean picture; a text-only ad has none and sits on the brand colour. Width and height are this format's delivered size.",
|
|
5
5
|
"width": 1080,
|
|
6
6
|
"height": 1350,
|
|
@@ -947,6 +947,12 @@ function round2(value) {
|
|
|
947
947
|
function asRecord(value) {
|
|
948
948
|
return value && typeof value === "object" ? value : {};
|
|
949
949
|
}
|
|
950
|
+
function bakerUses(value) {
|
|
951
|
+
const uses = asRecord(value);
|
|
952
|
+
const companies = typeof uses.companies === "number" ? uses.companies : 0;
|
|
953
|
+
if (companies === 0) return {};
|
|
954
|
+
return { baker_uses: companies, ...uses.ours === true ? { already_adapted: true } : {} };
|
|
955
|
+
}
|
|
950
956
|
function compactWinningAd(record) {
|
|
951
957
|
const dna = asRecord(record.dna);
|
|
952
958
|
return {
|
|
@@ -958,7 +964,12 @@ function compactWinningAd(record) {
|
|
|
958
964
|
summary: String(dna.creative_concept ?? ""),
|
|
959
965
|
advertiser_id: String(record.advertiser_id ?? ""),
|
|
960
966
|
ad_id: String(record.ad_id ?? ""),
|
|
961
|
-
media_url: String(record.media_url ?? "")
|
|
967
|
+
media_url: String(record.media_url ?? ""),
|
|
968
|
+
...typeof dna.visual === "string" && dna.visual ? { visual: dna.visual } : {},
|
|
969
|
+
...typeof dna.container === "string" && dna.container ? { container: dna.container } : {},
|
|
970
|
+
...typeof dna.mechanism === "string" && dna.mechanism ? { mechanism: dna.mechanism } : {},
|
|
971
|
+
...bakerUses(record.baker_uses),
|
|
972
|
+
...record.source === "followed" || record.source === "library" ? { source: record.source } : {}
|
|
962
973
|
};
|
|
963
974
|
}
|
|
964
975
|
function fullWinningAd(record) {
|
|
@@ -975,6 +986,7 @@ function fullWinningAd(record) {
|
|
|
975
986
|
awareness_stage: dna.awareness_stage ?? null,
|
|
976
987
|
target_persona: dna.target_persona ?? null,
|
|
977
988
|
hook_archetype: dna.hook_archetype ?? null,
|
|
989
|
+
mechanism: dna.mechanism ?? null,
|
|
978
990
|
industry: dna.industry ?? null
|
|
979
991
|
};
|
|
980
992
|
}
|
|
@@ -1299,4 +1311,4 @@ export {
|
|
|
1299
1311
|
captureVimeoCookie,
|
|
1300
1312
|
childEnvWith
|
|
1301
1313
|
};
|
|
1302
|
-
//# sourceMappingURL=chunk-
|
|
1314
|
+
//# sourceMappingURL=chunk-BRIJ4OWT.js.map
|