@d-zero/archaeologist 1.1.2 → 2.0.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.
Files changed (35) hide show
  1. package/dist/analyze-child-process.d.ts +9 -0
  2. package/dist/{analyze.js → analyze-child-process.js} +15 -28
  3. package/dist/analyze-main-process.d.ts +7 -0
  4. package/dist/analyze-main-process.js +46 -0
  5. package/dist/cli.js +13 -2
  6. package/dist/freeze-child-process.d.ts +3 -0
  7. package/dist/freeze-child-process.js +22 -0
  8. package/dist/freeze-main-process.d.ts +7 -0
  9. package/dist/freeze-main-process.js +34 -0
  10. package/dist/index.d.ts +1 -1
  11. package/dist/index.js +1 -1
  12. package/dist/modules/analize-url.d.ts +11 -0
  13. package/dist/{analize-url.js → modules/analize-url.js} +14 -0
  14. package/dist/{diff-images.d.ts → modules/diff-images.d.ts} +9 -3
  15. package/dist/{diff-images.js → modules/diff-images.js} +12 -0
  16. package/dist/{diff-tree.d.ts → modules/diff-tree.d.ts} +7 -0
  17. package/dist/{diff-tree.js → modules/diff-tree.js} +7 -0
  18. package/dist/{get-data.d.ts → modules/get-data.d.ts} +9 -2
  19. package/dist/{get-data.js → modules/get-data.js} +7 -0
  20. package/dist/read-config.d.ts +4 -0
  21. package/dist/read-config.js +4 -0
  22. package/dist/types.d.ts +13 -1
  23. package/dist/utils.d.ts +5 -0
  24. package/dist/utils.js +5 -0
  25. package/package.json +14 -12
  26. package/dist/analize-url.d.ts +0 -7
  27. package/dist/analyze.d.ts +0 -9
  28. package/dist/archaeologist.d.ts +0 -5
  29. package/dist/archaeologist.js +0 -18
  30. package/dist/diff-tree-color.d.ts +0 -1
  31. package/dist/diff-tree-color.js +0 -15
  32. package/dist/output-utils.d.ts +0 -1
  33. package/dist/output-utils.js +0 -6
  34. package/dist/read-hooks.d.ts +0 -2
  35. package/dist/read-hooks.js +0 -20
@@ -0,0 +1,9 @@
1
+ import type { URLPair } from './types.js';
2
+ import type { PageHook } from '@d-zero/puppeteer-page-scan';
3
+ export type ChildProcessParams = {
4
+ list: readonly URLPair[];
5
+ dir: string;
6
+ useOldMode: boolean;
7
+ htmlDiffOnly: boolean;
8
+ hooks?: readonly PageHook[];
9
+ };
@@ -1,22 +1,16 @@
1
- import { writeFile, mkdir } from 'node:fs/promises';
1
+ import { writeFile } from 'node:fs/promises';
2
2
  import path from 'node:path';
3
- import { deal } from '@d-zero/puppeteer-dealer';
3
+ import { createChildProcess } from '@d-zero/puppeteer-dealer';
4
+ import { delay } from '@d-zero/shared/delay';
4
5
  import c from 'ansi-colors';
