@qulib/core 0.1.0 → 0.1.1
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
|
@@ -92,7 +92,7 @@ Default file: **`qulib.config.ts`** in this package directory (or pass **`--conf
|
|
|
92
92
|
|
|
93
93
|
Optional `auth` for authenticated scanning — see commented example in `qulib.config.ts`. For local credentials, use a separate file (e.g. `qulib.test-auth.config.ts`, gitignored at the repo root) and point `--config` at it.
|
|
94
94
|
|
|
95
|
-
Use the same **
|
|
95
|
+
Use the same **hostname** for `--url` as your app’s canonical host when you can. The crawler treats **`www` and apex** (e.g. `example.com` and `www.example.com`) as the same site for internal link discovery, so hydration and redirects still queue in-site URLs.
|
|
96
96
|
|
|
97
97
|
## Scripts (from `packages/core`)
|
|
98
98
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"playwright-explorer.d.ts","sourceRoot":"","sources":["../../src/tools/playwright-explorer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,EAAwB,KAAK,cAAc,EAAc,MAAM,sCAAsC,CAAC;AAC7G,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"playwright-explorer.d.ts","sourceRoot":"","sources":["../../src/tools/playwright-explorer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,OAAO,EAAwB,KAAK,cAAc,EAAc,MAAM,sCAAsC,CAAC;AAC7G,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAgBjE,qBAAa,kBAAmB,YAAW,WAAW;IAC9C,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC;CAqJ/E"}
|
|
@@ -2,6 +2,19 @@ import { chromium } from '@playwright/test';
|
|
|
2
2
|
import { AxeBuilder } from '@axe-core/playwright';
|
|
3
3
|
import { createAuthenticatedContext } from './auth.js';
|
|
4
4
|
import { RouteInventorySchema } from '../schemas/route-inventory.schema.js';
|
|
5
|
+
function crawlHostKey(hostname) {
|
|
6
|
+
return hostname.replace(/^www\./i, '').toLowerCase();
|
|
7
|
+
}
|
|
8
|
+
function isInternalHref(href, baseUrlStr) {
|
|
9
|
+
try {
|
|
10
|
+
const u = new URL(href);
|
|
11
|
+
const base = new URL(baseUrlStr);
|
|
12
|
+
return u.protocol === base.protocol && crawlHostKey(u.hostname) === crawlHostKey(base.hostname);
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
5
18
|
export class PlaywrightExplorer {
|
|
6
19
|
async explore(baseUrl, config) {
|
|
7
20
|
const browser = await chromium.launch({ headless: true });
|
|
@@ -53,17 +66,8 @@ export class PlaywrightExplorer {
|
|
|
53
66
|
const hrefs = await page.evaluate(() => Array.from(document.querySelectorAll('a[href]'))
|
|
54
67
|
.map((a) => a.href)
|
|
55
68
|
.filter(Boolean));
|
|
56
|
-
const base = new URL(baseUrl);
|
|
57
69
|
const internalLinks = hrefs
|
|
58
|
-
.filter((href) =>
|
|
59
|
-
try {
|
|
60
|
-
const u = new URL(href);
|
|
61
|
-
return u.origin === base.origin;
|
|
62
|
-
}
|
|
63
|
-
catch {
|
|
64
|
-
return false;
|
|
65
|
-
}
|
|
66
|
-
})
|
|
70
|
+
.filter((href) => isInternalHref(href, baseUrl))
|
|
67
71
|
.map((href) => href.split('?')[0].split('#')[0]);
|
|
68
72
|
const uniqueInternal = [...new Set(internalLinks)];
|
|
69
73
|
for (const link of uniqueInternal) {
|