@drowlink/aeo-linter-core 0.1.3 → 0.1.5
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 +8 -7
- package/dist/__tests__/assertions.test.d.ts +2 -0
- package/dist/__tests__/assertions.test.d.ts.map +1 -0
- package/dist/__tests__/assertions.test.js +89 -0
- package/dist/__tests__/assertions.test.js.map +1 -0
- package/dist/__tests__/audit-contract.test.js +32 -0
- package/dist/__tests__/audit-contract.test.js.map +1 -1
- package/dist/__tests__/author-eeat-presence.test.d.ts +2 -0
- package/dist/__tests__/author-eeat-presence.test.d.ts.map +1 -0
- package/dist/__tests__/author-eeat-presence.test.js +137 -0
- package/dist/__tests__/author-eeat-presence.test.js.map +1 -0
- package/dist/__tests__/fact-citation-density.test.d.ts +2 -0
- package/dist/__tests__/fact-citation-density.test.d.ts.map +1 -0
- package/dist/__tests__/fact-citation-density.test.js +100 -0
- package/dist/__tests__/fact-citation-density.test.js.map +1 -0
- package/dist/__tests__/llms-txt.test.d.ts +2 -0
- package/dist/__tests__/llms-txt.test.d.ts.map +1 -0
- package/dist/__tests__/llms-txt.test.js +108 -0
- package/dist/__tests__/llms-txt.test.js.map +1 -0
- package/dist/__tests__/runner.test.js +16 -3
- package/dist/__tests__/runner.test.js.map +1 -1
- package/dist/__tests__/table-list-scannability.test.d.ts +2 -0
- package/dist/__tests__/table-list-scannability.test.d.ts.map +1 -0
- package/dist/__tests__/table-list-scannability.test.js +97 -0
- package/dist/__tests__/table-list-scannability.test.js.map +1 -0
- package/dist/audits/ai-accessibility/ai-llms-txt.d.ts +10 -0
- package/dist/audits/ai-accessibility/ai-llms-txt.d.ts.map +1 -0
- package/dist/audits/ai-accessibility/ai-llms-txt.js +52 -0
- package/dist/audits/ai-accessibility/ai-llms-txt.js.map +1 -0
- package/dist/audits/content-chunking/table-list-scannability.d.ts +10 -0
- package/dist/audits/content-chunking/table-list-scannability.d.ts.map +1 -0
- package/dist/audits/content-chunking/table-list-scannability.js +79 -0
- package/dist/audits/content-chunking/table-list-scannability.js.map +1 -0
- package/dist/audits/direct-answer-density/fact-citation-density.d.ts +10 -0
- package/dist/audits/direct-answer-density/fact-citation-density.d.ts.map +1 -0
- package/dist/audits/direct-answer-density/fact-citation-density.js +73 -0
- package/dist/audits/direct-answer-density/fact-citation-density.js.map +1 -0
- package/dist/audits/index.d.ts +5 -1
- package/dist/audits/index.d.ts.map +1 -1
- package/dist/audits/index.js +9 -1
- package/dist/audits/index.js.map +1 -1
- package/dist/audits/structured-data/author-eeat-presence.d.ts +10 -0
- package/dist/audits/structured-data/author-eeat-presence.d.ts.map +1 -0
- package/dist/audits/structured-data/author-eeat-presence.js +87 -0
- package/dist/audits/structured-data/author-eeat-presence.js.map +1 -0
- package/dist/config/default-config.d.ts.map +1 -1
- package/dist/config/default-config.js +19 -11
- package/dist/config/default-config.js.map +1 -1
- package/dist/gather/gatherers/content-chunks-gatherer.d.ts.map +1 -1
- package/dist/gather/gatherers/content-chunks-gatherer.js +8 -0
- package/dist/gather/gatherers/content-chunks-gatherer.js.map +1 -1
- package/dist/gather/gatherers/direct-answers-gatherer.d.ts.map +1 -1
- package/dist/gather/gatherers/direct-answers-gatherer.js +31 -0
- package/dist/gather/gatherers/direct-answers-gatherer.js.map +1 -1
- package/dist/gather/gatherers/jsonld-gatherer.d.ts +1 -1
- package/dist/gather/gatherers/jsonld-gatherer.d.ts.map +1 -1
- package/dist/gather/gatherers/jsonld-gatherer.js +89 -6
- package/dist/gather/gatherers/jsonld-gatherer.js.map +1 -1
- package/dist/gather/gatherers/llms-txt-gatherer.d.ts +11 -0
- package/dist/gather/gatherers/llms-txt-gatherer.d.ts.map +1 -0
- package/dist/gather/gatherers/llms-txt-gatherer.js +123 -0
- package/dist/gather/gatherers/llms-txt-gatherer.js.map +1 -0
- package/dist/gather/index.d.ts +1 -0
- package/dist/gather/index.d.ts.map +1 -1
- package/dist/gather/index.js +1 -0
- package/dist/gather/index.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/runner/assertions.d.ts +25 -0
- package/dist/runner/assertions.d.ts.map +1 -0
- package/dist/runner/assertions.js +53 -0
- package/dist/runner/assertions.js.map +1 -0
- package/dist/runner/runner.d.ts.map +1 -1
- package/dist/runner/runner.js +5 -1
- package/dist/runner/runner.js.map +1 -1
- package/dist/types/artifacts.d.ts +64 -0
- package/dist/types/artifacts.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -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,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,
|
|
1
|
+
{"version":3,"file":"runner.test.js","sourceRoot":"","sources":["../../src/__tests__/runner.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table-list-scannability.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/table-list-scannability.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { CheerioDriver } from '../gather/driver/cheerio-driver.js';
|
|
3
|
+
import { ContentChunksGatherer } from '../gather/gatherers/content-chunks-gatherer.js';
|
|
4
|
+
import { TableListScannabilityAudit } from '../audits/content-chunking/table-list-scannability.js';
|
|
5
|
+
describe('Table and List Scannability Audit', () => {
|
|
6
|
+
it('ContentChunksGatherer extracts table and list counts accurately', async () => {
|
|
7
|
+
const html = `
|
|
8
|
+
<!DOCTYPE html>
|
|
9
|
+
<html>
|
|
10
|
+
<body>
|
|
11
|
+
<main>
|
|
12
|
+
<h1>Comparison Matrix</h1>
|
|
13
|
+
<p>Here is an in-depth comparison of feature sets across modern AEO architectures.</p>
|
|
14
|
+
<table>
|
|
15
|
+
<thead>
|
|
16
|
+
<tr><th>Feature</th><th>Traditional SEO</th><th>AEO</th></tr>
|
|
17
|
+
</thead>
|
|
18
|
+
<tbody>
|
|
19
|
+
<tr><td>Target Engine</td><td>Google Search</td><td>SearchGPT / Perplexity</td></tr>
|
|
20
|
+
</tbody>
|
|
21
|
+
</table>
|
|
22
|
+
<h2>Implementation Steps</h2>
|
|
23
|
+
<ol>
|
|
24
|
+
<li>Enable LLM crawling via robots.txt</li>
|
|
25
|
+
<li>Structure JSON-LD schemas</li>
|
|
26
|
+
<li>Optimize direct answers</li>
|
|
27
|
+
</ol>
|
|
28
|
+
<ul>
|
|
29
|
+
<li>Item A</li>
|
|
30
|
+
<li>Item B</li>
|
|
31
|
+
</ul>
|
|
32
|
+
</main>
|
|
33
|
+
</body>
|
|
34
|
+
</html>
|
|
35
|
+
`;
|
|
36
|
+
const mockDriver = new CheerioDriver({
|
|
37
|
+
url: 'https://example.com/matrix',
|
|
38
|
+
html,
|
|
39
|
+
});
|
|
40
|
+
const gatherer = new ContentChunksGatherer();
|
|
41
|
+
const artifact = await gatherer.getArtifact({
|
|
42
|
+
url: 'https://example.com/matrix',
|
|
43
|
+
driver: mockDriver,
|
|
44
|
+
});
|
|
45
|
+
expect(artifact.totalTablesCount).toBe(1);
|
|
46
|
+
expect(artifact.structuredTablesCount).toBe(1);
|
|
47
|
+
expect(artifact.totalListsCount).toBe(2);
|
|
48
|
+
expect(artifact.totalListItemsCount).toBe(5);
|
|
49
|
+
});
|
|
50
|
+
it('TableListScannabilityAudit scores 1.0 when both tables and lists are present', async () => {
|
|
51
|
+
const mockArtifacts = {
|
|
52
|
+
ContentChunks: {
|
|
53
|
+
chunks: [{ id: 'c-1', text: 'Some text', wordCount: 200, estimatedTokens: 260, hasList: true, hasTable: true }],
|
|
54
|
+
totalWordCount: 200,
|
|
55
|
+
totalTablesCount: 1,
|
|
56
|
+
structuredTablesCount: 1,
|
|
57
|
+
totalListsCount: 1,
|
|
58
|
+
totalListItemsCount: 4,
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
const result = await TableListScannabilityAudit.audit(mockArtifacts);
|
|
62
|
+
expect(result.score).toBe(1);
|
|
63
|
+
expect(result.displayValue).toContain('1 table(s), 1 list(s)');
|
|
64
|
+
expect(result.details?.type).toBe('table');
|
|
65
|
+
});
|
|
66
|
+
it('TableListScannabilityAudit scores 0.3 on dense long articles with 0 tables and 0 lists', async () => {
|
|
67
|
+
const mockArtifacts = {
|
|
68
|
+
ContentChunks: {
|
|
69
|
+
chunks: [{ id: 'c-1', text: 'Long narrative', wordCount: 800, estimatedTokens: 1040, hasList: false, hasTable: false }],
|
|
70
|
+
totalWordCount: 800,
|
|
71
|
+
totalTablesCount: 0,
|
|
72
|
+
structuredTablesCount: 0,
|
|
73
|
+
totalListsCount: 0,
|
|
74
|
+
totalListItemsCount: 0,
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
const result = await TableListScannabilityAudit.audit(mockArtifacts);
|
|
78
|
+
expect(result.score).toBe(0.3);
|
|
79
|
+
expect(result.explanation).toContain('Breaking continuous paragraphs into bulleted lists');
|
|
80
|
+
});
|
|
81
|
+
it('TableListScannabilityAudit is lenient on short pages (<150 words)', async () => {
|
|
82
|
+
const mockArtifacts = {
|
|
83
|
+
ContentChunks: {
|
|
84
|
+
chunks: [{ id: 'c-1', text: 'Short blurb', wordCount: 80, estimatedTokens: 100, hasList: false, hasTable: false }],
|
|
85
|
+
totalWordCount: 80,
|
|
86
|
+
totalTablesCount: 0,
|
|
87
|
+
structuredTablesCount: 0,
|
|
88
|
+
totalListsCount: 0,
|
|
89
|
+
totalListItemsCount: 0,
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
const result = await TableListScannabilityAudit.audit(mockArtifacts);
|
|
93
|
+
expect(result.score).toBe(1);
|
|
94
|
+
expect(result.displayValue).toContain('Brief page');
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
//# sourceMappingURL=table-list-scannability.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table-list-scannability.test.js","sourceRoot":"","sources":["../../src/__tests__/table-list-scannability.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Audit verifying the presence and quality of /llms.txt and /llms-full.txt files
|
|
3
|
+
*/
|
|
4
|
+
import { Audit } from '../audit.js';
|
|
5
|
+
import type { Artifacts, AuditMeta, AuditResult } from '../../types/index.js';
|
|
6
|
+
export declare class AiLlmsTxtAudit extends Audit {
|
|
7
|
+
static meta: AuditMeta;
|
|
8
|
+
static audit(artifacts: Artifacts): Promise<AuditResult>;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=ai-llms-txt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-llms-txt.d.ts","sourceRoot":"","sources":["../../../src/audits/ai-accessibility/ai-llms-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,cAAe,SAAQ,KAAK;IACvC,OAAuB,IAAI,EAAE,SAAS,CAOpC;WAE2B,KAAK,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;CA+C/E"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Audit verifying the presence and quality of /llms.txt and /llms-full.txt files
|
|
3
|
+
*/
|
|
4
|
+
import { Audit } from '../audit.js';
|
|
5
|
+
export class AiLlmsTxtAudit extends Audit {
|
|
6
|
+
static meta = {
|
|
7
|
+
id: 'ai-llms-txt',
|
|
8
|
+
title: 'Website provides a standard /llms.txt file for LLM knowledge consumption',
|
|
9
|
+
failureTitle: 'Missing /llms.txt file for direct LLM and AI agent ingestion',
|
|
10
|
+
description: 'The /llms.txt standard (proposed by Answer.ai) provides clean, curated Markdown summaries and documentation links specifically formatted for LLM context windows and Answer Engines.',
|
|
11
|
+
requiredArtifacts: ['LlmsTxt'],
|
|
12
|
+
};
|
|
13
|
+
static async audit(artifacts) {
|
|
14
|
+
const llms = artifacts.LlmsTxt;
|
|
15
|
+
if (!llms.exists || !llms.rawContent) {
|
|
16
|
+
return this.generateAuditResult({
|
|
17
|
+
score: 0,
|
|
18
|
+
displayValue: 'No /llms.txt file found',
|
|
19
|
+
explanation: 'Create an /llms.txt file at your site root with an H1 title, summary blockquote, and markdown links to help AI systems read and cite your content efficiently.',
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
// Evaluate quality of the llms.txt file
|
|
23
|
+
let score = 0.8;
|
|
24
|
+
if (llms.totalDeclaredLinks > 0) {
|
|
25
|
+
score += 0.1;
|
|
26
|
+
}
|
|
27
|
+
if (llms.hasFullVersion) {
|
|
28
|
+
score += 0.1;
|
|
29
|
+
}
|
|
30
|
+
score = Math.min(1, score);
|
|
31
|
+
const summaryItems = [
|
|
32
|
+
{ property: 'File Status', value: llms.exists ? 'Found (/llms.txt)' : 'Missing' },
|
|
33
|
+
{ property: 'Title', value: llms.title || 'Not specified' },
|
|
34
|
+
{ property: 'Summary', value: llms.summary || 'Not specified' },
|
|
35
|
+
{ property: 'Declared Links', value: `${llms.totalDeclaredLinks} links across ${llms.sections.length} section(s)` },
|
|
36
|
+
{ property: 'Full Version (/llms-full.txt)', value: llms.hasFullVersion ? 'Available' : 'Not detected' },
|
|
37
|
+
{ property: 'File Size', value: `${llms.charCount} characters` },
|
|
38
|
+
];
|
|
39
|
+
const display = llms.hasFullVersion
|
|
40
|
+
? `/llms.txt & /llms-full.txt active (${llms.totalDeclaredLinks} links)`
|
|
41
|
+
: `/llms.txt active (${llms.totalDeclaredLinks} links declared)`;
|
|
42
|
+
return this.generateAuditResult({
|
|
43
|
+
score,
|
|
44
|
+
displayValue: display,
|
|
45
|
+
details: this.makeTableDetails([
|
|
46
|
+
{ key: 'property', label: 'Attribute', valueType: 'text' },
|
|
47
|
+
{ key: 'value', label: 'Detail', valueType: 'text' },
|
|
48
|
+
], summaryItems),
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=ai-llms-txt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-llms-txt.js","sourceRoot":"","sources":["../../../src/audits/ai-accessibility/ai-llms-txt.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAGpC,MAAM,OAAO,cAAe,SAAQ,KAAK;IAChC,MAAM,CAAU,IAAI,GAAc;QACvC,EAAE,EAAE,aAAa;QACjB,KAAK,EAAE,0EAA0E;QACjF,YAAY,EAAE,8DAA8D;QAC5E,WAAW,EACT,sLAAsL;QACxL,iBAAiB,EAAE,CAAC,SAAS,CAAC;KAC/B,CAAC;IAEK,MAAM,CAAU,KAAK,CAAC,KAAK,CAAC,SAAoB;QACrD,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC;QAE/B,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACrC,OAAO,IAAI,CAAC,mBAAmB,CAAC;gBAC9B,KAAK,EAAE,CAAC;gBACR,YAAY,EAAE,yBAAyB;gBACvC,WAAW,EACT,gKAAgK;aACnK,CAAC,CAAC;QACL,CAAC;QAED,wCAAwC;QACxC,IAAI,KAAK,GAAG,GAAG,CAAC;QAChB,IAAI,IAAI,CAAC,kBAAkB,GAAG,CAAC,EAAE,CAAC;YAChC,KAAK,IAAI,GAAG,CAAC;QACf,CAAC;QACD,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,KAAK,IAAI,GAAG,CAAC;QACf,CAAC;QACD,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QAE3B,MAAM,YAAY,GAAG;YACnB,EAAE,QAAQ,EAAE,aAAa,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,SAAS,EAAE;YACjF,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,eAAe,EAAE;YAC3D,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,IAAI,eAAe,EAAE;YAC/D,EAAE,QAAQ,EAAE,gBAAgB,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,kBAAkB,iBAAiB,IAAI,CAAC,QAAQ,CAAC,MAAM,aAAa,EAAE;YACnH,EAAE,QAAQ,EAAE,+BAA+B,EAAE,KAAK,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,cAAc,EAAE;YACxG,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,SAAS,aAAa,EAAE;SACjE,CAAC;QAEF,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc;YACjC,CAAC,CAAC,sCAAsC,IAAI,CAAC,kBAAkB,SAAS;YACxE,CAAC,CAAC,qBAAqB,IAAI,CAAC,kBAAkB,kBAAkB,CAAC;QAEnE,OAAO,IAAI,CAAC,mBAAmB,CAAC;YAC9B,KAAK;YACL,YAAY,EAAE,OAAO;YACrB,OAAO,EAAE,IAAI,CAAC,gBAAgB,CAC5B;gBACE,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE;gBAC1D,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE;aACrD,EACD,YAAY,CACb;SACF,CAAC,CAAC;IACL,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Audit verifying the presence and quality of structured tables and lists for fast LLM extraction.
|
|
3
|
+
*/
|
|
4
|
+
import { Audit } from '../audit.js';
|
|
5
|
+
import type { Artifacts, AuditMeta, AuditResult } from '../../types/index.js';
|
|
6
|
+
export declare class TableListScannabilityAudit extends Audit {
|
|
7
|
+
static meta: AuditMeta;
|
|
8
|
+
static audit(artifacts: Artifacts): Promise<AuditResult>;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=table-list-scannability.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table-list-scannability.d.ts","sourceRoot":"","sources":["../../../src/audits/content-chunking/table-list-scannability.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,0BAA2B,SAAQ,KAAK;IACnD,OAAuB,IAAI,EAAE,SAAS,CAOpC;WAE2B,KAAK,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;CA6E/E"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Audit verifying the presence and quality of structured tables and lists for fast LLM extraction.
|
|
3
|
+
*/
|
|
4
|
+
import { Audit } from '../audit.js';
|
|
5
|
+
export class TableListScannabilityAudit extends Audit {
|
|
6
|
+
static meta = {
|
|
7
|
+
id: 'table-list-scannability',
|
|
8
|
+
title: 'Content leverages structured HTML tables and lists for rapid LLM extraction',
|
|
9
|
+
failureTitle: 'Content lacks structured tables or lists for quick answer extraction',
|
|
10
|
+
description: 'Generative Answer Engines (SearchGPT, Perplexity, Gemini) strongly prioritize bulleted lists (<ul>/<ol>) and semantic comparison tables (<table>) over dense walls of text for extraction.',
|
|
11
|
+
requiredArtifacts: ['ContentChunks'],
|
|
12
|
+
};
|
|
13
|
+
static async audit(artifacts) {
|
|
14
|
+
const { chunks, totalWordCount, totalTablesCount, totalListsCount, totalListItemsCount, structuredTablesCount, } = artifacts.ContentChunks;
|
|
15
|
+
// Small or landing pages with minimal content don't require heavy tables/lists
|
|
16
|
+
if (totalWordCount < 150) {
|
|
17
|
+
return this.generateAuditResult({
|
|
18
|
+
score: 1,
|
|
19
|
+
displayValue: 'Brief page (tables/lists optional)',
|
|
20
|
+
explanation: 'Page has concise content under 150 words where extensive lists or tables are not strictly required.',
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
const chunksWithListOrTable = chunks.filter((c) => c.hasList || c.hasTable).length;
|
|
24
|
+
let score = 0.5;
|
|
25
|
+
let statusText = 'Needs Improvement';
|
|
26
|
+
if (totalTablesCount > 0 && totalListsCount > 0) {
|
|
27
|
+
score = 1.0;
|
|
28
|
+
statusText = 'Excellent (Tables & Lists present)';
|
|
29
|
+
}
|
|
30
|
+
else if (totalTablesCount > 0 || totalListsCount >= 2) {
|
|
31
|
+
score = 0.9;
|
|
32
|
+
statusText = 'Good (Structured elements detected)';
|
|
33
|
+
}
|
|
34
|
+
else if (totalListsCount === 1 && totalListItemsCount >= 3) {
|
|
35
|
+
score = 0.8;
|
|
36
|
+
statusText = 'Acceptable (Single list detected)';
|
|
37
|
+
}
|
|
38
|
+
else if (totalTablesCount === 0 && totalListsCount === 0) {
|
|
39
|
+
if (totalWordCount > 500) {
|
|
40
|
+
score = 0.3;
|
|
41
|
+
statusText = 'Dense wall of text (0 tables, 0 lists)';
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
score = 0.5;
|
|
45
|
+
statusText = 'No structured tables or lists found';
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const summaryTable = [
|
|
49
|
+
{
|
|
50
|
+
metric: 'Tables (<table>)',
|
|
51
|
+
count: String(totalTablesCount),
|
|
52
|
+
details: structuredTablesCount > 0 ? `${structuredTablesCount} with semantic <th>/<thead> headers` : 'No semantic <th> headers',
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
metric: 'Lists (<ul>/<ol>)',
|
|
56
|
+
count: String(totalListsCount),
|
|
57
|
+
details: `${totalListItemsCount} total <li> bullet/numbered item(s)`,
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
metric: 'Content Chunks with Structures',
|
|
61
|
+
count: `${chunksWithListOrTable} / ${chunks.length}`,
|
|
62
|
+
details: `${Math.round((chunksWithListOrTable / (chunks.length || 1)) * 100)}% of content blocks contain structured data`,
|
|
63
|
+
},
|
|
64
|
+
];
|
|
65
|
+
return this.generateAuditResult({
|
|
66
|
+
score,
|
|
67
|
+
displayValue: `${totalTablesCount} table(s), ${totalListsCount} list(s) (${totalListItemsCount} items)`,
|
|
68
|
+
explanation: score < 0.8
|
|
69
|
+
? 'Breaking continuous paragraphs into bulleted lists or comparison tables improves Answer Engine parsing and citation rate.'
|
|
70
|
+
: undefined,
|
|
71
|
+
details: this.makeTableDetails([
|
|
72
|
+
{ key: 'metric', label: 'Structured Element', valueType: 'text' },
|
|
73
|
+
{ key: 'count', label: 'Detected Count', valueType: 'text' },
|
|
74
|
+
{ key: 'details', label: 'Structure Quality', valueType: 'text' },
|
|
75
|
+
], summaryTable),
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=table-list-scannability.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table-list-scannability.js","sourceRoot":"","sources":["../../../src/audits/content-chunking/table-list-scannability.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Audit evaluating the presence of verifiable statistics, percentages, numerical metrics, and citations for GEO.
|
|
3
|
+
*/
|
|
4
|
+
import { Audit } from '../audit.js';
|
|
5
|
+
import type { Artifacts, AuditMeta, AuditResult } from '../../types/index.js';
|
|
6
|
+
export declare class FactCitationDensityAudit extends Audit {
|
|
7
|
+
static meta: AuditMeta;
|
|
8
|
+
static audit(artifacts: Artifacts): Promise<AuditResult>;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=fact-citation-density.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fact-citation-density.d.ts","sourceRoot":"","sources":["../../../src/audits/direct-answer-density/fact-citation-density.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,wBAAyB,SAAQ,KAAK;IACjD,OAAuB,IAAI,EAAE,SAAS,CAOpC;WAE2B,KAAK,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;CAuE/E"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Audit evaluating the presence of verifiable statistics, percentages, numerical metrics, and citations for GEO.
|
|
3
|
+
*/
|
|
4
|
+
import { Audit } from '../audit.js';
|
|
5
|
+
export class FactCitationDensityAudit extends Audit {
|
|
6
|
+
static meta = {
|
|
7
|
+
id: 'fact-citation-density',
|
|
8
|
+
title: 'Content incorporates concrete statistics, verifiable metrics, and authoritative citations',
|
|
9
|
+
failureTitle: 'Content lacks statistics, numerical metrics, or authoritative citations',
|
|
10
|
+
description: 'Generative Engine Optimization (GEO) research proves that incorporating empirical figures (percentages, numerical units) and citing trusted external sources boosts LLM citation likelihood by up to 40%.',
|
|
11
|
+
requiredArtifacts: ['DirectAnswers', 'ContentChunks'],
|
|
12
|
+
};
|
|
13
|
+
static async audit(artifacts) {
|
|
14
|
+
const { facts } = artifacts.DirectAnswers;
|
|
15
|
+
const { totalWordCount } = artifacts.ContentChunks;
|
|
16
|
+
if (totalWordCount < 150) {
|
|
17
|
+
return this.generateAuditResult({
|
|
18
|
+
score: 1,
|
|
19
|
+
displayValue: 'Brief page (statistical citations optional)',
|
|
20
|
+
explanation: 'Page has concise content under 150 words where empirical statistics and research citations are optional.',
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
const { percentagesCount, numericalMetricsCount, citationPhrasesCount, externalSourcesCount, externalSourcesUrls, totalFactSignals, } = facts;
|
|
24
|
+
let score = 0.5;
|
|
25
|
+
if (totalFactSignals >= 4 && externalSourcesCount >= 1) {
|
|
26
|
+
score = 1.0;
|
|
27
|
+
}
|
|
28
|
+
else if (totalFactSignals >= 3) {
|
|
29
|
+
score = 0.85;
|
|
30
|
+
}
|
|
31
|
+
else if (totalFactSignals >= 1) {
|
|
32
|
+
score = 0.65;
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
score = totalWordCount > 400 ? 0.3 : 0.5;
|
|
36
|
+
}
|
|
37
|
+
const summaryTable = [
|
|
38
|
+
{
|
|
39
|
+
metric: 'Percentages & Ratios (%)',
|
|
40
|
+
count: String(percentagesCount),
|
|
41
|
+
status: percentagesCount > 0 ? 'Detected' : 'None',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
metric: 'Numerical Metrics & Units',
|
|
45
|
+
count: String(numericalMetricsCount),
|
|
46
|
+
status: numericalMetricsCount > 0 ? 'Detected' : 'None',
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
metric: 'Citation Attribution Markers',
|
|
50
|
+
count: String(citationPhrasesCount),
|
|
51
|
+
status: citationPhrasesCount > 0 ? 'Detected' : 'None',
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
metric: 'External Authority Domains Linked',
|
|
55
|
+
count: String(externalSourcesCount),
|
|
56
|
+
status: externalSourcesUrls.length > 0 ? externalSourcesUrls.slice(0, 3).join(', ') : 'No external references',
|
|
57
|
+
},
|
|
58
|
+
];
|
|
59
|
+
return this.generateAuditResult({
|
|
60
|
+
score,
|
|
61
|
+
displayValue: `${totalFactSignals} fact signal(s) found (${percentagesCount} %, ${numericalMetricsCount} metrics, ${externalSourcesCount} sources)`,
|
|
62
|
+
explanation: score < 0.85
|
|
63
|
+
? 'Adding verifiable percentages, empirical numbers, and citations to authoritative sources significantly increases confidence and citation frequency in AI Answer Engines (Perplexity, SearchGPT, Gemini).'
|
|
64
|
+
: undefined,
|
|
65
|
+
details: this.makeTableDetails([
|
|
66
|
+
{ key: 'metric', label: 'Fact / Citation Signal', valueType: 'text' },
|
|
67
|
+
{ key: 'count', label: 'Count', valueType: 'text' },
|
|
68
|
+
{ key: 'status', label: 'Details / References', valueType: 'text' },
|
|
69
|
+
], summaryTable),
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=fact-citation-density.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fact-citation-density.js","sourceRoot":"","sources":["../../../src/audits/direct-answer-density/fact-citation-density.ts"],"names":[],"mappings":"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"}
|
package/dist/audits/index.d.ts
CHANGED
|
@@ -5,15 +5,19 @@ import { Audit } from './audit.js';
|
|
|
5
5
|
import { AiRobotsTxtAudit } from './ai-accessibility/ai-robots-txt.js';
|
|
6
6
|
import { AiXRobotsTagAudit } from './ai-accessibility/ai-x-robots-tag.js';
|
|
7
7
|
import { AiBotSitemapAudit } from './ai-accessibility/ai-bot-sitemap.js';
|
|
8
|
+
import { AiLlmsTxtAudit } from './ai-accessibility/ai-llms-txt.js';
|
|
8
9
|
import { JsonLdSyntaxValidityAudit } from './structured-data/jsonld-syntax-validity.js';
|
|
9
10
|
import { RagSchemaPresenceAudit } from './structured-data/rag-schema-presence.js';
|
|
10
11
|
import { EntitySameAsLinksAudit } from './structured-data/entity-sameas-links.js';
|
|
12
|
+
import { AuthorEeatPresenceAudit } from './structured-data/author-eeat-presence.js';
|
|
11
13
|
import { HeadingHierarchyAudit } from './content-chunking/heading-hierarchy.js';
|
|
12
14
|
import { SemanticContainersAudit } from './content-chunking/semantic-containers.js';
|
|
13
15
|
import { ChunkTokenDensityAudit } from './content-chunking/chunk-token-density.js';
|
|
16
|
+
import { TableListScannabilityAudit } from './content-chunking/table-list-scannability.js';
|
|
14
17
|
import { DirectDefinitionAnsweringAudit } from './direct-answer-density/direct-definition-answering.js';
|
|
15
18
|
import { ConciseAnswerWordCountAudit } from './direct-answer-density/concise-answer-wordcount.js';
|
|
16
19
|
import { QuestionHeadingAlignmentAudit } from './direct-answer-density/question-heading-alignment.js';
|
|
17
|
-
|
|
20
|
+
import { FactCitationDensityAudit } from './direct-answer-density/fact-citation-density.js';
|
|
21
|
+
export { Audit, AiRobotsTxtAudit, AiXRobotsTagAudit, AiBotSitemapAudit, AiLlmsTxtAudit, JsonLdSyntaxValidityAudit, RagSchemaPresenceAudit, EntitySameAsLinksAudit, AuthorEeatPresenceAudit, HeadingHierarchyAudit, SemanticContainersAudit, ChunkTokenDensityAudit, TableListScannabilityAudit, DirectDefinitionAnsweringAudit, ConciseAnswerWordCountAudit, QuestionHeadingAlignmentAudit, FactCitationDensityAudit, };
|
|
18
22
|
export declare const auditRegistry: Record<string, typeof Audit>;
|
|
19
23
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/audits/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGnC,OAAO,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/audits/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGnC,OAAO,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAGnE,OAAO,EAAE,yBAAyB,EAAE,MAAM,6CAA6C,CAAC;AACxF,OAAO,EAAE,sBAAsB,EAAE,MAAM,0CAA0C,CAAC;AAClF,OAAO,EAAE,sBAAsB,EAAE,MAAM,0CAA0C,CAAC;AAClF,OAAO,EAAE,uBAAuB,EAAE,MAAM,2CAA2C,CAAC;AAGpF,OAAO,EAAE,qBAAqB,EAAE,MAAM,yCAAyC,CAAC;AAChF,OAAO,EAAE,uBAAuB,EAAE,MAAM,2CAA2C,CAAC;AACpF,OAAO,EAAE,sBAAsB,EAAE,MAAM,2CAA2C,CAAC;AACnF,OAAO,EAAE,0BAA0B,EAAE,MAAM,+CAA+C,CAAC;AAG3F,OAAO,EAAE,8BAA8B,EAAE,MAAM,wDAAwD,CAAC;AACxG,OAAO,EAAE,2BAA2B,EAAE,MAAM,qDAAqD,CAAC;AAClG,OAAO,EAAE,6BAA6B,EAAE,MAAM,uDAAuD,CAAC;AACtG,OAAO,EAAE,wBAAwB,EAAE,MAAM,kDAAkD,CAAC;AAE5F,OAAO,EACL,KAAK,EACL,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,yBAAyB,EACzB,sBAAsB,EACtB,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,EACrB,uBAAuB,EACvB,sBAAsB,EACtB,0BAA0B,EAC1B,8BAA8B,EAC9B,2BAA2B,EAC3B,6BAA6B,EAC7B,wBAAwB,GACzB,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,KAAK,CAiBtD,CAAC"}
|
package/dist/audits/index.js
CHANGED
|
@@ -6,31 +6,39 @@ import { Audit } from './audit.js';
|
|
|
6
6
|
import { AiRobotsTxtAudit } from './ai-accessibility/ai-robots-txt.js';
|
|
7
7
|
import { AiXRobotsTagAudit } from './ai-accessibility/ai-x-robots-tag.js';
|
|
8
8
|
import { AiBotSitemapAudit } from './ai-accessibility/ai-bot-sitemap.js';
|
|
9
|
+
import { AiLlmsTxtAudit } from './ai-accessibility/ai-llms-txt.js';
|
|
9
10
|
// Structured Data
|
|
10
11
|
import { JsonLdSyntaxValidityAudit } from './structured-data/jsonld-syntax-validity.js';
|
|
11
12
|
import { RagSchemaPresenceAudit } from './structured-data/rag-schema-presence.js';
|
|
12
13
|
import { EntitySameAsLinksAudit } from './structured-data/entity-sameas-links.js';
|
|
14
|
+
import { AuthorEeatPresenceAudit } from './structured-data/author-eeat-presence.js';
|
|
13
15
|
// Content Chunking
|
|
14
16
|
import { HeadingHierarchyAudit } from './content-chunking/heading-hierarchy.js';
|
|
15
17
|
import { SemanticContainersAudit } from './content-chunking/semantic-containers.js';
|
|
16
18
|
import { ChunkTokenDensityAudit } from './content-chunking/chunk-token-density.js';
|
|
19
|
+
import { TableListScannabilityAudit } from './content-chunking/table-list-scannability.js';
|
|
17
20
|
// Direct Answer Density
|
|
18
21
|
import { DirectDefinitionAnsweringAudit } from './direct-answer-density/direct-definition-answering.js';
|
|
19
22
|
import { ConciseAnswerWordCountAudit } from './direct-answer-density/concise-answer-wordcount.js';
|
|
20
23
|
import { QuestionHeadingAlignmentAudit } from './direct-answer-density/question-heading-alignment.js';
|
|
21
|
-
|
|
24
|
+
import { FactCitationDensityAudit } from './direct-answer-density/fact-citation-density.js';
|
|
25
|
+
export { Audit, AiRobotsTxtAudit, AiXRobotsTagAudit, AiBotSitemapAudit, AiLlmsTxtAudit, JsonLdSyntaxValidityAudit, RagSchemaPresenceAudit, EntitySameAsLinksAudit, AuthorEeatPresenceAudit, HeadingHierarchyAudit, SemanticContainersAudit, ChunkTokenDensityAudit, TableListScannabilityAudit, DirectDefinitionAnsweringAudit, ConciseAnswerWordCountAudit, QuestionHeadingAlignmentAudit, FactCitationDensityAudit, };
|
|
22
26
|
export const auditRegistry = {
|
|
23
27
|
'ai-robots-txt': AiRobotsTxtAudit,
|
|
24
28
|
'ai-x-robots-tag': AiXRobotsTagAudit,
|
|
25
29
|
'ai-bot-sitemap': AiBotSitemapAudit,
|
|
30
|
+
'ai-llms-txt': AiLlmsTxtAudit,
|
|
26
31
|
'jsonld-syntax-validity': JsonLdSyntaxValidityAudit,
|
|
27
32
|
'rag-schema-presence': RagSchemaPresenceAudit,
|
|
28
33
|
'entity-sameas-links': EntitySameAsLinksAudit,
|
|
34
|
+
'author-eeat-presence': AuthorEeatPresenceAudit,
|
|
29
35
|
'heading-hierarchy': HeadingHierarchyAudit,
|
|
30
36
|
'semantic-containers': SemanticContainersAudit,
|
|
31
37
|
'chunk-token-density': ChunkTokenDensityAudit,
|
|
38
|
+
'table-list-scannability': TableListScannabilityAudit,
|
|
32
39
|
'direct-definition-answering': DirectDefinitionAnsweringAudit,
|
|
33
40
|
'concise-answer-wordcount': ConciseAnswerWordCountAudit,
|
|
34
41
|
'question-heading-alignment': QuestionHeadingAlignmentAudit,
|
|
42
|
+
'fact-citation-density': FactCitationDensityAudit,
|
|
35
43
|
};
|
|
36
44
|
//# sourceMappingURL=index.js.map
|
package/dist/audits/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/audits/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,mBAAmB;AACnB,OAAO,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/audits/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,mBAAmB;AACnB,OAAO,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAEnE,kBAAkB;AAClB,OAAO,EAAE,yBAAyB,EAAE,MAAM,6CAA6C,CAAC;AACxF,OAAO,EAAE,sBAAsB,EAAE,MAAM,0CAA0C,CAAC;AAClF,OAAO,EAAE,sBAAsB,EAAE,MAAM,0CAA0C,CAAC;AAClF,OAAO,EAAE,uBAAuB,EAAE,MAAM,2CAA2C,CAAC;AAEpF,mBAAmB;AACnB,OAAO,EAAE,qBAAqB,EAAE,MAAM,yCAAyC,CAAC;AAChF,OAAO,EAAE,uBAAuB,EAAE,MAAM,2CAA2C,CAAC;AACpF,OAAO,EAAE,sBAAsB,EAAE,MAAM,2CAA2C,CAAC;AACnF,OAAO,EAAE,0BAA0B,EAAE,MAAM,+CAA+C,CAAC;AAE3F,wBAAwB;AACxB,OAAO,EAAE,8BAA8B,EAAE,MAAM,wDAAwD,CAAC;AACxG,OAAO,EAAE,2BAA2B,EAAE,MAAM,qDAAqD,CAAC;AAClG,OAAO,EAAE,6BAA6B,EAAE,MAAM,uDAAuD,CAAC;AACtG,OAAO,EAAE,wBAAwB,EAAE,MAAM,kDAAkD,CAAC;AAE5F,OAAO,EACL,KAAK,EACL,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,yBAAyB,EACzB,sBAAsB,EACtB,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,EACrB,uBAAuB,EACvB,sBAAsB,EACtB,0BAA0B,EAC1B,8BAA8B,EAC9B,2BAA2B,EAC3B,6BAA6B,EAC7B,wBAAwB,GACzB,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAiC;IACzD,eAAe,EAAE,gBAAgB;IACjC,iBAAiB,EAAE,iBAAiB;IACpC,gBAAgB,EAAE,iBAAiB;IACnC,aAAa,EAAE,cAAc;IAC7B,wBAAwB,EAAE,yBAAyB;IACnD,qBAAqB,EAAE,sBAAsB;IAC7C,qBAAqB,EAAE,sBAAsB;IAC7C,sBAAsB,EAAE,uBAAuB;IAC/C,mBAAmB,EAAE,qBAAqB;IAC1C,qBAAqB,EAAE,uBAAuB;IAC9C,qBAAqB,EAAE,sBAAsB;IAC7C,yBAAyB,EAAE,0BAA0B;IACrD,6BAA6B,EAAE,8BAA8B;IAC7D,0BAA0B,EAAE,2BAA2B;IACvD,4BAA4B,EAAE,6BAA6B;IAC3D,uBAAuB,EAAE,wBAAwB;CAClD,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Audit verifying author credentials, publisher identity, and E-E-A-T signals for Answer Engines.
|
|
3
|
+
*/
|
|
4
|
+
import { Audit } from '../audit.js';
|
|
5
|
+
import type { Artifacts, AuditMeta, AuditResult } from '../../types/index.js';
|
|
6
|
+
export declare class AuthorEeatPresenceAudit extends Audit {
|
|
7
|
+
static meta: AuditMeta;
|
|
8
|
+
static audit(artifacts: Artifacts): Promise<AuditResult>;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=author-eeat-presence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"author-eeat-presence.d.ts","sourceRoot":"","sources":["../../../src/audits/structured-data/author-eeat-presence.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,uBAAwB,SAAQ,KAAK;IAChD,OAAuB,IAAI,EAAE,SAAS,CAOpC;WAE2B,KAAK,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;CA4F/E"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Audit verifying author credentials, publisher identity, and E-E-A-T signals for Answer Engines.
|
|
3
|
+
*/
|
|
4
|
+
import { Audit } from '../audit.js';
|
|
5
|
+
export class AuthorEeatPresenceAudit extends Audit {
|
|
6
|
+
static meta = {
|
|
7
|
+
id: 'author-eeat-presence',
|
|
8
|
+
title: 'Content features verified author credentials and E-E-A-T structured schema',
|
|
9
|
+
failureTitle: 'Missing author credentials, publisher identity, or E-E-A-T metadata',
|
|
10
|
+
description: 'Answer Engines and AI search systems rely on E-E-A-T signals (Author schema, sameAs profile links, publisher info, visible bylines) to prioritize trusted, expert content over automated spam.',
|
|
11
|
+
requiredArtifacts: ['JSONLD', 'ContentChunks'],
|
|
12
|
+
};
|
|
13
|
+
static async audit(artifacts) {
|
|
14
|
+
const { authorEeat } = artifacts.JSONLD;
|
|
15
|
+
const { totalWordCount } = artifacts.ContentChunks;
|
|
16
|
+
if (totalWordCount < 150) {
|
|
17
|
+
return this.generateAuditResult({
|
|
18
|
+
score: 1,
|
|
19
|
+
displayValue: 'Brief page (Author E-E-A-T optional)',
|
|
20
|
+
explanation: 'Page has brief content under 150 words where individual author bylines and schemas are optional.',
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
const { hasAuthorSchema, authorName, authorType, authorSameAsUrls, hasPublisherSchema, publisherName, hasDatePublished, datePublished, hasDateModified, dateModified, hasDomAuthorByline, domAuthorText, hasDomPublishedDate, } = authorEeat;
|
|
24
|
+
let score = 0.5;
|
|
25
|
+
let statusSummary = '';
|
|
26
|
+
if (hasAuthorSchema && authorSameAsUrls.length > 0 && (hasPublisherSchema || hasDomAuthorByline)) {
|
|
27
|
+
score = 1.0;
|
|
28
|
+
statusSummary = `Author verified: ${authorName || 'Expert'} with sameAs profile links`;
|
|
29
|
+
}
|
|
30
|
+
else if (hasAuthorSchema && (hasPublisherSchema || hasDomAuthorByline)) {
|
|
31
|
+
score = 0.85;
|
|
32
|
+
statusSummary = `Author schema detected: ${authorName || 'Identified'}`;
|
|
33
|
+
}
|
|
34
|
+
else if (hasAuthorSchema || hasDomAuthorByline) {
|
|
35
|
+
score = 0.65;
|
|
36
|
+
statusSummary = authorName || domAuthorText ? `Author byline found: ${authorName || domAuthorText}` : 'Basic author signal found';
|
|
37
|
+
}
|
|
38
|
+
else if (hasPublisherSchema || artifacts.JSONLD.hasOrganization) {
|
|
39
|
+
score = 0.5;
|
|
40
|
+
statusSummary = 'Publisher/Organization identified (no specific author)';
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
score = totalWordCount > 400 ? 0.2 : 0.4;
|
|
44
|
+
statusSummary = 'No author or publisher credentials detected';
|
|
45
|
+
}
|
|
46
|
+
const summaryTable = [
|
|
47
|
+
{
|
|
48
|
+
attribute: 'Author Name (Schema / DOM)',
|
|
49
|
+
value: authorName || domAuthorText || 'Not specified',
|
|
50
|
+
status: hasAuthorSchema || hasDomAuthorByline ? 'Present' : 'Missing',
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
attribute: 'Author Schema Type',
|
|
54
|
+
value: authorType || (hasAuthorSchema ? 'Person' : 'None'),
|
|
55
|
+
status: hasAuthorSchema ? 'Structured JSON-LD' : 'Missing',
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
attribute: 'Author Social / SameAs Links',
|
|
59
|
+
value: authorSameAsUrls.length > 0 ? authorSameAsUrls.slice(0, 3).join(', ') : 'None',
|
|
60
|
+
status: authorSameAsUrls.length > 0 ? 'Disambiguated' : 'Recommended',
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
attribute: 'Publisher / Organization',
|
|
64
|
+
value: publisherName || (artifacts.JSONLD.hasOrganization ? 'Organization schema found' : 'Not declared'),
|
|
65
|
+
status: hasPublisherSchema || artifacts.JSONLD.hasOrganization ? 'Present' : 'Missing',
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
attribute: 'Date Published / Modified',
|
|
69
|
+
value: datePublished || dateModified || (hasDomPublishedDate ? 'Visible in DOM' : 'Not specified'),
|
|
70
|
+
status: hasDatePublished || hasDateModified || hasDomPublishedDate ? 'Freshness tracked' : 'Missing',
|
|
71
|
+
},
|
|
72
|
+
];
|
|
73
|
+
return this.generateAuditResult({
|
|
74
|
+
score,
|
|
75
|
+
displayValue: statusSummary,
|
|
76
|
+
explanation: score < 0.85
|
|
77
|
+
? 'Adding an Article/Person schema with author name, jobTitle, sameAs links (LinkedIn/Twitter), and publisher info verifies content authority for AI Answer Engines.'
|
|
78
|
+
: undefined,
|
|
79
|
+
details: this.makeTableDetails([
|
|
80
|
+
{ key: 'attribute', label: 'E-E-A-T Signal', valueType: 'text' },
|
|
81
|
+
{ key: 'value', label: 'Value / Identifier', valueType: 'text' },
|
|
82
|
+
{ key: 'status', label: 'Evaluation', valueType: 'text' },
|
|
83
|
+
], summaryTable),
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=author-eeat-presence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"author-eeat-presence.js","sourceRoot":"","sources":["../../../src/audits/structured-data/author-eeat-presence.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"default-config.d.ts","sourceRoot":"","sources":["../../src/config/default-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,eAAO,MAAM,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"default-config.d.ts","sourceRoot":"","sources":["../../src/config/default-config.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,eAAO,MAAM,aAAa,EAAE,YA6E3B,CAAC"}
|