@opul/cli 0.1.1 → 0.1.2

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/index.js +43 -13
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -280,7 +280,11 @@ function overlayInitSource() {
280
280
  lower.style.cssText = "position:absolute;left:24px;bottom:24px;max-width:60%;background:" + INK2 + ";color:" + PAPER + ";font-size:16px;font-weight:600;line-height:1.2;letter-spacing:-0.025em;padding:8px 12px;border-radius:6px;opacity:0;transition:opacity 150ms ease;white-space:nowrap;";
281
281
  root.appendChild(lower);
282
282
  root.appendChild(cursor);
283
- (document.body || document.documentElement).appendChild(root);
283
+ document.documentElement.appendChild(root);
284
+ }
285
+ function ensure() {
286
+ if (!root || !document.documentElement.contains(root))
287
+ build();
284
288
  }
285
289
  function ready() {
286
290
  return new Promise((res) => {
@@ -298,6 +302,7 @@ function overlayInitSource() {
298
302
  const easeOutCubic = (t) => 1 - Math.pow(1 - t, 3);
299
303
  function move2(x, y, dur) {
300
304
  return new Promise((res) => {
305
+ ensure();
301
306
  const sx = pos.x;
302
307
  const sy = pos.y;
303
308
  const dx = x - sx;
@@ -321,6 +326,7 @@ function overlayInitSource() {
321
326
  }
322
327
  function click() {
323
328
  return new Promise((res) => {
329
+ ensure();
324
330
  cursor.animate([
325
331
  { transform: "translate(" + pos.x + "px," + pos.y + "px) scale(1)" },
326
332
  {
@@ -340,6 +346,7 @@ function overlayInitSource() {
340
346
  }
341
347
  function showLower(text) {
342
348
  return new Promise((res) => {
349
+ ensure();
343
350
  lower.textContent = text;
344
351
  void lower.offsetWidth;
345
352
  lower.style.opacity = "1";
@@ -348,6 +355,7 @@ function overlayInitSource() {
348
355
  }
349
356
  function hideLower2() {
350
357
  return new Promise((res) => {
358
+ ensure();
351
359
  lower.style.opacity = "0";
352
360
  setTimeout(res, 150);
353
361
  });
@@ -487,6 +495,7 @@ async function runStep(page, cast, step) {
487
495
  }
488
496
  case "hover": {
489
497
  const c2 = await centerOf(page, step.selector, timeout);
498
+ await ensureReady(page);
490
499
  if (step.name)
491
500
  await moveOverlay(page, c2.x, c2.y, MOVE_MS, step.name);
492
501
  else
@@ -497,6 +506,7 @@ async function runStep(page, cast, step) {
497
506
  }
498
507
  case "click": {
499
508
  const c2 = await centerOf(page, step.selector, timeout);
509
+ await ensureReady(page);
500
510
  await moveOverlay(page, c2.x, c2.y, MOVE_MS, step.name);
501
511
  await sleep(PRE_CLICK_MS);
502
512
  await overlayClick(page);
@@ -508,6 +518,7 @@ async function runStep(page, cast, step) {
508
518
  }
509
519
  case "type": {
510
520
  const c2 = await centerOf(page, step.selector, timeout);
521
+ await ensureReady(page);
511
522
  await moveOverlay(page, c2.x, c2.y, MOVE_MS, step.name);
512
523
  await sleep(PRE_CLICK_MS);
513
524
  await overlayClick(page);
@@ -889,29 +900,48 @@ function captureSource() {
889
900
  if (w.__opulCap || !w.__opulEmit)
890
901
  return;
891
902
  w.__opulCap = true;
903
+ const uniq = (s) => {
904
+ try {
905
+ return document.querySelectorAll(s).length === 1;
906
+ } catch {
907
+ return false;
908
+ }
909
+ };
910
+ const q = (s) => s.replace(/'/g, "\\'");
892
911
  const sel = (el) => {
893
912
  if (!el || el.nodeType !== 1)
894
913
  return null;
895
914
  const dd = el.closest("[data-demo]");
896
915
  if (dd)
897
916
  return `[data-demo='${dd.getAttribute("data-demo")}']`;
898
- if (el.id && document.querySelectorAll(`#${CSS.escape(el.id)}`).length === 1)
917
+ if (el.id && uniq(`#${CSS.escape(el.id)}`))
899
918
  return `#${CSS.escape(el.id)}`;
919
+ const al = el.getAttribute("aria-label");
920
+ if (al && uniq(`[aria-label='${q(al)}']`))
921
+ return `[aria-label='${q(al)}']`;
922
+ if (el.tagName === "A") {
923
+ const href = el.getAttribute("href");
924
+ if (href && href !== "#" && uniq(`a[href='${q(href)}']`))
925
+ return `a[href='${q(href)}']`;
926
+ }
900
927
  const parts = [];
901
928
  let node = el;
902
- while (node && node.nodeType === 1 && parts.length < 4) {
929
+ while (node && node.nodeType === 1 && node.tagName !== "HTML") {
903
930
  if (node.id) {
904
931
  parts.unshift(`#${CSS.escape(node.id)}`);
905
- break;
906
- }
907
- let part = node.tagName.toLowerCase();
908
- const parent = node.parentElement;
909
- if (parent) {
910
- const same = Array.from(parent.children).filter((c2) => c2.tagName === node.tagName);
911
- if (same.length > 1)
912
- part += `:nth-of-type(${same.indexOf(node) + 1})`;
932
+ if (uniq(parts.join(" > ")))
933
+ return parts.join(" > ");
934
+ } else {
935
+ const parent = node.parentElement;
936
+ let part = node.tagName.toLowerCase();
937
+ if (parent) {
938
+ const idx = Array.from(parent.children).indexOf(node) + 1;
939
+ part += `:nth-child(${idx})`;
940
+ }
941
+ parts.unshift(part);
942
+ if (uniq(parts.join(" > ")))
943
+ return parts.join(" > ");
913
944
  }
914
- parts.unshift(part);
915
945
  node = node.parentElement;
916
946
  }
917
947
  return parts.join(" > ");
@@ -1403,7 +1433,7 @@ function fail4(msg) {
1403
1433
 
1404
1434
  // src/index.ts
1405
1435
  var program = new Command();
1406
- program.name("opul").description("Record a product demo from your running web app.").version("0.1.0");
1436
+ program.name("opul").description("Record a product demo from your running web app.").version("0.1.2");
1407
1437
  program.command("init").description("Create an opul.steps.json stub").option("--out <file>", "output path", "opul.steps.json").action(initCommand);
1408
1438
  program.command("doctor").description("Check that Chrome and ffmpeg are installed").action(doctorCommand);
1409
1439
  program.command("record").description("Click through your app to generate a steps file").option("--url <url>", "app URL to open").option("--out <file>", "steps file to write", "opul.steps.json").option("--name <name>", "product/demo name").option("--chrome <path>", "path to Chrome executable").action(recordCommand);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opul/cli",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Record a polished product-demo video from your running web app — from the terminal.",
5
5
  "type": "module",
6
6
  "bin": {