@d-zero/archaeologist 3.3.2 → 3.4.0

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
@@ -26,6 +26,7 @@ URLリストを持つファイルを指定して実行します。
26
26
  - `-i, --ignore <selector>`: 無視するCSSセレクター
27
27
  - `-d, --devices <devices>`: デバイスプリセット(カンマ区切り、デフォルト: desktop-compact,mobile)
28
28
  - `--freeze <filepath>`: フリーズモード用ファイルパス
29
+ - `--combined`: 環境AとBのスクリーンショットを左右に並べた合成画像を出力
29
30
  - `--limit <number>`: 並列実行数の上限(デフォルト: 10)
30
31
  - `--debug`: デバッグモード(デフォルト: false)
31
32
  - `--verbose`: 詳細ログモード(デフォルト: false)
@@ -49,6 +50,9 @@ npx @d-zero/archaeologist -f urls.txt
49
50
  # カスタムデバイス指定
50
51
  npx @d-zero/archaeologist -f urls.txt --devices desktop,tablet,mobile
51
52
 
53
+ # 合成画像を出力(2つの環境のスクリーンショットを左右に並べて表示)
54
+ npx @d-zero/archaeologist -f urls.txt --combined
55
+
52
56
  # フリーズモード(参照用スクリーンショット作成)
53
57
  npx @d-zero/archaeologist --freeze urls.txt
