@drowlink/aeo-linter-core 0.1.1 → 0.1.4
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/dist/__tests__/audit-contract.test.js +12 -13
- package/dist/__tests__/audit-contract.test.js.map +1 -1
- package/dist/__tests__/gatherers.test.js +11 -12
- package/dist/__tests__/gatherers.test.js.map +1 -1
- package/dist/__tests__/runner.test.js +12 -12
- package/dist/__tests__/runner.test.js.map +1 -1
- package/dist/audits/ai-accessibility/ai-bot-sitemap.d.ts +1 -1
- package/dist/audits/ai-accessibility/ai-bot-sitemap.js +6 -6
- package/dist/audits/ai-accessibility/ai-bot-sitemap.js.map +1 -1
- package/dist/audits/ai-accessibility/ai-robots-txt.d.ts +1 -1
- package/dist/audits/ai-accessibility/ai-robots-txt.d.ts.map +1 -1
- package/dist/audits/ai-accessibility/ai-robots-txt.js +11 -12
- package/dist/audits/ai-accessibility/ai-robots-txt.js.map +1 -1
- package/dist/audits/ai-accessibility/ai-x-robots-tag.d.ts +1 -1
- package/dist/audits/ai-accessibility/ai-x-robots-tag.js +8 -8
- package/dist/audits/ai-accessibility/ai-x-robots-tag.js.map +1 -1
- package/dist/audits/audit.d.ts +13 -13
- package/dist/audits/audit.js +14 -14
- package/dist/audits/audit.js.map +1 -1
- package/dist/audits/content-chunking/chunk-token-density.d.ts +1 -1
- package/dist/audits/content-chunking/chunk-token-density.js +12 -12
- package/dist/audits/content-chunking/chunk-token-density.js.map +1 -1
- package/dist/audits/content-chunking/heading-hierarchy.d.ts +1 -1
- package/dist/audits/content-chunking/heading-hierarchy.js +13 -13
- package/dist/audits/content-chunking/heading-hierarchy.js.map +1 -1
- package/dist/audits/content-chunking/semantic-containers.d.ts +1 -1
- package/dist/audits/content-chunking/semantic-containers.js +7 -7
- package/dist/audits/content-chunking/semantic-containers.js.map +1 -1
- package/dist/audits/direct-answer-density/concise-answer-wordcount.d.ts +1 -1
- package/dist/audits/direct-answer-density/concise-answer-wordcount.js +11 -11
- package/dist/audits/direct-answer-density/concise-answer-wordcount.js.map +1 -1
- package/dist/audits/direct-answer-density/direct-definition-answering.d.ts +1 -1
- package/dist/audits/direct-answer-density/direct-definition-answering.js +12 -12
- package/dist/audits/direct-answer-density/direct-definition-answering.js.map +1 -1
- package/dist/audits/direct-answer-density/question-heading-alignment.d.ts +1 -1
- package/dist/audits/direct-answer-density/question-heading-alignment.js +7 -7
- package/dist/audits/direct-answer-density/question-heading-alignment.js.map +1 -1
- package/dist/audits/index.d.ts +1 -1
- package/dist/audits/index.js +1 -1
- package/dist/audits/structured-data/entity-sameas-links.d.ts +1 -1
- package/dist/audits/structured-data/entity-sameas-links.js +11 -11
- package/dist/audits/structured-data/entity-sameas-links.js.map +1 -1
- package/dist/audits/structured-data/jsonld-syntax-validity.d.ts +1 -1
- package/dist/audits/structured-data/jsonld-syntax-validity.js +12 -12
- package/dist/audits/structured-data/jsonld-syntax-validity.js.map +1 -1
- package/dist/audits/structured-data/rag-schema-presence.d.ts +1 -1
- package/dist/audits/structured-data/rag-schema-presence.js +13 -13
- package/dist/audits/structured-data/rag-schema-presence.js.map +1 -1
- package/dist/config/default-config.d.ts +2 -2
- package/dist/config/default-config.js +6 -6
- package/dist/config/default-config.js.map +1 -1
- package/dist/gather/driver/cheerio-driver.d.ts +1 -1
- package/dist/gather/driver/cheerio-driver.js +4 -4
- package/dist/gather/driver/cheerio-driver.js.map +1 -1
- package/dist/gather/gatherers/content-chunks-gatherer.d.ts +1 -1
- package/dist/gather/gatherers/content-chunks-gatherer.d.ts.map +1 -1
- package/dist/gather/gatherers/content-chunks-gatherer.js +4 -6
- package/dist/gather/gatherers/content-chunks-gatherer.js.map +1 -1
- package/dist/gather/gatherers/direct-answers-gatherer.d.ts +1 -1
- package/dist/gather/gatherers/direct-answers-gatherer.d.ts.map +1 -1
- package/dist/gather/gatherers/direct-answers-gatherer.js +4 -5
- package/dist/gather/gatherers/direct-answers-gatherer.js.map +1 -1
- package/dist/gather/gatherers/headings-hierarchy-gatherer.d.ts +1 -1
- package/dist/gather/gatherers/headings-hierarchy-gatherer.js +2 -2
- package/dist/gather/gatherers/headings-hierarchy-gatherer.js.map +1 -1
- package/dist/gather/gatherers/robots-txt-gatherer.d.ts +1 -1
- package/dist/gather/gatherers/robots-txt-gatherer.d.ts.map +1 -1
- package/dist/gather/gatherers/robots-txt-gatherer.js +2 -4
- package/dist/gather/gatherers/robots-txt-gatherer.js.map +1 -1
- package/dist/report/html-reporter.d.ts +2 -2
- package/dist/report/html-reporter.js +9 -9
- package/dist/report/html-reporter.js.map +1 -1
- package/dist/report/terminal-reporter.d.ts +1 -1
- package/dist/report/terminal-reporter.js +3 -3
- package/dist/report/terminal-reporter.js.map +1 -1
- package/dist/runner/aggregator.d.ts +3 -3
- package/dist/runner/aggregator.js +5 -5
- package/dist/runner/aggregator.js.map +1 -1
- package/dist/runner/runner.d.ts +7 -7
- package/dist/runner/runner.d.ts.map +1 -1
- package/dist/runner/runner.js +17 -18
- package/dist/runner/runner.js.map +1 -1
- package/dist/types/artifacts.d.ts +19 -21
- package/dist/types/artifacts.d.ts.map +1 -1
- package/dist/types/artifacts.js +3 -3
- package/dist/types/audit.d.ts +29 -29
- package/dist/types/audit.d.ts.map +1 -1
- package/dist/types/audit.js +2 -2
- package/dist/types/config.d.ts +21 -21
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.js +1 -1
- package/dist/types/gatherer.d.ts +6 -6
- package/dist/types/gatherer.d.ts.map +1 -1
- package/dist/types/gatherer.js +1 -1
- package/package.json +1 -1
|
@@ -4,35 +4,34 @@ import { defaultConfig } from '../config/default-config.js';
|
|
|
4
4
|
class MockRobotsAudit extends Audit {
|
|
5
5
|
static meta = {
|
|
6
6
|
id: 'ai-robots-txt',
|
|
7
|
-
title: '
|
|
8
|
-
failureTitle: '
|
|
9
|
-
description: '
|
|
7
|
+
title: 'robots.txt allows crawling by AI bots',
|
|
8
|
+
failureTitle: 'robots.txt blocks AI search crawlers',
|
|
9
|
+
description: 'Verifies directives for GPTBot, PerplexityBot, etc.',
|
|
10
10
|
requiredArtifacts: ['RobotsTxt'],
|
|
11
11
|
};
|
|
12
12
|
static async audit(artifacts) {
|
|
13
13
|
const isAllowed = artifacts.RobotsTxt.aiBotsStatus.gptBot === 'allowed';
|
|
14
14
|
return this.generateAuditResult({
|
|
15
15
|
score: this.binaryScore(isAllowed),
|
|
16
|
-
displayValue: isAllowed ? 'GPTBot
|
|
16
|
+
displayValue: isAllowed ? 'GPTBot allowed' : 'GPTBot blocked',
|
|
17
17
|
details: this.makeTableDetails([
|
|
18
|
-
{ key: 'bot', label: 'Bot
|
|
19
|
-
{ key: 'status', label: '
|
|
18
|
+
{ key: 'bot', label: 'AI Bot' },
|
|
19
|
+
{ key: 'status', label: 'Status' },
|
|
20
20
|
], [{ bot: 'GPTBot', status: artifacts.RobotsTxt.aiBotsStatus.gptBot }]),
|
|
21
21
|
});
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
describe('AEO Linter Core Contracts (Lighthouse Architecture)', () => {
|
|
25
|
-
it('
|
|
25
|
+
it('defines the 4 key AEO categories with weights summing to 100', () => {
|
|
26
26
|
const categories = Object.keys(defaultConfig.categories);
|
|
27
27
|
expect(categories).toContain('ai-accessibility');
|
|
28
28
|
expect(categories).toContain('structured-data');
|
|
29
29
|
expect(categories).toContain('content-chunking');
|
|
30
30
|
expect(categories).toContain('direct-answer-density');
|
|
31
|
-
// Verificar que la suma de pesos de categorías principales sea 100%
|
|
32
31
|
const totalWeight = Object.values(defaultConfig.categories).reduce((sum, cat) => sum + (cat.weight || 0), 0);
|
|
33
32
|
expect(totalWeight).toBe(100);
|
|
34
33
|
});
|
|
35
|
-
it('
|
|
34
|
+
it('executes a mock audit derived from Audit and produces a valid AuditResult', async () => {
|
|
36
35
|
const mockArtifacts = {
|
|
37
36
|
URL: {
|
|
38
37
|
requestedUrl: 'https://example.com',
|
|
@@ -74,8 +73,8 @@ describe('AEO Linter Core Contracts (Lighthouse Architecture)', () => {
|
|
|
74
73
|
sameAsUrls: [],
|
|
75
74
|
},
|
|
76
75
|
MetaTags: {
|
|
77
|
-
title: '
|
|
78
|
-
description: '
|
|
76
|
+
title: 'AEO Example',
|
|
77
|
+
description: 'Optimized meta description',
|
|
79
78
|
canonicalUrl: 'https://example.com',
|
|
80
79
|
viewport: 'width=device-width',
|
|
81
80
|
charset: 'utf-8',
|
|
@@ -84,7 +83,7 @@ describe('AEO Linter Core Contracts (Lighthouse Architecture)', () => {
|
|
|
84
83
|
robotsMeta: null,
|
|
85
84
|
},
|
|
86
85
|
HeadingsHierarchy: {
|
|
87
|
-
headings: [{ level: 1, text: '
|
|
86
|
+
headings: [{ level: 1, text: 'H1 Title', index: 0 }],
|
|
88
87
|
h1Count: 1,
|
|
89
88
|
h2Count: 0,
|
|
90
89
|
h3Count: 0,
|
|
@@ -113,7 +112,7 @@ describe('AEO Linter Core Contracts (Lighthouse Architecture)', () => {
|
|
|
113
112
|
expect(result.id).toBe('ai-robots-txt');
|
|
114
113
|
expect(result.score).toBe(1);
|
|
115
114
|
expect(result.scoreDisplayMode).toBe('binary');
|
|
116
|
-
expect(result.displayValue).toBe('GPTBot
|
|
115
|
+
expect(result.displayValue).toBe('GPTBot allowed');
|
|
117
116
|
expect(result.details?.type).toBe('table');
|
|
118
117
|
});
|
|
119
118
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit-contract.test.js","sourceRoot":"","sources":["../../src/__tests__/audit-contract.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAG5D,MAAM,eAAgB,SAAQ,KAAK;IAC1B,MAAM,CAAU,IAAI,GAAc;QACvC,EAAE,EAAE,eAAe;QACnB,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"audit-contract.test.js","sourceRoot":"","sources":["../../src/__tests__/audit-contract.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@ import { JSONLDGatherer } from '../gather/gatherers/jsonld-gatherer.js';
|
|
|
5
5
|
import { HeadingsHierarchyGatherer } from '../gather/gatherers/headings-hierarchy-gatherer.js';
|
|
6
6
|
import { DirectAnswersGatherer } from '../gather/gatherers/direct-answers-gatherer.js';
|
|
7
7
|
describe('Gatherers Pipeline', () => {
|
|
8
|
-
it('RobotsTxtGatherer
|
|
8
|
+
it('RobotsTxtGatherer parses AI bot directives correctly', async () => {
|
|
9
9
|
const mockRobotsContent = `
|
|
10
10
|
User-agent: GPTBot
|
|
11
11
|
Disallow: /private/
|
|
@@ -23,7 +23,6 @@ Sitemap: https://example.com/sitemap.xml
|
|
|
23
23
|
url: 'https://example.com/test',
|
|
24
24
|
html: '<html><body>Hello</body></html>',
|
|
25
25
|
});
|
|
26
|
-
// Mock fetch for robots.txt
|
|
27
26
|
mockDriver.fetch = async () => new Response(mockRobotsContent, {
|
|
28
27
|
status: 200,
|
|
29
28
|
headers: { 'content-type': 'text/plain' },
|
|
@@ -38,7 +37,7 @@ Sitemap: https://example.com/sitemap.xml
|
|
|
38
37
|
expect(artifact.aiBotsStatus.gptBot).toBe('allowed');
|
|
39
38
|
expect(artifact.aiBotsStatus.perplexityBot).toBe('disallowed');
|
|
40
39
|
});
|
|
41
|
-
it('JSONLDGatherer
|
|
40
|
+
it('JSONLDGatherer extracts schema types and sameAs links', async () => {
|
|
42
41
|
const html = `
|
|
43
42
|
<!DOCTYPE html>
|
|
44
43
|
<html>
|
|
@@ -49,10 +48,10 @@ Sitemap: https://example.com/sitemap.xml
|
|
|
49
48
|
"@type": "FAQPage",
|
|
50
49
|
"mainEntity": [{
|
|
51
50
|
"@type": "Question",
|
|
52
|
-
"name": "
|
|
51
|
+
"name": "What is AEO?",
|
|
53
52
|
"acceptedAnswer": {
|
|
54
53
|
"@type": "Answer",
|
|
55
|
-
"text": "AEO
|
|
54
|
+
"text": "AEO is Answer Engine Optimization."
|
|
56
55
|
}
|
|
57
56
|
}]
|
|
58
57
|
}
|
|
@@ -87,13 +86,13 @@ Sitemap: https://example.com/sitemap.xml
|
|
|
87
86
|
expect(artifact.hasSameAs).toBe(true);
|
|
88
87
|
expect(artifact.sameAsUrls).toContain('https://www.wikidata.org/wiki/Q12345');
|
|
89
88
|
});
|
|
90
|
-
it('HeadingsHierarchyGatherer
|
|
89
|
+
it('HeadingsHierarchyGatherer detects hierarchies and skipped levels', async () => {
|
|
91
90
|
const html = `
|
|
92
91
|
<html>
|
|
93
92
|
<body>
|
|
94
|
-
<h1>
|
|
95
|
-
<h3>
|
|
96
|
-
<h2>
|
|
93
|
+
<h1>Main Heading</h1>
|
|
94
|
+
<h3>Abrupt H3 jump without H2</h3>
|
|
95
|
+
<h2>Now an H2</h2>
|
|
97
96
|
</body>
|
|
98
97
|
</html>
|
|
99
98
|
`;
|
|
@@ -113,12 +112,12 @@ Sitemap: https://example.com/sitemap.xml
|
|
|
113
112
|
expect(artifact.skippedLevels[0]?.from).toBe(1);
|
|
114
113
|
expect(artifact.skippedLevels[0]?.to).toBe(3);
|
|
115
114
|
});
|
|
116
|
-
it('DirectAnswersGatherer
|
|
115
|
+
it('DirectAnswersGatherer detects questions and concise direct answers', async () => {
|
|
117
116
|
const html = `
|
|
118
117
|
<html>
|
|
119
118
|
<body>
|
|
120
|
-
<h2
|
|
121
|
-
<p>Answer Engine Optimization
|
|
119
|
+
<h2>What is Answer Engine Optimization?</h2>
|
|
120
|
+
<p>Answer Engine Optimization is a framework of web architecture, semantic chunking, and structured data practices designed to maximize visibility in generative AI engines and RAG retrieval pipelines.</p>
|
|
122
121
|
</body>
|
|
123
122
|
</html>
|
|
124
123
|
`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gatherers.test.js","sourceRoot":"","sources":["../../src/__tests__/gatherers.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,4CAA4C,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAC;AACxE,OAAO,EAAE,yBAAyB,EAAE,MAAM,oDAAoD,CAAC;AAE/F,OAAO,EAAE,qBAAqB,EAAE,MAAM,gDAAgD,CAAC;AAEvF,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"gatherers.test.js","sourceRoot":"","sources":["../../src/__tests__/gatherers.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,23 +4,23 @@ import { CheerioDriver } from '../gather/driver/cheerio-driver.js';
|
|
|
4
4
|
import { HtmlReporter } from '../report/html-reporter.js';
|
|
5
5
|
import { TerminalReporter } from '../report/terminal-reporter.js';
|
|
6
6
|
describe('Runner and Aggregator Full Pipeline', () => {
|
|
7
|
-
it('
|
|
7
|
+
it('executes the full 3-phase lifecycle and generates reports', async () => {
|
|
8
8
|
const mockHtml = `
|
|
9
9
|
<!DOCTYPE html>
|
|
10
|
-
<html lang="
|
|
10
|
+
<html lang="en">
|
|
11
11
|
<head>
|
|
12
12
|
<title>AEO Testing Page</title>
|
|
13
|
-
<meta name="description" content="
|
|
13
|
+
<meta name="description" content="AEO test page for linter verification">
|
|
14
14
|
<script type="application/ld+json">
|
|
15
15
|
{
|
|
16
16
|
"@context": "https://schema.org",
|
|
17
17
|
"@type": "FAQPage",
|
|
18
18
|
"mainEntity": [{
|
|
19
19
|
"@type": "Question",
|
|
20
|
-
"name": "
|
|
20
|
+
"name": "What is GEO?",
|
|
21
21
|
"acceptedAnswer": {
|
|
22
22
|
"@type": "Answer",
|
|
23
|
-
"text": "GEO
|
|
23
|
+
"text": "GEO is Generative Engine Optimization."
|
|
24
24
|
}
|
|
25
25
|
}]
|
|
26
26
|
}
|
|
@@ -37,12 +37,12 @@ describe('Runner and Aggregator Full Pipeline', () => {
|
|
|
37
37
|
<body>
|
|
38
38
|
<main>
|
|
39
39
|
<article>
|
|
40
|
-
<h1>
|
|
41
|
-
<h2
|
|
42
|
-
<p>
|
|
40
|
+
<h1>Complete Guide to AEO</h1>
|
|
41
|
+
<h2>What is direct answer density?</h2>
|
|
42
|
+
<p>Direct answer density is the proportion of user queries that receive a clear, synthesized definition in fewer than 60 words at the beginning of the topic section.</p>
|
|
43
43
|
|
|
44
|
-
<h2>
|
|
45
|
-
<p>
|
|
44
|
+
<h2>Semantic Structuring for RAG</h2>
|
|
45
|
+
<p>Partitioning text into structured 200 to 400 token passages optimizes semantic vector search accuracy across models like OpenAI and Cohere.</p>
|
|
46
46
|
</article>
|
|
47
47
|
</main>
|
|
48
48
|
</body>
|
|
@@ -64,9 +64,9 @@ describe('Runner and Aggregator Full Pipeline', () => {
|
|
|
64
64
|
expect(report.categories['structured-data']?.score).toBeGreaterThanOrEqual(0.8);
|
|
65
65
|
expect(report.categories['content-chunking']?.score).toBeGreaterThanOrEqual(0.8);
|
|
66
66
|
expect(report.categories['direct-answer-density']?.score).toBe(1);
|
|
67
|
-
//
|
|
67
|
+
// Verify report generators
|
|
68
68
|
const terminalOutput = TerminalReporter.generate(report);
|
|
69
|
-
expect(terminalOutput).toContain('
|
|
69
|
+
expect(terminalOutput).toContain('Overall AEO Score');
|
|
70
70
|
expect(terminalOutput).toContain('AI Accessibility & Crawling');
|
|
71
71
|
const htmlOutput = HtmlReporter.generate(report);
|
|
72
72
|
expect(htmlOutput).toContain('<!DOCTYPE html>');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.test.js","sourceRoot":"","sources":["../../src/__tests__/runner.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAElE,QAAQ,CAAC,qCAAqC,EAAE,GAAG,EAAE;IACnD,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"runner.test.js","sourceRoot":"","sources":["../../src/__tests__/runner.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAElE,QAAQ,CAAC,qCAAqC,EAAE,GAAG,EAAE;IACnD,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;QACzE,MAAM,QAAQ,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA0ChB,CAAC;QAEF,MAAM,UAAU,GAAG,IAAI,aAAa,CAAC;YACnC,GAAG,EAAE,8BAA8B;YACnC,IAAI,EAAE,QAAQ;SACf,CAAC,CAAC;QAEH,UAAU,CAAC,KAAK,GAAG,KAAK,IAAI,EAAE,CAC5B,IAAI,QAAQ,CAAC,4EAA4E,EAAE;YACzF,MAAM,EAAE,GAAG;SACZ,CAAC,CAAC;QAEL,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,8BAA8B,EAAE;YAC9D,MAAM,EAAE,UAAU;SACnB,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;QACxD,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;QAChD,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,kBAAkB,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC7D,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,iBAAiB,CAAC,EAAE,KAAK,CAAC,CAAC,sBAAsB,CAAC,GAAG,CAAC,CAAC;QAChF,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,kBAAkB,CAAC,EAAE,KAAK,CAAC,CAAC,sBAAsB,CAAC,GAAG,CAAC,CAAC;QACjF,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,uBAAuB,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAElE,2BAA2B;QAC3B,MAAM,cAAc,GAAG,gBAAgB,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACzD,MAAM,CAAC,cAAc,CAAC,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;QACtD,MAAM,CAAC,cAAc,CAAC,CAAC,SAAS,CAAC,6BAA6B,CAAC,CAAC;QAEhE,MAAM,UAAU,GAAG,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACjD,MAAM,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;QAChD,MAAM,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,8BAA8B,CAAC,CAAC;QAC7D,MAAM,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @fileoverview
|
|
2
|
+
* @fileoverview Audit verifying the declaration of valid XML Sitemaps in robots.txt
|
|
3
3
|
*/
|
|
4
4
|
import { Audit } from '../audit.js';
|
|
5
5
|
import type { Artifacts, AuditMeta, AuditResult } from '../../types/index.js';
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @fileoverview
|
|
2
|
+
* @fileoverview Audit verifying the declaration of valid XML Sitemaps in robots.txt
|
|
3
3
|
*/
|
|
4
4
|
import { Audit } from '../audit.js';
|
|
5
5
|
export class AiBotSitemapAudit extends Audit {
|
|
6
6
|
static meta = {
|
|
7
7
|
id: 'ai-bot-sitemap',
|
|
8
|
-
title: '
|
|
9
|
-
failureTitle: 'No
|
|
10
|
-
description: '
|
|
8
|
+
title: 'robots.txt declares valid XML Sitemaps',
|
|
9
|
+
failureTitle: 'No XML Sitemap declaration found in robots.txt',
|
|
10
|
+
description: 'XML Sitemaps enable Answer Engine crawlers to discover deep, structured content efficiently.',
|
|
11
11
|
requiredArtifacts: ['RobotsTxt'],
|
|
12
12
|
};
|
|
13
13
|
static async audit(artifacts) {
|
|
@@ -16,8 +16,8 @@ export class AiBotSitemapAudit extends Audit {
|
|
|
16
16
|
return this.generateAuditResult({
|
|
17
17
|
score: hasSitemap ? 1 : 0.5,
|
|
18
18
|
displayValue: hasSitemap
|
|
19
|
-
? `${sitemaps.length} sitemap(s)
|
|
20
|
-
: '
|
|
19
|
+
? `${sitemaps.length} sitemap(s) declared`
|
|
20
|
+
: 'No sitemap declared in robots.txt',
|
|
21
21
|
details: hasSitemap
|
|
22
22
|
? this.makeListDetails(sitemaps)
|
|
23
23
|
: undefined,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-bot-sitemap.js","sourceRoot":"","sources":["../../../src/audits/ai-accessibility/ai-bot-sitemap.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAGpC,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IACnC,MAAM,CAAU,IAAI,GAAc;QACvC,EAAE,EAAE,gBAAgB;QACpB,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"ai-bot-sitemap.js","sourceRoot":"","sources":["../../../src/audits/ai-accessibility/ai-bot-sitemap.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAGpC,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IACnC,MAAM,CAAU,IAAI,GAAc;QACvC,EAAE,EAAE,gBAAgB;QACpB,KAAK,EAAE,wCAAwC;QAC/C,YAAY,EAAE,gDAAgD;QAC9D,WAAW,EACT,8FAA8F;QAChG,iBAAiB,EAAE,CAAC,WAAW,CAAC;KACjC,CAAC;IAEK,MAAM,CAAU,KAAK,CAAC,KAAK,CAAC,SAAoB;QACrD,MAAM,QAAQ,GAAG,SAAS,CAAC,SAAS,CAAC,QAAQ,CAAC;QAC9C,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;QAEvC,OAAO,IAAI,CAAC,mBAAmB,CAAC;YAC9B,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG;YAC3B,YAAY,EAAE,UAAU;gBACtB,CAAC,CAAC,GAAG,QAAQ,CAAC,MAAM,sBAAsB;gBAC1C,CAAC,CAAC,mCAAmC;YACvC,OAAO,EAAE,UAAU;gBACjB,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC;gBAChC,CAAC,CAAC,SAAS;SACd,CAAC,CAAC;IACL,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @fileoverview
|
|
2
|
+
* @fileoverview Audit verifying whether robots.txt grants access to major AI crawlers
|
|
3
3
|
*/
|
|
4
4
|
import { Audit } from '../audit.js';
|
|
5
5
|
import type { Artifacts, AuditMeta, AuditResult } from '../../types/index.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-robots-txt.d.ts","sourceRoot":"","sources":["../../../src/audits/ai-accessibility/ai-robots-txt.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAE9E,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,OAAuB,IAAI,EAAE,SAAS,CAOpC;WAE2B,KAAK,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"ai-robots-txt.d.ts","sourceRoot":"","sources":["../../../src/audits/ai-accessibility/ai-robots-txt.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAE9E,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,OAAuB,IAAI,EAAE,SAAS,CAOpC;WAE2B,KAAK,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;CA+C/E"}
|
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @fileoverview
|
|
2
|
+
* @fileoverview Audit verifying whether robots.txt grants access to major AI crawlers
|
|
3
3
|
*/
|
|
4
4
|
import { Audit } from '../audit.js';
|
|
5
5
|
export class AiRobotsTxtAudit extends Audit {
|
|
6
6
|
static meta = {
|
|
7
7
|
id: 'ai-robots-txt',
|
|
8
|
-
title: '
|
|
9
|
-
failureTitle: '
|
|
10
|
-
description: '
|
|
8
|
+
title: 'robots.txt allows crawling by major AI search bots',
|
|
9
|
+
failureTitle: 'robots.txt blocks or restricts major AI search crawlers',
|
|
10
|
+
description: 'Answer Engines and RAG systems (SearchGPT/ChatGPT, Perplexity, Claude, Gemini) use dedicated crawlers like GPTBot, PerplexityBot, and ClaudeBot to index and cite up-to-date sources.',
|
|
11
11
|
requiredArtifacts: ['RobotsTxt'],
|
|
12
12
|
};
|
|
13
13
|
static async audit(artifacts) {
|
|
14
14
|
const robots = artifacts.RobotsTxt;
|
|
15
15
|
if (!robots.exists || !robots.rawContent) {
|
|
16
|
-
// Si no existe robots.txt, por estándar todos los bots tienen permitido el acceso total
|
|
17
16
|
return this.generateAuditResult({
|
|
18
17
|
score: 1,
|
|
19
|
-
displayValue: '
|
|
20
|
-
explanation: 'No
|
|
18
|
+
displayValue: 'robots.txt does not restrict access (unrestricted)',
|
|
19
|
+
explanation: 'No restrictive robots.txt file was found, allowing AI bots to access the content.',
|
|
21
20
|
});
|
|
22
21
|
}
|
|
23
22
|
const aiBots = [
|
|
@@ -25,7 +24,7 @@ export class AiRobotsTxtAudit extends Audit {
|
|
|
25
24
|
{ id: 'PerplexityBot', name: 'Perplexity AI', status: robots.aiBotsStatus.perplexityBot || 'not_specified' },
|
|
26
25
|
{ id: 'ClaudeBot', name: 'Anthropic Claude', status: robots.aiBotsStatus.claudeBot || 'not_specified' },
|
|
27
26
|
{ id: 'Google-Extended', name: 'Google Gemini / Vertex', status: robots.aiBotsStatus.googleExtended || 'not_specified' },
|
|
28
|
-
{ id: 'CCBot', name: 'Common Crawl (
|
|
27
|
+
{ id: 'CCBot', name: 'Common Crawl (Open Datasets)', status: robots.aiBotsStatus.ccBot || 'not_specified' },
|
|
29
28
|
{ id: 'Bytespider', name: 'ByteDance / Doubao', status: robots.aiBotsStatus.bytespider || 'not_specified' },
|
|
30
29
|
];
|
|
31
30
|
let allowedCount = 0;
|
|
@@ -36,17 +35,17 @@ export class AiRobotsTxtAudit extends Audit {
|
|
|
36
35
|
return {
|
|
37
36
|
bot: bot.id,
|
|
38
37
|
purpose: bot.name,
|
|
39
|
-
status: bot.status === 'disallowed' ? '
|
|
38
|
+
status: bot.status === 'disallowed' ? 'Blocked (Disallow)' : bot.status === 'partially_disallowed' ? 'Partially restricted' : 'Allowed',
|
|
40
39
|
};
|
|
41
40
|
});
|
|
42
41
|
const score = allowedCount / aiBots.length;
|
|
43
42
|
return this.generateAuditResult({
|
|
44
43
|
score: score >= 0.8 ? 1 : score,
|
|
45
|
-
displayValue: `${allowedCount}
|
|
44
|
+
displayValue: `${allowedCount} of ${aiBots.length} AI bots have crawling access allowed`,
|
|
46
45
|
details: this.makeTableDetails([
|
|
47
46
|
{ key: 'bot', label: 'User-Agent', valueType: 'code' },
|
|
48
|
-
{ key: 'purpose', label: '
|
|
49
|
-
{ key: 'status', label: '
|
|
47
|
+
{ key: 'purpose', label: 'Platform / Engine', valueType: 'text' },
|
|
48
|
+
{ key: 'status', label: 'Directive', valueType: 'status' },
|
|
50
49
|
], tableItems),
|
|
51
50
|
});
|
|
52
51
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-robots-txt.js","sourceRoot":"","sources":["../../../src/audits/ai-accessibility/ai-robots-txt.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAGpC,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAClC,MAAM,CAAU,IAAI,GAAc;QACvC,EAAE,EAAE,eAAe;QACnB,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"ai-robots-txt.js","sourceRoot":"","sources":["../../../src/audits/ai-accessibility/ai-robots-txt.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @fileoverview
|
|
2
|
+
* @fileoverview Audit verifying HTTP X-Robots-Tag headers for AI indexing permissions
|
|
3
3
|
*/
|
|
4
4
|
import { Audit } from '../audit.js';
|
|
5
5
|
import type { Artifacts, AuditMeta, AuditResult } from '../../types/index.js';
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @fileoverview
|
|
2
|
+
* @fileoverview Audit verifying HTTP X-Robots-Tag headers for AI indexing permissions
|
|
3
3
|
*/
|
|
4
4
|
import { Audit } from '../audit.js';
|
|
5
5
|
export class AiXRobotsTagAudit extends Audit {
|
|
6
6
|
static meta = {
|
|
7
7
|
id: 'ai-x-robots-tag',
|
|
8
|
-
title: '
|
|
9
|
-
failureTitle: '
|
|
10
|
-
description: '
|
|
8
|
+
title: 'HTTP headers do not block AI indexing or archiving',
|
|
9
|
+
failureTitle: 'HTTP X-Robots-Tag headers restrict AI indexing or archiving',
|
|
10
|
+
description: 'Directives like `noindex`, `noarchive`, or `noai` in the `X-Robots-Tag` HTTP header prevent AI search models from caching and retrieving the page in RAG pipelines.',
|
|
11
11
|
requiredArtifacts: ['HttpHeaders'],
|
|
12
12
|
};
|
|
13
13
|
static async audit(artifacts) {
|
|
@@ -15,7 +15,7 @@ export class AiXRobotsTagAudit extends Audit {
|
|
|
15
15
|
if (!xRobots) {
|
|
16
16
|
return this.generateAuditResult({
|
|
17
17
|
score: 1,
|
|
18
|
-
displayValue: '
|
|
18
|
+
displayValue: 'Clean X-Robots-Tag header (no restrictions)',
|
|
19
19
|
});
|
|
20
20
|
}
|
|
21
21
|
const lower = xRobots.toLowerCase();
|
|
@@ -25,10 +25,10 @@ export class AiXRobotsTagAudit extends Audit {
|
|
|
25
25
|
return this.generateAuditResult({
|
|
26
26
|
score: isBlocked ? 0 : 1,
|
|
27
27
|
displayValue: isBlocked
|
|
28
|
-
? `
|
|
29
|
-
: `
|
|
28
|
+
? `Blocking directives detected: ${foundBlocking.join(', ')}`
|
|
29
|
+
: `Permissive directives: ${xRobots}`,
|
|
30
30
|
explanation: isBlocked
|
|
31
|
-
? `
|
|
31
|
+
? `Detected '${xRobots}' in X-Robots-Tag header, preventing analysis by language models.`
|
|
32
32
|
: undefined,
|
|
33
33
|
});
|
|
34
34
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-x-robots-tag.js","sourceRoot":"","sources":["../../../src/audits/ai-accessibility/ai-x-robots-tag.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAGpC,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IACnC,MAAM,CAAU,IAAI,GAAc;QACvC,EAAE,EAAE,iBAAiB;QACrB,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"ai-x-robots-tag.js","sourceRoot":"","sources":["../../../src/audits/ai-accessibility/ai-x-robots-tag.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAGpC,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IACnC,MAAM,CAAU,IAAI,GAAc;QACvC,EAAE,EAAE,iBAAiB;QACrB,KAAK,EAAE,oDAAoD;QAC3D,YAAY,EAAE,6DAA6D;QAC3E,WAAW,EACT,qKAAqK;QACvK,iBAAiB,EAAE,CAAC,aAAa,CAAC;KACnC,CAAC;IAEK,MAAM,CAAU,KAAK,CAAC,KAAK,CAAC,SAAoB;QACrD,MAAM,OAAO,GAAG,SAAS,CAAC,WAAW,CAAC,UAAU,CAAC;QAEjD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,IAAI,CAAC,mBAAmB,CAAC;gBAC9B,KAAK,EAAE,CAAC;gBACR,YAAY,EAAE,6CAA6C;aAC5D,CAAC,CAAC;QACL,CAAC;QAED,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;QACpC,MAAM,kBAAkB,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;QACpE,MAAM,aAAa,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QAE1E,MAAM,SAAS,GAAG,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC;QAE3C,OAAO,IAAI,CAAC,mBAAmB,CAAC;YAC9B,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACxB,YAAY,EAAE,SAAS;gBACrB,CAAC,CAAC,iCAAiC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gBAC7D,CAAC,CAAC,0BAA0B,OAAO,EAAE;YACvC,WAAW,EAAE,SAAS;gBACpB,CAAC,CAAC,aAAa,OAAO,mEAAmE;gBACzF,CAAC,CAAC,SAAS;SACd,CAAC,CAAC;IACL,CAAC"}
|
package/dist/audits/audit.d.ts
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @fileoverview
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* @fileoverview Abstract base class Audit and result utilities following the Google Lighthouse pattern.
|
|
3
|
+
* Concrete audits inherit from Audit and implement their static `audit()` method as a pure function
|
|
4
|
+
* that evaluates required artifacts and returns an `AuditResult`.
|
|
5
5
|
*/
|
|
6
6
|
import type { Artifacts, AuditResult, AuditMeta, AuditContext, AuditDetails, TableHeading, TableDetails, ListDetails, ScoreDisplayMode } from '../types/index.js';
|
|
7
7
|
export declare abstract class Audit {
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
9
|
+
* Static metadata for the audit.
|
|
10
|
+
* Must be overridden by each concrete audit class.
|
|
11
11
|
*/
|
|
12
12
|
static meta: AuditMeta;
|
|
13
13
|
/**
|
|
14
|
-
*
|
|
15
|
-
* @param artifacts
|
|
16
|
-
* @param context
|
|
14
|
+
* Pure audit evaluation method.
|
|
15
|
+
* @param artifacts Immutable artifacts collected by Gatherers
|
|
16
|
+
* @param context Execution context
|
|
17
17
|
*/
|
|
18
18
|
static audit(artifacts: Artifacts, context?: AuditContext): Promise<AuditResult>;
|
|
19
19
|
/**
|
|
20
|
-
* Helper
|
|
20
|
+
* Helper to generate a standardized audit result
|
|
21
21
|
*/
|
|
22
22
|
static generateAuditResult(options: {
|
|
23
23
|
id?: string;
|
|
@@ -34,22 +34,22 @@ export declare abstract class Audit {
|
|
|
34
34
|
warnings?: string[];
|
|
35
35
|
}): AuditResult;
|
|
36
36
|
/**
|
|
37
|
-
* Helper
|
|
37
|
+
* Helper to construct table details (Lighthouse TableDetails)
|
|
38
38
|
*/
|
|
39
39
|
static makeTableDetails(headings: TableHeading[], items: Array<Record<string, unknown>>, summary?: TableDetails['summary']): TableDetails;
|
|
40
40
|
/**
|
|
41
|
-
* Helper
|
|
41
|
+
* Helper to construct list details
|
|
42
42
|
*/
|
|
43
43
|
static makeListDetails(items: Array<string | {
|
|
44
44
|
text: string;
|
|
45
45
|
subItems?: string[];
|
|
46
46
|
}>): ListDetails;
|
|
47
47
|
/**
|
|
48
|
-
* Helper
|
|
48
|
+
* Helper to compute binary score
|
|
49
49
|
*/
|
|
50
50
|
static binaryScore(condition: boolean): number;
|
|
51
51
|
/**
|
|
52
|
-
* Helper
|
|
52
|
+
* Helper to clamp score between min and max
|
|
53
53
|
*/
|
|
54
54
|
static clampScore(value: number, min?: number, max?: number): number;
|
|
55
55
|
}
|
package/dist/audits/audit.js
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @fileoverview
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* @fileoverview Abstract base class Audit and result utilities following the Google Lighthouse pattern.
|
|
3
|
+
* Concrete audits inherit from Audit and implement their static `audit()` method as a pure function
|
|
4
|
+
* that evaluates required artifacts and returns an `AuditResult`.
|
|
5
5
|
*/
|
|
6
6
|
export class Audit {
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
8
|
+
* Static metadata for the audit.
|
|
9
|
+
* Must be overridden by each concrete audit class.
|
|
10
10
|
*/
|
|
11
11
|
static meta;
|
|
12
12
|
/**
|
|
13
|
-
*
|
|
14
|
-
* @param artifacts
|
|
15
|
-
* @param context
|
|
13
|
+
* Pure audit evaluation method.
|
|
14
|
+
* @param artifacts Immutable artifacts collected by Gatherers
|
|
15
|
+
* @param context Execution context
|
|
16
16
|
*/
|
|
17
17
|
static async audit(artifacts, context) {
|
|
18
|
-
throw new Error(`
|
|
18
|
+
throw new Error(`The audit() method is not implemented in ${this.name}`);
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
|
-
* Helper
|
|
21
|
+
* Helper to generate a standardized audit result
|
|
22
22
|
*/
|
|
23
23
|
static generateAuditResult(options) {
|
|
24
24
|
const meta = this.meta || {
|
|
@@ -51,7 +51,7 @@ export class Audit {
|
|
|
51
51
|
};
|
|
52
52
|
}
|
|
53
53
|
/**
|
|
54
|
-
* Helper
|
|
54
|
+
* Helper to construct table details (Lighthouse TableDetails)
|
|
55
55
|
*/
|
|
56
56
|
static makeTableDetails(headings, items, summary) {
|
|
57
57
|
return {
|
|
@@ -62,7 +62,7 @@ export class Audit {
|
|
|
62
62
|
};
|
|
63
63
|
}
|
|
64
64
|
/**
|
|
65
|
-
* Helper
|
|
65
|
+
* Helper to construct list details
|
|
66
66
|
*/
|
|
67
67
|
static makeListDetails(items) {
|
|
68
68
|
return {
|
|
@@ -71,13 +71,13 @@ export class Audit {
|
|
|
71
71
|
};
|
|
72
72
|
}
|
|
73
73
|
/**
|
|
74
|
-
* Helper
|
|
74
|
+
* Helper to compute binary score
|
|
75
75
|
*/
|
|
76
76
|
static binaryScore(condition) {
|
|
77
77
|
return condition ? 1 : 0;
|
|
78
78
|
}
|
|
79
79
|
/**
|
|
80
|
-
* Helper
|
|
80
|
+
* Helper to clamp score between min and max
|
|
81
81
|
*/
|
|
82
82
|
static clampScore(value, min = 0, max = 1) {
|
|
83
83
|
return Math.min(Math.max(value, min), max);
|
package/dist/audits/audit.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/audits/audit.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAcH,MAAM,OAAgB,KAAK;IACzB;;;OAGG;IACI,MAAM,CAAC,IAAI,CAAY;IAE9B;;;;OAIG;IACI,MAAM,CAAC,KAAK,CAAC,KAAK,CACvB,SAAoB,EACpB,OAAsB;QAEtB,MAAM,IAAI,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/audits/audit.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAcH,MAAM,OAAgB,KAAK;IACzB;;;OAGG;IACI,MAAM,CAAC,IAAI,CAAY;IAE9B;;;;OAIG;IACI,MAAM,CAAC,KAAK,CAAC,KAAK,CACvB,SAAoB,EACpB,OAAsB;QAEtB,MAAM,IAAI,KAAK,CAAC,4CAA4C,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAC3E,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,mBAAmB,CAAC,OAajC;QACC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI;YACxB,EAAE,EAAE,OAAO,CAAC,EAAE,IAAI,eAAe;YACjC,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,eAAe;YACvC,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,EAAE;SACvC,CAAC;QAEF,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,KAAK,IAAI,IAAI,OAAO,CAAC,KAAK,IAAI,GAAG,CAAC;QACjE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QAE5F,IAAI,gBAAgB,GAAqB,OAAO,CAAC,gBAAgB,IAAI,SAAS,CAAC;QAC/E,IAAI,OAAO,CAAC,KAAK,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC;YACxD,gBAAgB,GAAG,eAAe,CAAC;QACrC,CAAC;aAAM,IAAI,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,KAAK,KAAK,CAAC,IAAI,OAAO,CAAC,KAAK,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC;YAC1H,gBAAgB,GAAG,QAAQ,CAAC;QAC9B,CAAC;QAED,OAAO;YACL,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,gBAAgB;YAChB,KAAK;YACL,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,IAAI,CAAC,WAAW;YACpD,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,QAAQ,EAAE,OAAO,CAAC,QAAQ;SAC3B,CAAC;IACJ,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,gBAAgB,CAC5B,QAAwB,EACxB,KAAqC,EACrC,OAAiC;QAEjC,OAAO;YACL,IAAI,EAAE,OAAO;YACb,QAAQ;YACR,KAAK;YACL,OAAO;SACR,CAAC;IACJ,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,eAAe,CAC3B,KAA4D;QAE5D,OAAO;YACL,IAAI,EAAE,MAAM;YACZ,KAAK;SACN,CAAC;IACJ,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,WAAW,CAAC,SAAkB;QAC1C,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3B,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,UAAU,CAAC,KAAa,EAAE,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC;QACtD,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;IAC7C,CAAC;CACF"}
|