@forkpoint/agent-lighthouse-core 0.2.0 → 0.2.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 +27 -0
- package/dist/index.d.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +65 -18
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +65 -18
- package/dist/index.mjs.map +1 -1
- package/package.json +8 -3
package/dist/index.mjs
CHANGED
|
@@ -507,7 +507,8 @@ function extractImages($) {
|
|
|
507
507
|
width: $(el).attr("width") ?? void 0,
|
|
508
508
|
height: $(el).attr("height") ?? void 0,
|
|
509
509
|
loading: $(el).attr("loading") ?? void 0,
|
|
510
|
-
role: $(el).attr("role") ?? void 0
|
|
510
|
+
role: $(el).attr("role") ?? void 0,
|
|
511
|
+
ariaHidden: $(el).attr("aria-hidden") ?? void 0
|
|
511
512
|
});
|
|
512
513
|
});
|
|
513
514
|
return images;
|
|
@@ -4647,9 +4648,6 @@ function matchesAnyType2(schema, types) {
|
|
|
4647
4648
|
function allSchemas3(ctx) {
|
|
4648
4649
|
return ctx.pages.flatMap((p) => flattenJsonLd(p.structuredData ?? p.jsonLd));
|
|
4649
4650
|
}
|
|
4650
|
-
function hasProps3(obj, keys) {
|
|
4651
|
-
return keys.filter((k) => !obj[k]);
|
|
4652
|
-
}
|
|
4653
4651
|
var ServiceProductSchemaAudit = class extends Audit {
|
|
4654
4652
|
static meta = {
|
|
4655
4653
|
id: "3.8",
|
|
@@ -4702,13 +4700,19 @@ var ServiceProductSchemaAudit = class extends Audit {
|
|
|
4702
4700
|
}
|
|
4703
4701
|
);
|
|
4704
4702
|
}
|
|
4705
|
-
const requiredProps = ["name", "description", "provider"];
|
|
4706
4703
|
const first2 = serviceProducts[0];
|
|
4707
|
-
const
|
|
4704
|
+
const isProduct = matchesAnyType2(first2, ["Product"]);
|
|
4705
|
+
const hasName = Boolean(first2["name"]);
|
|
4706
|
+
const hasDescription = Boolean(first2["description"]);
|
|
4707
|
+
const hasProviderOrBrand = isProduct ? Boolean(first2["brand"] || first2["manufacturer"] || first2["provider"] || first2["offers"]) : Boolean(first2["provider"]);
|
|
4708
|
+
const missing = [];
|
|
4709
|
+
if (!hasName) missing.push("name");
|
|
4710
|
+
if (!hasDescription) missing.push("description");
|
|
4711
|
+
if (!hasProviderOrBrand) missing.push(isProduct ? "brand/offers" : "provider");
|
|
4708
4712
|
const valid = missing.length === 0;
|
|
4709
4713
|
if (valid) {
|
|
4710
4714
|
return this.pass(
|
|
4711
|
-
`Service/Product schema found with name, description, and provider.`,
|
|
4715
|
+
`Service/Product schema found with name, description, and ${isProduct ? "brand/offers" : "provider"}.`,
|
|
4712
4716
|
"Service or Product schema with name, description, and provider.",
|
|
4713
4717
|
`Complete Service/Product schema (${serviceProducts.length} total)`
|
|
4714
4718
|
);
|
|
@@ -5354,7 +5358,7 @@ function matchesAnyType7(schema, types) {
|
|
|
5354
5358
|
function allSchemas8(ctx) {
|
|
5355
5359
|
return ctx.pages.flatMap((p) => flattenJsonLd(p.structuredData ?? p.jsonLd));
|
|
5356
5360
|
}
|
|
5357
|
-
function
|
|
5361
|
+
function hasProps3(obj, keys) {
|
|
5358
5362
|
return keys.filter((k) => !obj[k]);
|
|
5359
5363
|
}
|
|
5360
5364
|
var AuthorSchemaAudit = class extends Audit {
|
|
@@ -5435,11 +5439,11 @@ var AuthorSchemaAudit = class extends Audit {
|
|
|
5435
5439
|
}
|
|
5436
5440
|
const requiredProps = ["name", "jobTitle", "sameAs", "affiliation"];
|
|
5437
5441
|
const bestPerson = allPersons.reduce((best, p) => {
|
|
5438
|
-
const bestMissing =
|
|
5439
|
-
const currentMissing =
|
|
5442
|
+
const bestMissing = hasProps3(best, requiredProps).length;
|
|
5443
|
+
const currentMissing = hasProps3(p, requiredProps).length;
|
|
5440
5444
|
return currentMissing < bestMissing ? p : best;
|
|
5441
5445
|
}, allPersons[0]);
|
|
5442
|
-
const missing =
|
|
5446
|
+
const missing = hasProps3(bestPerson, requiredProps);
|
|
5443
5447
|
const complete = missing.length === 0;
|
|
5444
5448
|
if (complete) {
|
|
5445
5449
|
return this.pass(
|
|
@@ -11360,7 +11364,7 @@ var DecorativeImagesAudit = class extends Audit {
|
|
|
11360
11364
|
for (const img of images) {
|
|
11361
11365
|
if (img.alt === "") {
|
|
11362
11366
|
decorativeCount++;
|
|
11363
|
-
if (img.role === "presentation") {
|
|
11367
|
+
if (img.role === "presentation" || img.role === "none" || img.ariaHidden === "true") {
|
|
11364
11368
|
correctlyMarked++;
|
|
11365
11369
|
}
|
|
11366
11370
|
}
|
|
@@ -12584,8 +12588,19 @@ var CorsAiFilesAudit = class extends Audit {
|
|
|
12584
12588
|
async audit(ctx) {
|
|
12585
12589
|
const page = ctx.pages?.[0];
|
|
12586
12590
|
const aiPaths = ["/llms.txt", "/.well-known/ai-catalog.json"];
|
|
12591
|
+
const hasRootFiles = ctx.rootFiles && Object.keys(ctx.rootFiles).length > 0;
|
|
12592
|
+
const existingAiPaths = hasRootFiles ? aiPaths.filter((p) => ctx.rootFiles[p]?.status === 200) : aiPaths;
|
|
12593
|
+
if (hasRootFiles && existingAiPaths.length === 0) {
|
|
12594
|
+
return this.warn(
|
|
12595
|
+
"No AI files (/llms.txt, /.well-known/ai-catalog.json) found to check CORS headers.",
|
|
12596
|
+
"OPTIONS requests to /llms.txt and /.well-known/ai-catalog.json return Access-Control-Allow-Origin",
|
|
12597
|
+
"No applicable AI files found",
|
|
12598
|
+
void 0,
|
|
12599
|
+
page?.url
|
|
12600
|
+
);
|
|
12601
|
+
}
|
|
12587
12602
|
const corsResults = [];
|
|
12588
|
-
for (const path of
|
|
12603
|
+
for (const path of existingAiPaths) {
|
|
12589
12604
|
try {
|
|
12590
12605
|
const result = await ctx.fetch({
|
|
12591
12606
|
url: `${ctx.baseUrl}${path}`,
|
|
@@ -15075,9 +15090,33 @@ var AboutCredentialsAudit = class extends Audit {
|
|
|
15075
15090
|
}
|
|
15076
15091
|
};
|
|
15077
15092
|
async audit(ctx) {
|
|
15078
|
-
const aboutPaths = [
|
|
15079
|
-
|
|
15080
|
-
|
|
15093
|
+
const aboutPaths = [
|
|
15094
|
+
"/about/",
|
|
15095
|
+
"/about-us/",
|
|
15096
|
+
"/about",
|
|
15097
|
+
"/pages/about",
|
|
15098
|
+
"/pages/about-us",
|
|
15099
|
+
"/pages/our-story",
|
|
15100
|
+
"/our-story"
|
|
15101
|
+
];
|
|
15102
|
+
let aboutResult = void 0;
|
|
15103
|
+
for (const path of aboutPaths) {
|
|
15104
|
+
const file = ctx.rootFiles[path];
|
|
15105
|
+
if (file && file.status === 200 && file.body) {
|
|
15106
|
+
aboutResult = file;
|
|
15107
|
+
break;
|
|
15108
|
+
}
|
|
15109
|
+
}
|
|
15110
|
+
if (!aboutResult && ctx.pages) {
|
|
15111
|
+
const matchingPage = ctx.pages.find((p) => {
|
|
15112
|
+
const urlLower = p.url.toLowerCase();
|
|
15113
|
+
return urlLower.includes("/about") || urlLower.includes("/our-story") || urlLower.includes("/who-we-are");
|
|
15114
|
+
});
|
|
15115
|
+
if (matchingPage?.fetchResult?.status === 200 && matchingPage.fetchResult.body) {
|
|
15116
|
+
aboutResult = matchingPage.fetchResult;
|
|
15117
|
+
}
|
|
15118
|
+
}
|
|
15119
|
+
if (!aboutResult) {
|
|
15081
15120
|
for (const path of aboutPaths) {
|
|
15082
15121
|
try {
|
|
15083
15122
|
const result = await ctx.fetch({
|
|
@@ -15346,7 +15385,11 @@ var TRUST_PATTERNS = [
|
|
|
15346
15385
|
/\baward/i,
|
|
15347
15386
|
/\bas\s+seen\s+(in|on)\b/i,
|
|
15348
15387
|
/\bpartner(s|ed|ship)?\b/i,
|
|
15349
|
-
/\bcertif(ied|icate|ication)\b/i
|
|
15388
|
+
/\bcertif(ied|icate|ication)\b/i,
|
|
15389
|
+
/\b(money[-\s]back\s+guarantee|satisfaction\s+guarantee|guaranteed)\b/i,
|
|
15390
|
+
/\b(reviews|customer\s+rating|verified\s+(buyer|customer|review)|happy\s+customers)\b/i,
|
|
15391
|
+
/\b(sustainable|organic|fair\s+trade|b\s+corp|handcrafted|handmade)\b/i,
|
|
15392
|
+
/\b(secure\s+checkout|free\s+returns|free\s+shipping)\b/i
|
|
15350
15393
|
];
|
|
15351
15394
|
var TrustSignalsAudit = class extends Audit {
|
|
15352
15395
|
static meta = {
|
|
@@ -22052,7 +22095,11 @@ async function runScan(url, onProgress, pageOverrides, signal) {
|
|
|
22052
22095
|
"/policies/terms-of-service",
|
|
22053
22096
|
"/about/",
|
|
22054
22097
|
"/about-us/",
|
|
22055
|
-
"/about"
|
|
22098
|
+
"/about",
|
|
22099
|
+
"/pages/about",
|
|
22100
|
+
"/pages/about-us",
|
|
22101
|
+
"/pages/our-story",
|
|
22102
|
+
"/our-story"
|
|
22056
22103
|
];
|
|
22057
22104
|
logger.debug({ count: rootFilePaths.length }, "[orchestrator] Phase 1: Fetching root files");
|
|
22058
22105
|
const rootResults = await Promise.all(
|