demowright 0.1.0 → 2.0.4

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/config.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { n as defaultOptions } from "./setup-CfPylVYx.mjs";
1
+ import { n as defaultOptions } from "./setup-x03ZBQi1.mjs";
2
2
  import { createRequire } from "node:module";
3
3
  //#region src/config.ts
4
4
  /**
package/dist/helpers.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { a as getTtsProvider, o as init_hud_registry, s as isHudActive, u as storeAudioSegment } from "./hud-registry-CptkyV32.mjs";
1
+ import { c as isHudActive, d as storeAudioSegment, o as getTtsProvider, s as init_hud_registry } from "./hud-registry-D74THrir.mjs";
2
2
  //#region src/helpers.ts
3
3
  init_hud_registry();
4
4
  /**
@@ -32,6 +32,9 @@ function getTtsProvider(page) {
32
32
  function getGlobalTtsProvider() {
33
33
  return g.__qaHudGlobal.tts || false;
34
34
  }
35
+ function getCurrentSpec() {
36
+ return g.__qaHudGlobal.currentSpec;
37
+ }
35
38
  function setGlobalOutputDir(dir) {
36
39
  g.__qaHudGlobal.outputDir = dir;
37
40
  }
@@ -87,4 +90,4 @@ var init_hud_registry = __esmMin((() => {
87
90
  renderJobs = /* @__PURE__ */ new WeakMap();
88
91
  }));
89
92
  //#endregion
90
- export { getTtsProvider as a, registerHudPage as c, storeRenderJob as d, getRenderJob as i, setGlobalOutputDir as l, getGlobalOutputDir as n, init_hud_registry as o, getGlobalTtsProvider as r, isHudActive as s, getAudioSegments as t, storeAudioSegment as u };
93
+ export { getRenderJob as a, isHudActive as c, storeAudioSegment as d, storeRenderJob as f, getGlobalTtsProvider as i, registerHudPage as l, getCurrentSpec as n, getTtsProvider as o, getGlobalOutputDir as r, init_hud_registry as s, getAudioSegments as t, setGlobalOutputDir as u };
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { r as AudioWriter, t as applyHud } from "./setup-CfPylVYx.mjs";
2
- import { o as init_hud_registry, r as getGlobalTtsProvider } from "./hud-registry-CptkyV32.mjs";
1
+ import { r as AudioWriter, t as applyHud } from "./setup-x03ZBQi1.mjs";
2
+ import { i as getGlobalTtsProvider, s as init_hud_registry } from "./hud-registry-D74THrir.mjs";
3
3
  import { buildFfmpegCommand, createVideoScript, t as init_video_script } from "./video-script.mjs";
4
4
  import { annotate, caption, clickEl, hudWait, moveTo, moveToEl, narrate, subtitle, typeKeys } from "./helpers.mjs";
5
5
  import { installAutoAnnotate } from "./auto-annotate.mjs";
@@ -1,5 +1,5 @@
1
1
  import { r as __toCommonJS } from "./chunk-C0p4GxOx.mjs";
2
- import { c as registerHudPage, i as getRenderJob, l as setGlobalOutputDir, o as init_hud_registry, t as getAudioSegments } from "./hud-registry-CptkyV32.mjs";
2
+ import { a as getRenderJob, l as registerHudPage, n as getCurrentSpec, s as init_hud_registry, t as getAudioSegments, u as setGlobalOutputDir } from "./hud-registry-D74THrir.mjs";
3
3
  import { n as video_script_exports, t as init_video_script } from "./video-script.mjs";
4
4
  import { execSync } from "node:child_process";
5
5
  import { existsSync, mkdirSync, unlinkSync, writeFileSync } from "node:fs";
@@ -386,9 +386,10 @@ async function applyHud(context, options) {
386
386
  };
387
387
  const domInjector = getDomInjector();
388
388
  const videoPaths = [];