54
58
  ```
@@ -9,4 +9,5 @@ export type ChildProcessParams = {
9
9
  ignore?: string;
10
10
  devices?: readonly string[];
11
11
  hooks?: readonly PageHook[];
12
+ combined?: boolean;
12
13
  };
@@ -3,6 +3,7 @@ import path from 'node:path';
3
3
  import { createChildProcess } from '@d-zero/puppeteer-dealer';
4
4
  import { delay } from '@d-zero/shared/delay';
5
5
  import c from 'ansi-colors';
6
+ import { combineImages } from './modules/combine-images.js';
6
7
  import { diffImages } from './modules/diff-images.js';
7
8
  import { diffText } from './modules/diff-text.js';
8
9
  import { diffTree } from './modules/diff-tree.js';
@@ -10,7 +11,7 @@ import { getData } from './modules/get-data.js';
10
11
  import { normalizeTextDocument } from './modules/normalize-text-document.js';
11
12
  import { score } from './utils.js';
12
13
  createChildProcess((param) => {
13
- const { list, dir, types = ['image', 'dom', 'text'], selector, ignore, devices, } = param;
14
+ const { list, dir, types = ['image', 'dom', 'text'], selector, ignore, devices, combined = false, } = param;
14
15
  return {
15
16
  async eachPage({ page, url: urlA, index }, logger) {
16
17
  const urlPair = list.find(([url]) => url === urlA);
@@ -68,6 +69,13 @@ createChildProcess((param) => {
68
69
  const outFilePath = path.resolve(dir, `${id}_diff.png`);
69
70
  logger(`${sizeName} ${outputUrl} 📊 Save diff image to ${path.relative(dir, outFilePath)}`);
70
71
  await writeFile(outFilePath, imageDiff.images.diff);
72
+ // 合成画像を出力
73
+ if (combined) {
74
+ const combinedImage = await combineImages(imageDiff.images.a, imageDiff.images.b);
75
+ const combinedFilePath = path.resolve(dir, `${id}_combined.png`);
76
+ logger(`${sizeName} ${outputUrl} 🖼️ Save combined image to ${path.relative(dir, combinedFilePath)}`);
77
+ await writeFile(combinedFilePath, combinedImage);
78
+ }
71
79
  image = {
72
80
  matches: imageDiff.matches,
73
81
  file: outFilePath,
@@ -28,6 +28,7 @@ export async function analyze(list, options) {
28
28
  ignore: options?.ignore,
29
29
  devices: options?.devices,
30
30
  hooks: options?.hooks ?? [],
31
+ combined: options?.combined,
31
32
  }, {
32
33
  ...options,
33
34
  headless: useOldMode ? 'shell' : true,
package/dist/cli.js CHANGED
@@ -21,6 +21,7 @@ const { options, hasConfigFile } = createCLI({
21
21
  '\t-s, --selector <selector> CSS selector for specific elements',
22
22
  '\t-i, --ignore <ignore> CSS selector for elements to ignore',
23
23
  '\t--freeze <file> Freeze mode: capture reference screenshots',
24
+ '\t--combined Output side-by-side combined images (environment A and B)',
24
25
  '\t--limit <number> Limit concurrent processes',
25
26
  '\t--interval <ms> Interval between parallel executions (default: none)',
26
27
  '\t Format: number or "min-max" for random range',
@@ -33,6 +34,7 @@ const { options, hasConfigFile } = createCLI({
33
34
  'Examples:',
34
35
  '\tarchaeologist -f urls.txt',
35
36
  '\tarchaeologist -f urls.txt --devices desktop,mobile',
37
+ '\tarchaeologist -f urls.txt --combined',
36
38
  '\tarchaeologist --freeze urls.txt',
37
39
  ],
38
40
  parseArgs: (cli) => ({
@@ -45,6 +47,7 @@ const { options, hasConfigFile } = createCLI({
45
47
  devices: cli.devices ??
46
48
  // Alias for devices
47
49
  cli.device,
50
+ combined: cli.combined,
48
51
  }),
49
52
  validateArgs: (options) => {
50
53
  return !!(options.listfile?.length || options.freeze?.length);
@@ -58,6 +61,7 @@ if (hasConfigFile) {
58
61
  selector: options.selector,
59
62
  ignore: options.ignore,
60
63
  devices: options.devices ? parseList(options.devices) : undefined,
64
+ combined: options.combined,
61
65
  limit: options.limit,
62
66
  debug: options.debug,
63
67
  verbose: options.verbose,
@@ -0,0 +1,7 @@
1
+ /**
2
+ * 2枚の画像を左右に並べて合成する
3
+ * @param imageA 環境Aの画像バッファ
4
+ * @param imageB 環境Bの画像バッファ
5
+ * @returns 合成された画像のバッファ
6
+ */
7
+ export declare function combineImages(imageA: Buffer, imageB: Buffer): Promise<Buffer>;
@@ -0,0 +1,26 @@
1
+ import { Jimp, JimpMime } from 'jimp';
2
+ /**
3
+ * 2枚の画像を左右に並べて合成する
4
+ * @param imageA 環境Aの画像バッファ
5
+ * @param imageB 環境Bの画像バッファ
6
+ * @returns 合成された画像のバッファ
7
+ */
8
+ export async function combineImages(imageA, imageB) {
9
+ const imgA = await Jimp.read(imageA);
10
+ const imgB = await Jimp.read(imageB);
11
+ const padding = 20;
12
+ const widthA = imgA.width;
13
+ const heightA = imgA.height;
14
+ const widthB = imgB.width;
15
+ const heightB = imgB.height;
16
+ const combinedWidth = padding + widthA + padding + widthB + padding;
17
+ const combinedHeight = padding + Math.max(heightA, heightB) + padding;
18
+ const combined = new Jimp({
19
+ width: combinedWidth,
20
+ height: combinedHeight,
21
+ color: 0xff_ff_ff_ff,
22
+ });
23
+ combined.composite(imgA, padding, padding);
24
+ combined.composite(imgB, padding + widthA + padding, padding);
25
+ return combined.getBuffer(JimpMime.png);
26
+ }
package/dist/types.d.ts CHANGED
@@ -37,6 +37,7 @@ export interface AnalyzeOptions extends GeneralOptions {
37
37
  readonly selector?: string;
38
38
  readonly ignore?: string;
39
39
  readonly devices?: readonly string[];
40
+ readonly combined?: boolean;
40
41
  }
41
42
  export interface FreezeOptions extends GeneralOptions {
42
43
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@d-zero/archaeologist",
3
- "version": "3.3.2",
3
+ "version": "3.4.0",
4
4
  "description": "Uncover visual and HTML differences in web pages with precision",
5
5
  "author": "D-ZERO",
6
6
  "license": "MIT",
@@ -24,14 +24,14 @@
24
24
  "clean": "tsc --build --clean"
25
25
  },
26
26
  "dependencies": {
27
- "@d-zero/cli-core": "1.2.2",
27
+ "@d-zero/cli-core": "1.2.3",
28
28
  "@d-zero/fs": "0.2.2",
29
29
  "@d-zero/html-distiller": "2.0.1",
30
- "@d-zero/puppeteer-dealer": "0.5.12",
31
- "@d-zero/puppeteer-page-scan": "4.2.8",
32
- "@d-zero/puppeteer-screenshot": "3.2.8",
33
- "@d-zero/readtext": "1.1.12",
34
- "@d-zero/shared": "0.15.0",
30
+ "@d-zero/puppeteer-dealer": "0.6.1",
31
+ "@d-zero/puppeteer-page-scan": "4.3.1",
32
+ "@d-zero/puppeteer-screenshot": "3.2.10",
33
+ "@d-zero/readtext": "1.1.13",
34
+ "@d-zero/shared": "0.15.1",
35
35
  "ansi-colors": "4.1.3",
36
36
  "diff": "8.0.2",
37
37
  "front-matter": "4.0.2",
@@ -41,7 +41,7 @@
41
41
  "parse-diff": "0.11.1",
42
42
  "pixelmatch": "7.1.0",
43
43
  "pngjs": "7.0.0",
44
- "puppeteer": "24.27.0",
44
+ "puppeteer": "24.31.0",
45
45
  "strip-ansi": "7.1.2"
46
46
  },
47
47
  "devDependencies": {
@@ -49,5 +49,5 @@
49
49
  "@types/pixelmatch": "5.2.6",
50
50
  "@types/pngjs": "6.0.5"
51
51
  },
52
- "gitHead": "858864f8e57494a5a872431e1d772e18e4cc843a"
52
+ "gitHead": "9ed6da4277cf2f9d771df2a07e146fce6c7d4f3f"
53
53
  }