@wasao/kagemusha 0.1.0 → 0.2.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 +497 -58
- package/dist/commands/add.d.ts +6 -0
- package/dist/commands/add.d.ts.map +1 -0
- package/dist/commands/add.js +26 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/capture.d.ts +4 -2
- package/dist/commands/capture.d.ts.map +1 -1
- package/dist/commands/capture.js +236 -11
- package/dist/commands/capture.js.map +1 -1
- package/dist/commands/discover.d.ts +2 -0
- package/dist/commands/discover.d.ts.map +1 -0
- package/dist/commands/discover.js +62 -0
- package/dist/commands/discover.js.map +1 -0
- package/dist/commands/edit.d.ts +6 -0
- package/dist/commands/edit.d.ts.map +1 -0
- package/dist/commands/edit.js +120 -0
- package/dist/commands/edit.js.map +1 -0
- package/dist/commands/init.d.ts +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +220 -118
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/list.d.ts +2 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +33 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/login.d.ts +6 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +142 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/validate.js +1 -1
- package/dist/commands/validate.js.map +1 -1
- package/dist/editor/inject-script.d.ts +2 -0
- package/dist/editor/inject-script.d.ts.map +1 -0
- package/dist/editor/inject-script.js +768 -0
- package/dist/editor/inject-script.js.map +1 -0
- package/dist/index.js +32 -20
- package/dist/index.js.map +1 -1
- package/dist/lib/annotate.d.ts +2 -2
- package/dist/lib/annotate.d.ts.map +1 -1
- package/dist/lib/annotate.js +36 -44
- package/dist/lib/annotate.js.map +1 -1
- package/dist/lib/auth.d.ts +18 -0
- package/dist/lib/auth.d.ts.map +1 -0
- package/dist/lib/auth.js +45 -0
- package/dist/lib/auth.js.map +1 -0
- package/dist/lib/aws-error.d.ts +7 -0
- package/dist/lib/aws-error.d.ts.map +1 -0
- package/dist/lib/aws-error.js +74 -0
- package/dist/lib/aws-error.js.map +1 -0
- package/dist/lib/canonical.d.ts +22 -0
- package/dist/lib/canonical.d.ts.map +1 -0
- package/dist/lib/canonical.js +92 -0
- package/dist/lib/canonical.js.map +1 -0
- package/dist/lib/config.d.ts +2 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +23 -13
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/crawl.d.ts +1 -1
- package/dist/lib/crawl.d.ts.map +1 -1
- package/dist/lib/crawl.js +213 -20
- package/dist/lib/crawl.js.map +1 -1
- package/dist/lib/definition.d.ts +2 -0
- package/dist/lib/definition.d.ts.map +1 -0
- package/dist/lib/definition.js +6 -0
- package/dist/lib/definition.js.map +1 -0
- package/dist/lib/diff.d.ts +52 -0
- package/dist/lib/diff.d.ts.map +1 -0
- package/dist/lib/diff.js +41 -0
- package/dist/lib/diff.js.map +1 -0
- package/dist/lib/login-error.d.ts +10 -0
- package/dist/lib/login-error.d.ts.map +1 -0
- package/dist/lib/login-error.js +13 -0
- package/dist/lib/login-error.js.map +1 -0
- package/dist/lib/screenshot.d.ts +8 -2
- package/dist/lib/screenshot.d.ts.map +1 -1
- package/dist/lib/screenshot.js +44 -61
- package/dist/lib/screenshot.js.map +1 -1
- package/dist/lib/staging.d.ts +8 -0
- package/dist/lib/staging.d.ts.map +1 -0
- package/dist/lib/staging.js +24 -0
- package/dist/lib/staging.js.map +1 -0
- package/dist/types.d.ts +5 -23
- package/dist/types.d.ts.map +1 -1
- package/package.json +18 -11
- package/dist/commands/preview.d.ts +0 -6
- package/dist/commands/preview.d.ts.map +0 -1
- package/dist/commands/preview.js +0 -33
- package/dist/commands/preview.js.map +0 -1
- package/dist/commands/run.d.ts +0 -6
- package/dist/commands/run.d.ts.map +0 -1
- package/dist/commands/run.js +0 -39
- package/dist/commands/run.js.map +0 -1
- package/dist/lib/upload.d.ts +0 -9
- package/dist/lib/upload.d.ts.map +0 -1
- package/dist/lib/upload.js +0 -43
- package/dist/lib/upload.js.map +0 -1
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { GetObjectCommand, NoSuchKey, PutObjectCommand, S3Client, } from "@aws-sdk/client-s3";
|
|
4
|
+
const DEFAULT_OUTPUT_DIR = "screenshots";
|
|
5
|
+
export const getOutputDir = (config, projectRoot) => {
|
|
6
|
+
const configured = config.publish?.outputDir ?? DEFAULT_OUTPUT_DIR;
|
|
7
|
+
return path.isAbsolute(configured)
|
|
8
|
+
? configured
|
|
9
|
+
: path.join(projectRoot, configured);
|
|
10
|
+
};
|
|
11
|
+
export const getCanonicalPath = (config, projectRoot, id) => path.join(getOutputDir(config, projectRoot), `${id}.png`);
|
|
12
|
+
// Extract AWS region from a virtual-hosted–style S3 URL or s3.<region>.amazonaws.com endpoint.
|
|
13
|
+
// Returns undefined for legacy global URLs (s3.amazonaws.com) or custom CDN domains.
|
|
14
|
+
const extractRegionFromCdnBase = (cdnBaseUrl) => {
|
|
15
|
+
if (!cdnBaseUrl)
|
|
16
|
+
return undefined;
|
|
17
|
+
const m = cdnBaseUrl.match(/\.s3[.-]([a-z0-9-]+)\.amazonaws\.com/i);
|
|
18
|
+
return m?.[1];
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* S3-backed canonical store.
|
|
22
|
+
* Local mode has no remote — outputDir itself is the source of truth.
|
|
23
|
+
*/
|
|
24
|
+
export class S3Canonical {
|
|
25
|
+
bucket;
|
|
26
|
+
cdnBaseUrl;
|
|
27
|
+
client;
|
|
28
|
+
constructor(bucket, cdnBaseUrl) {
|
|
29
|
+
this.bucket = bucket;
|
|
30
|
+
this.cdnBaseUrl = cdnBaseUrl;
|
|
31
|
+
const region = extractRegionFromCdnBase(cdnBaseUrl);
|
|
32
|
+
this.client = new S3Client(region ? { region } : {});
|
|
33
|
+
}
|
|
34
|
+
keyOf(id) {
|
|
35
|
+
return `${id}/latest.png`;
|
|
36
|
+
}
|
|
37
|
+
/** Download canonical for `id` to `localPath`. Returns "not-found" if absent. */
|
|
38
|
+
async fetch(id, localPath) {
|
|
39
|
+
try {
|
|
40
|
+
const res = await this.client.send(new GetObjectCommand({ Bucket: this.bucket, Key: this.keyOf(id) }));
|
|
41
|
+
const bytes = await res.Body?.transformToByteArray();
|
|
42
|
+
if (!bytes)
|
|
43
|
+
return "not-found";
|
|
44
|
+
fs.mkdirSync(path.dirname(localPath), { recursive: true });
|
|
45
|
+
fs.writeFileSync(localPath, bytes);
|
|
46
|
+
return "ok";
|
|
47
|
+
}
|
|
48
|
+
catch (e) {
|
|
49
|
+
if (e instanceof NoSuchKey)
|
|
50
|
+
return "not-found";
|
|
51
|
+
if (e?.name === "NoSuchKey")
|
|
52
|
+
return "not-found";
|
|
53
|
+
if (e?.Code === "NoSuchKey")
|
|
54
|
+
return "not-found";
|
|
55
|
+
throw e;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/** Upload `localPath` as the canonical for `id`. */
|
|
59
|
+
async push(id, localPath) {
|
|
60
|
+
const body = fs.readFileSync(localPath);
|
|
61
|
+
await this.client.send(new PutObjectCommand({
|
|
62
|
+
Bucket: this.bucket,
|
|
63
|
+
Key: this.keyOf(id),
|
|
64
|
+
Body: body,
|
|
65
|
+
ContentType: "image/png",
|
|
66
|
+
CacheControl: "no-cache",
|
|
67
|
+
}));
|
|
68
|
+
// History snapshot for debug / rollback. Replace `:` so the key works
|
|
69
|
+
// in URLs without %3A encoding (S3 accepts it but URL-embedding breaks).
|
|
70
|
+
const timestamp = new Date().toISOString().replaceAll(":", "-");
|
|
71
|
+
const historyKey = `${id}/${timestamp}.png`;
|
|
72
|
+
await this.client.send(new PutObjectCommand({
|
|
73
|
+
Bucket: this.bucket,
|
|
74
|
+
Key: historyKey,
|
|
75
|
+
Body: body,
|
|
76
|
+
ContentType: "image/png",
|
|
77
|
+
}));
|
|
78
|
+
}
|
|
79
|
+
label() {
|
|
80
|
+
return this.cdnBaseUrl ?? `s3://${this.bucket}`;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
export const createS3Canonical = (config) => {
|
|
84
|
+
const publish = config.publish;
|
|
85
|
+
if (publish?.destination !== "s3")
|
|
86
|
+
return null;
|
|
87
|
+
if (!publish.cdnBucket) {
|
|
88
|
+
throw new Error("publish.cdnBucket is required for s3 destination");
|
|
89
|
+
}
|
|
90
|
+
return new S3Canonical(publish.cdnBucket, publish.cdnBaseUrl);
|
|
91
|
+
};
|
|
92
|
+
//# sourceMappingURL=canonical.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canonical.js","sourceRoot":"","sources":["../../src/lib/canonical.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/config.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { KagemushaConfig, Route, ScreenshotDefinition } from "../types.js";
|
|
2
2
|
export declare function findProjectRoot(startDir?: string): string;
|
|
3
3
|
export declare function loadConfig(projectRoot?: string): KagemushaConfig;
|
|
4
|
+
export declare function getDefinitionsPath(projectRoot?: string): string;
|
|
4
5
|
export declare function loadDefinitions(projectRoot?: string): ScreenshotDefinition[];
|
|
6
|
+
export declare function saveDefinitions(definitions: ScreenshotDefinition[], projectRoot?: string): void;
|
|
5
7
|
export declare function loadRouting(projectRoot?: string): Route[];
|
|
6
8
|
export declare function loadDefinitionById(id: string, projectRoot?: string): ScreenshotDefinition | undefined;
|
|
7
9
|
export declare function validateConfig(config: KagemushaConfig): string[];
|
package/dist/lib/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAMhF,wBAAgB,eAAe,CAAC,QAAQ,GAAE,MAAsB,GAAG,MAAM,CAWxE;AAED,wBAAgB,UAAU,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,eAAe,CAYhE;AAED,wBAAgB,eAAe,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,oBAAoB,EAAE,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAMhF,wBAAgB,eAAe,CAAC,QAAQ,GAAE,MAAsB,GAAG,MAAM,CAWxE;AAED,wBAAgB,UAAU,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,eAAe,CAYhE;AAED,wBAAgB,kBAAkB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAG/D;AAED,wBAAgB,eAAe,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,oBAAoB,EAAE,CAS5E;AAED,wBAAgB,eAAe,CAC9B,WAAW,EAAE,oBAAoB,EAAE,EACnC,WAAW,CAAC,EAAE,MAAM,GAClB,IAAI,CAIN;AAED,wBAAgB,WAAW,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,KAAK,EAAE,CAWzD;AAED,wBAAgB,kBAAkB,CACjC,EAAE,EAAE,MAAM,EACV,WAAW,CAAC,EAAE,MAAM,GAClB,oBAAoB,GAAG,SAAS,CAGlC;AA0BD,wBAAgB,cAAc,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,EAAE,CAWhE;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,oBAAoB,GAAG,MAAM,EAAE,CAWtE"}
|
package/dist/lib/config.js
CHANGED
|
@@ -2,7 +2,7 @@ import fs from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { parse as parseYaml } from "yaml";
|
|
4
4
|
const CONFIG_FILENAME = "kagemusha.config.yaml";
|
|
5
|
-
const
|
|
5
|
+
const DEFINITIONS_FILE = ".kagemusha/definitions.json";
|
|
6
6
|
const ROUTING_FILENAME = ".kagemusha/routing.yaml";
|
|
7
7
|
export function findProjectRoot(startDir = process.cwd()) {
|
|
8
8
|
let dir = startDir;
|
|
@@ -25,17 +25,22 @@ export function loadConfig(projectRoot) {
|
|
|
25
25
|
resolveEnvVars(config);
|
|
26
26
|
return config;
|
|
27
27
|
}
|
|
28
|
-
export function
|
|
28
|
+
export function getDefinitionsPath(projectRoot) {
|
|
29
29
|
const root = projectRoot ?? findProjectRoot();
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
return path.join(root, DEFINITIONS_FILE);
|
|
31
|
+
}
|
|
32
|
+
export function loadDefinitions(projectRoot) {
|
|
33
|
+
const defsPath = getDefinitionsPath(projectRoot);
|
|
34
|
+
if (!fs.existsSync(defsPath)) {
|
|
32
35
|
return [];
|
|
33
36
|
}
|
|
34
|
-
const
|
|
35
|
-
return
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
const content = fs.readFileSync(defsPath, "utf-8");
|
|
38
|
+
return JSON.parse(content);
|
|
39
|
+
}
|
|
40
|
+
export function saveDefinitions(definitions, projectRoot) {
|
|
41
|
+
const defsPath = getDefinitionsPath(projectRoot);
|
|
42
|
+
fs.mkdirSync(path.dirname(defsPath), { recursive: true });
|
|
43
|
+
fs.writeFileSync(defsPath, `${JSON.stringify(definitions, null, 2)}\n`);
|
|
39
44
|
}
|
|
40
45
|
export function loadRouting(projectRoot) {
|
|
41
46
|
const root = projectRoot ?? findProjectRoot();
|
|
@@ -57,7 +62,13 @@ function resolveEnvVars(obj) {
|
|
|
57
62
|
if (typeof obj === "object") {
|
|
58
63
|
for (const [key, value] of Object.entries(obj)) {
|
|
59
64
|
if (typeof value === "string") {
|
|
60
|
-
obj[key] = value.replace(/\$\{(\w+)\}/g, (_, envVar) =>
|
|
65
|
+
obj[key] = value.replace(/\$\{(\w+)\}/g, (_, envVar) => {
|
|
66
|
+
const v = process.env[envVar];
|
|
67
|
+
if (v === undefined) {
|
|
68
|
+
throw new Error(`Environment variable \${${envVar}} is referenced in kagemusha.config.yaml but not set.`);
|
|
69
|
+
}
|
|
70
|
+
return v;
|
|
71
|
+
});
|
|
61
72
|
}
|
|
62
73
|
else if (typeof value === "object") {
|
|
63
74
|
resolveEnvVars(value);
|
|
@@ -83,9 +94,8 @@ export function validateDefinition(def) {
|
|
|
83
94
|
errors.push("url is required");
|
|
84
95
|
if (!def.capture)
|
|
85
96
|
errors.push("capture is required");
|
|
86
|
-
if (def.capture &&
|
|
87
|
-
|
|
88
|
-
errors.push(`capture.mode must be "fullPage", "selector", or "crop"`);
|
|
97
|
+
if (def.capture && !["fullPage", "crop"].includes(def.capture.mode)) {
|
|
98
|
+
errors.push(`capture.mode must be "fullPage" or "crop"`);
|
|
89
99
|
}
|
|
90
100
|
return errors;
|
|
91
101
|
}
|
package/dist/lib/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAG1C,MAAM,eAAe,GAAG,uBAAuB,CAAC;AAChD,MAAM,
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/crawl.d.ts
CHANGED
|
@@ -2,5 +2,5 @@ export interface DiscoveredPage {
|
|
|
2
2
|
path: string;
|
|
3
3
|
title: string;
|
|
4
4
|
}
|
|
5
|
-
export declare
|
|
5
|
+
export declare const discoverPages: (baseUrl: string, projectRoot?: string, maxDepth?: number, maxPages?: number) => Promise<DiscoveredPage[]>;
|
|
6
6
|
//# sourceMappingURL=crawl.d.ts.map
|
package/dist/lib/crawl.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crawl.d.ts","sourceRoot":"","sources":["../../src/lib/crawl.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"crawl.d.ts","sourceRoot":"","sources":["../../src/lib/crawl.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACd;AAED,eAAO,MAAM,aAAa,GACzB,SAAS,MAAM,EACf,cAAc,MAAM,EACpB,iBAAY,EACZ,iBAAc,KACZ,OAAO,CAAC,cAAc,EAAE,CA6L1B,CAAC"}
|
package/dist/lib/crawl.js
CHANGED
|
@@ -1,12 +1,101 @@
|
|
|
1
|
-
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import { authContextOptions, getAuthMetaPath } from "./auth.js";
|
|
4
|
+
export const discoverPages = async (baseUrl, projectRoot, maxDepth = 3, maxPages = 200) => {
|
|
2
5
|
const { chromium } = await import("playwright-chromium");
|
|
3
6
|
const browser = await chromium.launch({ headless: true });
|
|
4
|
-
const context = await browser.newContext();
|
|
7
|
+
const context = await browser.newContext(authContextOptions(projectRoot));
|
|
5
8
|
const origin = new URL(baseUrl).origin;
|
|
6
9
|
const visited = new Set();
|
|
7
10
|
const results = [];
|
|
8
|
-
const
|
|
11
|
+
const metaPath = projectRoot ? getAuthMetaPath(projectRoot) : "";
|
|
12
|
+
let startUrl = baseUrl;
|
|
13
|
+
let loginPath = "";
|
|
14
|
+
if (metaPath && fs.existsSync(metaPath)) {
|
|
15
|
+
const meta = JSON.parse(fs.readFileSync(metaPath, "utf-8"));
|
|
16
|
+
if (meta.loginPath) {
|
|
17
|
+
loginPath = meta.loginPath;
|
|
18
|
+
const loginUrl = new URL(meta.loginPath, baseUrl).toString();
|
|
19
|
+
results.push({ path: meta.loginPath, title: "Login" });
|
|
20
|
+
visited.add(normalizeUrl(loginUrl, origin) ?? loginUrl);
|
|
21
|
+
}
|
|
22
|
+
if (meta.landingPath) {
|
|
23
|
+
startUrl = new URL(meta.landingPath, baseUrl).toString();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
const seenPatterns = new Set();
|
|
9
27
|
try {
|
|
28
|
+
// Phase 1: Click nav elements on start page to discover SPA routes
|
|
29
|
+
console.log(chalk.gray(" Phase 1: Clicking navigation elements...\n"));
|
|
30
|
+
const navUrls = await discoverByClicking(context, startUrl, origin, loginPath);
|
|
31
|
+
// Add start page
|
|
32
|
+
const startNorm = normalizeUrl(startUrl, origin);
|
|
33
|
+
if (startNorm) {
|
|
34
|
+
const startPattern = toPattern(new URL(startNorm).pathname);
|
|
35
|
+
seenPatterns.add(startPattern);
|
|
36
|
+
visited.add(startNorm);
|
|
37
|
+
}
|
|
38
|
+
// Queue nav-discovered URLs for BFS
|
|
39
|
+
const queue = [];
|
|
40
|
+
for (const url of navUrls) {
|
|
41
|
+
const norm = normalizeUrl(url, origin);
|
|
42
|
+
if (!norm || visited.has(norm))
|
|
43
|
+
continue;
|
|
44
|
+
const pat = toPattern(new URL(norm).pathname);
|
|
45
|
+
if (seenPatterns.has(pat))
|
|
46
|
+
continue;
|
|
47
|
+
queue.push({ url: norm, depth: 1 });
|
|
48
|
+
}
|
|
49
|
+
// Also queue startUrl for link collection
|
|
50
|
+
if (startNorm && !visited.has(startNorm)) {
|
|
51
|
+
queue.unshift({ url: startNorm, depth: 0 });
|
|
52
|
+
}
|
|
53
|
+
// Add start page to results
|
|
54
|
+
const startPage = await context.newPage();
|
|
55
|
+
let sessionExpired = false;
|
|
56
|
+
try {
|
|
57
|
+
await startPage.goto(startUrl, {
|
|
58
|
+
waitUntil: "networkidle",
|
|
59
|
+
timeout: 60000,
|
|
60
|
+
});
|
|
61
|
+
const title = await startPage.title();
|
|
62
|
+
const pagePath = new URL(startPage.url()).pathname;
|
|
63
|
+
// Detect expired session
|
|
64
|
+
if (loginPath && pagePath === loginPath) {
|
|
65
|
+
console.log(chalk.yellow(`\n⚠ Redirected to ${loginPath} — session expired? Run "kagemusha login" first.\n`));
|
|
66
|
+
sessionExpired = true;
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
const startPattern = toPattern(pagePath);
|
|
70
|
+
seenPatterns.add(startPattern);
|
|
71
|
+
results.push({ path: pagePath, title: title || pagePath });
|
|
72
|
+
console.log(chalk.gray(` ${pagePath}`) +
|
|
73
|
+
` ${chalk.green("✓")} ${chalk.white(title)}`);
|
|
74
|
+
// Collect <a href> links from start page
|
|
75
|
+
const links = await collectLinks(startPage, origin);
|
|
76
|
+
for (const link of links) {
|
|
77
|
+
if (visited.has(link))
|
|
78
|
+
continue;
|
|
79
|
+
const linkPattern = toPattern(new URL(link).pathname);
|
|
80
|
+
if (seenPatterns.has(linkPattern))
|
|
81
|
+
continue;
|
|
82
|
+
queue.push({ url: link, depth: 1 });
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
catch (e) {
|
|
87
|
+
console.log(chalk.yellow(`\n⚠ Start page failed: ${e instanceof Error ? e.message : e}. Continuing with nav-discovered URLs.\n`));
|
|
88
|
+
}
|
|
89
|
+
finally {
|
|
90
|
+
await startPage.close().catch(() => { });
|
|
91
|
+
}
|
|
92
|
+
if (sessionExpired) {
|
|
93
|
+
return results;
|
|
94
|
+
}
|
|
95
|
+
// Phase 2: BFS crawl from discovered URLs
|
|
96
|
+
if (queue.length > 0) {
|
|
97
|
+
console.log(chalk.gray(`\n Phase 2: Crawling ${queue.length} discovered URLs...\n`));
|
|
98
|
+
}
|
|
10
99
|
while (queue.length > 0 && results.length < maxPages) {
|
|
11
100
|
const item = queue.shift();
|
|
12
101
|
if (!item)
|
|
@@ -14,15 +103,29 @@ export async function discoverPages(baseUrl, maxDepth = 2, maxPages = 50) {
|
|
|
14
103
|
const normalized = normalizeUrl(item.url, origin);
|
|
15
104
|
if (!normalized || visited.has(normalized))
|
|
16
105
|
continue;
|
|
106
|
+
const pattern = toPattern(new URL(normalized).pathname);
|
|
107
|
+
if (seenPatterns.has(pattern))
|
|
108
|
+
continue;
|
|
109
|
+
seenPatterns.add(pattern);
|
|
17
110
|
visited.add(normalized);
|
|
111
|
+
const urlPath = new URL(normalized).pathname;
|
|
112
|
+
process.stdout.write(chalk.gray(` ${urlPath}`));
|
|
113
|
+
const page = await context.newPage();
|
|
18
114
|
try {
|
|
19
|
-
const page = await context.newPage();
|
|
20
115
|
await page.goto(normalized, {
|
|
21
|
-
waitUntil: "
|
|
22
|
-
timeout:
|
|
116
|
+
waitUntil: "networkidle",
|
|
117
|
+
timeout: 60000,
|
|
23
118
|
});
|
|
24
119
|
const title = await page.title();
|
|
25
120
|
const pagePath = new URL(page.url()).pathname;
|
|
121
|
+
// Skip if redirected to a known pattern
|
|
122
|
+
const finalPattern = toPattern(pagePath);
|
|
123
|
+
if (finalPattern !== pattern && seenPatterns.has(finalPattern)) {
|
|
124
|
+
process.stdout.write(chalk.gray(" (skip)\n"));
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
seenPatterns.add(finalPattern);
|
|
128
|
+
process.stdout.write(` ${chalk.green("✓")} ${chalk.white(title)}\n`);
|
|
26
129
|
results.push({
|
|
27
130
|
path: pagePath,
|
|
28
131
|
title: title || pagePath,
|
|
@@ -30,36 +133,128 @@ export async function discoverPages(baseUrl, maxDepth = 2, maxPages = 50) {
|
|
|
30
133
|
if (item.depth < maxDepth) {
|
|
31
134
|
const links = await collectLinks(page, origin);
|
|
32
135
|
for (const link of links) {
|
|
33
|
-
if (
|
|
34
|
-
|
|
35
|
-
|
|
136
|
+
if (visited.has(link))
|
|
137
|
+
continue;
|
|
138
|
+
const linkPattern = toPattern(new URL(link).pathname);
|
|
139
|
+
if (seenPatterns.has(linkPattern))
|
|
140
|
+
continue;
|
|
141
|
+
queue.push({ url: link, depth: item.depth + 1 });
|
|
36
142
|
}
|
|
37
143
|
}
|
|
38
|
-
await page.close();
|
|
39
144
|
}
|
|
40
145
|
catch {
|
|
41
|
-
|
|
146
|
+
process.stdout.write(chalk.yellow(" (timeout, skip)\n"));
|
|
147
|
+
}
|
|
148
|
+
finally {
|
|
149
|
+
await page.close().catch(() => { });
|
|
42
150
|
}
|
|
43
151
|
}
|
|
152
|
+
if (results.length >= maxPages) {
|
|
153
|
+
console.log(chalk.gray(`\n Reached max ${maxPages} pages, stopping.\n`));
|
|
154
|
+
}
|
|
44
155
|
}
|
|
45
156
|
finally {
|
|
46
157
|
await browser.close();
|
|
47
158
|
}
|
|
48
159
|
return results;
|
|
49
|
-
}
|
|
50
|
-
|
|
160
|
+
};
|
|
161
|
+
// Click nav/sidebar link elements and collect URLs they navigate to.
|
|
162
|
+
// We collect accessible names (text || aria-label) up front, then re-resolve
|
|
163
|
+
// each label by name on every iteration so SPA re-renders don't cause us
|
|
164
|
+
// to click the wrong element.
|
|
165
|
+
const discoverByClicking = async (context, startUrl, origin, loginPath) => {
|
|
166
|
+
const page = await context.newPage();
|
|
167
|
+
try {
|
|
168
|
+
await page.goto(startUrl, { waitUntil: "networkidle", timeout: 60000 });
|
|
169
|
+
// Check if redirected to login
|
|
170
|
+
if (loginPath && new URL(page.url()).pathname === loginPath) {
|
|
171
|
+
return [];
|
|
172
|
+
}
|
|
173
|
+
// Collect accessible labels for nav links first, then page-wide links.
|
|
174
|
+
const candidates = [];
|
|
175
|
+
const seen = new Set();
|
|
176
|
+
// Use accessible name (text || aria-label) so getByRole({ name }) can
|
|
177
|
+
// resolve the element again on click. Other attributes don't participate
|
|
178
|
+
// in accessible name and would be unreachable.
|
|
179
|
+
const collectLabels = async (locator, preferNav) => {
|
|
180
|
+
const count = await locator.count();
|
|
181
|
+
for (let i = 0; i < count; i++) {
|
|
182
|
+
const el = locator.nth(i);
|
|
183
|
+
let name = ((await el.textContent().catch(() => null)) ?? "").trim();
|
|
184
|
+
if (!name) {
|
|
185
|
+
name = ((await el.getAttribute("aria-label").catch(() => null)) ?? "").trim();
|
|
186
|
+
}
|
|
187
|
+
if (!name || seen.has(name))
|
|
188
|
+
continue;
|
|
189
|
+
seen.add(name);
|
|
190
|
+
candidates.push({ name, preferNav });
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
await collectLabels(page.getByRole("navigation").getByRole("link"), true);
|
|
194
|
+
await collectLabels(page.getByRole("link"), false);
|
|
195
|
+
console.log(chalk.gray(` Found ${candidates.length} link label(s) to try\n`));
|
|
196
|
+
const discoveredUrls = [];
|
|
197
|
+
for (const { name, preferNav } of candidates) {
|
|
198
|
+
try {
|
|
199
|
+
const root = preferNav
|
|
200
|
+
? page
|
|
201
|
+
.getByRole("navigation")
|
|
202
|
+
.getByRole("link", { name, exact: true })
|
|
203
|
+
: page.getByRole("link", { name, exact: true });
|
|
204
|
+
const el = root.first();
|
|
205
|
+
if (!(await el.isVisible().catch(() => false)))
|
|
206
|
+
continue;
|
|
207
|
+
const beforeUrl = page.url();
|
|
208
|
+
await el.click({ timeout: 3000 });
|
|
209
|
+
await page
|
|
210
|
+
.waitForLoadState("networkidle", { timeout: 5000 })
|
|
211
|
+
.catch(() => { });
|
|
212
|
+
await page.waitForTimeout(500);
|
|
213
|
+
const afterUrl = page.url();
|
|
214
|
+
if (afterUrl !== beforeUrl && new URL(afterUrl).origin === origin) {
|
|
215
|
+
const afterPath = new URL(afterUrl).pathname;
|
|
216
|
+
if (afterPath !== loginPath) {
|
|
217
|
+
discoveredUrls.push(afterUrl);
|
|
218
|
+
console.log(chalk.green(` + ${afterPath}`) + chalk.gray(` ${name}`));
|
|
219
|
+
}
|
|
220
|
+
await page.goto(startUrl, {
|
|
221
|
+
waitUntil: "networkidle",
|
|
222
|
+
timeout: 10000,
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
catch {
|
|
227
|
+
// Skip elements that can't be clicked or text didn't resolve
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return discoveredUrls;
|
|
231
|
+
}
|
|
232
|
+
finally {
|
|
233
|
+
await page.close().catch(() => { });
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
// Replace numeric IDs, UUIDs, and hex strings with * to detect same-structure URLs
|
|
237
|
+
const toPattern = (pathname) => pathname
|
|
238
|
+
.split("/")
|
|
239
|
+
.map((seg) => /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(seg)
|
|
240
|
+
? "*"
|
|
241
|
+
: /^\d+$/.test(seg)
|
|
242
|
+
? "*"
|
|
243
|
+
: /^[0-9a-f]{8,}$/i.test(seg)
|
|
244
|
+
? "*"
|
|
245
|
+
: seg)
|
|
246
|
+
.join("/");
|
|
247
|
+
const collectLinks = async (page, origin) => {
|
|
51
248
|
const hrefs = await page.evaluate(() => Array.from(document.querySelectorAll("a[href]")).map((a) => a.href));
|
|
52
249
|
return hrefs
|
|
53
250
|
.map((href) => normalizeUrl(href, origin))
|
|
54
251
|
.filter((url) => url !== null);
|
|
55
|
-
}
|
|
56
|
-
|
|
252
|
+
};
|
|
253
|
+
const normalizeUrl = (url, origin) => {
|
|
57
254
|
try {
|
|
58
255
|
const parsed = new URL(url, origin);
|
|
59
|
-
// Same origin only
|
|
60
256
|
if (parsed.origin !== origin)
|
|
61
257
|
return null;
|
|
62
|
-
// Skip non-page resources
|
|
63
258
|
const skip = [
|
|
64
259
|
".js",
|
|
65
260
|
".css",
|
|
@@ -80,10 +275,8 @@ function normalizeUrl(url, origin) {
|
|
|
80
275
|
];
|
|
81
276
|
if (skip.some((ext) => parsed.pathname.endsWith(ext)))
|
|
82
277
|
return null;
|
|
83
|
-
// Skip anchors and mailto
|
|
84
278
|
if (url.startsWith("mailto:") || url.startsWith("tel:"))
|
|
85
279
|
return null;
|
|
86
|
-
// Remove hash and search params for deduplication
|
|
87
280
|
parsed.hash = "";
|
|
88
281
|
parsed.search = "";
|
|
89
282
|
return parsed.toString();
|
|
@@ -91,5 +284,5 @@ function normalizeUrl(url, origin) {
|
|
|
91
284
|
catch {
|
|
92
285
|
return null;
|
|
93
286
|
}
|
|
94
|
-
}
|
|
287
|
+
};
|
|
95
288
|
//# sourceMappingURL=crawl.js.map
|
package/dist/lib/crawl.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"crawl.js","sourceRoot":"","sources":["../../src/lib/crawl.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"crawl.js","sourceRoot":"","sources":["../../src/lib/crawl.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../../src/lib/definition.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,GAAI,SAAS,MAAM,KAAG,MAKT,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"definition.js","sourceRoot":"","sources":["../../src/lib/definition.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,OAAe,EAAU,EAAE,CAC3D,OAAO;KACL,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;KAClB,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC;KACrB,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC;KACtB,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export interface Dimensions {
|
|
2
|
+
width: number;
|
|
3
|
+
height: number;
|
|
4
|
+
}
|
|
5
|
+
export type DiffStatus = {
|
|
6
|
+
id: string;
|
|
7
|
+
status: "unchanged";
|
|
8
|
+
} | {
|
|
9
|
+
id: string;
|
|
10
|
+
status: "new";
|
|
11
|
+
} | {
|
|
12
|
+
id: string;
|
|
13
|
+
status: "missing";
|
|
14
|
+
reason?: string;
|
|
15
|
+
} | {
|
|
16
|
+
id: string;
|
|
17
|
+
status: "changed";
|
|
18
|
+
reason: "pixel-diff";
|
|
19
|
+
diffPercentage: number;
|
|
20
|
+
diffPath: string;
|
|
21
|
+
} | {
|
|
22
|
+
id: string;
|
|
23
|
+
status: "changed";
|
|
24
|
+
reason: "layout-diff";
|
|
25
|
+
canonical: Dimensions;
|
|
26
|
+
staging: Dimensions;
|
|
27
|
+
};
|
|
28
|
+
export interface DiffOptions {
|
|
29
|
+
/** Color difference threshold per pixel (0-1). Lower = stricter. Default 0.1 */
|
|
30
|
+
pixelThreshold?: number;
|
|
31
|
+
/** Ignore anti-aliased pixels (treat them as equal). Default true */
|
|
32
|
+
ignoreAntiAliasing?: boolean;
|
|
33
|
+
}
|
|
34
|
+
export type DiffResult = {
|
|
35
|
+
match: true;
|
|
36
|
+
} | {
|
|
37
|
+
match: false;
|
|
38
|
+
reason: "layout-diff";
|
|
39
|
+
canonical: Dimensions;
|
|
40
|
+
staging: Dimensions;
|
|
41
|
+
} | {
|
|
42
|
+
match: false;
|
|
43
|
+
reason: "pixel-diff";
|
|
44
|
+
diffCount: number;
|
|
45
|
+
diffPercentage: number;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Compare two PNG files using pixelmatch and write the diff visualization.
|
|
49
|
+
* If dimensions differ, returns layout-diff without writing a diff image.
|
|
50
|
+
*/
|
|
51
|
+
export declare const diffImages: (baseline: string, current: string, diffPath: string, options?: DiffOptions) => Promise<DiffResult>;
|
|
52
|
+
//# sourceMappingURL=diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/lib/diff.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,UAAU;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,UAAU,GACnB;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,GACnC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,KAAK,CAAA;CAAE,GAC7B;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,SAAS,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAClD;IACA,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,SAAS,CAAC;IAClB,MAAM,EAAE,YAAY,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;CAChB,GACD;IACA,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,SAAS,CAAC;IAClB,MAAM,EAAE,aAAa,CAAC;IACtB,SAAS,EAAE,UAAU,CAAC;IACtB,OAAO,EAAE,UAAU,CAAC;CACnB,CAAC;AAEL,MAAM,WAAW,WAAW;IAC3B,gFAAgF;IAChF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qEAAqE;IACrE,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,MAAM,UAAU,GACnB;IAAE,KAAK,EAAE,IAAI,CAAA;CAAE,GACf;IACA,KAAK,EAAE,KAAK,CAAC;IACb,MAAM,EAAE,aAAa,CAAC;IACtB,SAAS,EAAE,UAAU,CAAC;IACtB,OAAO,EAAE,UAAU,CAAC;CACnB,GACD;IACA,KAAK,EAAE,KAAK,CAAC;IACb,MAAM,EAAE,YAAY,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;CACtB,CAAC;AAKL;;;GAGG;AACH,eAAO,MAAM,UAAU,GACtB,UAAU,MAAM,EAChB,SAAS,MAAM,EACf,UAAU,MAAM,EAChB,UAAS,WAAgB,KACvB,OAAO,CAAC,UAAU,CAoCpB,CAAC"}
|