afterbefore 0.1.5 → 0.1.6

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/index.js CHANGED
@@ -4,6 +4,7 @@ import { unlinkSync } from "fs";
4
4
  import { exec } from "child_process";
5
5
 
6
6
  // src/logger.ts
7
+ import { writeFileSync } from "fs";
7
8
  import chalk from "chalk";
8
9
  import ora from "ora";
9
10
  var BAR_WIDTH = 20;
@@ -14,7 +15,13 @@ var Logger = class {
14
15
  lastStep = 0;
15
16
  lastLabel = "";
16
17
  pipelineActive = false;
18
+ logBuffer = [];
19
+ log(level, message) {
20
+ const ts = (/* @__PURE__ */ new Date()).toISOString();
21
+ this.logBuffer.push(`${ts} [${level}] ${message}`);
22
+ }
17
23
  info(message) {
24
+ this.log("info", message);
18
25
  if (this.pipelineActive) return;
19
26
  if (this.spinner) {
20
27
  this.spinner.clear();
@@ -25,6 +32,7 @@ var Logger = class {
25
32
  }
26
33
  }
27
34
  success(message) {
35
+ this.log("ok", message);
28
36
  if (this.pipelineActive) return;
29
37
  if (this.spinner) {
30
38
  this.spinner.clear();
@@ -35,6 +43,7 @@ var Logger = class {
35
43
  }
36
44
  }
37
45
  warn(message) {
46
+ this.log("warn", message);
38
47
  if (this.spinner) {
39
48
  this.spinner.clear();
40
49
  console.log(chalk.yellow("\u26A0"), message);
@@ -44,6 +53,7 @@ var Logger = class {
44
53
  }
45
54
  }
46
55
  error(message) {
56
+ this.log("error", message);
47
57
  if (this.spinner) {
48
58
  this.spinner.clear();
49
59
  console.error(chalk.red("\u2716"), message);
@@ -53,6 +63,7 @@ var Logger = class {
53
63
  }
54
64
  }
55
65
  dim(message) {
66
+ this.log("debug", message);
56
67
  if (this.pipelineActive) return;
57
68
  if (this.spinner) {
58
69
  this.spinner.clear();
@@ -63,6 +74,7 @@ var Logger = class {
63
74
  }
64
75
  }
65
76
  spin(message) {
77
+ this.log("info", message);
66
78
  this.clearSpinner();
67
79
  this.spinner = ora(message).start();
68
80
  return this.spinner;
@@ -76,6 +88,7 @@ var Logger = class {
76
88
  this.lastLabel = "";
77
89
  this.pipelineActive = true;
78
90
  this.clearSpinner();
91
+ this.log("info", `Pipeline started (${total} steps)`);
79
92
  const text = this.renderPipeline(0, "Starting...");
80
93
  this.spinner = ora({
81
94
  text: chalk.dim(text),
@@ -86,6 +99,7 @@ var Logger = class {
86
99
  if (step === this.lastStep && label === this.lastLabel) return;
87
100
  this.lastStep = step;
88
101
  this.lastLabel = label;
102
+ this.log("step", `${step}/${this.pipelineTotal} ${label}`);
89
103
  const text = chalk.dim(this.renderPipeline(step, label));
90
104
  if (!this.spinner) {
91
105
  this.spinner = ora({
@@ -98,28 +112,33 @@ var Logger = class {
98
112
  }
99
113
  completePipeline(finished = false) {
100
114
  this.pipelineActive = false;
115
+ this.log("info", `Pipeline ${finished ? "completed" : "stopped"}`);
101
116
  if (this.spinner) {
102
117
  if (finished) {
103
118
  this.spinner.stop();
104
- const bar = "\u2588".repeat(BAR_WIDTH);
119
+ const bar = "#".repeat(BAR_WIDTH);
105
120
  console.log(`${chalk.green("\u2714")} ${bar}`);
106
121
  } else {
107
122
  this.spinner.stop();
108
123
  }
109
124
  this.spinner = null;
110
125
  } else if (finished) {
111
- const bar = "\u2588".repeat(BAR_WIDTH);
126
+ const bar = "#".repeat(BAR_WIDTH);
112
127
  console.log(`${chalk.green("\u2714")} ${bar}`);
113
128
  }
114
129
  this.pipelineTotal = 0;
115
130
  this.lastStep = 0;
116
131
  this.lastLabel = "";
117
132
  }
133
+ writeLogFile(filePath) {
134
+ if (this.logBuffer.length === 0) return;
135
+ writeFileSync(filePath, this.logBuffer.join("\n") + "\n", "utf-8");
136
+ }
118
137
  renderPipeline(step, label) {
119
138
  const total = this.pipelineTotal || 1;
120
139
  const clampedStep = Math.max(0, Math.min(step, total));
121
140
  const filled = Math.round(clampedStep / total * BAR_WIDTH);
122
- const bar = "\u2588".repeat(filled) + "\u2591".repeat(BAR_WIDTH - filled);
141
+ const bar = "#".repeat(filled) + "-".repeat(BAR_WIDTH - filled);
123
142
  return ` ${bar} ${clampedStep}/${total} ${label}`;
124
143
  }
125
144
  clearSpinner() {
@@ -1298,13 +1317,19 @@ async function captureRoutes(tasks, beforeUrl, afterUrl, outputDir, options) {
1298
1317
  tagChangedComponentInstances(afterPage, changedComponents),
1299
1318
  tagChangedComponentInstances(beforePage, changedComponents)
1300
1319
  ]);
1320
+ logger.dim(` Component detection on ${task.route}: ${changedComponents.length} source(s), ${afterInstances.length} after / ${beforeInstances.length} before instance(s)`);
1301
1321
  const afterBySource = groupBySource(afterInstances);
1302
1322
  const beforeBySource = groupBySource(beforeInstances);
1303
1323
  for (const source of changedComponents) {
1304
1324
  const afterList = afterBySource.get(source) ?? [];
1305
1325
  const beforeList = beforeBySource.get(source) ?? [];
1306
1326
  const pairCount = Math.min(afterList.length, beforeList.length);
1307
- if (pairCount === 0) continue;
1327
+ if (pairCount === 0) {
1328
+ if (afterList.length > 0 || beforeList.length > 0) {
1329
+ logger.dim(` ${source}: ${afterList.length} after / ${beforeList.length} before (skipping unpaired)`);
1330
+ }
1331
+ continue;
1332
+ }
1308
1333
  for (let pairIndex = 0; pairIndex < pairCount; pairIndex++) {
1309
1334
  const afterInstance = afterList[pairIndex];
1310
1335
  const beforeInstance = beforeList[pairIndex];
@@ -1312,13 +1337,6 @@ async function captureRoutes(tasks, beforeUrl, afterUrl, outputDir, options) {
1312
1337
  const itemSlug = `${sourceSlug}-${pairIndex + 1}`;
1313
1338
  const componentName = afterInstance.name || beforeInstance.name || source.split("/").pop() || source;
1314
1339
  const baseLabel = `${task.label} [${componentName} #${pairIndex + 1}]`;
1315
- const contextPrefix = `${task.prefix}~cmp.${itemSlug}~context`;
1316
- results.push({
1317
- route: `${baseLabel} [context]`,
1318
- prefix: contextPrefix,
1319
- beforePath,
1320
- afterPath
1321
- });
1322
1340
  const parentPrefix = `${task.prefix}~cmp.${itemSlug}~parent`;
1323
1341
  const parentBeforePath = join6(outputDir, `${parentPrefix}-before.png`);
1324
1342
  const parentAfterPath = join6(outputDir, `${parentPrefix}-after.png`);
@@ -1369,6 +1387,15 @@ async function captureRoutes(tasks, beforeUrl, afterUrl, outputDir, options) {
1369
1387
  afterPath: componentAfterPath
1370
1388
  });
1371
1389
  }
1390
+ if (parentBeforeOk && parentAfterOk || componentBeforeOk && componentAfterOk) {
1391
+ const contextPrefix = `${task.prefix}~cmp.${itemSlug}~context`;
1392
+ results.push({
1393
+ route: `${baseLabel} [context]`,
1394
+ prefix: contextPrefix,
1395
+ beforePath,
1396
+ afterPath
1397
+ });
1398
+ }
1372
1399
  }
1373
1400
  }
1374
1401
  }
@@ -1558,7 +1585,7 @@ async function compareScreenshots(captures, outputDir, threshold = 0.1, options)
1558
1585
  }
1559
1586
 
1560
1587
  // src/stages/report.ts
1561
- import { writeFileSync } from "fs";
1588
+ import { writeFileSync as writeFileSync2 } from "fs";
1562
1589
  import { join as join8 } from "path";
1563
1590
  import { execSync as execSync4 } from "child_process";
1564
1591
 
@@ -1731,11 +1758,11 @@ async function generateReport(results, outputDir, options) {
1731
1758
  await ensureDir(outputDir);
1732
1759
  const summaryMd = generateSummaryMd(results);
1733
1760
  const summaryPath = join8(outputDir, "summary.md");
1734
- writeFileSync(summaryPath, summaryMd, "utf-8");
1761
+ writeFileSync2(summaryPath, summaryMd, "utf-8");
1735
1762
  logger.success(`Written summary to ${summaryPath}`);
1736
1763
  const reportHtml = generateReportHtml(results, outputDir);
1737
1764
  const indexPath = join8(outputDir, "index.html");
1738
- writeFileSync(indexPath, reportHtml, "utf-8");
1765
+ writeFileSync2(indexPath, reportHtml, "utf-8");
1739
1766
  logger.success(`Written report to ${indexPath}`);
1740
1767
  if (options.post) {
1741
1768
  const prNumber = findPrNumber();
@@ -1838,7 +1865,7 @@ async function runPipeline(options) {
1838
1865
  const outputDir = resolve4(cwd, output, sessionName);
1839
1866
  const startTime = Date.now();
1840
1867
  try {
1841
- const version = true ? "0.1.5" : "dev";
1868
+ const version = true ? "0.1.6" : "dev";
1842
1869
  console.log(`
1843
1870
  afterbefore v${version} \xB7 Comparing against ${base}
1844
1871
  `);
@@ -1976,6 +2003,10 @@ afterbefore v${version} \xB7 Comparing against ${base}
1976
2003
  openInBrowser(resolve4(outputDir, "index.html"));
1977
2004
  }
1978
2005
  } finally {
2006
+ try {
2007
+ logger.writeLogFile(resolve4(outputDir, "debug.log"));
2008
+ } catch {
2009
+ }
1979
2010
  await cleanupRegistry.runAll();
1980
2011
  }
1981
2012
  }