5
- import { analyzeUrlList } from './analize-url.js';
6
- import { diffImages } from './diff-images.js';
7
- import { diffTree } from './diff-tree.js';
8
- import { getData } from './get-data.js';
9
- import { score } from './output-utils.js';
10
- export async function analyze(list, options) {
11
- const results = [];
12
- const dir = path.resolve(process.cwd(), '.archaeologist');
13
- await mkdir(dir, { recursive: true }).catch(() => { });
14
- const urlInfo = analyzeUrlList(list);
15
- const useOldMode = urlInfo.hasAuth || urlInfo.hasNoSSL;
16
- await deal(list.map(([urlA]) => ({ id: null, url: urlA })), (_, done, total) => {
17
- return `${c.bold.magenta('🕵️ Archaeologist')} ${done}/${total}`;
18
- }, {
19
- async deal(page, _, urlA, logger, index) {
6
+ import { diffImages } from './modules/diff-images.js';
7
+ import { diffTree } from './modules/diff-tree.js';
8
+ import { getData } from './modules/get-data.js';
9
+ import { score } from './utils.js';
10
+ createChildProcess((param) => {
11
+ const { list, dir, htmlDiffOnly } = param;
12
+ return {
13
+ async eachPage({ page, url: urlA, index }, logger) {
20
14
  const urlPair = list.find(([url]) => url === urlA);
21
15
  if (!urlPair) {
22
16
  throw new Error(`Failed to find urlPair: ${urlA}`);
@@ -24,7 +18,7 @@ export async function analyze(list, options) {
24
18
  const dataPair = [];
25
19
  for (const url of urlPair) {
26
20
  const data = await getData(page, url, {
27
- ...options,
21
+ htmlDiffOnly,
28
22
  }, logger);
29
23
  dataPair.push(data);
30
24
  await delay(600);
@@ -89,14 +83,7 @@ export async function analyze(list, options) {
89
83
  target: [a.url, b.url],
90
84
  screenshots: screenshotResult,
91
85
  };
92
- results.push(result);
86
+ return result;
93
87
  },
94
- }, {
95
- ...options,
96
- headless: useOldMode ? 'shell' : true,
97
- });
98
- return results;
99
- }
100
- function delay(ms) {
101
- return new Promise((resolve) => setTimeout(resolve, ms));
102
- }
88
+ };
89
+ });
@@ -0,0 +1,7 @@
1
+ import type { AnalyzeOptions, URLPair } from './types.js';
2
+ /**
3
+ *
4
+ * @param list
5
+ * @param options
6
+ */
7
+ export declare function analyze(list: readonly URLPair[], options?: AnalyzeOptions): Promise<void>;
@@ -0,0 +1,46 @@
1
+ import { mkdir } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { createProcess, deal } from '@d-zero/puppeteer-dealer';
4
+ import c from 'ansi-colors';
5
+ import { analyzeUrlList } from './modules/analize-url.js';
6
+ import { score } from './utils.js';
7
+ /**
8
+ *
9
+ * @param list
10
+ * @param options
11
+ */
12
+ export async function analyze(list, options) {
13
+ const results = [];
14
+ const dir = path.resolve(process.cwd(), '.archaeologist');
15
+ await mkdir(dir, { recursive: true }).catch(() => { });
16
+ const urlInfo = analyzeUrlList(list);
17
+ const useOldMode = urlInfo.hasAuth || urlInfo.hasNoSSL;
18
+ await deal(list.map(([urlA]) => ({ id: null, url: urlA })), (_, done, total) => {
19
+ return `${c.bold.magenta('🕵️ Archaeologist')} ${done}/${total}`;
20
+ }, () => {
21
+ return createProcess(path.resolve(import.meta.dirname, 'analyze-child-process.js'), {
22
+ list,
23
+ dir,
24
+ useOldMode,
25
+ htmlDiffOnly: options?.htmlDiffOnly ?? false,
26
+ hooks: options?.hooks ?? [],
27
+ }, {
28
+ ...options,
29
+ headless: useOldMode ? 'shell' : true,
30
+ });
31
+ }, (result) => {
32
+ results.push(result);
33
+ });
34
+ const output = [];
35
+ for (const result of results) {
36
+ output.push(c.gray(`${result.target.join(' vs ')}`));
37
+ for (const [sizeName, { image, dom }] of Object.entries(result.screenshots)) {
38
+ if (image) {
39
+ const { matches, file } = image;
40
+ output.push(` ${c.bgMagenta(` ${sizeName} `)} ${score(matches, 0.9)} ${file}`);
41
+ }
42
+ output.push(` ${c.bgBlueBright(' HTML ')}: ${score(dom.matches, 0.995)} ${dom.file}`);
43
+ }
44
+ }
45
+ process.stdout.write(output.join('\n') + '\n');
46
+ }
package/dist/cli.js CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import minimist from 'minimist';
3
- import { archaeologist } from './archaeologist.js';
3
+ import { analyze } from './analyze-main-process.js';
4
+ import { freeze } from './freeze-main-process.js';
4
5
  import { readConfig } from './read-config.js';
5
6
  const cli = minimist(process.argv.slice(2), {
6
7
  alias: {
@@ -9,7 +10,7 @@ const cli = minimist(process.argv.slice(2), {
9
10
  });
10
11
  if (cli.listfile?.length) {
11
12
  const { pairList, hooks } = await readConfig(cli.listfile);
12
- await archaeologist(pairList, {
13
+ await analyze(pairList, {
13
14
  hooks,
14
15
  limit: cli.limit ? Number.parseInt(cli.limit) : undefined,
15
16
  debug: !!cli.debug,
@@ -17,5 +18,15 @@ if (cli.listfile?.length) {
17
18
  });
18
19
  process.exit(0);
19
20
  }
21
+ if (cli.freeze) {
22
+ const { pairList, hooks } = await readConfig(cli.freeze);
23
+ const list = pairList.map(([urlA]) => urlA);
24
+ await freeze(list, {
25
+ hooks,
26
+ limit: cli.limit ? Number.parseInt(cli.limit) : undefined,
27
+ debug: !!cli.debug,
28
+ });
29
+ process.exit(0);
30
+ }
20
31
  process.stderr.write('Usage: archaeologist -f <listfile> [--limit <number>]\n');
21
32
  process.exit(1);
@@ -0,0 +1,3 @@
1
+ export type ChildProcessParams = {
2
+ dir: string;
3
+ };
@@ -0,0 +1,22 @@
1
+ import { writeFile } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { createChildProcess } from '@d-zero/puppeteer-dealer';
4
+ import { delay } from '@d-zero/shared/delay';
5
+ import { getData } from './modules/get-data.js';
6
+ createChildProcess((param) => {
7
+ const { dir } = param;
8
+ return {
9
+ async eachPage({ page, id, url }, logger) {
10
+ const data = await getData(page, url, {}, logger);
11
+ await delay(600);
12
+ for (const size of Object.values(data.screenshots)) {
13
+ const jsonFile = path.resolve(dir, `${id}_${size.id}.html`);
14
+ const ssFile = path.resolve(dir, `${id}_${size.id}.png`);
15
+ await writeFile(jsonFile, size.dom, 'utf8');
16
+ if (size.binary) {
17
+ await writeFile(ssFile, size.binary);
18
+ }
19
+ }
20
+ },
21
+ };
22
+ });
@@ -0,0 +1,7 @@
1
+ import type { FreezeOptions } from './types.js';
2
+ /**
3
+ *
4
+ * @param list
5
+ * @param options
6
+ */
7
+ export declare function freeze(list: readonly string[], options?: FreezeOptions): Promise<string>;
@@ -0,0 +1,34 @@
1
+ import { mkdir, writeFile } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { zip } from '@d-zero/fs/zip';
4
+ import { createProcess, deal } from '@d-zero/puppeteer-dealer';
5
+ import { timestamp } from '@d-zero/shared/timestamp';
6
+ import c from 'ansi-colors';
7
+ import { analyzeUrlList } from './modules/analize-url.js';
8
+ /**
9
+ *
10
+ * @param list
11
+ * @param options
12
+ */
13
+ export async function freeze(list, options) {
14
+ const name = `${timestamp('YYYYMMDD')}.archae`;
15
+ const dir = path.resolve(process.cwd(), `.${name}`);
16
+ await mkdir(dir, { recursive: true }).catch(() => { });
17
+ const urlInfo = analyzeUrlList(list);
18
+ const useOldMode = urlInfo.hasAuth || urlInfo.hasNoSSL;
19
+ await deal(list.map((url) => ({ id: null, url })), (_, done, total) => {
20
+ return `${c.bold.magenta('🕵️ Archaeologist Freeze❄️')} ${done}/${total}`;
21
+ }, () => {
22
+ return createProcess(path.resolve(import.meta.dirname, 'freeze-child-process.js'), {
23
+ dir,
24
+ }, {
25
+ ...options,
26
+ headless: useOldMode ? 'shell' : true,
27
+ });
28
+ });
29
+ const urlListPath = path.resolve(dir, '_URL_LIST.json');
30
+ await writeFile(urlListPath, JSON.stringify(list, null, '\t'), 'utf8');
31
+ const zipPath = path.resolve(process.cwd(), `${name}.zip`);
32
+ await zip(zipPath, dir);
33
+ return zipPath;
34
+ }
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { archaeologist } from './archaeologist.js';
1
+ export { analyze as archaeologist } from './analyze-main-process.js';
2
2
  export * from './types.js';
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- export { archaeologist } from './archaeologist.js';
1
+ export { analyze as archaeologist } from './analyze-main-process.js';
2
2
  export * from './types.js';
@@ -0,0 +1,11 @@
1
+ import type { URLPair } from '../types.js';
2
+ type AnalyzedUrlList = {
3
+ hasAuth: boolean;
4
+ hasNoSSL: boolean;
5
+ };
6
+ /**
7
+ *
8
+ * @param list
9
+ */
10
+ export declare function analyzeUrlList(list: readonly (URLPair | string)[]): AnalyzedUrlList;
11
+ export {};
@@ -1,9 +1,23 @@
1
+ /**
2
+ *
3
+ * @param list
4
+ */
1
5
  export function analyzeUrlList(list) {
2
6
  const result = {
3
7
  hasAuth: false,
4
8
  hasNoSSL: false,
5
9
  };
6
10
  for (const urlPair of list) {
11
+ if (typeof urlPair === 'string') {
12
+ const urlObj = new URL(urlPair);
13
+ if (urlObj.username || urlObj.password) {
14
+ result.hasAuth = true;
15
+ }
16
+ if (urlObj.protocol === 'http:') {
17
+ result.hasNoSSL = true;
18
+ }
19
+ continue;
20
+ }
7
21
  for (const url of urlPair) {
8
22
  const urlObj = new URL(url);
9
23
  if (urlObj.username || urlObj.password) {
@@ -16,12 +16,18 @@ export type DiffImagesPhase = {
16
16
  };
17
17
  };
18
18
  type DiffImagesListener = (phase: keyof DiffImagesPhase, data: DiffImagesPhase[keyof DiffImagesPhase]) => void;
19
+ /**
20
+ *
21
+ * @param dataA
22
+ * @param dataB
23
+ * @param listener
24
+ */
19
25
  export declare function diffImages(dataA: Screenshot, dataB: Screenshot, listener: DiffImagesListener): Promise<{
20
26
  matches: number;
21
27
  images: {
22
- a: Buffer;
23
- b: Buffer;
24
- diff: Buffer;
28
+ a: Buffer<ArrayBufferLike>;
29
+ b: Buffer<ArrayBufferLike>;
30
+ diff: Buffer<ArrayBufferLike>;
25
31
  };
26
32
  } | null>;
27
33
  export {};
@@ -1,6 +1,12 @@
1
1
  import { Jimp, HorizontalAlign, VerticalAlign, JimpMime } from 'jimp';
2
2
  import pixelmatch from 'pixelmatch';
3
3
  import { PNG } from 'pngjs';
4
+ /**
5
+ *
6
+ * @param dataA
7
+ * @param dataB
8
+ * @param listener
9
+ */
4
10
  export async function diffImages(dataA, dataB, listener) {
5
11
  if (!dataA.binary || !dataB.binary) {
6
12
  return null;
@@ -31,6 +37,12 @@ export async function diffImages(dataA, dataB, listener) {
31
37
  },
32
38
  };
33
39
  }
40
+ /**
41
+ *
42
+ * @param bin
43
+ * @param width
44
+ * @param height
45
+ */
34
46
  async function resizeImg(bin, width, height) {
35
47
  const img = await Jimp.read(bin);
36
48
  img.contain({
@@ -1,3 +1,10 @@
1
+ /**
2
+ *
3
+ * @param urlA
4
+ * @param urlB
5
+ * @param dataA
6
+ * @param dataB
7
+ */
1
8
  export declare function diffTree(urlA: string, urlB: string, dataA: string, dataB: string): {
2
9
  changed: boolean;
3
10
  maxLine: number;
@@ -1,5 +1,12 @@
1
1
  import { createTwoFilesPatch } from 'diff';
2
2
  import parse from 'parse-diff';
3
+ /**
4
+ *
5
+ * @param urlA
6
+ * @param urlB
7
+ * @param dataA
8
+ * @param dataB
9
+ */
3
10
  export function diffTree(urlA, urlB, dataA, dataB) {
4
11
  const result = createTwoFilesPatch(urlA, urlB, dataA, dataB);
5
12
  const info = parse(result)[0];
@@ -1,8 +1,15 @@
1
- import type { PageData } from './types.js';
2
- import type { Page } from '@d-zero/puppeteer-page';
1
+ import type { PageData } from '../types.js';
3
2
  import type { PageHook } from '@d-zero/puppeteer-screenshot';
3
+ import type { Page } from 'puppeteer';
4
4
  export interface GetDataOptions {
5
5
  readonly hooks?: readonly PageHook[];
6
6
  readonly htmlDiffOnly?: boolean;
7
7
  }
8
+ /**
9
+ *
10
+ * @param page
11
+ * @param url
12
+ * @param options
13
+ * @param update
14
+ */
8
15
  export declare function getData(page: Page, url: string, options: GetDataOptions, update: (log: string) => void): Promise<PageData>;
@@ -1,5 +1,12 @@
1
1
  import { distill } from '@d-zero/html-distiller';
2
2
  import { screenshotListener, screenshot } from '@d-zero/puppeteer-screenshot';
3
+ /**
4
+ *
5
+ * @param page
6
+ * @param url
7
+ * @param options
8
+ * @param update
9
+ */
3
10
  export async function getData(page, url, options, update) {
4
11
  const htmlDiffOnly = options.htmlDiffOnly ?? false;
5
12
  const screenshots = await screenshot(page, url, {
@@ -1,3 +1,7 @@
1
+ /**
2
+ *
3
+ * @param filePath
4
+ */
1
5
  export declare function readConfig(filePath: string): Promise<{
2
6
  pairList: [string, string][];
3
7
  hooks: import("@d-zero/puppeteer-page-scan").PageHook[];
@@ -3,6 +3,10 @@ import path from 'node:path';
3
3
  import { readPageHooks } from '@d-zero/puppeteer-page-scan';
4
4
  import { toList } from '@d-zero/readtext/list';
5
5
  import fm from 'front-matter';
6
+ /**
7
+ *
8
+ * @param filePath
9
+ */
6
10
  export async function readConfig(filePath) {
7
11
  const fileContent = await fs.readFile(filePath, 'utf8');
8
12
  const content =
package/dist/types.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export type { PageHook } from '@d-zero/puppeteer-screenshot';
2
- import type { Screenshot } from '@d-zero/puppeteer-screenshot';
2
+ import type { PageHook, Screenshot } from '@d-zero/puppeteer-screenshot';
3
3
  export type PageData = {
4
4
  url: string;
5
5
  screenshots: Record<string, Screenshot & {
@@ -24,3 +24,15 @@ export type DOMResult = {
24
24
  diff: string | null;
25
25
  file: string;
26
26
  };
27
+ export interface ArchaeologistOptions extends AnalyzeOptions {
28
+ }
29
+ export interface AnalyzeOptions extends GeneralOptions {
30
+ readonly htmlDiffOnly?: boolean;
31
+ }
32
+ export interface FreezeOptions extends GeneralOptions {
33
+ }
34
+ interface GeneralOptions {
35
+ readonly hooks: readonly PageHook[];
36
+ readonly limit?: number;
37
+ readonly debug?: boolean;
38
+ }
package/dist/utils.d.ts CHANGED
@@ -1 +1,6 @@
1
+ /**
2
+ *
3
+ * @param matches
4
+ * @param threshold
5
+ */
1
6
  export declare function score(matches: number, threshold: number): string;
package/dist/utils.js CHANGED
@@ -1,4 +1,9 @@
1
1
  import c from 'ansi-colors';
2
+ /**
3
+ *
4
+ * @param matches
5
+ * @param threshold
6
+ */
2
7
  export function score(matches, threshold) {
3
8
  const color = matches > threshold ? c.green : c.red;
4
9
  const num = (matches * 100).toFixed(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@d-zero/archaeologist",
3
- "version": "1.1.2",
3
+ "version": "2.0.0",
4
4
  "description": "Uncover visual and HTML differences in web pages with precision",
5
5
  "author": "D-ZERO",
6
6
  "license": "MIT",
@@ -27,25 +27,27 @@
27
27
  "clean": "tsc --build --clean"
28
28
  },
29
29
  "dependencies": {
30
- "@d-zero/html-distiller": "1.0.1",
31
- "@d-zero/puppeteer-dealer": "0.2.0",
32
- "@d-zero/puppeteer-page-scan": "2.0.0",
33
- "@d-zero/puppeteer-screenshot": "2.0.0",
34
- "@d-zero/readtext": "1.1.1",
30
+ "@d-zero/fs": "0.2.0",
31
+ "@d-zero/html-distiller": "1.0.3",
32
+ "@d-zero/puppeteer-dealer": "0.4.0",
33
+ "@d-zero/puppeteer-page-scan": "4.0.0",
34
+ "@d-zero/puppeteer-screenshot": "3.0.1",
35
+ "@d-zero/readtext": "1.1.3",
36
+ "@d-zero/shared": "0.8.0",
35
37
  "ansi-colors": "4.1.3",
36
- "diff": "7.0.0",
38
+ "diff": "8.0.1",
37
39
  "front-matter": "4.0.2",
38
40
  "jimp": "1.6.0",
39
41
  "minimist": "1.2.8",
40
42
  "parse-diff": "0.11.1",
41
- "pixelmatch": "6.0.0",
42
- "pngjs": "7.0.0"
43
+ "pixelmatch": "7.1.0",
44
+ "pngjs": "7.0.0",
45
+ "puppeteer": "24.9.0"
43
46
  },
44
47
  "devDependencies": {
45
- "@d-zero/puppeteer-page": "0.2.0",
46
- "@types/diff": "6.0.0",
48
+ "@types/diff": "8.0.0",
47
49
  "@types/pixelmatch": "5.2.6",
48
50
  "@types/pngjs": "6.0.5"
49
51
  },
50
- "gitHead": "1eb1c03400580040119121e11ffb33acd876fe1b"
52
+ "gitHead": "4e9cc7b87e0fef91b6f2d4edfb66ca9134b2491b"
51
53
  }
@@ -1,7 +0,0 @@
1
- import type { URLPair } from './types.js';
2
- type AnalyzedUrlList = {
3
- hasAuth: boolean;
4
- hasNoSSL: boolean;
5
- };
6
- export declare function analyzeUrlList(list: readonly URLPair[]): AnalyzedUrlList;
7
- export {};
package/dist/analyze.d.ts DELETED
@@ -1,9 +0,0 @@
1
- import type { Result, URLPair } from './types.js';
2
- import type { PageHook } from '@d-zero/puppeteer-screenshot';
3
- export interface AnalyzeOptions {
4
- readonly hooks: readonly PageHook[];
5
- readonly htmlDiffOnly?: boolean;
6
- readonly limit?: number;
7
- readonly debug?: boolean;
8
- }
9
- export declare function analyze(list: readonly URLPair[], options?: AnalyzeOptions): Promise<Result[]>;
@@ -1,5 +0,0 @@
1
- import type { AnalyzeOptions } from './analyze.js';
2
- import type { URLPair } from './types.js';
3
- export interface ArchaeologistOptions extends AnalyzeOptions {
4
- }
5
- export declare function archaeologist(list: readonly URLPair[], options?: ArchaeologistOptions): Promise<void>;
@@ -1,18 +0,0 @@
1
- import c from 'ansi-colors';
2
- import { analyze } from './analyze.js';
3
- import { score } from './output-utils.js';
4
- export async function archaeologist(list, options) {
5
- const results = await analyze(list, options);
6
- const output = [];
7
- for (const result of results) {
8
- output.push(c.gray(`${result.target.join(' vs ')}`));
9
- for (const [sizeName, { image, dom }] of Object.entries(result.screenshots)) {
10
- if (image) {
11
- const { matches, file } = image;
12
- output.push(` ${c.bgMagenta(` ${sizeName} `)} ${score(matches, 0.9)} ${file}`);
13
- }
14
- output.push(` ${c.bgBlueBright(' HTML ')}: ${score(dom.matches, 0.995)} ${dom.file}`);
15
- }
16
- }
17
- process.stdout.write(output.join('\n') + '\n');
18
- }
@@ -1 +0,0 @@
1
- export declare function diffTreeColor(diff: string): string;
@@ -1,15 +0,0 @@
1
- import c from 'ansi-colors';
2
- export function diffTreeColor(diff) {
3
- return diff
4
- .split('\n')
5
- .map((line) => {
6
- if (line.startsWith('+')) {
7
- return c.green(line);
8
- }
9
- if (line.startsWith('-')) {
10
- return c.red(line);
11
- }
12
- return c.gray(line);
13
- })
14
- .join('\n');
15
- }
@@ -1 +0,0 @@
1
- export declare function score(matches: number, threshold: number): string;
@@ -1,6 +0,0 @@
1
- import c from 'ansi-colors';
2
- export function score(matches, threshold) {
3
- const color = matches > threshold ? c.green : c.red;
4
- const num = (matches * 100).toFixed(1);
5
- return c.bold(color(`${num}%`));
6
- }
@@ -1,2 +0,0 @@
1
- import type { PageHook } from '@d-zero/puppeteer-screenshot';
2
- export declare function readHooks(hooks: readonly string[], listfile: string): Promise<PageHook[]>;
@@ -1,20 +0,0 @@
1
- import path from 'node:path';
2
- export async function readHooks(hooks, listfile) {
3
- const listfileDir = path.dirname(listfile);
4
- const pageHooks = await Promise.all(hooks.map(async (hook) => {
5
- const hookAbsPath = path.isAbsolute(hook) ? hook : path.resolve(listfileDir, hook);
6
- const { default: mod } = await import(hookAbsPath).catch((error) => {
7
- if (error instanceof Error &&
8
- 'code' in error &&
9
- error.code === 'ERR_MODULE_NOT_FOUND') {
10
- throw new Error(`Hook: ${hook} not found`, { cause: error });
11
- }
12
- throw error;
13
- });
14
- if (typeof mod !== 'function') {
15
- throw new TypeError(`Hook ${hook} is not a function`);
16
- }
17
- return mod;
18
- }));
19
- return pageHooks;
20
- }