@tileflow/capture 0.1.0-alpha.30 → 0.1.0-alpha.32

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 CHANGED
@@ -1,5 +1,10 @@
1
1
  # @tileflow/capture
2
2
 
3
+ For the complete CLI workflow, use `describe`, `inspect`, `capture`, `compare`, and Map DevTools (`preview`)
4
+ as described in the [CLI guide](https://github.com/tileflow/tileflow-sdk/blob/main/packages/cli/README.md).
5
+ New still captures include their normalized `definition` for later review. The CLI stores immutable
6
+ capture IDs so `compare --before <id> --after <id>` can reuse evidence without rendering again.
7
+
3
8
  Headless Tileflow map capture for Node.js. Produce PNGs with versioned receipts, compare reviewed
4
9
  baselines, or inspect differences between deliberate renders. Use the
5
10
  [CLI](https://github.com/tileflow/tileflow-sdk/blob/main/packages/cli/README.md) for ordinary terminal
@@ -243,7 +248,9 @@ the perceptual metric and optional diff image are additional evidence. Never upd
243
248
  merely to make a failing comparison pass.
244
249
 
245
250
  `compareTileflowCapturesForReview` compares two deliberate renders with different styles while
246
- requiring compatible framing, renderer, and data identity. `analyzeTileflowCaptureReference` analyzes
251
+ requiring compatible framing, renderer, and data identity. It accepts captures with or without a
252
+ retained `definition`; when present, that definition must match the explicit review definition.
253
+ `analyzeTileflowCaptureReference` analyzes
247
254
  an external PNG without claiming receipt compatibility. Neither operation approves a baseline.
248
255
  See the [receipt and comparison reference](https://github.com/tileflow/tileflow-sdk/blob/main/packages/capture/docs/receipts-and-comparison.md),
249
256
  also included under `docs/` in the installed package, for identities, metrics, and limits.
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Browser } from 'playwright';
2
2
  import { T as TileflowCaptureRendererIdentity, a as TileflowShotReceiptV1, b as TileflowCaptureReceipt, c as TileflowCaptureDataInput, d as TileflowCaptureWorldIdentity } from './receipt-CfZkzyXd.js';
3
3
  export { C as CreateTileflowCaptureReceiptInput, e as CreateTileflowShotReceiptInput, f as TileflowCaptureDataBindings, g as TileflowCaptureDataCapabilities, h as TileflowCaptureDataIdentity, i as TileflowCaptureDataSemantics, j as TileflowCaptureDataSource, k as TileflowCaptureVectorIdentity, l as TileflowCaptureVerification, m as createTileflowCaptureReceipt, n as createTileflowCaptureRendererIdentity, o as createTileflowShotReceipt, p as parseTileflowCaptureReceipt, q as parseTileflowShotReceipt, s as serializeTileflowCaptureReceipt, r as serializeTileflowShotReceipt, t as tileflowCaptureReceiptLimits, u as tileflowCaptureReceiptSchemaVersion, v as tileflowCaptureRuntime, w as tileflowShotReceiptLimits, x as tileflowShotReceiptSchemaVersion, y as validateTileflowCaptureReceipt, z as validateTileflowShotReceipt } from './receipt-CfZkzyXd.js';
4
- import { NormalizedTileflowCaptureShot, TileflowCaptureScene, MapLibreStyle, NormalizedTileflowCaptureScene } from '@tileflow/core';
4
+ import { NormalizedTileflowCaptureShot, NormalizedTileflowCaptureScene, TileflowCaptureScene, MapLibreStyle } from '@tileflow/core';
5
5
  import { TileflowBuildAsset, TileflowIconResolutionOptions, TileflowBuildArtifacts } from '@tileflow/dev/artifacts';
6
6
 
7
7
  type TileflowBrowserInstallProgress = 'installing' | 'installed';
@@ -90,6 +90,10 @@ type TileflowCaptureOptions = {
90
90
  };
91
91
  type CreateTileflowCaptureSessionOptions = Omit<TileflowCaptureOptions, 'scenes'>;
92
92
  type TileflowCapture = {
93
+ /** Concrete normalized frame retained for later review without rendering again. */
94
+ definition?: NormalizedTileflowCaptureScene & {
95
+ theme: string;
96
+ };
93
97
  scene: string;
94
98
  map: string;
95
99
  theme: string;
package/dist/index.js CHANGED
@@ -350,6 +350,7 @@ var tileflowBrowserModule = `${readFileSync2(
350
350
  globalThis.__tileflowRegisterContourProtocol = registerTileflowContourProtocol;
351
351
  globalThis.__tileflowRegisterPmtilesProtocol = registerTileflowPmtilesProtocol;
352
352
  globalThis.__tileflowAttachAtmosphere = attachTileflowAtmosphere;
353
+ globalThis.__tileflowAttachNotices = attachTileflowNotices;
353
354
  globalThis.__tileflowCreateThemeController = createTileflowThemeController;`;
354
355
  async function captureStandaloneTileflowScene(input) {
355
356
  if (input.scene.target.kind !== "map") {
@@ -1010,6 +1011,8 @@ window.__tileflowCaptureLoad = async function(input) {
1010
1011
  window.__tileflowMap = map;
1011
1012
  window.__tileflowCaptureStyle = input.style;
1012
1013
  window.__tileflowAttachAtmosphere(map);
1014
+ // Notices such as "Not for navigation" are part of the map, so captured images keep them.
1015
+ window.__tileflowAttachNotices(map);
1013
1016
  return await waitForMapEvent(map, "load", input.mapEventTimeoutMs);
1014
1017
  } catch (error) {
1015
1018
  return {status: "failed", reason: "error", message: String(error?.message || error || "")};
@@ -2689,6 +2692,7 @@ var TileflowCaptureSessionImpl = class {
2689
2692
  width: rendered.width
2690
2693
  });
2691
2694
  captures.push({
2695
+ definition: scene,
2692
2696
  scene: sceneName,
2693
2697
  map: scene.map,
2694
2698
  theme: scene.theme,
@@ -3769,7 +3773,9 @@ function snapshotReviewInputs(leftInput, rightInput) {
3769
3773
  }
3770
3774
  function inspectReviewInput(input, role) {
3771
3775
  const wrapper = readPlainDataRecord(input, `${role} review input`, ["capture", "definition"]);
3772
- const capture = readPlainDataRecord(wrapper.capture, `${role} capture`, reviewCaptureKeys);
3776
+ const capture = readPlainDataRecord(wrapper.capture, `${role} capture`, reviewCaptureKeys, [
3777
+ "definition"
3778
+ ]);
3773
3779
  const definition = clonePlainDataValue(
3774
3780
  wrapper.definition,
3775
3781
  `${role} definition`
@@ -3786,6 +3792,12 @@ function inspectReviewInput(input, role) {
3786
3792
  const png = requireReviewPng(capture.png, role);
3787
3793
  return {
3788
3794
  capture: {
3795
+ ...capture.definition === void 0 ? {} : {
3796
+ definition: clonePlainDataValue(
3797
+ capture.definition,
3798
+ `${role} capture.definition`
3799
+ )
3800
+ },
3789
3801
  scene: capture.scene,
3790
3802
  map: capture.map,
3791
3803
  theme: capture.theme,
@@ -3940,7 +3952,7 @@ function clonePlainDataValue(value, path, state = {
3940
3952
  state.ancestors.delete(value);
3941
3953
  }
3942
3954
  }
3943
- function readPlainDataRecord(value, path, expectedKeys) {
3955
+ function readPlainDataRecord(value, path, expectedKeys, optionalKeys = []) {
3944
3956
  if (!value || typeof value !== "object" || Array.isArray(value)) {
3945
3957
  throw invalidReview(`The ${path} must be a plain data object.`);
3946
3958
  }
@@ -3964,7 +3976,7 @@ function readPlainDataRecord(value, path, expectedKeys) {
3964
3976
  entries.push([key, descriptor.value]);
3965
3977
  }
3966
3978
  if (expectedKeys) {
3967
- const actual = entries.map(([key]) => key).sort(compareCodeUnits5);
3979
+ const actual = entries.map(([key]) => key).filter((key) => !optionalKeys.includes(key)).sort(compareCodeUnits5);
3968
3980
  const wanted = [...expectedKeys].sort(compareCodeUnits5);
3969
3981
  if (actual.length !== wanted.length || actual.some((key, index) => key !== wanted[index])) {
3970
3982
  throw invalidReview(`The ${path} contains missing or unsupported fields.`);
@@ -3983,6 +3995,9 @@ async function validateReviewCapture(input, role) {
3983
3995
  if (!sameCanonicalValue(input.definition, definition)) {
3984
3996
  throw invalidReview(`The ${role} review definition must be the exact normalized shape.`);
3985
3997
  }
3998
+ if (input.capture.definition !== void 0 && !sameCanonicalValue(input.capture.definition, definition)) {
3999
+ throw invalidReview(`The ${role} retained capture definition does not match its review.`);
4000
+ }
3986
4001
  let parsedReceipt;
3987
4002
  try {
3988
4003
  parsedReceipt = validateTileflowCaptureReceipt(input.capture.receipt);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tileflow/capture",
3
- "version": "0.1.0-alpha.30",
3
+ "version": "0.1.0-alpha.32",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Deterministic local visual capture and comparison for Tileflow maps.",
6
6
  "engines": {
@@ -48,8 +48,8 @@
48
48
  "access": "public"
49
49
  },
50
50
  "dependencies": {
51
- "@tileflow/core": ">=0.1.0-alpha.34 <0.1.0-beta.0",
52
- "@tileflow/dev": ">=0.1.0-alpha.31 <0.1.0-beta.0",
51
+ "@tileflow/core": ">=0.1.0-alpha.37 <0.1.0-beta.0",
52
+ "@tileflow/dev": ">=0.1.0-alpha.34 <0.1.0-beta.0",
53
53
  "maplibre-gl": "6.13.0",
54
54
  "pixelmatch": "7.2.0",
55
55
  "playwright": "1.62.1",
@@ -68,12 +68,12 @@
68
68
  "vite": "^8.0.16",
69
69
  "vue": "^3.5.43",
70
70
  "webpack": "5.108.3",
71
- "@tileflow/maps": "0.1.0-alpha.8",
72
71
  "@tileflow/next": "0.1.0-alpha.25",
73
- "@tileflow/react": "0.1.0-alpha.29",
74
- "@tileflow/svelte": "0.1.0-alpha.28",
72
+ "@tileflow/maps": "0.1.0-alpha.11",
73
+ "@tileflow/react": "0.1.0-alpha.32",
74
+ "@tileflow/svelte": "0.1.0-alpha.30",
75
75
  "@tileflow/vite": "0.1.0-alpha.25",
76
- "@tileflow/vue": "0.1.0-alpha.28",
76
+ "@tileflow/vue": "0.1.0-alpha.30",
77
77
  "@tileflow/webpack": "0.1.0-alpha.25"
78
78
  },
79
79
  "scripts": {