389
+ const pageNames = [];
389
390
  async function setupPage(page) {
390
391
  registerHudPage(page, { tts: opts.tts });
391
- wrapNavigation(page, domInjector, hudOpts);
392
+ wrapNavigation(page, domInjector, hudOpts, pageNames);
392
393
  if (opts.actionDelay > 0) patchPageDelay(page, opts.actionDelay);
393
394
  if (audioWriter) {
394
395
  await setupAudioCapture(page, audioWriter);
@@ -424,7 +425,7 @@ async function applyHud(context, options) {
424
425
  buildAndSaveAudioTrack(segments, audioPath, firstSegMs);
425
426
  } else if (audioWriter.totalSamples > 0) audioWriter.save(audioPath);
426
427
  else return;
427
- const mp4Path = join(outDir, audioPath.split("/").pop().replace(/\.wav$/, ".mp4"));
428
+ const mp4Path = join(outDir, `${getCurrentSpec() ?? pageNames[0] ?? `demowright-${Date.now()}`}.mp4`);
428
429
  const trimSec = (audioOffsetMs / 1e3).toFixed(3);
429
430
  let muxed = false;
430
431
  for (const videoPath of videoPaths) try {
@@ -447,17 +448,32 @@ async function applyHud(context, options) {
447
448
  /**
448
449
  * Wraps page navigation methods to inject HUD DOM after each navigation.
449
450
  */
450
- function wrapNavigation(page, domInjector, hudOpts) {
451
+ function wrapNavigation(page, domInjector, hudOpts, pageNames) {
451
452
  async function injectDom() {
452
453
  try {
453
454
  if (page.isClosed()) return;
454
455
  await page.evaluate(domInjector, hudOpts);
455
456
  } catch {}
456
457
  }
458
+ async function captureTitle() {
459
+ if (!pageNames) return;
460
+ try {
461
+ if (page.isClosed()) return;
462
+ let title = await page.title();
463
+ if (!title) title = await page.evaluate(() => {
464
+ return document.querySelector("h1, .brand, [class*='logo'], header h2")?.textContent?.trim() ?? "";
465
+ });
466
+ if (title) {
467
+ const clean = title.replace(/[^a-z0-9]+/gi, "-").replace(/^-|-$/g, "").toLowerCase().slice(0, 60);
468
+ if (clean && !clean.startsWith("loading")) pageNames.push(clean);
469
+ }
470
+ } catch {}
471
+ }
457
472
  const originalGoto = page.goto.bind(page);
458
473
  page.goto = async function(...args) {
459
474
  const result = await originalGoto(...args);
460
475
  await injectDom();
476
+ await captureTitle();
461
477
  return result;
462
478
  };
463
479
  const originalReload = page.reload.bind(page);
package/dist/setup.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { n as defaultOptions, t as applyHud } from "./setup-CfPylVYx.mjs";
1
+ import { n as defaultOptions, t as applyHud } from "./setup-x03ZBQi1.mjs";
2
2
  export { applyHud, defaultOptions };
@@ -1,5 +1,5 @@
1
1
  import { n as __exportAll, t as __esmMin } from "./chunk-C0p4GxOx.mjs";
2
- import { a as getTtsProvider, d as storeRenderJob, n as getGlobalOutputDir, o as init_hud_registry, r as getGlobalTtsProvider, s as isHudActive, u as storeAudioSegment } from "./hud-registry-CptkyV32.mjs";
2
+ import { c as isHudActive, d as storeAudioSegment, f as storeRenderJob, i as getGlobalTtsProvider, o as getTtsProvider, r as getGlobalOutputDir, s as init_hud_registry } from "./hud-registry-D74THrir.mjs";
3
3
  import { mkdirSync, writeFileSync } from "node:fs";
4
4
  import { join } from "node:path";
5
5
  //#region src/video-script.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "demowright",
3
- "version": "0.1.0",
3
+ "version": "2.0.4",
4
4
  "description": "Playwright video production plugin — cursor overlay, keystroke badges, TTS narration, and narration-driven video scripts for test recordings",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -35,7 +35,8 @@
35
35
  }
36
36
  },
37
37
  "publishConfig": {
38
- "access": "public"
38
+ "access": "public",
39
+ "provenance": true
39
40
  },
40
41
  "scripts": {
41
42
  "build": "tsdown",
package/register.cjs CHANGED
@@ -17,12 +17,13 @@ if (process.env.QA_HUD === "0") {
17
17
  const originalLoad = Module._load;
18
18
  let contextProtoPatched = false;
19
19
 
20
+ // Track the current spec file for naming output videos
21
+ const g = globalThis;
22
+ if (!g.__qaHudGlobal) g.__qaHudGlobal = { audioSegments: new Map() };
23
+
20
24
  Module._load = function qaHudLoad(request, parent, isMain) {
21
25
  const result = originalLoad.call(this, request, parent, isMain);
22
26
 
23
- // We need to patch BrowserContext.prototype, but it's not exported.
24
- // Instead, we patch the BrowserType launch methods to intercept
25
- // the Browser they return, then patch Browser.newContext.
26
27
  if (!contextProtoPatched && request === "playwright-core") {
27
28
  contextProtoPatched = true;
28
29
 
@@ -56,6 +57,15 @@ if (process.env.QA_HUD === "0") {
56
57
 
57
58
  let applyHudCache = null;
58
59
  async function applyHudToContext(context) {
60
+ // Detect spec filename from the call stack or Playwright context metadata
61
+ try {
62
+ const stack = new Error().stack || "";
63
+ const specMatch = stack.match(/([\/\\][\w.-]+\.spec\.[tj]s)/);
64
+ if (specMatch) {
65
+ const path = require("node:path");
66
+ g.__qaHudGlobal.currentSpec = path.basename(specMatch[1]).replace(/\.spec\.[tj]s$/, "");
67
+ }
68
+ } catch {}
59
69
  try {
60
70
  if (!applyHudCache) {
61
71
  const mod = await import("./src/setup.ts");