waygraph 0.10.6 → 0.10.8

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 (2) hide show
  1. package/dist/cli.js +79 -12
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -1286,10 +1286,12 @@ function extractVerifyHighlights(block, resultTag) {
1286
1286
  * __wgNext no-ops once already consumed - but looked live when it wasn't).
1287
1287
  * Disables the button and mem-key textareas, and swaps whichever gate
1288
1288
  * text was showing (manual button or "Auto-advancing...") to "Running...".
1289
+ * When autoCollapsePanel is set (QA video / autoplay), tuck the stepper
1290
+ * away so ring captions + the app fill the frame - Dan: stepper + auto panels.
1289
1291
  */
1290
- async function markStepRunning(page) {
1292
+ async function markStepRunning(page, opts) {
1291
1293
  await page
1292
- .evaluate(() => {
1294
+ .evaluate(({ autoCollapsePanel }) => {
1293
1295
  const runBtn = document.getElementById("wg-run");
1294
1296
  if (runBtn) {
1295
1297
  runBtn.disabled = true;
@@ -1300,7 +1302,15 @@ async function markStepRunning(page) {
1300
1302
  document.querySelectorAll("#wg-panel textarea[data-key]").forEach((ta) => {
1301
1303
  ta.disabled = true;
1302
1304
  });
1303
- })
1305
+ if (autoCollapsePanel) {
1306
+ const panel = document.getElementById("wg-panel");
1307
+ if (panel) {
1308
+ panel.classList.add("wg-collapsed");
1309
+ const toggle = panel.querySelector("[data-wg-toggle]");
1310
+ if (toggle) toggle.textContent = "Show";
1311
+ }
1312
+ }
1313
+ }, { autoCollapsePanel: !!(opts && opts.autoCollapsePanel) })
1304
1314
  .catch(() => {});
1305
1315
  }
1306
1316
 
@@ -1815,7 +1825,9 @@ async function runStepMode(engine, start, end, context, page, mem, resolved, slo
1815
1825
  }
1816
1826
  }
1817
1827
  }
1818
- await markStepRunning(page);
1828
+ const recordingVideo = !!process.env.WAYGRAPH_VIDEO;
1829
+ const autoCollapsePanel = recordingVideo || (await currentAutoplay());
1830
+ await markStepRunning(page, { autoCollapsePanel });
1819
1831
  // NavBlock click-nav: label the upcoming Locator.click demo cursor as
1820
1832
  // "nav: <block>" so pia/demo watchers see cursor+pulse on click nav
1821
1833
  // (not only on regular Block clicks).
@@ -1997,6 +2009,18 @@ async function runChainedFlows(chainFlow, chainFlows, context, mem, page) {
1997
2009
  }
1998
2010
  }
1999
2011
 
2012
+ /** Parses WAYGRAPH_VIDEO_VIEWPORT / --video-viewport: "1920x1080" or "1920,1080". */
2013
+ function parseVideoViewport(raw) {
2014
+ if (!raw || !raw.trim()) return null;
2015
+ const m = raw.trim().match(/^(\d{3,5})[xX,](\d{3,5})$/);
2016
+ if (!m) return null;
2017
+ const width = Number(m[1]);
2018
+ const height = Number(m[2]);
2019
+ if (!Number.isFinite(width) || !Number.isFinite(height)) return null;
2020
+ if (width < 320 || height < 240 || width > 7680 || height > 4320) return null;
2021
+ return { width, height };
2022
+ }
2023
+
2000
2024
  async function main() {
2001
2025
  const projectDir = process.argv[2];
2002
2026
  const spec = process.argv[3];
@@ -2170,6 +2194,13 @@ async function main() {
2170
2194
  videoDir = videoEnv === "1" ? join(projectDir, ".waygraph-videos") : videoEnv;
2171
2195
  mkdirSync(videoDir, { recursive: true });
2172
2196
  }
2197
+ /** Fixed 16:9 capture for --video (demo QA and headless run). Step+video no longer maximizes. */
2198
+ const DEFAULT_VIDEO_VIEWPORT = { width: 1920, height: 1080 };
2199
+ const DEFAULT_RUN_VIDEO_VIEWPORT = { width: 1280, height: 720 };
2200
+ const videoViewportParsed = parseVideoViewport(process.env.WAYGRAPH_VIDEO_VIEWPORT);
2201
+ const fixedVideoViewport = videoDir
2202
+ ? (videoViewportParsed ?? (step ? DEFAULT_VIDEO_VIEWPORT : DEFAULT_RUN_VIDEO_VIEWPORT))
2203
+ : null;
2173
2204
  const engine = new Engine({ headless: !headed, slowMo });
2174
2205
  let result;
2175
2206
  // Non-interactive execution (no --step) runs the whole chain as one
@@ -2200,14 +2231,20 @@ async function main() {
2200
2231
  const browser = await chromium.launch({
2201
2232
  headless: !headed,
2202
2233
  slowMo,
2203
- args: step ? ["--start-maximized"] : [],
2234
+ // Maximized only for interactive step mode WITHOUT a fixed video viewport -
2235
+ // recording uses a locked 16:9 viewport so .webm has no gray letterboxing.
2236
+ args: step && !fixedVideoViewport ? ["--start-maximized"] : [],
2204
2237
  ...(executablePath ? { executablePath } : {}),
2205
2238
  });
2206
- const contextOpts = step
2207
- ? { baseURL, viewport: null }
2208
- : { baseURL, viewport: { width: 1280, height: 720 } };
2239
+ const contextOpts = fixedVideoViewport
2240
+ ? { baseURL, viewport: fixedVideoViewport }
2241
+ : step
2242
+ ? { baseURL, viewport: null }
2243
+ : { baseURL, viewport: { width: 1280, height: 720 } };
2209
2244
  if (videoDir) {
2210
- contextOpts.recordVideo = { dir: videoDir };
2245
+ contextOpts.recordVideo = fixedVideoViewport
2246
+ ? { dir: videoDir, size: fixedVideoViewport }
2247
+ : { dir: videoDir };
2211
2248
  }
2212
2249
  const context = await browser.newContext(contextOpts);
2213
2250
  let pageForVideo = null;
@@ -2693,6 +2730,7 @@ function initCommand(projectName) {
2693
2730
  process.exit(1);
2694
2731
  }
2695
2732
  const targetDir = resolve(process.cwd(), projectName);
2733
+ const pkgName = basename(targetDir);
2696
2734
  if (existsSync(targetDir)) {
2697
2735
  const entries = readdirSync(targetDir);
2698
2736
  if (entries.length > 0) {
@@ -2715,10 +2753,10 @@ function initCommand(projectName) {
2715
2753
  rmSync(gitignoreSrc);
2716
2754
  }
2717
2755
  const packageJsonPath = join(targetDir, "package.json");
2718
- writeFileSync(packageJsonPath, readFileSync(packageJsonPath, "utf-8").replaceAll("__PROJECT_NAME__", projectName));
2719
- console.log(`Scaffolded ${projectName}/`);
2756
+ writeFileSync(packageJsonPath, readFileSync(packageJsonPath, "utf-8").replaceAll("__PROJECT_NAME__", pkgName));
2757
+ console.log(`Scaffolded ${pkgName}/`);
2720
2758
  console.log("");
2721
- console.log(` cd ${projectName}`);
2759
+ console.log(` cd ${relative(process.cwd(), targetDir) || pkgName}`);
2722
2760
  console.log(" npm install");
2723
2761
  console.log(" npx playwright install chromium");
2724
2762
  console.log(" npm test");
@@ -2847,6 +2885,11 @@ function parseRunFlags(argv) {
2847
2885
  }
2848
2886
  }
2849
2887
  }
2888
+ else if (a === "--video-viewport" || a.startsWith("--video-viewport=")) {
2889
+ const t = takeFlagValue(argv, i, a, "--video-viewport");
2890
+ out.videoViewport = t.value;
2891
+ i = t.nextI;
2892
+ }
2850
2893
  else if (a === "--blocks" || a.startsWith("--blocks=")) {
2851
2894
  if (a.startsWith("--blocks=")) {
2852
2895
  out.blocks = a.slice("--blocks=".length);
@@ -2873,6 +2916,21 @@ function parseRunFlags(argv) {
2873
2916
  }
2874
2917
  return out;
2875
2918
  }
2919
+ /** Parses WAYGRAPH_VIDEO_VIEWPORT / --video-viewport: "1920x1080" or "1920,1080". */
2920
+ function parseVideoViewportFlag(raw) {
2921
+ if (!raw?.trim())
2922
+ return null;
2923
+ const m = raw.trim().match(/^(\d{3,5})[xX,](\d{3,5})$/);
2924
+ if (!m)
2925
+ return null;
2926
+ const width = Number(m[1]);
2927
+ const height = Number(m[2]);
2928
+ if (!Number.isFinite(width) || !Number.isFinite(height))
2929
+ return null;
2930
+ if (width < 320 || height < 240 || width > 7680 || height > 4320)
2931
+ return null;
2932
+ return { width, height };
2933
+ }
2876
2934
  /** Writes flag values into process.env so the chain child inherits them. Flags beat prior env. */
2877
2935
  function applyRunFlags(flags, opts) {
2878
2936
  if (flags.autoPlayVideo) {
@@ -2912,6 +2970,13 @@ function applyRunFlags(flags, opts) {
2912
2970
  if (flags.video !== undefined) {
2913
2971
  process.env.WAYGRAPH_VIDEO = flags.video || "1";
2914
2972
  }
2973
+ if (flags.videoViewport !== undefined) {
2974
+ if (!parseVideoViewportFlag(flags.videoViewport)) {
2975
+ console.error('waygraph: --video-viewport must look like "1920x1080"');
2976
+ process.exit(1);
2977
+ }
2978
+ process.env.WAYGRAPH_VIDEO_VIEWPORT = flags.videoViewport;
2979
+ }
2915
2980
  if (flags.data !== undefined) {
2916
2981
  process.env.WAYGRAPH_DATA = flags.data;
2917
2982
  }
@@ -3071,11 +3136,13 @@ Primary (less is more):
3071
3136
  --data '{...}' Mem seed JSON (or inline flow({...}))
3072
3137
  --auto-next Auto-advance steps (alias: --autoplay)
3073
3138
  --auto-play-video QA: --auto-next + --video (+ step)
3139
+ --video-viewport WxH Recording size (default demo: 1920x1080)
3074
3140
  --title / --base-url
3075
3141
  waygraph run [--blocks <flow|file|spec>] Execute (no overlay unless --step)
3076
3142
  --data '{...}'
3077
3143
  --non-headless Show browser
3078
3144
  --video [dir] Record .webm
3145
+ --video-viewport WxH Recording size (default run: 1280x720)
3079
3146
 
3080
3147
  Also:
3081
3148
  waygraph list | nav | validate | check | graph | init <name>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "waygraph",
3
- "version": "0.10.6",
3
+ "version": "0.10.8",
4
4
  "type": "module",
5
5
  "description": "A typed graph of reusable Blocks for driving a browser through E2E flows.",
6
6
  "license": "MIT",