@invarn/cibuild 2.4.6 → 2.4.7
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/dist/cli.cjs +31 -12
- package/dist/src/commands/fidelity-trim.test.js +1 -1
- package/dist/src/yaml/steps/render-post-processor.d.ts +4 -1
- package/dist/src/yaml/steps/render-post-processor.d.ts.map +1 -1
- package/dist/src/yaml/steps/render-post-processor.js +21 -2
- package/dist/src/yaml/steps/render-post-processor.test.js +18 -0
- package/dist/src/yaml/steps/trim-align.d.ts +4 -2
- package/dist/src/yaml/steps/trim-align.d.ts.map +1 -1
- package/dist/src/yaml/steps/trim-align.js +24 -5
- package/dist/src/yaml/steps/trim-align.test.js +8 -5
- package/dist/src/yaml/steps/ui-fidelity-render-android.test.js +5 -1
- package/package.json +1 -1
|
@@ -49,7 +49,7 @@ describe('handleFidelityTrimCommand', () => {
|
|
|
49
49
|
const status = handleFidelityTrimCommand([input, out]);
|
|
50
50
|
expect(status).toBe(0);
|
|
51
51
|
const printed = stdout.mock.calls.map((c) => String(c[0])).join('');
|
|
52
|
-
expect(printed).toBe('TRIMDIMS 30 40 0 0 100 80\n');
|
|
52
|
+
expect(printed).toBe('TRIMDIMS 30 40 0 0 100 80 10 20\n');
|
|
53
53
|
expect(stderr).not.toHaveBeenCalled();
|
|
54
54
|
}
|
|
55
55
|
finally {
|
|
@@ -42,11 +42,14 @@
|
|
|
42
42
|
export declare const RENDER_SCRIPT_TRIM_STAGE: string;
|
|
43
43
|
/** A rendered/reference/source dimension pair in pixels, as TRIMDIMS reports. */
|
|
44
44
|
export type TrimDimsPair = [number, number];
|
|
45
|
-
/** Parsed TRIMDIMS line: rendered (trimmed) / reference / pre-trim source px
|
|
45
|
+
/** Parsed TRIMDIMS line: rendered (trimmed) / reference / pre-trim source px,
|
|
46
|
+
* plus the crop origin within the source — null when the helper predates it
|
|
47
|
+
* (unknown, never assumed zero). */
|
|
46
48
|
export interface TrimDims {
|
|
47
49
|
rendered: TrimDimsPair;
|
|
48
50
|
reference: TrimDimsPair;
|
|
49
51
|
source: TrimDimsPair;
|
|
52
|
+
offset: TrimDimsPair | null;
|
|
50
53
|
}
|
|
51
54
|
/** How the stage will spawn the fidelity-trim helper. */
|
|
52
55
|
export interface TrimHelperInvocation {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render-post-processor.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/render-post-processor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAMH;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,wBAAwB,EAAE,
|
|
1
|
+
{"version":3,"file":"render-post-processor.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/render-post-processor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAMH;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,wBAAwB,EAAE,MAkLtC,CAAC;AAEF,iFAAiF;AACjF,MAAM,MAAM,YAAY,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE5C;;qCAEqC;AACrC,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,YAAY,CAAC;IACvB,SAAS,EAAE,YAAY,CAAC;IACxB,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;CAC7B;AAED,yDAAyD;AACzD,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,sBAAsB;IACrC,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAAC;IAC/C,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IAChC,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,oBAAoB,CAAC;IAC3D,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG;QAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC1F;AAED;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CAAC,SAAS,CAAC,EAAE;IACpD,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,GAAG,sBAAsB,CAkBzB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,IAAI,CAqBhD"}
|
|
@@ -49,8 +49,10 @@ function roundTwo(value) {
|
|
|
49
49
|
return Math.round(value * 100) / 100;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
// Parse the helper's "TRIMDIMS <rW> <rH> <refW> <refH> <srcW> <srcH>
|
|
53
|
-
// (rendered/reference/source px
|
|
52
|
+
// Parse the helper's "TRIMDIMS <rW> <rH> <refW> <refH> <srcW> <srcH>
|
|
53
|
+
// [<offX> <offY>]" line (rendered/reference/source px + the crop origin;
|
|
54
|
+
// last one wins). The origin is null on a 6-number line — an old helper may
|
|
55
|
+
// well have trimmed something, so an absent origin means UNKNOWN, never zero.
|
|
54
56
|
function parseTrimDims(stdout) {
|
|
55
57
|
var lines = String(stdout || '').split('\n');
|
|
56
58
|
for (var i = lines.length - 1; i >= 0; i--) {
|
|
@@ -61,10 +63,19 @@ function parseTrimDims(stdout) {
|
|
|
61
63
|
Number(parts[4]), Number(parts[5]), Number(parts[6]),
|
|
62
64
|
];
|
|
63
65
|
if (nums.every(function (n) { return Number.isFinite(n); })) {
|
|
66
|
+
var offset = null;
|
|
67
|
+
if (parts.length >= 9) {
|
|
68
|
+
var offX = Number(parts[7]);
|
|
69
|
+
var offY = Number(parts[8]);
|
|
70
|
+
if (Number.isFinite(offX) && Number.isFinite(offY)) {
|
|
71
|
+
offset = [offX, offY];
|
|
72
|
+
}
|
|
73
|
+
}
|
|
64
74
|
return {
|
|
65
75
|
rendered: [nums[0], nums[1]],
|
|
66
76
|
reference: [nums[2], nums[3]],
|
|
67
77
|
source: [nums[4], nums[5]],
|
|
78
|
+
offset: offset,
|
|
68
79
|
};
|
|
69
80
|
}
|
|
70
81
|
}
|
|
@@ -189,6 +200,14 @@ function trimRenderedImage(entry, renderedPath) {
|
|
|
189
200
|
// before and after the fix).
|
|
190
201
|
source_px: dims.source,
|
|
191
202
|
};
|
|
203
|
+
// The crop origin, when the helper reported one: where the trimmed image
|
|
204
|
+
// sits inside the source raster. The dashboard subtracts it to place the
|
|
205
|
+
// layout dump's window-space geometry on the trimmed bytes; omitted (not
|
|
206
|
+
// null) when unknown, so a pre-offset helper's dimensions keep their old
|
|
207
|
+
// shape exactly.
|
|
208
|
+
if (dims.offset !== null) {
|
|
209
|
+
entry.dimensions.trim_offset_px = dims.offset;
|
|
210
|
+
}
|
|
192
211
|
// Surface how much margin was removed -- a no-op (source == rendered) means
|
|
193
212
|
// the view fills an opaque canvas with no transparent or uniform margin.
|
|
194
213
|
log(
|
|
@@ -18,8 +18,25 @@ describe('dimension reporting (TRIMDIMS parsing)', () => {
|
|
|
18
18
|
rendered: [320, 640],
|
|
19
19
|
reference: [160, 320],
|
|
20
20
|
source: [400, 800],
|
|
21
|
+
// A 6-number line is the pre-offset helper — the origin is unknown, not
|
|
22
|
+
// zero: an old binary may well have trimmed something.
|
|
23
|
+
offset: null,
|
|
21
24
|
});
|
|
22
25
|
});
|
|
26
|
+
test('parses the crop origin from an 8-number TRIMDIMS line', () => {
|
|
27
|
+
const dims = parseTrimDims('TRIMDIMS 320 640 160 320 400 800 40 77\n');
|
|
28
|
+
expect(dims).toEqual({
|
|
29
|
+
rendered: [320, 640],
|
|
30
|
+
reference: [160, 320],
|
|
31
|
+
source: [400, 800],
|
|
32
|
+
offset: [40, 77],
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
test('a non-numeric origin degrades to offset null, never to garbage', () => {
|
|
36
|
+
const dims = parseTrimDims('TRIMDIMS 320 640 160 320 400 800 x y\n');
|
|
37
|
+
expect(dims?.offset).toBeNull();
|
|
38
|
+
expect(dims?.rendered).toEqual([320, 640]);
|
|
39
|
+
});
|
|
23
40
|
test('returns null when no TRIMDIMS line is present', () => {
|
|
24
41
|
expect(parseTrimDims('rendered HomeView\nsome other log line\n')).toBeNull();
|
|
25
42
|
expect(parseTrimDims('')).toBeNull();
|
|
@@ -35,6 +52,7 @@ describe('dimension reporting (TRIMDIMS parsing)', () => {
|
|
|
35
52
|
rendered: [320, 640],
|
|
36
53
|
reference: [160, 320],
|
|
37
54
|
source: [400, 800],
|
|
55
|
+
offset: null,
|
|
38
56
|
});
|
|
39
57
|
});
|
|
40
58
|
test('returns null for a truncated or non-numeric TRIMDIMS line', () => {
|
|
@@ -78,8 +78,10 @@ export interface TrimAlignResult {
|
|
|
78
78
|
* The helper entry point, argv-compatible with the retired Swift helper:
|
|
79
79
|
* `[in.png, out.png]` or `[in.png, out.png, aligned.png, reference.png]`.
|
|
80
80
|
* Crops the input to its content bounding box, optionally writes a
|
|
81
|
-
* reference-sized aligned copy (best-effort), and reports a TRIMDIMS line
|
|
82
|
-
*
|
|
81
|
+
* reference-sized aligned copy (best-effort), and reports a TRIMDIMS line
|
|
82
|
+
* (`TRIMDIMS <rW> <rH> <refW> <refH> <srcW> <srcH> <offX> <offY>` — the crop
|
|
83
|
+
* origin appended 2026-08-01, older consumers ignore it). Same exit codes,
|
|
84
|
+
* same stdout/stderr shape as the Swift helper.
|
|
83
85
|
*/
|
|
84
86
|
export declare function runTrimAlign(argv: string[]): TrimAlignResult;
|
|
85
87
|
//# sourceMappingURL=trim-align.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trim-align.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/trim-align.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAE5B,0DAA0D;AAC1D,MAAM,WAAW,UAAU;IACzB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,+CAA+C;AAC/C,eAAO,MAAM,eAAe,KAAK,CAAC;AAClC,eAAO,MAAM,oBAAoB,KAAK,CAAC;AACvC,eAAO,MAAM,oBAAoB,KAAK,CAAC;AACvC,eAAO,MAAM,sBAAsB,KAAK,CAAC;AA0BzC;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,GAAG,UAAU,EACzB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,UAAU,GAAG,IAAI,CAkGnB;AAED,+EAA+E;AAC/E,wBAAgB,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,UAAU,GAAG,GAAG,CAOxD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI,CAyE1E;AAED,uEAAuE;AACvE,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED
|
|
1
|
+
{"version":3,"file":"trim-align.d.ts","sourceRoot":"","sources":["../../../../src/yaml/steps/trim-align.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAE5B,0DAA0D;AAC1D,MAAM,WAAW,UAAU;IACzB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,+CAA+C;AAC/C,eAAO,MAAM,eAAe,KAAK,CAAC;AAClC,eAAO,MAAM,oBAAoB,KAAK,CAAC;AACvC,eAAO,MAAM,oBAAoB,KAAK,CAAC;AACvC,eAAO,MAAM,sBAAsB,KAAK,CAAC;AA0BzC;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,GAAG,UAAU,EACzB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,UAAU,GAAG,IAAI,CAkGnB;AAED,+EAA+E;AAC/E,wBAAgB,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,UAAU,GAAG,GAAG,CAOxD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI,CAyE1E;AAED,uEAAuE;AACvE,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,eAAe,CA8F5D"}
|
|
@@ -266,8 +266,10 @@ export function fitPad(src, width, height) {
|
|
|
266
266
|
* The helper entry point, argv-compatible with the retired Swift helper:
|
|
267
267
|
* `[in.png, out.png]` or `[in.png, out.png, aligned.png, reference.png]`.
|
|
268
268
|
* Crops the input to its content bounding box, optionally writes a
|
|
269
|
-
* reference-sized aligned copy (best-effort), and reports a TRIMDIMS line
|
|
270
|
-
*
|
|
269
|
+
* reference-sized aligned copy (best-effort), and reports a TRIMDIMS line
|
|
270
|
+
* (`TRIMDIMS <rW> <rH> <refW> <refH> <srcW> <srcH> <offX> <offY>` — the crop
|
|
271
|
+
* origin appended 2026-08-01, older consumers ignore it). Same exit codes,
|
|
272
|
+
* same stdout/stderr shape as the Swift helper.
|
|
271
273
|
*/
|
|
272
274
|
export function runTrimAlign(argv) {
|
|
273
275
|
if (argv.length < 2) {
|
|
@@ -338,10 +340,27 @@ export function runTrimAlign(argv) {
|
|
|
338
340
|
}
|
|
339
341
|
}
|
|
340
342
|
}
|
|
341
|
-
// Report: rendered (trimmed) px, reference px (0 0 when unavailable),
|
|
342
|
-
//
|
|
343
|
+
// Report: rendered (trimmed) px, reference px (0 0 when unavailable), the
|
|
344
|
+
// pre-trim source px (how much margin was removed), then the CROP ORIGIN —
|
|
345
|
+
// where the trimmed image's top-left sits inside the source. The origin is
|
|
346
|
+
// what lets a consumer place source-coordinate geometry (the layout dump's
|
|
347
|
+
// window-space bounds) onto the trimmed bytes; without it every finding
|
|
348
|
+
// spotlight drew shifted by exactly this offset on the first padded
|
|
349
|
+
// wrappers (the 2026-08-01 diagnosis). Appended, never inserted: TRIMDIMS
|
|
350
|
+
// parsers require >= 7 fields and ignore extras, so an old parser reading a
|
|
351
|
+
// new line (and a new parser reading an old 6-number line) both degrade
|
|
352
|
+
// safely to "origin unknown".
|
|
343
353
|
const stdout = 'TRIMDIMS ' +
|
|
344
|
-
[
|
|
354
|
+
[
|
|
355
|
+
box.width,
|
|
356
|
+
box.height,
|
|
357
|
+
referenceWidth,
|
|
358
|
+
referenceHeight,
|
|
359
|
+
image.width,
|
|
360
|
+
image.height,
|
|
361
|
+
box.x,
|
|
362
|
+
box.y,
|
|
363
|
+
].join(' ') +
|
|
345
364
|
'\n';
|
|
346
365
|
return { status: 0, stdout, stderr: '' };
|
|
347
366
|
}
|
|
@@ -72,8 +72,11 @@ describe('runTrimAlign — trim', () => {
|
|
|
72
72
|
// The crop is a raw pixel copy of the content region.
|
|
73
73
|
expect(pixelAt(out, 0, 0)).toEqual([255, 0, 0, 255]);
|
|
74
74
|
expect(pixelAt(out, 59, 39)).toEqual([255, 0, 0, 255]);
|
|
75
|
-
// TRIMDIMS: rendered (trimmed) px, reference px (0 0 without one), source
|
|
76
|
-
|
|
75
|
+
// TRIMDIMS: rendered (trimmed) px, reference px (0 0 without one), source
|
|
76
|
+
// px, then the crop origin — where the trimmed image sits in the source.
|
|
77
|
+
// The origin is what lets a consumer place source-coordinate geometry on
|
|
78
|
+
// the trimmed bytes (the 2026-08-01 spotlight diagnosis).
|
|
79
|
+
expect(result.stdout.trim()).toBe('TRIMDIMS 60 40 0 0 200 200 30 50');
|
|
77
80
|
});
|
|
78
81
|
test('crops an opaque uniform-background wrapper to its content card', () => {
|
|
79
82
|
const dir = scene();
|
|
@@ -115,7 +118,7 @@ describe('runTrimAlign — trim', () => {
|
|
|
115
118
|
// content — the opaque box (the whole image) is kept, exit 0.
|
|
116
119
|
expect(result.status).toBe(0);
|
|
117
120
|
expect(pngSize(out)).toEqual({ width: 64, height: 48 });
|
|
118
|
-
expect(result.stdout.trim()).toBe('TRIMDIMS 64 48 0 0 64 48');
|
|
121
|
+
expect(result.stdout.trim()).toBe('TRIMDIMS 64 48 0 0 64 48 0 0');
|
|
119
122
|
});
|
|
120
123
|
test('is a no-op crop when content touches every edge', () => {
|
|
121
124
|
const dir = scene();
|
|
@@ -150,7 +153,7 @@ describe('runTrimAlign — aligned output', () => {
|
|
|
150
153
|
// reference-sized canvas (preserving aspect) for a 1:1 overlay.
|
|
151
154
|
expect(pngSize(out)).toEqual({ width: 60, height: 40 });
|
|
152
155
|
expect(pngSize(aligned)).toEqual({ width: 100, height: 50 });
|
|
153
|
-
expect(result.stdout.trim()).toBe('TRIMDIMS 60 40 100 50 200 200');
|
|
156
|
+
expect(result.stdout.trim()).toBe('TRIMDIMS 60 40 100 50 200 200 30 50');
|
|
154
157
|
});
|
|
155
158
|
test('fits a wide render into a square reference without distortion (transparent letterbox)', () => {
|
|
156
159
|
const dir = scene();
|
|
@@ -222,7 +225,7 @@ describe('runTrimAlign — aligned output', () => {
|
|
|
222
225
|
const result = runTrimAlign([input, out, aligned, join(dir, 'nope.png')]);
|
|
223
226
|
expect(result.status).toBe(0);
|
|
224
227
|
expect(existsSync(aligned)).toBe(false);
|
|
225
|
-
expect(result.stdout.trim()).toBe('TRIMDIMS 50 30 0 0 100 100');
|
|
228
|
+
expect(result.stdout.trim()).toBe('TRIMDIMS 50 30 0 0 100 100 10 10');
|
|
226
229
|
});
|
|
227
230
|
});
|
|
228
231
|
// ---- failure contract ------------------------------------------------------------
|
|
@@ -73,7 +73,7 @@ const FAKE_CI_LINES = [
|
|
|
73
73
|
" printf '\\x89PNG\\r\\n\\x1a\\n' > \"$aligned_png\"",
|
|
74
74
|
' printf \'aligned:%s\' "$(basename "$in_png")" >> "$aligned_png"',
|
|
75
75
|
' fi',
|
|
76
|
-
' echo "TRIMDIMS 320 640 160 320 400 800"',
|
|
76
|
+
' echo "TRIMDIMS 320 640 160 320 400 800 40 77"',
|
|
77
77
|
' exit 0 ;;',
|
|
78
78
|
' *) exit 0 ;;',
|
|
79
79
|
'esac',
|
|
@@ -328,6 +328,10 @@ describe('android render runtime — render + trim (happy path)', () => {
|
|
|
328
328
|
reference_px: [160, 320],
|
|
329
329
|
// the fake helper's TRIMDIMS pre-trim source px (fields 5-6)
|
|
330
330
|
source_px: [400, 800],
|
|
331
|
+
// …and the crop origin (fields 7-8): where the trimmed image sits in the
|
|
332
|
+
// source, so geometry captured in window coordinates can be placed on
|
|
333
|
+
// the trimmed bytes (the 2026-08-01 spotlight diagnosis).
|
|
334
|
+
trim_offset_px: [40, 77],
|
|
331
335
|
});
|
|
332
336
|
expect(isPng(artifact(project, 'ui-fidelity/rendered/XProof.png'))).toBe(true);
|
|
333
337
|
expect(isPng(artifact(project, 'ui-fidelity/aligned/XProof.png'))).toBe(true);
|