@drowlink/aeo-linter-core 0.1.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.
Files changed (161) hide show
  1. package/dist/__tests__/audit-contract.test.d.ts +2 -0
  2. package/dist/__tests__/audit-contract.test.d.ts.map +1 -0
  3. package/dist/__tests__/audit-contract.test.js +120 -0
  4. package/dist/__tests__/audit-contract.test.js.map +1 -0
  5. package/dist/__tests__/gatherers.test.d.ts +2 -0
  6. package/dist/__tests__/gatherers.test.d.ts.map +1 -0
  7. package/dist/__tests__/gatherers.test.js +139 -0
  8. package/dist/__tests__/gatherers.test.js.map +1 -0
  9. package/dist/__tests__/runner.test.d.ts +2 -0
  10. package/dist/__tests__/runner.test.d.ts.map +1 -0
  11. package/dist/__tests__/runner.test.js +77 -0
  12. package/dist/__tests__/runner.test.js.map +1 -0
  13. package/dist/audits/ai-accessibility/ai-bot-sitemap.d.ts +10 -0
  14. package/dist/audits/ai-accessibility/ai-bot-sitemap.d.ts.map +1 -0
  15. package/dist/audits/ai-accessibility/ai-bot-sitemap.js +27 -0
  16. package/dist/audits/ai-accessibility/ai-bot-sitemap.js.map +1 -0
  17. package/dist/audits/ai-accessibility/ai-robots-txt.d.ts +10 -0
  18. package/dist/audits/ai-accessibility/ai-robots-txt.d.ts.map +1 -0
  19. package/dist/audits/ai-accessibility/ai-robots-txt.js +54 -0
  20. package/dist/audits/ai-accessibility/ai-robots-txt.js.map +1 -0
  21. package/dist/audits/ai-accessibility/ai-x-robots-tag.d.ts +10 -0
  22. package/dist/audits/ai-accessibility/ai-x-robots-tag.d.ts.map +1 -0
  23. package/dist/audits/ai-accessibility/ai-x-robots-tag.js +36 -0
  24. package/dist/audits/ai-accessibility/ai-x-robots-tag.js.map +1 -0
  25. package/dist/audits/audit.d.ts +56 -0
  26. package/dist/audits/audit.d.ts.map +1 -0
  27. package/dist/audits/audit.js +86 -0
  28. package/dist/audits/audit.js.map +1 -0
  29. package/dist/audits/content-chunking/chunk-token-density.d.ts +10 -0
  30. package/dist/audits/content-chunking/chunk-token-density.d.ts.map +1 -0
  31. package/dist/audits/content-chunking/chunk-token-density.js +44 -0
  32. package/dist/audits/content-chunking/chunk-token-density.js.map +1 -0
  33. package/dist/audits/content-chunking/heading-hierarchy.d.ts +10 -0
  34. package/dist/audits/content-chunking/heading-hierarchy.d.ts.map +1 -0
  35. package/dist/audits/content-chunking/heading-hierarchy.js +54 -0
  36. package/dist/audits/content-chunking/heading-hierarchy.js.map +1 -0
  37. package/dist/audits/content-chunking/semantic-containers.d.ts +10 -0
  38. package/dist/audits/content-chunking/semantic-containers.d.ts.map +1 -0
  39. package/dist/audits/content-chunking/semantic-containers.js +34 -0
  40. package/dist/audits/content-chunking/semantic-containers.js.map +1 -0
  41. package/dist/audits/direct-answer-density/concise-answer-wordcount.d.ts +10 -0
  42. package/dist/audits/direct-answer-density/concise-answer-wordcount.d.ts.map +1 -0
  43. package/dist/audits/direct-answer-density/concise-answer-wordcount.js +42 -0
  44. package/dist/audits/direct-answer-density/concise-answer-wordcount.js.map +1 -0
  45. package/dist/audits/direct-answer-density/direct-definition-answering.d.ts +10 -0
  46. package/dist/audits/direct-answer-density/direct-definition-answering.d.ts.map +1 -0
  47. package/dist/audits/direct-answer-density/direct-definition-answering.js +43 -0
  48. package/dist/audits/direct-answer-density/direct-definition-answering.js.map +1 -0
  49. package/dist/audits/direct-answer-density/question-heading-alignment.d.ts +10 -0
  50. package/dist/audits/direct-answer-density/question-heading-alignment.d.ts.map +1 -0
  51. package/dist/audits/direct-answer-density/question-heading-alignment.js +35 -0
  52. package/dist/audits/direct-answer-density/question-heading-alignment.js.map +1 -0
  53. package/dist/audits/index.d.ts +19 -0
  54. package/dist/audits/index.d.ts.map +1 -0
  55. package/dist/audits/index.js +36 -0
  56. package/dist/audits/index.js.map +1 -0
  57. package/dist/audits/structured-data/entity-sameas-links.d.ts +10 -0
  58. package/dist/audits/structured-data/entity-sameas-links.d.ts.map +1 -0
  59. package/dist/audits/structured-data/entity-sameas-links.js +43 -0
  60. package/dist/audits/structured-data/entity-sameas-links.js.map +1 -0
  61. package/dist/audits/structured-data/jsonld-syntax-validity.d.ts +10 -0
  62. package/dist/audits/structured-data/jsonld-syntax-validity.d.ts.map +1 -0
  63. package/dist/audits/structured-data/jsonld-syntax-validity.js +43 -0
  64. package/dist/audits/structured-data/jsonld-syntax-validity.js.map +1 -0
  65. package/dist/audits/structured-data/rag-schema-presence.d.ts +10 -0
  66. package/dist/audits/structured-data/rag-schema-presence.d.ts.map +1 -0
  67. package/dist/audits/structured-data/rag-schema-presence.js +48 -0
  68. package/dist/audits/structured-data/rag-schema-presence.js.map +1 -0
  69. package/dist/config/default-config.d.ts +7 -0
  70. package/dist/config/default-config.d.ts.map +1 -0
  71. package/dist/config/default-config.js +71 -0
  72. package/dist/config/default-config.js.map +1 -0
  73. package/dist/gather/driver/cheerio-driver.d.ts +27 -0
  74. package/dist/gather/driver/cheerio-driver.d.ts.map +1 -0
  75. package/dist/gather/driver/cheerio-driver.js +64 -0
  76. package/dist/gather/driver/cheerio-driver.js.map +1 -0
  77. package/dist/gather/gatherer.d.ts +12 -0
  78. package/dist/gather/gatherer.d.ts.map +1 -0
  79. package/dist/gather/gatherer.js +6 -0
  80. package/dist/gather/gatherer.js.map +1 -0
  81. package/dist/gather/gatherers/content-chunks-gatherer.d.ts +10 -0
  82. package/dist/gather/gatherers/content-chunks-gatherer.d.ts.map +1 -0
  83. package/dist/gather/gatherers/content-chunks-gatherer.js +100 -0
  84. package/dist/gather/gatherers/content-chunks-gatherer.js.map +1 -0
  85. package/dist/gather/gatherers/direct-answers-gatherer.d.ts +10 -0
  86. package/dist/gather/gatherers/direct-answers-gatherer.d.ts.map +1 -0
  87. package/dist/gather/gatherers/direct-answers-gatherer.js +58 -0
  88. package/dist/gather/gatherers/direct-answers-gatherer.js.map +1 -0
  89. package/dist/gather/gatherers/headings-hierarchy-gatherer.d.ts +10 -0
  90. package/dist/gather/gatherers/headings-hierarchy-gatherer.d.ts.map +1 -0
  91. package/dist/gather/gatherers/headings-hierarchy-gatherer.js +60 -0
  92. package/dist/gather/gatherers/headings-hierarchy-gatherer.js.map +1 -0
  93. package/dist/gather/gatherers/http-headers-gatherer.d.ts +10 -0
  94. package/dist/gather/gatherers/http-headers-gatherer.d.ts.map +1 -0
  95. package/dist/gather/gatherers/http-headers-gatherer.js +25 -0
  96. package/dist/gather/gatherers/http-headers-gatherer.js.map +1 -0
  97. package/dist/gather/gatherers/jsonld-gatherer.d.ts +11 -0
  98. package/dist/gather/gatherers/jsonld-gatherer.d.ts.map +1 -0
  99. package/dist/gather/gatherers/jsonld-gatherer.js +110 -0
  100. package/dist/gather/gatherers/jsonld-gatherer.js.map +1 -0
  101. package/dist/gather/gatherers/meta-tags-gatherer.d.ts +10 -0
  102. package/dist/gather/gatherers/meta-tags-gatherer.d.ts.map +1 -0
  103. package/dist/gather/gatherers/meta-tags-gatherer.js +45 -0
  104. package/dist/gather/gatherers/meta-tags-gatherer.js.map +1 -0
  105. package/dist/gather/gatherers/robots-txt-gatherer.d.ts +12 -0
  106. package/dist/gather/gatherers/robots-txt-gatherer.d.ts.map +1 -0
  107. package/dist/gather/gatherers/robots-txt-gatherer.js +139 -0
  108. package/dist/gather/gatherers/robots-txt-gatherer.js.map +1 -0
  109. package/dist/gather/gatherers/url-gatherer.d.ts +10 -0
  110. package/dist/gather/gatherers/url-gatherer.d.ts.map +1 -0
  111. package/dist/gather/gatherers/url-gatherer.js +19 -0
  112. package/dist/gather/gatherers/url-gatherer.js.map +1 -0
  113. package/dist/gather/index.d.ts +14 -0
  114. package/dist/gather/index.d.ts.map +1 -0
  115. package/dist/gather/index.js +14 -0
  116. package/dist/gather/index.js.map +1 -0
  117. package/dist/index.d.ts +11 -0
  118. package/dist/index.d.ts.map +1 -0
  119. package/dist/index.js +11 -0
  120. package/dist/index.js.map +1 -0
  121. package/dist/report/html-reporter.d.ts +11 -0
  122. package/dist/report/html-reporter.d.ts.map +1 -0
  123. package/dist/report/html-reporter.js +285 -0
  124. package/dist/report/html-reporter.js.map +1 -0
  125. package/dist/report/index.d.ts +6 -0
  126. package/dist/report/index.d.ts.map +1 -0
  127. package/dist/report/index.js +6 -0
  128. package/dist/report/index.js.map +1 -0
  129. package/dist/report/terminal-reporter.d.ts +8 -0
  130. package/dist/report/terminal-reporter.d.ts.map +1 -0
  131. package/dist/report/terminal-reporter.js +50 -0
  132. package/dist/report/terminal-reporter.js.map +1 -0
  133. package/dist/runner/aggregator.d.ts +17 -0
  134. package/dist/runner/aggregator.d.ts.map +1 -0
  135. package/dist/runner/aggregator.js +59 -0
  136. package/dist/runner/aggregator.js.map +1 -0
  137. package/dist/runner/runner.d.ts +29 -0
  138. package/dist/runner/runner.d.ts.map +1 -0
  139. package/dist/runner/runner.js +125 -0
  140. package/dist/runner/runner.js.map +1 -0
  141. package/dist/types/artifacts.d.ts +188 -0
  142. package/dist/types/artifacts.d.ts.map +1 -0
  143. package/dist/types/artifacts.js +7 -0
  144. package/dist/types/artifacts.js.map +1 -0
  145. package/dist/types/audit.d.ts +122 -0
  146. package/dist/types/audit.d.ts.map +1 -0
  147. package/dist/types/audit.js +6 -0
  148. package/dist/types/audit.js.map +1 -0
  149. package/dist/types/config.d.ts +74 -0
  150. package/dist/types/config.d.ts.map +1 -0
  151. package/dist/types/config.js +5 -0
  152. package/dist/types/config.js.map +1 -0
  153. package/dist/types/gatherer.d.ts +32 -0
  154. package/dist/types/gatherer.d.ts.map +1 -0
  155. package/dist/types/gatherer.js +5 -0
  156. package/dist/types/gatherer.js.map +1 -0
  157. package/dist/types/index.d.ts +8 -0
  158. package/dist/types/index.d.ts.map +1 -0
  159. package/dist/types/index.js +8 -0
  160. package/dist/types/index.js.map +1 -0
  161. package/package.json +54 -0
