@answerable-kit/audit 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 (162) hide show
  1. package/README.md +58 -0
  2. package/dist/checks/a1-title.d.ts +2 -0
  3. package/dist/checks/a1-title.d.ts.map +1 -0
  4. package/dist/checks/a1-title.js +34 -0
  5. package/dist/checks/a1-title.js.map +1 -0
  6. package/dist/checks/a10-apple-touch.d.ts +2 -0
  7. package/dist/checks/a10-apple-touch.d.ts.map +1 -0
  8. package/dist/checks/a10-apple-touch.js +21 -0
  9. package/dist/checks/a10-apple-touch.js.map +1 -0
  10. package/dist/checks/a3-description.d.ts +2 -0
  11. package/dist/checks/a3-description.d.ts.map +1 -0
  12. package/dist/checks/a3-description.js +34 -0
  13. package/dist/checks/a3-description.js.map +1 -0
  14. package/dist/checks/a4-canonical.d.ts +2 -0
  15. package/dist/checks/a4-canonical.d.ts.map +1 -0
  16. package/dist/checks/a4-canonical.js +32 -0
  17. package/dist/checks/a4-canonical.js.map +1 -0
  18. package/dist/checks/a5-html-lang.d.ts +2 -0
  19. package/dist/checks/a5-html-lang.d.ts.map +1 -0
  20. package/dist/checks/a5-html-lang.js +38 -0
  21. package/dist/checks/a5-html-lang.js.map +1 -0
  22. package/dist/checks/a6-viewport.d.ts +2 -0
  23. package/dist/checks/a6-viewport.d.ts.map +1 -0
  24. package/dist/checks/a6-viewport.js +30 -0
  25. package/dist/checks/a6-viewport.js.map +1 -0
  26. package/dist/checks/a7-charset.d.ts +2 -0
  27. package/dist/checks/a7-charset.d.ts.map +1 -0
  28. package/dist/checks/a7-charset.js +32 -0
  29. package/dist/checks/a7-charset.js.map +1 -0
  30. package/dist/checks/a8-robots.d.ts +2 -0
  31. package/dist/checks/a8-robots.d.ts.map +1 -0
  32. package/dist/checks/a8-robots.js +46 -0
  33. package/dist/checks/a8-robots.js.map +1 -0
  34. package/dist/checks/a9-favicon.d.ts +2 -0
  35. package/dist/checks/a9-favicon.d.ts.map +1 -0
  36. package/dist/checks/a9-favicon.js +28 -0
  37. package/dist/checks/a9-favicon.js.map +1 -0
  38. package/dist/checks/b1-single-h1.d.ts +2 -0
  39. package/dist/checks/b1-single-h1.d.ts.map +1 -0
  40. package/dist/checks/b1-single-h1.js +32 -0
  41. package/dist/checks/b1-single-h1.js.map +1 -0
  42. package/dist/checks/b11-internal-links.d.ts +2 -0
  43. package/dist/checks/b11-internal-links.d.ts.map +1 -0
  44. package/dist/checks/b11-internal-links.js +30 -0
  45. package/dist/checks/b11-internal-links.js.map +1 -0
  46. package/dist/checks/b14-lists-or-tables.d.ts +2 -0
  47. package/dist/checks/b14-lists-or-tables.d.ts.map +1 -0
  48. package/dist/checks/b14-lists-or-tables.js +26 -0
  49. package/dist/checks/b14-lists-or-tables.js.map +1 -0
  50. package/dist/checks/b3-heading-hierarchy.d.ts +2 -0
  51. package/dist/checks/b3-heading-hierarchy.d.ts.map +1 -0
  52. package/dist/checks/b3-heading-hierarchy.js +36 -0
  53. package/dist/checks/b3-heading-hierarchy.js.map +1 -0
  54. package/dist/checks/b4-h2-sections.d.ts +2 -0
  55. package/dist/checks/b4-h2-sections.d.ts.map +1 -0
  56. package/dist/checks/b4-h2-sections.js +32 -0
  57. package/dist/checks/b4-h2-sections.js.map +1 -0
  58. package/dist/checks/b8-external-citations.d.ts +2 -0
  59. package/dist/checks/b8-external-citations.d.ts.map +1 -0
  60. package/dist/checks/b8-external-citations.js +41 -0
  61. package/dist/checks/b8-external-citations.js.map +1 -0
  62. package/dist/checks/c1-json-ld.d.ts +2 -0
  63. package/dist/checks/c1-json-ld.d.ts.map +1 -0
  64. package/dist/checks/c1-json-ld.js +69 -0
  65. package/dist/checks/c1-json-ld.js.map +1 -0
  66. package/dist/checks/c2-organization.d.ts +2 -0
  67. package/dist/checks/c2-organization.d.ts.map +1 -0
  68. package/dist/checks/c2-organization.js +67 -0
  69. package/dist/checks/c2-organization.js.map +1 -0
  70. package/dist/checks/d1-about-page-linked.d.ts +2 -0
  71. package/dist/checks/d1-about-page-linked.d.ts.map +1 -0
  72. package/dist/checks/d1-about-page-linked.js +24 -0
  73. package/dist/checks/d1-about-page-linked.js.map +1 -0
  74. package/dist/checks/d2-privacy-linked.d.ts +2 -0
  75. package/dist/checks/d2-privacy-linked.d.ts.map +1 -0
  76. package/dist/checks/d2-privacy-linked.js +24 -0
  77. package/dist/checks/d2-privacy-linked.js.map +1 -0
  78. package/dist/checks/d3-terms-linked.d.ts +2 -0
  79. package/dist/checks/d3-terms-linked.d.ts.map +1 -0
  80. package/dist/checks/d3-terms-linked.js +24 -0
  81. package/dist/checks/d3-terms-linked.js.map +1 -0
  82. package/dist/checks/d4-contact-accessible.d.ts +2 -0
  83. package/dist/checks/d4-contact-accessible.d.ts.map +1 -0
  84. package/dist/checks/d4-contact-accessible.js +30 -0
  85. package/dist/checks/d4-contact-accessible.js.map +1 -0
  86. package/dist/checks/d5-chrome-trust-link.d.ts +2 -0
  87. package/dist/checks/d5-chrome-trust-link.d.ts.map +1 -0
  88. package/dist/checks/d5-chrome-trust-link.js +24 -0
  89. package/dist/checks/d5-chrome-trust-link.js.map +1 -0
  90. package/dist/checks/d6-footer-trust-links.d.ts +2 -0
  91. package/dist/checks/d6-footer-trust-links.d.ts.map +1 -0
  92. package/dist/checks/d6-footer-trust-links.js +49 -0
  93. package/dist/checks/d6-footer-trust-links.js.map +1 -0
  94. package/dist/checks/e1-review-profile.d.ts +2 -0
  95. package/dist/checks/e1-review-profile.d.ts.map +1 -0
  96. package/dist/checks/e1-review-profile.js +38 -0
  97. package/dist/checks/e1-review-profile.js.map +1 -0
  98. package/dist/checks/e10-same-as-three.d.ts +2 -0
  99. package/dist/checks/e10-same-as-three.d.ts.map +1 -0
  100. package/dist/checks/e10-same-as-three.js +81 -0
  101. package/dist/checks/e10-same-as-three.js.map +1 -0
  102. package/dist/checks/e11-linkedin-linked.d.ts +2 -0
  103. package/dist/checks/e11-linkedin-linked.d.ts.map +1 -0
  104. package/dist/checks/e11-linkedin-linked.js +24 -0
  105. package/dist/checks/e11-linkedin-linked.js.map +1 -0
  106. package/dist/checks/e7-github-linked.d.ts +2 -0
  107. package/dist/checks/e7-github-linked.d.ts.map +1 -0
  108. package/dist/checks/e7-github-linked.js +24 -0
  109. package/dist/checks/e7-github-linked.js.map +1 -0
  110. package/dist/checks/f1-og-title.d.ts +2 -0
  111. package/dist/checks/f1-og-title.d.ts.map +1 -0
  112. package/dist/checks/f1-og-title.js +21 -0
  113. package/dist/checks/f1-og-title.js.map +1 -0
  114. package/dist/checks/f2-og-description.d.ts +2 -0
  115. package/dist/checks/f2-og-description.d.ts.map +1 -0
  116. package/dist/checks/f2-og-description.js +21 -0
  117. package/dist/checks/f2-og-description.js.map +1 -0
  118. package/dist/checks/f3-og-image.d.ts +2 -0
  119. package/dist/checks/f3-og-image.d.ts.map +1 -0
  120. package/dist/checks/f3-og-image.js +28 -0
  121. package/dist/checks/f3-og-image.js.map +1 -0
  122. package/dist/checks/f5-og-url.d.ts +2 -0
  123. package/dist/checks/f5-og-url.d.ts.map +1 -0
  124. package/dist/checks/f5-og-url.js +28 -0
  125. package/dist/checks/f5-og-url.js.map +1 -0
  126. package/dist/checks/f6-twitter-card.d.ts +2 -0
  127. package/dist/checks/f6-twitter-card.d.ts.map +1 -0
  128. package/dist/checks/f6-twitter-card.js +29 -0
  129. package/dist/checks/f6-twitter-card.js.map +1 -0
  130. package/dist/checks/f7-twitter-image.d.ts +2 -0
  131. package/dist/checks/f7-twitter-image.d.ts.map +1 -0
  132. package/dist/checks/f7-twitter-image.js +33 -0
  133. package/dist/checks/f7-twitter-image.js.map +1 -0
  134. package/dist/checks/registry.d.ts +10 -0
  135. package/dist/checks/registry.d.ts.map +1 -0
  136. package/dist/checks/registry.js +75 -0
  137. package/dist/checks/registry.js.map +1 -0
  138. package/dist/crawler.d.ts +40 -0
  139. package/dist/crawler.d.ts.map +1 -0
  140. package/dist/crawler.js +66 -0
  141. package/dist/crawler.js.map +1 -0
  142. package/dist/index.d.ts +48 -0
  143. package/dist/index.d.ts.map +1 -0
  144. package/dist/index.js +47 -0
  145. package/dist/index.js.map +1 -0
  146. package/dist/parser.d.ts +15 -0
  147. package/dist/parser.d.ts.map +1 -0
  148. package/dist/parser.js +10 -0
  149. package/dist/parser.js.map +1 -0
  150. package/dist/reporters/console.d.ts +12 -0
  151. package/dist/reporters/console.d.ts.map +1 -0
  152. package/dist/reporters/console.js +110 -0
  153. package/dist/reporters/console.js.map +1 -0
  154. package/dist/runner.d.ts +35 -0
  155. package/dist/runner.d.ts.map +1 -0
  156. package/dist/runner.js +120 -0
  157. package/dist/runner.js.map +1 -0
  158. package/dist/types.d.ts +52 -0
  159. package/dist/types.d.ts.map +1 -0
  160. package/dist/types.js +2 -0
  161. package/dist/types.js.map +1 -0
  162. package/package.json +48 -0