@@ -0,0 +1,86 @@
1
+ /**
2
+ * @fileoverview Clase base abstracta Audit y utilidades de resultado, siguiendo el diseño de Google Lighthouse.
3
+ * Cada auditoría concreta hereda de Audit e implementa su método estático `audit()` como una función pura
4
+ * que evalúa los artefactos requeridos y produce un `AuditResult`.
5
+ */
6
+ export class Audit {
7
+ /**
8
+ * Metadatos estáticos de la auditoría.
9
+ * Debe ser sobrescrito por cada subclase de auditoría concreta.
10
+ */
11
+ static meta;
12
+ /**
13
+ * Método puro de ejecución de la auditoría.
14
+ * @param artifacts Artefactos inmutables recolectados por los Gatherers
15
+ * @param context Contexto de ejecución opcional
16
+ */
17
+ static async audit(artifacts, context) {
18
+ throw new Error(`El método audit() no ha sido implementado en ${this.name}`);
19
+ }
20
+ /**
21
+ * Helper para generar un resultado de auditoría consistente
22
+ */
23
+ static generateAuditResult(options) {
24
+ const meta = this.meta || {
25
+ id: options.id ?? 'unknown-audit',
26
+ title: options.title ?? 'Unknown Audit',
27
+ description: options.description ?? '',
28
+ };
29
+ const isPassing = options.score !== null && options.score >= 0.9;
30
+ const title = options.title ?? (isPassing ? meta.title : (meta.failureTitle || meta.title));
31
+ let scoreDisplayMode = options.scoreDisplayMode ?? 'numeric';
32
+ if (options.score === null && !options.scoreDisplayMode) {
33
+ scoreDisplayMode = 'notApplicable';
34
+ }
35
+ else if (typeof options.score === 'number' && (options.score === 0 || options.score === 1) && !options.scoreDisplayMode) {
36
+ scoreDisplayMode = 'binary';
37
+ }
38
+ return {
39
+ id: meta.id,
40
+ score: options.score,
41
+ scoreDisplayMode,
42
+ title,
43
+ description: options.description ?? meta.description,
44
+ numericValue: options.numericValue,
45
+ numericUnit: options.numericUnit,
46
+ displayValue: options.displayValue,
47
+ explanation: options.explanation,
48
+ errorMessage: options.errorMessage,
49
+ details: options.details,
50
+ warnings: options.warnings,
51
+ };
52
+ }
53
+ /**
54
+ * Helper para construir un detalle de tipo tabla (Lighthouse TableDetails)
55
+ */
56
+ static makeTableDetails(headings, items, summary) {
57
+ return {
58
+ type: 'table',
59
+ headings,
60
+ items,
61
+ summary,
62
+ };
63
+ }
64
+ /**
65
+ * Helper para construir un detalle de tipo lista
66
+ */
67
+ static makeListDetails(items) {
68
+ return {
69
+ type: 'list',
70
+ items,
71
+ };
72
+ }
73
+ /**
74
+ * Helper para calcular puntaje binario
75
+ */
76
+ static binaryScore(condition) {
77
+ return condition ? 1 : 0;
78
+ }
79
+ /**
80
+ * Helper para calcular puntaje normalizado lineal o acotado
81
+ */
82
+ static clampScore(value, min = 0, max = 1) {
83
+ return Math.min(Math.max(value, min), max);
84
+ }
85
+ }
86
+ //# sourceMappingURL=audit.js.map
@@ -0,0 +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,gDAAgD,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAC/E,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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @fileoverview Auditoría para evaluar el tamaño y densidad de tokens de los bloques de contenido (para RAG)
3
+ */
4
+ import { Audit } from '../audit.js';
5
+ import type { Artifacts, AuditMeta, AuditResult } from '../../types/index.js';
6
+ export declare class ChunkTokenDensityAudit extends Audit {
7
+ static meta: AuditMeta;
8
+ static audit(artifacts: Artifacts): Promise<AuditResult>;
9
+ }
10
+ //# sourceMappingURL=chunk-token-density.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk-token-density.d.ts","sourceRoot":"","sources":["../../../src/audits/content-chunking/chunk-token-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,sBAAuB,SAAQ,KAAK;IAC/C,OAAuB,IAAI,EAAE,SAAS,CAOpC;WAE2B,KAAK,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;CAqC/E"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * @fileoverview Auditoría para evaluar el tamaño y densidad de tokens de los bloques de contenido (para RAG)
3
+ */
4
+ import { Audit } from '../audit.js';
5
+ export class ChunkTokenDensityAudit extends Audit {
6
+ static meta = {
7
+ id: 'chunk-token-density',
8
+ title: 'Los bloques de contenido mantienen una densidad óptima de tokens para RAG (150 - 500 tokens)',
9
+ failureTitle: 'Los bloques de contenido son excesivamente largos o fragmentados',
10
+ description: 'La mayoría de modelos de embeddings de RAG (OpenAI text-embedding-3, Cohere Embed, Voyage) rinden con mayor precisión cuando los pasajes tienen entre 150 y 500 tokens estructurados bajo un encabezado temático.',
11
+ requiredArtifacts: ['ContentChunks'],
12
+ };
13
+ static async audit(artifacts) {
14
+ const contentChunks = artifacts.ContentChunks;
15
+ const chunks = contentChunks.chunks;
16
+ if (chunks.length === 0) {
17
+ return this.generateAuditResult({
18
+ score: 0.5,
19
+ displayValue: 'No se encontraron bloques sustanciales de texto',
20
+ });
21
+ }
22
+ const optimalChunks = chunks.filter((c) => c.estimatedTokens >= 100 && c.estimatedTokens <= 600);
23
+ const ratio = optimalChunks.length / chunks.length;
24
+ const tableItems = chunks.slice(0, 10).map((c) => ({
25
+ id: c.id,
26
+ heading: c.headingText || '(Sin encabezado)',
27
+ words: c.wordCount,
28
+ tokens: `~${c.estimatedTokens}`,
29
+ status: c.estimatedTokens >= 100 && c.estimatedTokens <= 600 ? 'Óptimo' : c.estimatedTokens < 100 ? 'Muy corto' : 'Muy extenso',
30
+ }));
31
+ return this.generateAuditResult({
32
+ score: ratio >= 0.7 ? 1 : Math.max(0.4, ratio),
33
+ displayValue: `${optimalChunks.length} de ${chunks.length} bloques con tamaño óptimo (Promedio: ~${contentChunks.averageChunkTokenCount} tokens)`,
34
+ details: this.makeTableDetails([
35
+ { key: 'id', label: 'ID', valueType: 'code' },
36
+ { key: 'heading', label: 'Encabezado Asociado', valueType: 'text' },
37
+ { key: 'words', label: 'Palabras', valueType: 'numeric' },
38
+ { key: 'tokens', label: 'Tokens Estimados', valueType: 'numeric' },
39
+ { key: 'status', label: 'Diagnóstico', valueType: 'status' },
40
+ ], tableItems),
41
+ });
42
+ }
43
+ }
44
+ //# sourceMappingURL=chunk-token-density.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk-token-density.js","sourceRoot":"","sources":["../../../src/audits/content-chunking/chunk-token-density.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAGpC,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IACxC,MAAM,CAAU,IAAI,GAAc;QACvC,EAAE,EAAE,qBAAqB;QACzB,KAAK,EAAE,8FAA8F;QACrG,YAAY,EAAE,kEAAkE;QAChF,WAAW,EACT,mNAAmN;QACrN,iBAAiB,EAAE,CAAC,eAAe,CAAC;KACrC,CAAC;IAEK,MAAM,CAAU,KAAK,CAAC,KAAK,CAAC,SAAoB;QACrD,MAAM,aAAa,GAAG,SAAS,CAAC,aAAa,CAAC;QAC9C,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC;QAEpC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,IAAI,CAAC,mBAAmB,CAAC;gBAC9B,KAAK,EAAE,GAAG;gBACV,YAAY,EAAE,iDAAiD;aAChE,CAAC,CAAC;QACL,CAAC;QAED,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe,IAAI,GAAG,IAAI,CAAC,CAAC,eAAe,IAAI,GAAG,CAAC,CAAC;QACjG,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAEnD,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACjD,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,OAAO,EAAE,CAAC,CAAC,WAAW,IAAI,kBAAkB;YAC5C,KAAK,EAAE,CAAC,CAAC,SAAS;YAClB,MAAM,EAAE,IAAI,CAAC,CAAC,eAAe,EAAE;YAC/B,MAAM,EAAE,CAAC,CAAC,eAAe,IAAI,GAAG,IAAI,CAAC,CAAC,eAAe,IAAI,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,GAAG,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,aAAa;SAChI,CAAC,CAAC,CAAC;QAEJ,OAAO,IAAI,CAAC,mBAAmB,CAAC;YAC9B,KAAK,EAAE,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC;YAC9C,YAAY,EAAE,GAAG,aAAa,CAAC,MAAM,OAAO,MAAM,CAAC,MAAM,0CAA0C,aAAa,CAAC,sBAAsB,UAAU;YACjJ,OAAO,EAAE,IAAI,CAAC,gBAAgB,CAC5B;gBACE,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE;gBAC7C,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,qBAAqB,EAAE,SAAS,EAAE,MAAM,EAAE;gBACnE,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE;gBACzD,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,kBAAkB,EAAE,SAAS,EAAE,SAAS,EAAE;gBAClE,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,QAAQ,EAAE;aAC7D,EACD,UAAU,CACX;SACF,CAAC,CAAC;IACL,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @fileoverview Auditoría para validar la jerarquía secuencial de encabezados H1-H6
3
+ */
4
+ import { Audit } from '../audit.js';
5
+ import type { Artifacts, AuditMeta, AuditResult } from '../../types/index.js';
6
+ export declare class HeadingHierarchyAudit extends Audit {
7
+ static meta: AuditMeta;
8
+ static audit(artifacts: Artifacts): Promise<AuditResult>;
9
+ }
10
+ //# sourceMappingURL=heading-hierarchy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heading-hierarchy.d.ts","sourceRoot":"","sources":["../../../src/audits/content-chunking/heading-hierarchy.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,qBAAsB,SAAQ,KAAK;IAC9C,OAAuB,IAAI,EAAE,SAAS,CAOpC;WAE2B,KAAK,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;CAgD/E"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * @fileoverview Auditoría para validar la jerarquía secuencial de encabezados H1-H6
3
+ */
4
+ import { Audit } from '../audit.js';
5
+ export class HeadingHierarchyAudit extends Audit {
6
+ static meta = {
7
+ id: 'heading-hierarchy',
8
+ title: 'La estructura de encabezados H1-H6 es secuencial y cuenta con un único H1',
9
+ failureTitle: 'La jerarquía de encabezados contiene saltos de nivel o múltiples H1',
10
+ description: 'Una jerarquía clara y secuencial (H1 -> H2 -> H3) permite a los algoritmos de segmentación de RAG indexar el documento en fragmentos con contexto semántico preciso.',
11
+ requiredArtifacts: ['HeadingsHierarchy'],
12
+ };
13
+ static async audit(artifacts) {
14
+ const hierarchy = artifacts.HeadingsHierarchy;
15
+ if (hierarchy.headings.length === 0) {
16
+ return this.generateAuditResult({
17
+ score: 0,
18
+ displayValue: 'No se encontraron encabezados (H1-H6)',
19
+ explanation: 'El documento carece de encabezados semánticos para estructurar el contenido.',
20
+ });
21
+ }
22
+ let deductions = 0;
23
+ const issues = [];
24
+ if (hierarchy.h1Count === 0) {
25
+ deductions += 0.4;
26
+ issues.push('Falta el encabezado principal H1');
27
+ }
28
+ else if (hierarchy.h1Count > 1) {
29
+ deductions += 0.2;
30
+ issues.push(`Se detectaron ${hierarchy.h1Count} etiquetas H1 (se recomienda exactamente una)`);
31
+ }
32
+ if (!hierarchy.isHierarchySequential) {
33
+ deductions += 0.3;
34
+ issues.push(`Se encontraron ${hierarchy.skippedLevels.length} saltos bruscos de nivel (e.g. H1 a H3)`);
35
+ }
36
+ const score = this.clampScore(1 - deductions);
37
+ return this.generateAuditResult({
38
+ score,
39
+ displayValue: issues.length === 0 ? 'Jerarquía óptima y secuencial' : issues.join(', '),
40
+ details: hierarchy.skippedLevels.length > 0
41
+ ? this.makeTableDetails([
42
+ { key: 'from', label: 'Desde Nivel', valueType: 'code' },
43
+ { key: 'to', label: 'Hacia Nivel', valueType: 'code' },
44
+ { key: 'text', label: 'Texto del Encabezado', valueType: 'text' },
45
+ ], hierarchy.skippedLevels.map((s) => ({
46
+ from: `H${s.from}`,
47
+ to: `H${s.to}`,
48
+ text: s.text,
49
+ })))
50
+ : undefined,
51
+ });
52
+ }
53
+ }
54
+ //# sourceMappingURL=heading-hierarchy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heading-hierarchy.js","sourceRoot":"","sources":["../../../src/audits/content-chunking/heading-hierarchy.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAGpC,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IACvC,MAAM,CAAU,IAAI,GAAc;QACvC,EAAE,EAAE,mBAAmB;QACvB,KAAK,EAAE,2EAA2E;QAClF,YAAY,EAAE,qEAAqE;QACnF,WAAW,EACT,sKAAsK;QACxK,iBAAiB,EAAE,CAAC,mBAAmB,CAAC;KACzC,CAAC;IAEK,MAAM,CAAU,KAAK,CAAC,KAAK,CAAC,SAAoB;QACrD,MAAM,SAAS,GAAG,SAAS,CAAC,iBAAiB,CAAC;QAE9C,IAAI,SAAS,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACpC,OAAO,IAAI,CAAC,mBAAmB,CAAC;gBAC9B,KAAK,EAAE,CAAC;gBACR,YAAY,EAAE,uCAAuC;gBACrD,WAAW,EAAE,8EAA8E;aAC5F,CAAC,CAAC;QACL,CAAC;QAED,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,MAAM,MAAM,GAAa,EAAE,CAAC;QAE5B,IAAI,SAAS,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;YAC5B,UAAU,IAAI,GAAG,CAAC;YAClB,MAAM,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;QAClD,CAAC;aAAM,IAAI,SAAS,CAAC,OAAO,GAAG,CAAC,EAAE,CAAC;YACjC,UAAU,IAAI,GAAG,CAAC;YAClB,MAAM,CAAC,IAAI,CAAC,iBAAiB,SAAS,CAAC,OAAO,+CAA+C,CAAC,CAAC;QACjG,CAAC;QAED,IAAI,CAAC,SAAS,CAAC,qBAAqB,EAAE,CAAC;YACrC,UAAU,IAAI,GAAG,CAAC;YAClB,MAAM,CAAC,IAAI,CAAC,kBAAkB,SAAS,CAAC,aAAa,CAAC,MAAM,yCAAyC,CAAC,CAAC;QACzG,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC;QAE9C,OAAO,IAAI,CAAC,mBAAmB,CAAC;YAC9B,KAAK;YACL,YAAY,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;YACvF,OAAO,EAAE,SAAS,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC;gBACzC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CACnB;oBACE,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,EAAE;oBACxD,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,EAAE;oBACtD,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,sBAAsB,EAAE,SAAS,EAAE,MAAM,EAAE;iBAClE,EACD,SAAS,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBAClC,IAAI,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE;oBAClB,EAAE,EAAE,IAAI,CAAC,CAAC,EAAE,EAAE;oBACd,IAAI,EAAE,CAAC,CAAC,IAAI;iBACb,CAAC,CAAC,CACJ;gBACH,CAAC,CAAC,SAAS;SACd,CAAC,CAAC;IACL,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @fileoverview Auditoría para evaluar el uso de etiquetas HTML5 semánticas (<article>, <section>, <main>)
3
+ */
4
+ import { Audit } from '../audit.js';
5
+ import type { Artifacts, AuditMeta, AuditResult } from '../../types/index.js';
6
+ export declare class SemanticContainersAudit extends Audit {
7
+ static meta: AuditMeta;
8
+ static audit(artifacts: Artifacts): Promise<AuditResult>;
9
+ }
10
+ //# sourceMappingURL=semantic-containers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semantic-containers.d.ts","sourceRoot":"","sources":["../../../src/audits/content-chunking/semantic-containers.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;CAuB/E"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * @fileoverview Auditoría para evaluar el uso de etiquetas HTML5 semánticas (<article>, <section>, <main>)
3
+ */
4
+ import { Audit } from '../audit.js';
5
+ export class SemanticContainersAudit extends Audit {
6
+ static meta = {
7
+ id: 'semantic-containers',
8
+ title: 'El contenido utiliza contenedores semánticos (<main>, <article>, <section>)',
9
+ failureTitle: 'El contenido depende de <div> genéricos sin estructura semántica HTML5',
10
+ description: 'Las etiquetas semánticas como <main>, <article> y <section> delimitan el contenido principal respecto al boilerplate (nav, sidebar, footer), facilitando el chunking limpio en parsers de IA.',
11
+ requiredArtifacts: ['ContentChunks'],
12
+ };
13
+ static async audit(artifacts) {
14
+ const chunks = artifacts.ContentChunks;
15
+ const hasMain = chunks.hasSemanticMain;
16
+ const hasArticleOrSection = chunks.hasSemanticArticle || chunks.hasSemanticSections;
17
+ let score = 0.3;
18
+ if (hasMain && hasArticleOrSection) {
19
+ score = 1;
20
+ }
21
+ else if (hasMain || hasArticleOrSection) {
22
+ score = 0.7;
23
+ }
24
+ const tags = chunks.semanticTagsUsed.length > 0 ? chunks.semanticTagsUsed.join(', ') : 'Ninguna (<div/body>)';
25
+ return this.generateAuditResult({
26
+ score,
27
+ displayValue: `Etiquetas semánticas detectadas: ${tags}`,
28
+ explanation: score < 1
29
+ ? 'Recomendamos encapsular el contenido clave dentro de <main> y subdividirlo en <article> o <section>.'
30
+ : undefined,
31
+ });
32
+ }
33
+ }
34
+ //# sourceMappingURL=semantic-containers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"semantic-containers.js","sourceRoot":"","sources":["../../../src/audits/content-chunking/semantic-containers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAGpC,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IACzC,MAAM,CAAU,IAAI,GAAc;QACvC,EAAE,EAAE,qBAAqB;QACzB,KAAK,EAAE,6EAA6E;QACpF,YAAY,EAAE,wEAAwE;QACtF,WAAW,EACT,+LAA+L;QACjM,iBAAiB,EAAE,CAAC,eAAe,CAAC;KACrC,CAAC;IAEK,MAAM,CAAU,KAAK,CAAC,KAAK,CAAC,SAAoB;QACrD,MAAM,MAAM,GAAG,SAAS,CAAC,aAAa,CAAC;QAEvC,MAAM,OAAO,GAAG,MAAM,CAAC,eAAe,CAAC;QACvC,MAAM,mBAAmB,GAAG,MAAM,CAAC,kBAAkB,IAAI,MAAM,CAAC,mBAAmB,CAAC;QAEpF,IAAI,KAAK,GAAG,GAAG,CAAC;QAChB,IAAI,OAAO,IAAI,mBAAmB,EAAE,CAAC;YACnC,KAAK,GAAG,CAAC,CAAC;QACZ,CAAC;aAAM,IAAI,OAAO,IAAI,mBAAmB,EAAE,CAAC;YAC1C,KAAK,GAAG,GAAG,CAAC;QACd,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,sBAAsB,CAAC;QAE9G,OAAO,IAAI,CAAC,mBAAmB,CAAC;YAC9B,KAAK;YACL,YAAY,EAAE,oCAAoC,IAAI,EAAE;YACxD,WAAW,EAAE,KAAK,GAAG,CAAC;gBACpB,CAAC,CAAC,sGAAsG;gBACxG,CAAC,CAAC,SAAS;SACd,CAAC,CAAC;IACL,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @fileoverview Auditoría para evaluar la concisión de respuestas (ideal 30 a 60 palabras)
3
+ */
4
+ import { Audit } from '../audit.js';
5
+ import type { Artifacts, AuditMeta, AuditResult } from '../../types/index.js';
6
+ export declare class ConciseAnswerWordCountAudit extends Audit {
7
+ static meta: AuditMeta;
8
+ static audit(artifacts: Artifacts): Promise<AuditResult>;
9
+ }
10
+ //# sourceMappingURL=concise-answer-wordcount.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"concise-answer-wordcount.d.ts","sourceRoot":"","sources":["../../../src/audits/direct-answer-density/concise-answer-wordcount.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,2BAA4B,SAAQ,KAAK;IACpD,OAAuB,IAAI,EAAE,SAAS,CAOpC;WAE2B,KAAK,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;CAkC/E"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * @fileoverview Auditoría para evaluar la concisión de respuestas (ideal 30 a 60 palabras)
3
+ */
4
+ import { Audit } from '../audit.js';
5
+ export class ConciseAnswerWordCountAudit extends Audit {
6
+ static meta = {
7
+ id: 'concise-answer-wordcount',
8
+ title: 'Las respuestas directas tienen una extensión concisa óptima (30 - 60 palabras)',
9
+ failureTitle: 'Las respuestas directas son excesivamente extensas o demasiado escuetas',
10
+ description: 'Los modelos de lenguaje prefieren respuestas de 30 a 60 palabras como respuesta inicial o fragmento destacado para sintetizar en sus resúmenes.',
11
+ requiredArtifacts: ['DirectAnswers'],
12
+ };
13
+ static async audit(artifacts) {
14
+ const directAnswers = artifacts.DirectAnswers;
15
+ const pairs = directAnswers.pairs;
16
+ if (pairs.length === 0) {
17
+ return this.generateAuditResult({
18
+ score: 0.5,
19
+ displayValue: 'Sin preguntas detectadas',
20
+ });
21
+ }
22
+ const conciseCount = directAnswers.conciseAnswersCount;
23
+ const ratio = conciseCount / pairs.length;
24
+ const score = ratio >= 0.6 ? 1 : Math.max(0.3, ratio);
25
+ return this.generateAuditResult({
26
+ score,
27
+ displayValue: `${conciseCount} de ${pairs.length} respuestas con longitud concisa óptima`,
28
+ numericValue: conciseCount,
29
+ numericUnit: 'respuestas',
30
+ details: this.makeTableDetails([
31
+ { key: 'question', label: 'Pregunta', valueType: 'text' },
32
+ { key: 'words', label: 'Conteo de Palabras', valueType: 'numeric' },
33
+ { key: 'status', label: 'Evaluación', valueType: 'status' },
34
+ ], pairs.map((p) => ({
35
+ question: p.question,
36
+ words: p.answerWordCount,
37
+ status: p.isConcise ? 'Conciso (30-60 palabras)' : p.answerWordCount < 20 ? 'Demasiado breve' : 'Extenso (>75 palabras)',
38
+ }))),
39
+ });
40
+ }
41
+ }
42
+ //# sourceMappingURL=concise-answer-wordcount.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"concise-answer-wordcount.js","sourceRoot":"","sources":["../../../src/audits/direct-answer-density/concise-answer-wordcount.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAGpC,MAAM,OAAO,2BAA4B,SAAQ,KAAK;IAC7C,MAAM,CAAU,IAAI,GAAc;QACvC,EAAE,EAAE,0BAA0B;QAC9B,KAAK,EAAE,gFAAgF;QACvF,YAAY,EAAE,yEAAyE;QACvF,WAAW,EACT,iJAAiJ;QACnJ,iBAAiB,EAAE,CAAC,eAAe,CAAC;KACrC,CAAC;IAEK,MAAM,CAAU,KAAK,CAAC,KAAK,CAAC,SAAoB;QACrD,MAAM,aAAa,GAAG,SAAS,CAAC,aAAa,CAAC;QAC9C,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC;QAElC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC,mBAAmB,CAAC;gBAC9B,KAAK,EAAE,GAAG;gBACV,YAAY,EAAE,0BAA0B;aACzC,CAAC,CAAC;QACL,CAAC;QAED,MAAM,YAAY,GAAG,aAAa,CAAC,mBAAmB,CAAC;QACvD,MAAM,KAAK,GAAG,YAAY,GAAG,KAAK,CAAC,MAAM,CAAC;QAC1C,MAAM,KAAK,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAEtD,OAAO,IAAI,CAAC,mBAAmB,CAAC;YAC9B,KAAK;YACL,YAAY,EAAE,GAAG,YAAY,OAAO,KAAK,CAAC,MAAM,yCAAyC;YACzF,YAAY,EAAE,YAAY;YAC1B,WAAW,EAAE,YAAY;YACzB,OAAO,EAAE,IAAI,CAAC,gBAAgB,CAC5B;gBACE,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE;gBACzD,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,oBAAoB,EAAE,SAAS,EAAE,SAAS,EAAE;gBACnE,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE;aAC5D,EACD,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBAChB,QAAQ,EAAE,CAAC,CAAC,QAAQ;gBACpB,KAAK,EAAE,CAAC,CAAC,eAAe;gBACxB,MAAM,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,GAAG,EAAE,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,wBAAwB;aACzH,CAAC,CAAC,CACJ;SACF,CAAC,CAAC;IACL,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @fileoverview Auditoría para evaluar la presencia de definiciones directas a preguntas clave
3
+ */
4
+ import { Audit } from '../audit.js';
5
+ import type { Artifacts, AuditMeta, AuditResult } from '../../types/index.js';
6
+ export declare class DirectDefinitionAnsweringAudit extends Audit {
7
+ static meta: AuditMeta;
8
+ static audit(artifacts: Artifacts): Promise<AuditResult>;
9
+ }
10
+ //# sourceMappingURL=direct-definition-answering.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"direct-definition-answering.d.ts","sourceRoot":"","sources":["../../../src/audits/direct-answer-density/direct-definition-answering.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,8BAA+B,SAAQ,KAAK;IACvD,OAAuB,IAAI,EAAE,SAAS,CAOpC;WAE2B,KAAK,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;CAoC/E"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * @fileoverview Auditoría para evaluar la presencia de definiciones directas a preguntas clave
3
+ */
4
+ import { Audit } from '../audit.js';
5
+ export class DirectDefinitionAnsweringAudit extends Audit {
6
+ static meta = {
7
+ id: 'direct-definition-answering',
8
+ title: 'Las preguntas clave se responden de forma directa con definiciones claras en el primer párrafo',
9
+ failureTitle: 'Faltan respuestas directas o definiciones claras tras las preguntas clave',
10
+ description: 'Los Answer Engines (Perplexity, SearchGPT, Google AI Overviews) seleccionan pasajes que entregan una respuesta directa en las primeras líneas (e.g. "X es un...", "El proceso consiste en..."), en lugar de rodeos introductorios.',
11
+ requiredArtifacts: ['DirectAnswers'],
12
+ };
13
+ static async audit(artifacts) {
14
+ const directAnswers = artifacts.DirectAnswers;
15
+ const pairs = directAnswers.pairs;
16
+ if (pairs.length === 0) {
17
+ return this.generateAuditResult({
18
+ score: 0.5,
19
+ displayValue: 'No se detectaron preguntas en encabezados para evaluar respuestas directas',
20
+ explanation: 'Incorporar encabezados con formato de pregunta (e.g. "¿Qué es X?") favorece la captura de snippets en Answer Engines.',
21
+ });
22
+ }
23
+ const definitionPairs = pairs.filter((p) => p.hasDirectDefinition);
24
+ const score = Math.max(0.3, definitionPairs.length / pairs.length);
25
+ const tableItems = pairs.map((p) => ({
26
+ question: p.question,
27
+ words: p.answerWordCount,
28
+ hasDef: p.hasDirectDefinition ? 'Sí (Definición clara)' : 'No (Indirecto o descriptivo)',
29
+ preview: p.answerText.length > 80 ? p.answerText.slice(0, 80) + '...' : p.answerText,
30
+ }));
31
+ return this.generateAuditResult({
32
+ score: definitionPairs.length > 0 ? (score >= 0.5 ? 1 : 0.7) : 0.4,
33
+ displayValue: `${definitionPairs.length} de ${pairs.length} preguntas responden con definición directa inmediata`,
34
+ details: this.makeTableDetails([
35
+ { key: 'question', label: 'Pregunta Detectada', valueType: 'text' },
36
+ { key: 'hasDef', label: 'Patrón de Respuesta', valueType: 'status' },
37
+ { key: 'words', label: 'Palabras', valueType: 'numeric' },
38
+ { key: 'preview', label: 'Extracto de Respuesta', valueType: 'text' },
39
+ ], tableItems),
40
+ });
41
+ }
42
+ }
43
+ //# sourceMappingURL=direct-definition-answering.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"direct-definition-answering.js","sourceRoot":"","sources":["../../../src/audits/direct-answer-density/direct-definition-answering.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAGpC,MAAM,OAAO,8BAA+B,SAAQ,KAAK;IAChD,MAAM,CAAU,IAAI,GAAc;QACvC,EAAE,EAAE,6BAA6B;QACjC,KAAK,EAAE,gGAAgG;QACvG,YAAY,EAAE,2EAA2E;QACzF,WAAW,EACT,oOAAoO;QACtO,iBAAiB,EAAE,CAAC,eAAe,CAAC;KACrC,CAAC;IAEK,MAAM,CAAU,KAAK,CAAC,KAAK,CAAC,SAAoB;QACrD,MAAM,aAAa,GAAG,SAAS,CAAC,aAAa,CAAC;QAC9C,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC;QAElC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC,mBAAmB,CAAC;gBAC9B,KAAK,EAAE,GAAG;gBACV,YAAY,EAAE,4EAA4E;gBAC1F,WAAW,EAAE,uHAAuH;aACrI,CAAC,CAAC;QACL,CAAC;QAED,MAAM,eAAe,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC;QACnE,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,eAAe,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;QAEnE,MAAM,UAAU,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACnC,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,KAAK,EAAE,CAAC,CAAC,eAAe;YACxB,MAAM,EAAE,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,8BAA8B;YACxF,OAAO,EAAE,CAAC,CAAC,UAAU,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU;SACrF,CAAC,CAAC,CAAC;QAEJ,OAAO,IAAI,CAAC,mBAAmB,CAAC;YAC9B,KAAK,EAAE,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG;YAClE,YAAY,EAAE,GAAG,eAAe,CAAC,MAAM,OAAO,KAAK,CAAC,MAAM,uDAAuD;YACjH,OAAO,EAAE,IAAI,CAAC,gBAAgB,CAC5B;gBACE,EAAE,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,EAAE;gBACnE,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,qBAAqB,EAAE,SAAS,EAAE,QAAQ,EAAE;gBACpE,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE;gBACzD,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,uBAAuB,EAAE,SAAS,EAAE,MAAM,EAAE;aACtE,EACD,UAAU,CACX;SACF,CAAC,CAAC;IACL,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @fileoverview Auditoría para evaluar la formulación de preguntas orientadas a intención de búsqueda en encabezados
3
+ */
4
+ import { Audit } from '../audit.js';
5
+ import type { Artifacts, AuditMeta, AuditResult } from '../../types/index.js';
6
+ export declare class QuestionHeadingAlignmentAudit extends Audit {
7
+ static meta: AuditMeta;
8
+ static audit(artifacts: Artifacts): Promise<AuditResult>;
9
+ }
10
+ //# sourceMappingURL=question-heading-alignment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"question-heading-alignment.d.ts","sourceRoot":"","sources":["../../../src/audits/direct-answer-density/question-heading-alignment.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,6BAA8B,SAAQ,KAAK;IACtD,OAAuB,IAAI,EAAE,SAAS,CAOpC;WAE2B,KAAK,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;CAyB/E"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * @fileoverview Auditoría para evaluar la formulación de preguntas orientadas a intención de búsqueda en encabezados
3
+ */
4
+ import { Audit } from '../audit.js';
5
+ export class QuestionHeadingAlignmentAudit extends Audit {
6
+ static meta = {
7
+ id: 'question-heading-alignment',
8
+ title: 'Se estructuran encabezados explícitos en formato de pregunta o consulta de usuario',
9
+ failureTitle: 'Faltan encabezados orientados a consultas de búsqueda o preguntas frecuentes',
10
+ description: 'Formular encabezados (H2/H3) como preguntas naturales (e.g. "¿Cómo funciona X?", "¿Por qué elegir Y?") incrementa sustancialmente el match semántico en búsquedas vectoriales y RAG.',
11
+ requiredArtifacts: ['HeadingsHierarchy', 'DirectAnswers'],
12
+ };
13
+ static async audit(artifacts) {
14
+ const headings = artifacts.HeadingsHierarchy.headings;
15
+ const directAnswers = artifacts.DirectAnswers;
16
+ const questionHeadings = directAnswers.pairs.length;
17
+ const totalSubheadings = headings.filter((h) => h.level === 2 || h.level === 3).length;
18
+ if (totalSubheadings === 0) {
19
+ return this.generateAuditResult({
20
+ score: 0.5,
21
+ displayValue: 'No se encontraron subtítulos H2 o H3',
22
+ });
23
+ }
24
+ const ratio = questionHeadings / Math.max(1, totalSubheadings);
25
+ const score = questionHeadings >= 1 ? (ratio >= 0.25 ? 1 : 0.8) : 0.4;
26
+ return this.generateAuditResult({
27
+ score,
28
+ displayValue: `${questionHeadings} de ${totalSubheadings} subtítulos estructurados como pregunta`,
29
+ explanation: questionHeadings === 0
30
+ ? 'Recomendamos redactar al menos 1 o 2 subtítulos H2/H3 como preguntas directas que los usuarios suelen consultar.'
31
+ : undefined,
32
+ });
33
+ }
34
+ }
35
+ //# sourceMappingURL=question-heading-alignment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"question-heading-alignment.js","sourceRoot":"","sources":["../../../src/audits/direct-answer-density/question-heading-alignment.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAGpC,MAAM,OAAO,6BAA8B,SAAQ,KAAK;IAC/C,MAAM,CAAU,IAAI,GAAc;QACvC,EAAE,EAAE,4BAA4B;QAChC,KAAK,EAAE,oFAAoF;QAC3F,YAAY,EAAE,8EAA8E;QAC5F,WAAW,EACT,sLAAsL;QACxL,iBAAiB,EAAE,CAAC,mBAAmB,EAAE,eAAe,CAAC;KAC1D,CAAC;IAEK,MAAM,CAAU,KAAK,CAAC,KAAK,CAAC,SAAoB;QACrD,MAAM,QAAQ,GAAG,SAAS,CAAC,iBAAiB,CAAC,QAAQ,CAAC;QACtD,MAAM,aAAa,GAAG,SAAS,CAAC,aAAa,CAAC;QAE9C,MAAM,gBAAgB,GAAG,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC;QACpD,MAAM,gBAAgB,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;QAEvF,IAAI,gBAAgB,KAAK,CAAC,EAAE,CAAC;YAC3B,OAAO,IAAI,CAAC,mBAAmB,CAAC;gBAC9B,KAAK,EAAE,GAAG;gBACV,YAAY,EAAE,sCAAsC;aACrD,CAAC,CAAC;QACL,CAAC;QAED,MAAM,KAAK,GAAG,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAC;QAC/D,MAAM,KAAK,GAAG,gBAAgB,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;QAEtE,OAAO,IAAI,CAAC,mBAAmB,CAAC;YAC9B,KAAK;YACL,YAAY,EAAE,GAAG,gBAAgB,OAAO,gBAAgB,yCAAyC;YACjG,WAAW,EAAE,gBAAgB,KAAK,CAAC;gBACjC,CAAC,CAAC,kHAAkH;gBACpH,CAAC,CAAC,SAAS;SACd,CAAC,CAAC;IACL,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @fileoverview Exportación y registro central de todas las auditorías disponibles
3
+ */
4
+ import { Audit } from './audit.js';
5
+ import { AiRobotsTxtAudit } from './ai-accessibility/ai-robots-txt.js';
6
+ import { AiXRobotsTagAudit } from './ai-accessibility/ai-x-robots-tag.js';
7
+ import { AiBotSitemapAudit } from './ai-accessibility/ai-bot-sitemap.js';
8
+ import { JsonLdSyntaxValidityAudit } from './structured-data/jsonld-syntax-validity.js';
9
+ import { RagSchemaPresenceAudit } from './structured-data/rag-schema-presence.js';
10
+ import { EntitySameAsLinksAudit } from './structured-data/entity-sameas-links.js';
11
+ import { HeadingHierarchyAudit } from './content-chunking/heading-hierarchy.js';
12
+ import { SemanticContainersAudit } from './content-chunking/semantic-containers.js';
13
+ import { ChunkTokenDensityAudit } from './content-chunking/chunk-token-density.js';
14
+ import { DirectDefinitionAnsweringAudit } from './direct-answer-density/direct-definition-answering.js';
15
+ import { ConciseAnswerWordCountAudit } from './direct-answer-density/concise-answer-wordcount.js';
16
+ import { QuestionHeadingAlignmentAudit } from './direct-answer-density/question-heading-alignment.js';
17
+ export { Audit, AiRobotsTxtAudit, AiXRobotsTagAudit, AiBotSitemapAudit, JsonLdSyntaxValidityAudit, RagSchemaPresenceAudit, EntitySameAsLinksAudit, HeadingHierarchyAudit, SemanticContainersAudit, ChunkTokenDensityAudit, DirectDefinitionAnsweringAudit, ConciseAnswerWordCountAudit, QuestionHeadingAlignmentAudit, };
18
+ export declare const auditRegistry: Record<string, typeof Audit>;
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +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;AAGzE,OAAO,EAAE,yBAAyB,EAAE,MAAM,6CAA6C,CAAC;AACxF,OAAO,EAAE,sBAAsB,EAAE,MAAM,0CAA0C,CAAC;AAClF,OAAO,EAAE,sBAAsB,EAAE,MAAM,0CAA0C,CAAC;AAGlF,OAAO,EAAE,qBAAqB,EAAE,MAAM,yCAAyC,CAAC;AAChF,OAAO,EAAE,uBAAuB,EAAE,MAAM,2CAA2C,CAAC;AACpF,OAAO,EAAE,sBAAsB,EAAE,MAAM,2CAA2C,CAAC;AAGnF,OAAO,EAAE,8BAA8B,EAAE,MAAM,wDAAwD,CAAC;AACxG,OAAO,EAAE,2BAA2B,EAAE,MAAM,qDAAqD,CAAC;AAClG,OAAO,EAAE,6BAA6B,EAAE,MAAM,uDAAuD,CAAC;AAEtG,OAAO,EACL,KAAK,EACL,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,yBAAyB,EACzB,sBAAsB,EACtB,sBAAsB,EACtB,qBAAqB,EACrB,uBAAuB,EACvB,sBAAsB,EACtB,8BAA8B,EAC9B,2BAA2B,EAC3B,6BAA6B,GAC9B,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,KAAK,CAatD,CAAC"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @fileoverview Exportación y registro central de todas las auditorías disponibles
3
+ */
4
+ import { Audit } from './audit.js';
5
+ // AI Accessibility
6
+ import { AiRobotsTxtAudit } from './ai-accessibility/ai-robots-txt.js';
7
+ import { AiXRobotsTagAudit } from './ai-accessibility/ai-x-robots-tag.js';
8
+ import { AiBotSitemapAudit } from './ai-accessibility/ai-bot-sitemap.js';
9
+ // Structured Data
10
+ import { JsonLdSyntaxValidityAudit } from './structured-data/jsonld-syntax-validity.js';
11
+ import { RagSchemaPresenceAudit } from './structured-data/rag-schema-presence.js';
12
+ import { EntitySameAsLinksAudit } from './structured-data/entity-sameas-links.js';
13
+ // Content Chunking
14
+ import { HeadingHierarchyAudit } from './content-chunking/heading-hierarchy.js';
15
+ import { SemanticContainersAudit } from './content-chunking/semantic-containers.js';
16
+ import { ChunkTokenDensityAudit } from './content-chunking/chunk-token-density.js';
17
+ // Direct Answer Density
18
+ import { DirectDefinitionAnsweringAudit } from './direct-answer-density/direct-definition-answering.js';
19
+ import { ConciseAnswerWordCountAudit } from './direct-answer-density/concise-answer-wordcount.js';
20
+ import { QuestionHeadingAlignmentAudit } from './direct-answer-density/question-heading-alignment.js';
21
+ export { Audit, AiRobotsTxtAudit, AiXRobotsTagAudit, AiBotSitemapAudit, JsonLdSyntaxValidityAudit, RagSchemaPresenceAudit, EntitySameAsLinksAudit, HeadingHierarchyAudit, SemanticContainersAudit, ChunkTokenDensityAudit, DirectDefinitionAnsweringAudit, ConciseAnswerWordCountAudit, QuestionHeadingAlignmentAudit, };
22
+ export const auditRegistry = {
23
+ 'ai-robots-txt': AiRobotsTxtAudit,
24
+ 'ai-x-robots-tag': AiXRobotsTagAudit,
25
+ 'ai-bot-sitemap': AiBotSitemapAudit,
26
+ 'jsonld-syntax-validity': JsonLdSyntaxValidityAudit,
27
+ 'rag-schema-presence': RagSchemaPresenceAudit,
28
+ 'entity-sameas-links': EntitySameAsLinksAudit,
29
+ 'heading-hierarchy': HeadingHierarchyAudit,
30
+ 'semantic-containers': SemanticContainersAudit,
31
+ 'chunk-token-density': ChunkTokenDensityAudit,
32
+ 'direct-definition-answering': DirectDefinitionAnsweringAudit,
33
+ 'concise-answer-wordcount': ConciseAnswerWordCountAudit,
34
+ 'question-heading-alignment': QuestionHeadingAlignmentAudit,
35
+ };
36
+ //# sourceMappingURL=index.js.map
@@ -0,0 +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;AAEzE,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;AAElF,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;AAEnF,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;AAEtG,OAAO,EACL,KAAK,EACL,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,yBAAyB,EACzB,sBAAsB,EACtB,sBAAsB,EACtB,qBAAqB,EACrB,uBAAuB,EACvB,sBAAsB,EACtB,8BAA8B,EAC9B,2BAA2B,EAC3B,6BAA6B,GAC9B,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAiC;IACzD,eAAe,EAAE,gBAAgB;IACjC,iBAAiB,EAAE,iBAAiB;IACpC,gBAAgB,EAAE,iBAAiB;IACnC,wBAAwB,EAAE,yBAAyB;IACnD,qBAAqB,EAAE,sBAAsB;IAC7C,qBAAqB,EAAE,sBAAsB;IAC7C,mBAAmB,EAAE,qBAAqB;IAC1C,qBAAqB,EAAE,uBAAuB;IAC9C,qBAAqB,EAAE,sBAAsB;IAC7C,6BAA6B,EAAE,8BAA8B;IAC7D,0BAA0B,EAAE,2BAA2B;IACvD,4BAA4B,EAAE,6BAA6B;CAC5D,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @fileoverview Auditoría para evaluar la presencia de enlaces de desambiguación de entidades sameAs
3
+ */
4
+ import { Audit } from '../audit.js';
5
+ import type { Artifacts, AuditMeta, AuditResult } from '../../types/index.js';
6
+ export declare class EntitySameAsLinksAudit extends Audit {
7
+ static meta: AuditMeta;
8
+ static audit(artifacts: Artifacts): Promise<AuditResult>;
9
+ }
10
+ //# sourceMappingURL=entity-sameas-links.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entity-sameas-links.d.ts","sourceRoot":"","sources":["../../../src/audits/structured-data/entity-sameas-links.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,sBAAuB,SAAQ,KAAK;IAC/C,OAAuB,IAAI,EAAE,SAAS,CAOpC;WAE2B,KAAK,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC;CAiC/E"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * @fileoverview Auditoría para evaluar la presencia de enlaces de desambiguación de entidades sameAs
3
+ */
4
+ import { Audit } from '../audit.js';
5
+ export class EntitySameAsLinksAudit extends Audit {
6
+ static meta = {
7
+ id: 'entity-sameas-links',
8
+ title: 'Se definen propiedades sameAs para desambiguación en Grafos de Conocimiento',
9
+ failureTitle: 'No se encontraron enlaces sameAs en los datos estructurados',
10
+ description: 'La propiedad `sameAs` (con enlaces a Wikidata, Wikipedia, Crunchbase o perfiles oficiales) conecta la marca o tema con entidades verificadas en el Knowledge Graph de los LLMs.',
11
+ requiredArtifacts: ['JSONLD'],
12
+ };
13
+ static async audit(artifacts) {
14
+ const jsonld = artifacts.JSONLD;
15
+ const sameAsUrls = jsonld.sameAsUrls;
16
+ const hasSameAs = sameAsUrls.length > 0;
17
+ const score = hasSameAs ? 1 : 0.4;
18
+ const tableItems = sameAsUrls.map((url) => {
19
+ let authority = 'Enlace de Autoridad Externa';
20
+ if (url.includes('wikidata.org'))
21
+ authority = 'Wikidata (Alta Confianza)';
22
+ else if (url.includes('wikipedia.org'))
23
+ authority = 'Wikipedia (Alta Confianza)';
24
+ else if (url.includes('linkedin.com') || url.includes('twitter.com') || url.includes('x.com'))
25
+ authority = 'Red Social Oficial';
26
+ return {
27
+ url,
28
+ type: authority,
29
+ };
30
+ });
31
+ return this.generateAuditResult({
32
+ score,
33
+ displayValue: hasSameAs ? `${sameAsUrls.length} enlace(s) sameAs encontrados` : 'Sin enlaces sameAs',
34
+ details: hasSameAs
35
+ ? this.makeTableDetails([
36
+ { key: 'url', label: 'URL sameAs', valueType: 'url' },
37
+ { key: 'type', label: 'Tipo de Entidad', valueType: 'text' },
38
+ ], tableItems)
39
+ : undefined,
40
+ });
41
+ }
42
+ }
43
+ //# sourceMappingURL=entity-sameas-links.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entity-sameas-links.js","sourceRoot":"","sources":["../../../src/audits/structured-data/entity-sameas-links.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAGpC,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IACxC,MAAM,CAAU,IAAI,GAAc;QACvC,EAAE,EAAE,qBAAqB;QACzB,KAAK,EAAE,6EAA6E;QACpF,YAAY,EAAE,6DAA6D;QAC3E,WAAW,EACT,iLAAiL;QACnL,iBAAiB,EAAE,CAAC,QAAQ,CAAC;KAC9B,CAAC;IAEK,MAAM,CAAU,KAAK,CAAC,KAAK,CAAC,SAAoB;QACrD,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC;QAChC,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;QAErC,MAAM,SAAS,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC;QACxC,MAAM,KAAK,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;QAElC,MAAM,UAAU,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;YACxC,IAAI,SAAS,GAAG,6BAA6B,CAAC;YAC9C,IAAI,GAAG,CAAC,QAAQ,CAAC,cAAc,CAAC;gBAAE,SAAS,GAAG,2BAA2B,CAAC;iBACrE,IAAI,GAAG,CAAC,QAAQ,CAAC,eAAe,CAAC;gBAAE,SAAS,GAAG,4BAA4B,CAAC;iBAC5E,IAAI,GAAG,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC;gBAAE,SAAS,GAAG,oBAAoB,CAAC;YAEhI,OAAO;gBACL,GAAG;gBACH,IAAI,EAAE,SAAS;aAChB,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC,mBAAmB,CAAC;YAC9B,KAAK;YACL,YAAY,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,MAAM,+BAA+B,CAAC,CAAC,CAAC,oBAAoB;YACpG,OAAO,EAAE,SAAS;gBAChB,CAAC,CAAC,IAAI,CAAC,gBAAgB,CACnB;oBACE,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,KAAK,EAAE;oBACrD,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,EAAE;iBAC7D,EACD,UAAU,CACX;gBACH,CAAC,CAAC,SAAS;SACd,CAAC,CAAC;IACL,CAAC"}