@@ -0,0 +1,66 @@
1
+ import { AnswerableError, parseAbsoluteUrl } from '@answerable-kit/core';
2
+ import { loadHtml } from './parser.js';
3
+ export const DEFAULT_USER_AGENT = 'Answerable/0.0.0 (+https://github.com/Anuj7411/answerable)';
4
+ export const DEFAULT_TIMEOUT_MS = 15_000;
5
+ /**
6
+ * Thrown when the crawler can't reach the target URL or the response
7
+ * isn't a 2xx with HTML-shaped content.
8
+ */
9
+ export class CrawlError extends AnswerableError {
10
+ url;
11
+ httpStatus;
12
+ constructor(message, options) {
13
+ super('ANSWERABLE_CRAWL_FAILED', message, { cause: options.cause });
14
+ this.url = options.url;
15
+ this.httpStatus = options.status;
16
+ this.name = 'CrawlError';
17
+ }
18
+ }
19
+ /**
20
+ * Fetch a URL and parse the response into a cheerio DOM. Follows
21
+ * redirects (delegated to native fetch). Sets a polite User-Agent.
22
+ * Throws `CrawlError` on network failure or non-2xx response.
23
+ *
24
+ * @throws InvalidUrlError if `url` is not a valid absolute http(s) URL.
25
+ * @throws CrawlError on network failure, timeout, or non-2xx response.
26
+ */
27
+ export async function fetchAndParse(url, options = {}) {
28
+ const target = parseAbsoluteUrl(url);
29
+ const userAgent = options.userAgent ?? DEFAULT_USER_AGENT;
30
+ const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
31
+ const fetchImpl = options.fetchImpl ?? fetch;
32
+ const controller = new AbortController();
33
+ const timeoutHandle = setTimeout(() => controller.abort(), timeoutMs);
34
+ let response;
35
+ try {
36
+ response = await fetchImpl(target, {
37
+ headers: {
38
+ 'User-Agent': userAgent,
39
+ Accept: 'text/html,application/xhtml+xml',
40
+ },
41
+ redirect: 'follow',
42
+ signal: controller.signal,
43
+ });
44
+ }
45
+ catch (cause) {
46
+ throw new CrawlError(`Failed to fetch ${target}`, { url: target, cause });
47
+ }
48
+ finally {
49
+ clearTimeout(timeoutHandle);
50
+ }
51
+ if (!response.ok) {
52
+ throw new CrawlError(`Request to ${target} returned HTTP ${response.status}`, {
53
+ url: target,
54
+ status: response.status,
55
+ });
56
+ }
57
+ const html = await response.text();
58
+ return {
59
+ url: target,
60
+ finalUrl: response.url || target,
61
+ status: response.status,
62
+ html,
63
+ dom: loadHtml(html),
64
+ };
65
+ }
66
+ //# sourceMappingURL=crawler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crawler.js","sourceRoot":"","sources":["../src/crawler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACzE,OAAO,EAAiB,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEtD,MAAM,CAAC,MAAM,kBAAkB,GAAG,4DAA4D,CAAC;AAE/F,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAiBzC;;;GAGG;AACH,MAAM,OAAO,UAAW,SAAQ,eAAe;IACpC,GAAG,CAAS;IACZ,UAAU,CAAqB;IAExC,YACE,OAAe,EACf,OAAqF;QAErF,KAAK,CAAC,yBAAyB,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QACpE,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;QACvB,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;QACjC,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;IAC3B,CAAC;CACF;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,GAAW,EACX,UAAgC,EAAE;IAElC,MAAM,MAAM,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC;IACrC,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,kBAAkB,CAAC;IAC1D,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,kBAAkB,CAAC;IAC1D,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC;IAE7C,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,aAAa,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,SAAS,CAAC,CAAC;IAEtE,IAAI,QAAkB,CAAC;IACvB,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,SAAS,CAAC,MAAM,EAAE;YACjC,OAAO,EAAE;gBACP,YAAY,EAAE,SAAS;gBACvB,MAAM,EAAE,iCAAiC;aAC1C;YACD,QAAQ,EAAE,QAAQ;YAClB,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,UAAU,CAAC,mBAAmB,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAC5E,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,aAAa,CAAC,CAAC;IAC9B,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,UAAU,CAAC,cAAc,MAAM,kBAAkB,QAAQ,CAAC,MAAM,EAAE,EAAE;YAC5E,GAAG,EAAE,MAAM;YACX,MAAM,EAAE,QAAQ,CAAC,MAAM;SACxB,CAAC,CAAC;IACL,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IACnC,OAAO;QACL,GAAG,EAAE,MAAM;QACX,QAAQ,EAAE,QAAQ,CAAC,GAAG,IAAI,MAAM;QAChC,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,IAAI;QACJ,GAAG,EAAE,QAAQ,CAAC,IAAI,CAAC;KACpB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * @answerable-kit/audit — audit engine for the Answerable SEO toolkit.
3
+ * Fetches a target URL, parses HTML, runs every registered check in
4
+ * parallel, and returns a structured report. Ships with foundations
5
+ * + the first 5 checks (A1, A3, A4, A5, C1); the remaining 45 land
6
+ * in subsequent PRs.
7
+ */
8
+ export declare const VERSION = "0.0.0";
9
+ export { CrawlError, DEFAULT_TIMEOUT_MS, DEFAULT_USER_AGENT, fetchAndParse, type FetchAndParseOptions, type FetchAndParseResult, } from './crawler.js';
10
+ export { type AuditDom, loadHtml } from './parser.js';
11
+ export { DEFAULT_CHECKS } from './checks/registry.js';
12
+ export { audit, bandFromScore, runChecks, type AuditConvenienceOptions, type RunChecksInput, } from './runner.js';
13
+ export { consoleReport, type ConsoleReportOptions } from './reporters/console.js';
14
+ export type { AuditOptions, AuditReport, CheckRunResult, ScoreBand } from './types.js';
15
+ export { a1Title } from './checks/a1-title.js';
16
+ export { a3Description } from './checks/a3-description.js';
17
+ export { a4Canonical } from './checks/a4-canonical.js';
18
+ export { a5HtmlLang } from './checks/a5-html-lang.js';
19
+ export { a6Viewport } from './checks/a6-viewport.js';
20
+ export { a7Charset } from './checks/a7-charset.js';
21
+ export { a8Robots } from './checks/a8-robots.js';
22
+ export { a9Favicon } from './checks/a9-favicon.js';
23
+ export { a10AppleTouchIcon } from './checks/a10-apple-touch.js';
24
+ export { b1SingleH1 } from './checks/b1-single-h1.js';
25
+ export { b3HeadingHierarchy } from './checks/b3-heading-hierarchy.js';
26
+ export { b4H2Sections } from './checks/b4-h2-sections.js';
27
+ export { b8ExternalCitations } from './checks/b8-external-citations.js';
28
+ export { b11InternalLinks } from './checks/b11-internal-links.js';
29
+ export { b14ListsOrTables } from './checks/b14-lists-or-tables.js';
30
+ export { c1JsonLd } from './checks/c1-json-ld.js';
31
+ export { c2Organization } from './checks/c2-organization.js';
32
+ export { d1AboutPageLinked } from './checks/d1-about-page-linked.js';
33
+ export { d2PrivacyLinked } from './checks/d2-privacy-linked.js';
34
+ export { d3TermsLinked } from './checks/d3-terms-linked.js';
35
+ export { d4ContactAccessible } from './checks/d4-contact-accessible.js';
36
+ export { d5ChromeTrustLink } from './checks/d5-chrome-trust-link.js';
37
+ export { d6FooterTrustLinks } from './checks/d6-footer-trust-links.js';
38
+ export { e1ReviewProfile } from './checks/e1-review-profile.js';
39
+ export { e7GithubLinked } from './checks/e7-github-linked.js';
40
+ export { e10SameAsThree } from './checks/e10-same-as-three.js';
41
+ export { e11LinkedinLinked } from './checks/e11-linkedin-linked.js';
42
+ export { f1OgTitle } from './checks/f1-og-title.js';
43
+ export { f2OgDescription } from './checks/f2-og-description.js';
44
+ export { f3OgImage } from './checks/f3-og-image.js';
45
+ export { f5OgUrl } from './checks/f5-og-url.js';
46
+ export { f6TwitterCard } from './checks/f6-twitter-card.js';
47
+ export { f7TwitterImage } from './checks/f7-twitter-image.js';
48
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,eAAO,MAAM,OAAO,UAAU,CAAC;AAE/B,OAAO,EACL,UAAU,EACV,kBAAkB,EAClB,kBAAkB,EAClB,aAAa,EACb,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,GACzB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,KAAK,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEtD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,EACL,KAAK,EACL,aAAa,EACb,SAAS,EACT,KAAK,uBAAuB,EAC5B,KAAK,cAAc,GACpB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,aAAa,EAAE,KAAK,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAElF,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvF,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,47 @@
1
+ /**
2
+ * @answerable-kit/audit — audit engine for the Answerable SEO toolkit.
3
+ * Fetches a target URL, parses HTML, runs every registered check in
4
+ * parallel, and returns a structured report. Ships with foundations
5
+ * + the first 5 checks (A1, A3, A4, A5, C1); the remaining 45 land
6
+ * in subsequent PRs.
7
+ */
8
+ export const VERSION = '0.0.0';
9
+ export { CrawlError, DEFAULT_TIMEOUT_MS, DEFAULT_USER_AGENT, fetchAndParse, } from './crawler.js';
10
+ export { loadHtml } from './parser.js';
11
+ export { DEFAULT_CHECKS } from './checks/registry.js';
12
+ export { audit, bandFromScore, runChecks, } from './runner.js';
13
+ export { consoleReport } from './reporters/console.js';
14
+ export { a1Title } from './checks/a1-title.js';
15
+ export { a3Description } from './checks/a3-description.js';
16
+ export { a4Canonical } from './checks/a4-canonical.js';
17
+ export { a5HtmlLang } from './checks/a5-html-lang.js';
18
+ export { a6Viewport } from './checks/a6-viewport.js';
19
+ export { a7Charset } from './checks/a7-charset.js';
20
+ export { a8Robots } from './checks/a8-robots.js';
21
+ export { a9Favicon } from './checks/a9-favicon.js';
22
+ export { a10AppleTouchIcon } from './checks/a10-apple-touch.js';
23
+ export { b1SingleH1 } from './checks/b1-single-h1.js';
24
+ export { b3HeadingHierarchy } from './checks/b3-heading-hierarchy.js';
25
+ export { b4H2Sections } from './checks/b4-h2-sections.js';
26
+ export { b8ExternalCitations } from './checks/b8-external-citations.js';
27
+ export { b11InternalLinks } from './checks/b11-internal-links.js';
28
+ export { b14ListsOrTables } from './checks/b14-lists-or-tables.js';
29
+ export { c1JsonLd } from './checks/c1-json-ld.js';
30
+ export { c2Organization } from './checks/c2-organization.js';
31
+ export { d1AboutPageLinked } from './checks/d1-about-page-linked.js';
32
+ export { d2PrivacyLinked } from './checks/d2-privacy-linked.js';
33
+ export { d3TermsLinked } from './checks/d3-terms-linked.js';
34
+ export { d4ContactAccessible } from './checks/d4-contact-accessible.js';
35
+ export { d5ChromeTrustLink } from './checks/d5-chrome-trust-link.js';
36
+ export { d6FooterTrustLinks } from './checks/d6-footer-trust-links.js';
37
+ export { e1ReviewProfile } from './checks/e1-review-profile.js';
38
+ export { e7GithubLinked } from './checks/e7-github-linked.js';
39
+ export { e10SameAsThree } from './checks/e10-same-as-three.js';
40
+ export { e11LinkedinLinked } from './checks/e11-linkedin-linked.js';
41
+ export { f1OgTitle } from './checks/f1-og-title.js';
42
+ export { f2OgDescription } from './checks/f2-og-description.js';
43
+ export { f3OgImage } from './checks/f3-og-image.js';
44
+ export { f5OgUrl } from './checks/f5-og-url.js';
45
+ export { f6TwitterCard } from './checks/f6-twitter-card.js';
46
+ export { f7TwitterImage } from './checks/f7-twitter-image.js';
47
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAE/B,OAAO,EACL,UAAU,EACV,kBAAkB,EAClB,kBAAkB,EAClB,aAAa,GAGd,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAiB,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEtD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,EACL,KAAK,EACL,aAAa,EACb,SAAS,GAGV,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,aAAa,EAA6B,MAAM,wBAAwB,CAAC;AAIlF,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { type CheerioAPI } from 'cheerio';
2
+ /**
3
+ * Parser handle for every check. Re-exporting cheerio's `CheerioAPI`
4
+ * type means consumers of this package can write their own checks
5
+ * without depending on cheerio directly (they pick up the type from
6
+ * `@answerable-kit/audit`).
7
+ */
8
+ export type AuditDom = CheerioAPI;
9
+ /**
10
+ * Parse raw HTML into the DOM handle every check receives.
11
+ * Thin wrapper around `cheerio.load` so we can swap parsers later
12
+ * without touching every call site.
13
+ */
14
+ export declare function loadHtml(html: string): AuditDom;
15
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAQ,MAAM,SAAS,CAAC;AAEhD;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,GAAG,UAAU,CAAC;AAElC;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAE/C"}
package/dist/parser.js ADDED
@@ -0,0 +1,10 @@
1
+ import { load } from 'cheerio';
2
+ /**
3
+ * Parse raw HTML into the DOM handle every check receives.
4
+ * Thin wrapper around `cheerio.load` so we can swap parsers later
5
+ * without touching every call site.
6
+ */
7
+ export function loadHtml(html) {
8
+ return load(html);
9
+ }
10
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,IAAI,EAAE,MAAM,SAAS,CAAC;AAUhD;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC;AACpB,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { AuditReport } from '../types.js';
2
+ export interface ConsoleReportOptions {
3
+ /** Suppress ANSI color escapes (for testing or non-TTY pipelines). */
4
+ readonly color?: boolean;
5
+ }
6
+ /**
7
+ * Render an `AuditReport` as a human-readable, terminal-friendly string.
8
+ * Groups failures by severity descending, then lists every passing
9
+ * check at the bottom for confidence.
10
+ */
11
+ export declare function consoleReport(report: AuditReport, options?: ConsoleReportOptions): string;
12
+ //# sourceMappingURL=console.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../../src/reporters/console.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAA6B,MAAM,aAAa,CAAC;AAmB1E,MAAM,WAAW,oBAAoB;IACnC,sEAAsE;IACtE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,GAAE,oBAAyB,GAAG,MAAM,CAmD7F"}
@@ -0,0 +1,110 @@
1
+ import kleur from 'kleur';
2
+ const SEVERITY_ORDER = ['critical', 'high', 'medium', 'low'];
3
+ const SEVERITY_LABEL = {
4
+ critical: 'CRITICAL',
5
+ high: 'HIGH',
6
+ medium: 'MEDIUM',
7
+ low: 'LOW',
8
+ };
9
+ const BAND_LABEL = {
10
+ critical: 'Critical',
11
+ weak: 'Weak',
12
+ average: 'Average',
13
+ strong: 'Strong',
14
+ excellent: 'Excellent',
15
+ };
16
+ /**
17
+ * Render an `AuditReport` as a human-readable, terminal-friendly string.
18
+ * Groups failures by severity descending, then lists every passing
19
+ * check at the bottom for confidence.
20
+ */
21
+ export function consoleReport(report, options = {}) {
22
+ const enableColor = options.color ?? true;
23
+ const c = enableColor ? kleur : disableKleur();
24
+ const failures = report.results.filter((r) => r.status === 'fail' || r.status === 'warn');
25
+ const skips = report.results.filter((r) => r.status === 'skip');
26
+ const passes = report.results.filter((r) => r.status === 'pass');
27
+ const lines = [];
28
+ lines.push(c.bold(`Audit · ${report.url}`));
29
+ lines.push(`Fetched ${report.fetchedAt}`);
30
+ lines.push('');
31
+ lines.push(`${c.bold('Score:')} ${scoreColor(c, report.score)(`${report.score}/100`)} ${c.dim(`(${BAND_LABEL[report.band]})`)}`);
32
+ lines.push(c.dim(`${report.summary.pass} pass · ${report.summary.fail} fail · ${report.summary.warn} warn · ${report.summary.skip} skip`));
33
+ // Failures + warnings grouped by severity.
34
+ for (const sev of SEVERITY_ORDER) {
35
+ const inGroup = failures.filter((r) => r.severity === sev);
36
+ if (inGroup.length === 0)
37
+ continue;
38
+ lines.push('');
39
+ lines.push(c.bold(severityColor(c, sev)(`[${SEVERITY_LABEL[sev]}] ${inGroup.length} issue(s)`)));
40
+ for (const r of inGroup) {
41
+ lines.push(...formatFinding(c, r));
42
+ }
43
+ }
44
+ if (skips.length > 0) {
45
+ lines.push('');
46
+ lines.push(c.bold(c.gray(`[SKIPPED] ${skips.length}`)));
47
+ for (const r of skips) {
48
+ lines.push(c.gray(` ${r.id} · ${r.description}${r.error ? ` — ${r.error}` : ''}`));
49
+ }
50
+ }
51
+ if (passes.length > 0) {
52
+ lines.push('');
53
+ lines.push(c.bold(c.green(`[PASSED] ${passes.length}`)));
54
+ for (const r of passes) {
55
+ lines.push(c.dim(` ${r.id} · ${r.description}`));
56
+ }
57
+ }
58
+ return lines.join('\n');
59
+ }
60
+ function formatFinding(c, r) {
61
+ const lines = [` ${c.bold(r.id)} · ${r.description}`];
62
+ if (r.evidence !== undefined) {
63
+ lines.push(c.dim(` ${truncate(r.evidence, 200)}`));
64
+ }
65
+ if (r.fixRecommendation !== undefined) {
66
+ lines.push(` ${c.cyan('Fix:')} ${truncate(r.fixRecommendation, 200)}`);
67
+ }
68
+ lines.push(c.dim(` ${r.docsUrl}`));
69
+ return lines;
70
+ }
71
+ function severityColor(c, severity) {
72
+ switch (severity) {
73
+ case 'critical':
74
+ return c.red;
75
+ case 'high':
76
+ return c.yellow;
77
+ case 'medium':
78
+ return c.blue;
79
+ case 'low':
80
+ return c.gray;
81
+ }
82
+ }
83
+ function scoreColor(c, score) {
84
+ if (score >= 81)
85
+ return c.green;
86
+ if (score >= 61)
87
+ return c.yellow;
88
+ if (score >= 41)
89
+ return c.magenta;
90
+ return c.red;
91
+ }
92
+ function truncate(s, max) {
93
+ if (s.length <= max)
94
+ return s;
95
+ return `${s.slice(0, max - 1)}…`;
96
+ }
97
+ /**
98
+ * Returns a no-op shim with the same shape as kleur so we can pass it
99
+ * through the formatter when color is disabled.
100
+ */
101
+ function disableKleur() {
102
+ const identity = (s) => String(s);
103
+ const colors = ['red', 'yellow', 'blue', 'gray', 'green', 'magenta', 'cyan', 'bold', 'dim'];
104
+ const shim = identity;
105
+ for (const name of colors) {
106
+ shim[name] = identity;
107
+ }
108
+ return shim;
109
+ }
110
+ //# sourceMappingURL=console.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"console.js","sourceRoot":"","sources":["../../src/reporters/console.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import type { AbsoluteUrl, Check } from '@answerable-kit/core';
2
+ import { type FetchAndParseOptions } from './crawler.js';
3
+ import { type AuditDom } from './parser.js';
4
+ import type { AuditReport, ScoreBand } from './types.js';
5
+ export interface RunChecksInput {
6
+ readonly url: AbsoluteUrl;
7
+ readonly html: string;
8
+ readonly dom: AuditDom;
9
+ /** Override the default check set. Defaults to every registered check. */
10
+ readonly checks?: readonly Check<AuditDom>[];
11
+ }
12
+ /**
13
+ * Pure runner: takes pre-parsed input and returns the report.
14
+ * No network. Tests use this exclusively so CI never hits live URLs.
15
+ *
16
+ * Each check runs in parallel via `Promise.all`. A thrown check is
17
+ * captured and recorded as a `skip` with the error message — the
18
+ * audit always completes.
19
+ */
20
+ export declare function runChecks(input: RunChecksInput): Promise<AuditReport>;
21
+ /**
22
+ * Map an integer score to its AUDIT-FRAMEWORK band.
23
+ * 0-40 critical · 41-60 weak · 61-80 average · 81-90 strong · 91-100 excellent
24
+ */
25
+ export declare function bandFromScore(score: number): ScoreBand;
26
+ export interface AuditConvenienceOptions extends FetchAndParseOptions {
27
+ readonly checks?: readonly Check<AuditDom>[];
28
+ }
29
+ /**
30
+ * Convenience wrapper: fetches the target URL and runs the audit.
31
+ * Real-world callers use this; tests use `runChecks` directly with
32
+ * fixture HTML.
33
+ */
34
+ export declare function audit(url: string, options?: AuditConvenienceOptions): Promise<AuditReport>;
35
+ //# sourceMappingURL=runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,KAAK,EAAe,MAAM,sBAAsB,CAAC;AAG5E,OAAO,EAAE,KAAK,oBAAoB,EAAiB,MAAM,cAAc,CAAC;AACxE,OAAO,EAAE,KAAK,QAAQ,EAAY,MAAM,aAAa,CAAC;AACtD,OAAO,KAAK,EAAE,WAAW,EAAkB,SAAS,EAAE,MAAM,YAAY,CAAC;AAEzE,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC;IACvB,0EAA0E;IAC1E,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;CAC9C;AAED;;;;;;;GAOG;AACH,wBAAsB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC,CA2C3E;AAuCD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAMtD;AAED,MAAM,WAAW,uBAAwB,SAAQ,oBAAoB;IACnE,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;CAC9C;AAED;;;;GAIG;AACH,wBAAsB,KAAK,CACzB,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,uBAA4B,GACpC,OAAO,CAAC,WAAW,CAAC,CAUtB"}
package/dist/runner.js ADDED
@@ -0,0 +1,120 @@
1
+ import { parseAbsoluteUrl } from '@answerable-kit/core';
2
+ import { DEFAULT_CHECKS } from './checks/registry.js';
3
+ import { fetchAndParse } from './crawler.js';
4
+ import { loadHtml } from './parser.js';
5
+ /**
6
+ * Pure runner: takes pre-parsed input and returns the report.
7
+ * No network. Tests use this exclusively so CI never hits live URLs.
8
+ *
9
+ * Each check runs in parallel via `Promise.all`. A thrown check is
10
+ * captured and recorded as a `skip` with the error message — the
11
+ * audit always completes.
12
+ */
13
+ export async function runChecks(input) {
14
+ const checks = input.checks ?? DEFAULT_CHECKS;
15
+ const fetchedAt = new Date().toISOString();
16
+ const results = await Promise.all(checks.map(async (check) => {
17
+ try {
18
+ const result = await check.run({ url: input.url, html: input.html, dom: input.dom });
19
+ return buildResult(check, result);
20
+ }
21
+ catch (err) {
22
+ const message = err instanceof Error ? err.message : String(err);
23
+ return {
24
+ id: check.id,
25
+ category: check.category,
26
+ severity: check.severity,
27
+ description: check.description,
28
+ maxPoints: check.points,
29
+ earnedPoints: 0,
30
+ status: 'skip',
31
+ docsUrl: check.docsUrl,
32
+ error: message,
33
+ };
34
+ }
35
+ }));
36
+ const summary = {
37
+ pass: results.filter((r) => r.status === 'pass').length,
38
+ fail: results.filter((r) => r.status === 'fail').length,
39
+ warn: results.filter((r) => r.status === 'warn').length,
40
+ skip: results.filter((r) => r.status === 'skip').length,
41
+ };
42
+ const score = computeScore(results);
43
+ return {
44
+ url: input.url,
45
+ fetchedAt,
46
+ results,
47
+ score,
48
+ band: bandFromScore(score),
49
+ summary,
50
+ };
51
+ }
52
+ function buildResult(check, result) {
53
+ const earnedPoints = result.status === 'pass' ? check.points : 0;
54
+ const out = {
55
+ id: check.id,
56
+ category: check.category,
57
+ severity: check.severity,
58
+ description: check.description,
59
+ maxPoints: check.points,
60
+ earnedPoints,
61
+ status: result.status,
62
+ docsUrl: check.docsUrl,
63
+ };
64
+ return result.evidence !== undefined || result.fixRecommendation !== undefined
65
+ ? {
66
+ ...out,
67
+ ...(result.evidence !== undefined && { evidence: result.evidence }),
68
+ ...(result.fixRecommendation !== undefined && {
69
+ fixRecommendation: result.fixRecommendation,
70
+ }),
71
+ }
72
+ : out;
73
+ }
74
+ /**
75
+ * Compute the integer score against the *checks that actually ran*
76
+ * (excluding skips). Lets category-filtered audits score on their
77
+ * own denominator rather than always against 100.
78
+ */
79
+ function computeScore(results) {
80
+ const consideredResults = results.filter((r) => r.status !== 'skip');
81
+ if (consideredResults.length === 0)
82
+ return 0;
83
+ const maxPossible = consideredResults.reduce((sum, r) => sum + r.maxPoints, 0);
84
+ if (maxPossible === 0)
85
+ return 0;
86
+ const earned = consideredResults.reduce((sum, r) => sum + r.earnedPoints, 0);
87
+ return Math.round((earned / maxPossible) * 100);
88
+ }
89
+ /**
90
+ * Map an integer score to its AUDIT-FRAMEWORK band.
91
+ * 0-40 critical · 41-60 weak · 61-80 average · 81-90 strong · 91-100 excellent
92
+ */
93
+ export function bandFromScore(score) {
94
+ if (score <= 40)
95
+ return 'critical';
96
+ if (score <= 60)
97
+ return 'weak';
98
+ if (score <= 80)
99
+ return 'average';
100
+ if (score <= 90)
101
+ return 'strong';
102
+ return 'excellent';
103
+ }
104
+ /**
105
+ * Convenience wrapper: fetches the target URL and runs the audit.
106
+ * Real-world callers use this; tests use `runChecks` directly with
107
+ * fixture HTML.
108
+ */
109
+ export async function audit(url, options = {}) {
110
+ const parsed = parseAbsoluteUrl(url);
111
+ const fetched = await fetchAndParse(parsed, options);
112
+ const dom = fetched.dom ?? loadHtml(fetched.html);
113
+ return runChecks({
114
+ url: parsed,
115
+ html: fetched.html,
116
+ dom,
117
+ ...(options.checks !== undefined && { checks: options.checks }),
118
+ });
119
+ }
120
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ import type { AbsoluteUrl, Category, Severity } from '@answerable-kit/core';
2
+ /**
3
+ * Outcome of a single check after the runner has resolved any errors
4
+ * and attached the check's static metadata.
5
+ */
6
+ export interface CheckRunResult {
7
+ readonly id: string;
8
+ readonly category: Category;
9
+ readonly severity: Severity;
10
+ readonly description: string;
11
+ /** Max points this check is worth toward the 100-point total. */
12
+ readonly maxPoints: number;
13
+ /** Points actually earned (full on `pass`, otherwise 0). */
14
+ readonly earnedPoints: number;
15
+ readonly status: 'pass' | 'fail' | 'warn' | 'skip';
16
+ readonly evidence?: string | undefined;
17
+ readonly fixRecommendation?: string | undefined;
18
+ readonly docsUrl: string;
19
+ /** Populated when the check itself threw — the runner caught it. */
20
+ readonly error?: string | undefined;
21
+ }
22
+ export type ScoreBand = 'critical' | 'weak' | 'average' | 'strong' | 'excellent';
23
+ /**
24
+ * Final audit report consumed by reporters and CI integrations.
25
+ *
26
+ * `score` is computed against the sum of `maxPoints` for the *checks
27
+ * that ran* — so partial-suite runs (e.g. category filters) score on
28
+ * their own denominator rather than always against 100.
29
+ */
30
+ export interface AuditReport {
31
+ readonly url: AbsoluteUrl;
32
+ readonly fetchedAt: string;
33
+ readonly results: readonly CheckRunResult[];
34
+ /** 0–100. Integer, rounded. */
35
+ readonly score: number;
36
+ readonly band: ScoreBand;
37
+ readonly summary: {
38
+ readonly pass: number;
39
+ readonly fail: number;
40
+ readonly warn: number;
41
+ readonly skip: number;
42
+ };
43
+ }
44
+ export interface AuditOptions {
45
+ /** Override the default check registry (e.g. category subsets). */
46
+ readonly checks?: readonly never[];
47
+ /** Override the default User-Agent header. Rarely useful. */
48
+ readonly userAgent?: string;
49
+ /** Hard timeout in milliseconds for the initial fetch. */
50
+ readonly timeoutMs?: number;
51
+ }
52
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAE5E;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,iEAAiE;IACjE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,4DAA4D;IAC5D,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IACnD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,oEAAoE;IACpE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACrC;AAED,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,WAAW,CAAC;AAEjF;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,SAAS,cAAc,EAAE,CAAC;IAC5C,+BAA+B;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE;QAChB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;KACvB,CAAC;CACH;AAED,MAAM,WAAW,YAAY;IAC3B,mEAAmE;IACnE,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,KAAK,EAAE,CAAC;IACnC,6DAA6D;IAC7D,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,0DAA0D;IAC1D,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@answerable-kit/audit",
3
+ "version": "0.1.0",
4
+ "description": "Audit engine for the Answerable SEO toolkit. Crawls a target URL, runs the 50-check framework, and reports findings with evidence + fix recommendations.",
5
+ "license": "MIT",
6
+ "author": "Anuj Ojha",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/Anuj7411/answerable.git",
10
+ "directory": "packages/audit"
11
+ },
12
+ "homepage": "https://github.com/Anuj7411/answerable/tree/main/packages/audit#readme",
13
+ "bugs": "https://github.com/Anuj7411/answerable/issues",
14
+ "type": "module",
15
+ "main": "./dist/index.js",
16
+ "types": "./dist/index.d.ts",
17
+ "exports": {
18
+ ".": {
19
+ "types": "./dist/index.d.ts",
20
+ "import": "./dist/index.js"
21
+ }
22
+ },
23
+ "files": ["dist", "README.md"],
24
+ "sideEffects": false,
25
+ "publishConfig": {
26
+ "access": "public"
27
+ },
28
+ "scripts": {
29
+ "build": "tsc -p tsconfig.build.json",
30
+ "test": "vitest run",
31
+ "test:watch": "vitest",
32
+ "typecheck": "tsc --noEmit",
33
+ "clean": "rimraf dist .tsbuildinfo"
34
+ },
35
+ "engines": {
36
+ "node": ">=20.0.0"
37
+ },
38
+ "dependencies": {
39
+ "@answerable-kit/core": "workspace:*",
40
+ "cheerio": "^1.0.0",
41
+ "kleur": "^4.1.5"
42
+ },
43
+ "devDependencies": {
44
+ "rimraf": "^6.0.1",
45
+ "typescript": "^5.7.3",
46
+ "vitest": "^3.0.5"
47
+ }
48
+ }