@reddoorla/maintenance 0.93.1 → 0.94.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -13
- package/dist/airtable-JGCPS7JH.js +9 -0
- package/dist/{announce-6OS4C57D.js → announce-PGT4SZZB.js} +6 -6
- package/dist/{bump-deps-GI7PHMOC.js → bump-deps-6OR7LL4E.js} +3 -3
- package/dist/{chunk-7NYN2P6I.js → chunk-3Z6X3BHU.js} +15 -8
- package/dist/chunk-3Z6X3BHU.js.map +1 -0
- package/dist/{chunk-MVDMKKBN.js → chunk-4AIYWWKV.js} +12 -5
- package/dist/chunk-4AIYWWKV.js.map +1 -0
- package/dist/{chunk-QLIUDTY6.js → chunk-5EEMTJMT.js} +10 -7
- package/dist/chunk-5EEMTJMT.js.map +1 -0
- package/dist/{chunk-4NUKMPOO.js → chunk-5FCBYK6L.js} +3 -3
- package/dist/{chunk-PR343K7F.js → chunk-5GUJ36TL.js} +2 -2
- package/dist/{chunk-P6AORG32.js → chunk-6R56OKJZ.js} +2 -2
- package/dist/{chunk-E22WAIF2.js → chunk-AEUABPAJ.js} +3 -3
- package/dist/{chunk-ZRI5VRPG.js → chunk-BYGPUUCT.js} +2 -2
- package/dist/{chunk-SKI23ZZH.js → chunk-HTABUCF4.js} +2 -2
- package/dist/{chunk-FCS36FDT.js → chunk-KQB2BX4V.js} +3 -3
- package/dist/{chunk-AX22DH6S.js → chunk-KZRR4NFG.js} +3 -3
- package/dist/{chunk-BJQCIJOY.js → chunk-REJCSA4H.js} +230 -805
- package/dist/chunk-REJCSA4H.js.map +1 -0
- package/dist/{chunk-CVJF2IC5.js → chunk-TGUESYGF.js} +17 -3
- package/dist/{chunk-CVJF2IC5.js.map → chunk-TGUESYGF.js.map} +1 -1
- package/dist/{chunk-JB4Q3C3M.js → chunk-TO7DJYLZ.js} +92 -15
- package/dist/{chunk-JB4Q3C3M.js.map → chunk-TO7DJYLZ.js.map} +1 -1
- package/dist/chunk-WJMPCVOR.js +4222 -0
- package/dist/chunk-WJMPCVOR.js.map +1 -0
- package/dist/{chunk-NDCOOI3V.js → chunk-WMBLR5VA.js} +3 -3
- package/dist/{chunk-QBAAZY7W.js → chunk-WVNDEYXL.js} +3 -3
- package/dist/{chunk-7BZUOZPU.js → chunk-XN37VTDB.js} +2 -2
- package/dist/{chunk-Q47DU255.js → chunk-Z2K4JPQ3.js} +2 -2
- package/dist/cli/bin.js +26 -26
- package/dist/cli/commands/audit.js +12 -12
- package/dist/{convert-to-pnpm-ONFP3JKF.js → convert-to-pnpm-3RVGUBBR.js} +3 -3
- package/dist/{db-HSZ6D5DU.js → db-FL7ZBF6H.js} +5 -5
- package/dist/{digest-EOA4JLTV.js → digest-TZ3QQOSF.js} +7 -7
- package/dist/{digest-collectors-ZA3BTS3R.js → digest-collectors-EHFY2OQC.js} +6 -6
- package/dist/{ensure-site-SF6KICTN.js → ensure-site-WIDO6LGU.js} +3 -3
- package/dist/{fleet-state-3LQUQHYD.js → fleet-state-UEVZ3X3J.js} +4 -4
- package/dist/{forms-notify-target-RMZPKT6S.js → forms-notify-target-2LWF5C5B.js} +3 -3
- package/dist/{github-signals-3WLIJ5RR.js → github-signals-GAHNOAHS.js} +5 -5
- package/dist/{header-image-DOCDFFRO.js → header-image-YN3AQRY3.js} +2 -2
- package/dist/{health-endpoint-DHKJUPRM.js → health-endpoint-XLNBWVHK.js} +3 -3
- package/dist/{health-mirror-55RRU6BI.js → health-mirror-EB76EERV.js} +4 -4
- package/dist/{import-airtable-OHVY344G.js → import-airtable-TAKSN4NV.js} +3 -3
- package/dist/index.d.ts +87 -6
- package/dist/index.js +15 -12
- package/dist/index.js.map +1 -1
- package/dist/{init-ZRKWYCKA.js → init-YCLSGIEP.js} +6 -6
- package/dist/{launch-6X5OXPF2.js → launch-FSHDTXSM.js} +9 -9
- package/dist/{lighthouse-airtable-3GUWHETW.js → lighthouse-airtable-YMH4UA7R.js} +3 -3
- package/dist/{onboard-6NHGCKGB.js → onboard-NKE6GZKL.js} +3 -3
- package/dist/{orchestrate-KMQIUP3H.js → orchestrate-MWXENQOS.js} +4 -4
- package/dist/{parity-623WNFZG.js → parity-CAJ477PS.js} +5 -5
- package/dist/{pipeline-AQBFG5WM.js → pipeline-MATFYQRC.js} +3 -2
- package/dist/{preflight-VPHQYWTY.js → preflight-4VQP7JJL.js} +5 -5
- package/dist/{prismic-ci-A2HI7NNJ.js → prismic-ci-DM352L2Q.js} +3 -3
- package/dist/{prismic-models-QTKIMFBC.js → prismic-models-Q32ARSYS.js} +7 -7
- package/dist/prospect/types.d.ts +584 -1
- package/dist/prospect/types.js +10 -1
- package/dist/{prospect-audit-RKUVSTLN.js → prospect-audit-MT6RGMOY.js} +3 -3
- package/dist/{render-7G43BSK5.js → render-JE5P26H5.js} +3 -2
- package/dist/{render-7G43BSK5.js.map → render-JE5P26H5.js.map} +1 -1
- package/dist/{render-from-row-P5CWM3MQ.js → render-from-row-IFSBHWDH.js} +3 -3
- package/dist/{renovate-dispatch-6GQWTRKX.js → renovate-dispatch-U5Q52SKT.js} +2 -2
- package/dist/{report-Y4LXDHRV.js → report-6FFHGUUS.js} +14 -14
- package/dist/{report-mirror-6ZDCAQZB.js → report-mirror-IP64R7B3.js} +4 -4
- package/dist/{self-updating-D5XOWS7V.js → self-updating-5DVDIEHB.js} +3 -3
- package/dist/{selftest-IFGSJP4X.js → selftest-LJYXBIO5.js} +6 -6
- package/dist/{site-mirror-3E7JYTJG.js → site-mirror-UKHREAD6.js} +4 -4
- package/dist/{smoke-suite-GXC5JZPH.js → smoke-suite-NUTC7IUK.js} +4 -4
- package/dist/{submissions-UMJS3YST.js → submissions-5GKJPCIH.js} +2 -2
- package/dist/{svelte-codemods-A3EARSRP.js → svelte-codemods-U4NIT6CV.js} +3 -3
- package/dist/{sync-ESP5ZQUU.js → sync-K3PKHVLH.js} +5 -5
- package/dist/{sync-configs-KSESOHFF.js → sync-configs-S2JYY6QU.js} +3 -3
- package/dist/{upgrade-ZLNVEIEA.js → upgrade-YFZCMUPE.js} +3 -3
- package/dist/{websites-D6WYFAES.js → websites-TB4TCAWM.js} +2 -2
- package/dist/{write-audits-to-airtable-K352LZQY.js → write-audits-to-airtable-53EVXKMU.js} +4 -4
- package/package.json +1 -1
- package/dist/airtable-QG5ICI3Y.js +0 -9
- package/dist/chunk-7NYN2P6I.js.map +0 -1
- package/dist/chunk-BJQCIJOY.js.map +0 -1
- package/dist/chunk-MVDMKKBN.js.map +0 -1
- package/dist/chunk-QLIUDTY6.js.map +0 -1
- /package/dist/{airtable-QG5ICI3Y.js.map → airtable-JGCPS7JH.js.map} +0 -0
- /package/dist/{announce-6OS4C57D.js.map → announce-PGT4SZZB.js.map} +0 -0
- /package/dist/{bump-deps-GI7PHMOC.js.map → bump-deps-6OR7LL4E.js.map} +0 -0
- /package/dist/{chunk-4NUKMPOO.js.map → chunk-5FCBYK6L.js.map} +0 -0
- /package/dist/{chunk-PR343K7F.js.map → chunk-5GUJ36TL.js.map} +0 -0
- /package/dist/{chunk-P6AORG32.js.map → chunk-6R56OKJZ.js.map} +0 -0
- /package/dist/{chunk-E22WAIF2.js.map → chunk-AEUABPAJ.js.map} +0 -0
- /package/dist/{chunk-ZRI5VRPG.js.map → chunk-BYGPUUCT.js.map} +0 -0
- /package/dist/{chunk-SKI23ZZH.js.map → chunk-HTABUCF4.js.map} +0 -0
- /package/dist/{chunk-FCS36FDT.js.map → chunk-KQB2BX4V.js.map} +0 -0
- /package/dist/{chunk-AX22DH6S.js.map → chunk-KZRR4NFG.js.map} +0 -0
- /package/dist/{chunk-NDCOOI3V.js.map → chunk-WMBLR5VA.js.map} +0 -0
- /package/dist/{chunk-QBAAZY7W.js.map → chunk-WVNDEYXL.js.map} +0 -0
- /package/dist/{chunk-7BZUOZPU.js.map → chunk-XN37VTDB.js.map} +0 -0
- /package/dist/{chunk-Q47DU255.js.map → chunk-Z2K4JPQ3.js.map} +0 -0
- /package/dist/{convert-to-pnpm-ONFP3JKF.js.map → convert-to-pnpm-3RVGUBBR.js.map} +0 -0
- /package/dist/{db-HSZ6D5DU.js.map → db-FL7ZBF6H.js.map} +0 -0
- /package/dist/{digest-EOA4JLTV.js.map → digest-TZ3QQOSF.js.map} +0 -0
- /package/dist/{digest-collectors-ZA3BTS3R.js.map → digest-collectors-EHFY2OQC.js.map} +0 -0
- /package/dist/{ensure-site-SF6KICTN.js.map → ensure-site-WIDO6LGU.js.map} +0 -0
- /package/dist/{fleet-state-3LQUQHYD.js.map → fleet-state-UEVZ3X3J.js.map} +0 -0
- /package/dist/{forms-notify-target-RMZPKT6S.js.map → forms-notify-target-2LWF5C5B.js.map} +0 -0
- /package/dist/{github-signals-3WLIJ5RR.js.map → github-signals-GAHNOAHS.js.map} +0 -0
- /package/dist/{header-image-DOCDFFRO.js.map → header-image-YN3AQRY3.js.map} +0 -0
- /package/dist/{health-endpoint-DHKJUPRM.js.map → health-endpoint-XLNBWVHK.js.map} +0 -0
- /package/dist/{health-mirror-55RRU6BI.js.map → health-mirror-EB76EERV.js.map} +0 -0
- /package/dist/{import-airtable-OHVY344G.js.map → import-airtable-TAKSN4NV.js.map} +0 -0
- /package/dist/{init-ZRKWYCKA.js.map → init-YCLSGIEP.js.map} +0 -0
- /package/dist/{launch-6X5OXPF2.js.map → launch-FSHDTXSM.js.map} +0 -0
- /package/dist/{lighthouse-airtable-3GUWHETW.js.map → lighthouse-airtable-YMH4UA7R.js.map} +0 -0
- /package/dist/{onboard-6NHGCKGB.js.map → onboard-NKE6GZKL.js.map} +0 -0
- /package/dist/{orchestrate-KMQIUP3H.js.map → orchestrate-MWXENQOS.js.map} +0 -0
- /package/dist/{parity-623WNFZG.js.map → parity-CAJ477PS.js.map} +0 -0
- /package/dist/{pipeline-AQBFG5WM.js.map → pipeline-MATFYQRC.js.map} +0 -0
- /package/dist/{preflight-VPHQYWTY.js.map → preflight-4VQP7JJL.js.map} +0 -0
- /package/dist/{prismic-ci-A2HI7NNJ.js.map → prismic-ci-DM352L2Q.js.map} +0 -0
- /package/dist/{prismic-models-QTKIMFBC.js.map → prismic-models-Q32ARSYS.js.map} +0 -0
- /package/dist/{prospect-audit-RKUVSTLN.js.map → prospect-audit-MT6RGMOY.js.map} +0 -0
- /package/dist/{render-from-row-P5CWM3MQ.js.map → render-from-row-IFSBHWDH.js.map} +0 -0
- /package/dist/{renovate-dispatch-6GQWTRKX.js.map → renovate-dispatch-U5Q52SKT.js.map} +0 -0
- /package/dist/{report-Y4LXDHRV.js.map → report-6FFHGUUS.js.map} +0 -0
- /package/dist/{report-mirror-6ZDCAQZB.js.map → report-mirror-IP64R7B3.js.map} +0 -0
- /package/dist/{self-updating-D5XOWS7V.js.map → self-updating-5DVDIEHB.js.map} +0 -0
- /package/dist/{selftest-IFGSJP4X.js.map → selftest-LJYXBIO5.js.map} +0 -0
- /package/dist/{site-mirror-3E7JYTJG.js.map → site-mirror-UKHREAD6.js.map} +0 -0
- /package/dist/{smoke-suite-GXC5JZPH.js.map → smoke-suite-NUTC7IUK.js.map} +0 -0
- /package/dist/{submissions-UMJS3YST.js.map → submissions-5GKJPCIH.js.map} +0 -0
- /package/dist/{svelte-codemods-A3EARSRP.js.map → svelte-codemods-U4NIT6CV.js.map} +0 -0
- /package/dist/{sync-ESP5ZQUU.js.map → sync-K3PKHVLH.js.map} +0 -0
- /package/dist/{sync-configs-KSESOHFF.js.map → sync-configs-S2JYY6QU.js.map} +0 -0
- /package/dist/{upgrade-ZLNVEIEA.js.map → upgrade-YFZCMUPE.js.map} +0 -0
- /package/dist/{websites-D6WYFAES.js.map → websites-TB4TCAWM.js.map} +0 -0
- /package/dist/{write-audits-to-airtable-K352LZQY.js.map → write-audits-to-airtable-53EVXKMU.js.map} +0 -0
package/dist/prospect/types.d.ts
CHANGED
|
@@ -582,6 +582,424 @@ type GoalFit = {
|
|
|
582
582
|
};
|
|
583
583
|
declare function orderRequirements(reqs: GoalRequirement[]): GoalRequirement[];
|
|
584
584
|
|
|
585
|
+
/**
|
|
586
|
+
* What they are running, named back to them.
|
|
587
|
+
*
|
|
588
|
+
* This is not a check and it must never try to be. Nothing here passes or
|
|
589
|
+
* fails, nothing here enters the denominator, and no line of it belongs in the
|
|
590
|
+
* fix list. It exists to answer the reader's first silent question — do these
|
|
591
|
+
* people know what they are talking about — before a single finding is made.
|
|
592
|
+
*
|
|
593
|
+
* "You're on WordPress running the Astra theme with Elementor, your forms are
|
|
594
|
+
* Gravity Forms, your DNS is at GoDaddy and your mail is Google Workspace" is a
|
|
595
|
+
* sentence nobody sending a cold audit can write, and it costs us almost
|
|
596
|
+
* nothing because every receipt for it is already in the crawl.
|
|
597
|
+
*
|
|
598
|
+
* The discipline is the same as everywhere else in this codebase, and it is the
|
|
599
|
+
* whole reason `evidence` is non-optional on `StackItem`: every line is an
|
|
600
|
+
* OBSERVATION WITH A RECEIPT — the exact URL or header we read it off — never
|
|
601
|
+
* an inference we cannot show. A reader who disputes a line can go and look at
|
|
602
|
+
* the thing we looked at.
|
|
603
|
+
*
|
|
604
|
+
* The failure this module must not commit is the mirror of the one the checks
|
|
605
|
+
* must not commit. There, our missing measurement must not become their defect.
|
|
606
|
+
* Here, our missing measurement must not become "they don't have one": a
|
|
607
|
+
* WordPress site behind a caching plugin that rewrites asset paths is
|
|
608
|
+
* completely invisible to this, and so is any site whose markup we never read.
|
|
609
|
+
* `measured` says whether we were in a position to see anything at all, and the
|
|
610
|
+
* report must be able to say "we could not tell" rather than implying absence.
|
|
611
|
+
*/
|
|
612
|
+
type StackLayer = "cms" | "theme" | "plugin" | "page-builder" | "framework" | "hosting" | "ecommerce" | "forms" | "analytics" | "fonts";
|
|
613
|
+
/** Display order in the readout. Broadest thing first — a reader wants "you're
|
|
614
|
+
* on WordPress" before "you load Hotjar". */
|
|
615
|
+
declare const LAYER_ORDER: StackLayer[];
|
|
616
|
+
declare const LAYER_LABELS: Record<StackLayer, string>;
|
|
617
|
+
type StackItem = {
|
|
618
|
+
layer: StackLayer;
|
|
619
|
+
/** What we are naming, spelled the way its own vendor spells it. */
|
|
620
|
+
name: string;
|
|
621
|
+
/**
|
|
622
|
+
* The receipt — the URL or response header we read it off, truncated only for
|
|
623
|
+
* length. Never optional and never synthesised: a line without a receipt is
|
|
624
|
+
* an assertion, and this module does not make assertions.
|
|
625
|
+
*/
|
|
626
|
+
evidence: string;
|
|
627
|
+
};
|
|
628
|
+
type StackReadout = {
|
|
629
|
+
/**
|
|
630
|
+
* Were we in a position to see anything?
|
|
631
|
+
*
|
|
632
|
+
* False when no page we read carried a `scriptSrcs` array — which is every
|
|
633
|
+
* report stored before that field existed, and any run whose pages all failed
|
|
634
|
+
* to fetch. An empty `items` with `measured: false` means "we could not
|
|
635
|
+
* tell"; with `measured: true` it means "we read the markup and recognised
|
|
636
|
+
* nothing in it", which is a real and unremarkable answer for a hand-built
|
|
637
|
+
* site.
|
|
638
|
+
*/
|
|
639
|
+
measured: boolean;
|
|
640
|
+
items: StackItem[];
|
|
641
|
+
/** How many pages' markup we actually read. The honest denominator for any
|
|
642
|
+
* sentence that starts "we did not see". */
|
|
643
|
+
pagesExamined: number;
|
|
644
|
+
/** Did we also read response headers? They carry the hosting and CDN half,
|
|
645
|
+
* and a run without them can say nothing about either. */
|
|
646
|
+
headersExamined: boolean;
|
|
647
|
+
};
|
|
648
|
+
|
|
649
|
+
/**
|
|
650
|
+
* What the domain itself says, as opposed to what the website says.
|
|
651
|
+
*
|
|
652
|
+
* Five questions, one lookup each, and none of them touches the prospect's web
|
|
653
|
+
* server at all — so this is the cheapest section of the whole audit and the
|
|
654
|
+
* one nobody else sends. "Anyone can send email as you" and "your domain
|
|
655
|
+
* renews in 41 days" are findings a reader acts on the same afternoon, and
|
|
656
|
+
* neither is visible from any amount of reading their HTML.
|
|
657
|
+
*
|
|
658
|
+
* `basics.ts` deliberately excludes TLS certificate expiry, on the grounds that
|
|
659
|
+
* a successful https fetch already proved the certificate valid to a real
|
|
660
|
+
* client. DOMAIN expiry is a different thing entirely — nothing about today's
|
|
661
|
+
* successful request tells you the registration lapses in six weeks — which is
|
|
662
|
+
* why it belongs here and that one does not.
|
|
663
|
+
*
|
|
664
|
+
* EVERY FAILURE MODE HERE IS OURS. A DNS timeout, a resolver that refuses, an
|
|
665
|
+
* RDAP service that is down, a TLD that publishes no expiry: each is a gap in
|
|
666
|
+
* our measurement and each must come back `unmeasured`. The one thing this
|
|
667
|
+
* module must never do is report "no SPF record" because the lookup failed —
|
|
668
|
+
* that is our network outage printed as their security hole.
|
|
669
|
+
*/
|
|
670
|
+
type DnsFindings = {
|
|
671
|
+
/** False when the domain itself could not be determined — nothing below is
|
|
672
|
+
* then attributable to the prospect. */
|
|
673
|
+
measured: boolean;
|
|
674
|
+
domain: string | null;
|
|
675
|
+
/** The apex TXT record starting `v=spf1`, or null when there is none.
|
|
676
|
+
* `undefined` means the lookup did not answer — a different claim. */
|
|
677
|
+
spf: string | null | undefined;
|
|
678
|
+
/** The `_dmarc` TXT record starting `v=DMARC1`. Same three states. */
|
|
679
|
+
dmarc: string | null | undefined;
|
|
680
|
+
/** Mail exchangers for the apex, lowest preference first. */
|
|
681
|
+
mx: string[] | undefined;
|
|
682
|
+
/** Whether the domain in a published `mailto:` can receive mail. Null when
|
|
683
|
+
* the site publishes no email address to check. */
|
|
684
|
+
contactMx: {
|
|
685
|
+
domain: string;
|
|
686
|
+
hasMx: boolean;
|
|
687
|
+
} | null | undefined;
|
|
688
|
+
/** ISO date the registration lapses, from RDAP. Undefined when RDAP did not
|
|
689
|
+
* answer or the registry publishes no expiry, which many ccTLDs do not. */
|
|
690
|
+
expiresAt: string | undefined;
|
|
691
|
+
};
|
|
692
|
+
|
|
693
|
+
/** A URL that answered, that provably did not, or that we could not read.
|
|
694
|
+
* The third is not a failure and never enters a denominator. */
|
|
695
|
+
type ProbeVerdict = "ok" | "broken" | "unverified";
|
|
696
|
+
type UrlProbe = {
|
|
697
|
+
url: string;
|
|
698
|
+
status: number | null;
|
|
699
|
+
verdict: ProbeVerdict;
|
|
700
|
+
};
|
|
701
|
+
type HttpFindings = {
|
|
702
|
+
/** False when we had no origin to probe — nothing below is then about them. */
|
|
703
|
+
measured: boolean;
|
|
704
|
+
/** Requests this stage made, reported so the cost is visible. */
|
|
705
|
+
requests: number;
|
|
706
|
+
/** The icon a browser tab actually gets. `url` is what the page declared, or
|
|
707
|
+
* the conventional `/favicon.ico` when it declared nothing. */
|
|
708
|
+
favicon: {
|
|
709
|
+
url: string;
|
|
710
|
+
declared: boolean;
|
|
711
|
+
verdict: ProbeVerdict;
|
|
712
|
+
} | undefined;
|
|
713
|
+
/** What `http://` does. `hops` counts redirects; `https` is where it landed. */
|
|
714
|
+
httpUpgrade: {
|
|
715
|
+
hops: number | null;
|
|
716
|
+
https: boolean;
|
|
717
|
+
} | undefined;
|
|
718
|
+
/** Two homepage samples. Equal statuses mean nothing to report; different
|
|
719
|
+
* ones are the only evidence that would justify the word "intermittent". */
|
|
720
|
+
homeSamples: [number | null, number | null] | undefined;
|
|
721
|
+
/** A path fetched with and without its trailing slash. `settled` is true when
|
|
722
|
+
* the two agree on one address — either by redirect or by canonical. */
|
|
723
|
+
trailingSlash: {
|
|
724
|
+
path: string;
|
|
725
|
+
settled: boolean;
|
|
726
|
+
detail: string;
|
|
727
|
+
} | undefined;
|
|
728
|
+
/** `/index.html`, and whether it duplicates the homepage rather than
|
|
729
|
+
* redirecting or declaring the homepage canonical. Null when it 404s, which
|
|
730
|
+
* is the correct behaviour and not a finding. */
|
|
731
|
+
indexAlias: {
|
|
732
|
+
duplicate: boolean;
|
|
733
|
+
detail: string;
|
|
734
|
+
} | null | undefined;
|
|
735
|
+
/** The same path in a different case. Null when it 404s — also correct. */
|
|
736
|
+
caseAlias: {
|
|
737
|
+
path: string;
|
|
738
|
+
duplicate: boolean;
|
|
739
|
+
detail: string;
|
|
740
|
+
} | null | undefined;
|
|
741
|
+
/** Sampled sitemap URLs. Null when there is no sitemap to sample. */
|
|
742
|
+
sitemapUrls: {
|
|
743
|
+
checked: number;
|
|
744
|
+
total: number;
|
|
745
|
+
broken: UrlProbe[];
|
|
746
|
+
} | null | undefined;
|
|
747
|
+
/** Outbound links to other sites. Null when the site links out nowhere. */
|
|
748
|
+
externalLinks: {
|
|
749
|
+
checked: number;
|
|
750
|
+
total: number;
|
|
751
|
+
broken: UrlProbe[];
|
|
752
|
+
} | null | undefined;
|
|
753
|
+
/** The image that appears when the site is shared. Null when none is
|
|
754
|
+
* declared — Tier 1 owns that, and saying it twice reads as two problems. */
|
|
755
|
+
ogImage: {
|
|
756
|
+
url: string;
|
|
757
|
+
verdict: ProbeVerdict;
|
|
758
|
+
width: number | null;
|
|
759
|
+
height: number | null;
|
|
760
|
+
} | null | undefined;
|
|
761
|
+
/** The header logo, and the rule we used to find it, so a reader can tell
|
|
762
|
+
* whether we found the right image. */
|
|
763
|
+
logo: {
|
|
764
|
+
url: string;
|
|
765
|
+
how: string;
|
|
766
|
+
verdict: ProbeVerdict;
|
|
767
|
+
} | null | undefined;
|
|
768
|
+
/** Internal links reached through more than one redirect. */
|
|
769
|
+
redirectChains: {
|
|
770
|
+
checked: number;
|
|
771
|
+
chained: {
|
|
772
|
+
url: string;
|
|
773
|
+
hops: number;
|
|
774
|
+
}[];
|
|
775
|
+
} | undefined;
|
|
776
|
+
};
|
|
777
|
+
|
|
778
|
+
type FormProbe = {
|
|
779
|
+
/** The page we probed, so a finding has an address. */
|
|
780
|
+
url: string;
|
|
781
|
+
/**
|
|
782
|
+
* Whether an empty submit was refused.
|
|
783
|
+
*
|
|
784
|
+
* `undefined` means we could not tell — the form sits in a cross-origin
|
|
785
|
+
* iframe, or the click threw, or the browser pass never ran. It is never a
|
|
786
|
+
* failure: a form we could not reach is our gap, not their defect.
|
|
787
|
+
*/
|
|
788
|
+
emptyRefused: boolean | undefined;
|
|
789
|
+
/** How it refused, in words a report can print. */
|
|
790
|
+
emptyHow: string | null;
|
|
791
|
+
/** Same, for an address that is not an address. Null when the form asks for
|
|
792
|
+
* no email at all, which is a form we have nothing to say about here. */
|
|
793
|
+
invalidEmailRefused: boolean | null | undefined;
|
|
794
|
+
invalidEmailHow: string | null;
|
|
795
|
+
/** Requests the interceptor stopped. The receipt for "we sent nothing". */
|
|
796
|
+
blocked: number;
|
|
797
|
+
};
|
|
798
|
+
|
|
799
|
+
/**
|
|
800
|
+
* What axe-core found, in the browser the crawl already opened.
|
|
801
|
+
*
|
|
802
|
+
* WHAT THIS IS AND IS NOT NEW. The Lighthouse stage we already run IS axe — a
|
|
803
|
+
* subset of roughly forty-five rules, reported as one number between 0 and 100.
|
|
804
|
+
* Running it ourselves does not discover a different site; it does three things
|
|
805
|
+
* that number cannot:
|
|
806
|
+
*
|
|
807
|
+
* - turns "accessibility: 82" into named rules with named fixes, each with an
|
|
808
|
+
* element to go and look at;
|
|
809
|
+
* - adds the rules Lighthouse omits — every `best-practice` landmark and
|
|
810
|
+
* heading rule, which is most of what is structurally wrong with most
|
|
811
|
+
* sites, and which a wcag-tags-only scan cannot see at all;
|
|
812
|
+
* - absorbs several checks we would otherwise have written worse by hand
|
|
813
|
+
* (link names, tap-target size, viewport zoom, `lang`, form labels).
|
|
814
|
+
*
|
|
815
|
+
* THE TAG SET IS THE WHOLE POINT. Our own fleet audit scans `wcag2a`,
|
|
816
|
+
* `wcag2aa`, `wcag21a`, `wcag21aa`, `wcag22aa` and nothing else, and every
|
|
817
|
+
* landmark and heading-order rule in axe is tagged `best-practice` — so a green
|
|
818
|
+
* run there proves nothing about structure. This runs the DEFAULT rule set,
|
|
819
|
+
* which is all of them.
|
|
820
|
+
*
|
|
821
|
+
* WHAT IT MAY NOT SAY. Never that a site "is inaccessible", and never a score.
|
|
822
|
+
* axe finds what a machine can find, which is a minority of what a disabled
|
|
823
|
+
* person actually encounters; a page can pass every rule here and be unusable.
|
|
824
|
+
* The report says: we ran N rules, these M produced findings, here is the
|
|
825
|
+
* element and the rule's own explanation. That is a fact with a receipt, and it
|
|
826
|
+
* is all this instrument earns.
|
|
827
|
+
*/
|
|
828
|
+
type AxeImpact = "minor" | "moderate" | "serious" | "critical";
|
|
829
|
+
/** One rule that produced findings on one page. Sized for persistence: the
|
|
830
|
+
* node COUNT plus a single example, never every matching element. */
|
|
831
|
+
type AxeViolation = {
|
|
832
|
+
/** axe's rule id — `color-contrast`, `landmark-one-main`. Stable, and the
|
|
833
|
+
* thing to search for. */
|
|
834
|
+
id: string;
|
|
835
|
+
impact: AxeImpact | null;
|
|
836
|
+
/** axe's own one-line explanation. Quoted rather than paraphrased: it is
|
|
837
|
+
* written by people who know the rule better than we do. */
|
|
838
|
+
help: string;
|
|
839
|
+
helpUrl: string;
|
|
840
|
+
/** Elements on this page the rule matched. */
|
|
841
|
+
nodes: number;
|
|
842
|
+
/** One of them, truncated — so a reader can go and find it. */
|
|
843
|
+
sample: string | null;
|
|
844
|
+
};
|
|
845
|
+
type AxePageResult = {
|
|
846
|
+
violations: AxeViolation[];
|
|
847
|
+
/**
|
|
848
|
+
* Rules that found something to judge on this page and judged it fine.
|
|
849
|
+
*
|
|
850
|
+
* NOT "the number of rules axe has". Measured on our own report page, the
|
|
851
|
+
* default set is 90 rules, of which 42 passed, 47 were INAPPLICABLE — the
|
|
852
|
+
* page contains no table, no video, no iframe, so those rules had nothing to
|
|
853
|
+
* look at — and one was incomplete. Printing 90 as though we had checked 90
|
|
854
|
+
* things would be a number inflated on our own behalf, which is why
|
|
855
|
+
* `inapplicable` is carried rather than quietly folded into this one.
|
|
856
|
+
*/
|
|
857
|
+
passes: number;
|
|
858
|
+
/** Rules axe could not decide — genuinely "we do not know", reported as such
|
|
859
|
+
* rather than folded into either column. */
|
|
860
|
+
incomplete: number;
|
|
861
|
+
/** WHICH rules those were. A count alone tells a reader three things need a
|
|
862
|
+
* human without saying what to look at, which is a worry rather than a job.
|
|
863
|
+
* Optional: absent on any result stored before it was captured. */
|
|
864
|
+
incompleteIds?: string[];
|
|
865
|
+
/** Rules with nothing on the page to check. Carried so the report can say
|
|
866
|
+
* "43 of axe's 90 rules had something to check here" and be exactly right. */
|
|
867
|
+
inapplicable: number;
|
|
868
|
+
};
|
|
869
|
+
type AccessibilityResult = {
|
|
870
|
+
/**
|
|
871
|
+
* Did the rules run anywhere?
|
|
872
|
+
*
|
|
873
|
+
* False when no page carried a result — every report stored before this
|
|
874
|
+
* existed, every run whose browser never started, and every test that stubs
|
|
875
|
+
* the renderer. An empty `violations` with `measured: false` means "we did
|
|
876
|
+
* not look"; with `measured: true` it means the rules ran and found nothing,
|
|
877
|
+
* which is a real and excellent answer.
|
|
878
|
+
*/
|
|
879
|
+
measured: boolean;
|
|
880
|
+
pagesExamined: number;
|
|
881
|
+
/**
|
|
882
|
+
* Rules that had something to check and passed — the number the report may
|
|
883
|
+
* print as "we checked N things", and no larger one.
|
|
884
|
+
*
|
|
885
|
+
* The MAXIMUM across pages, never the sum. The same rule set runs on every
|
|
886
|
+
* page, so summing reports "210 checks" for 42 rules over five pages. Max is
|
|
887
|
+
* a deliberate under-count where pages differ: it can only understate what we
|
|
888
|
+
* looked at, and understating our own work is the safe direction.
|
|
889
|
+
*/
|
|
890
|
+
rulesPassed: number;
|
|
891
|
+
rulesIncomplete: number;
|
|
892
|
+
/** The undecided rules by name, so the disclosure can say what to look at
|
|
893
|
+
* instead of only how many. Empty when none, absent-safe for old reports. */
|
|
894
|
+
incompleteIds: string[];
|
|
895
|
+
/** Rules that found nothing on these pages to apply to. Not a pass and not a
|
|
896
|
+
* failure — the page simply has no table, video or iframe for them. */
|
|
897
|
+
rulesInapplicable: number;
|
|
898
|
+
/** Rules that produced findings, worst impact first, each naming the pages it
|
|
899
|
+
* fired on. Capped — see `violationsTotal`. */
|
|
900
|
+
violations: (AxeViolation & {
|
|
901
|
+
pages: string[];
|
|
902
|
+
})[];
|
|
903
|
+
/** True number of distinct rules with findings, before the cap. A truncated
|
|
904
|
+
* list that looks complete is the quiet lie this codebase is built to avoid. */
|
|
905
|
+
violationsTotal: number;
|
|
906
|
+
};
|
|
907
|
+
/**
|
|
908
|
+
* What the browser itself reported while the page was open.
|
|
909
|
+
*
|
|
910
|
+
* Collected in the SAME pass as the rendered DOM and the axe run — listeners
|
|
911
|
+
* attached before navigation, one viewport resize after it. A resize reflows
|
|
912
|
+
* the page the browser has already loaded; it costs no request and puts nothing
|
|
913
|
+
* extra on the prospect's server, which is why the mobile-overflow measurement
|
|
914
|
+
* is affordable at all.
|
|
915
|
+
*/
|
|
916
|
+
type PageVitals = {
|
|
917
|
+
/** Uncaught exceptions and `console.error` calls, capped and deduped. The
|
|
918
|
+
* most demonstrable "your site is broken" evidence there is. */
|
|
919
|
+
consoleErrors: string[];
|
|
920
|
+
/**
|
|
921
|
+
* Requests the page made that failed or came back 4xx/5xx.
|
|
922
|
+
*
|
|
923
|
+
* `firstParty` decides whether it is a finding at all. A blocked third-party
|
|
924
|
+
* analytics beacon is our network or an ad blocker; a 404 on the site's own
|
|
925
|
+
* stylesheet is theirs, and only the second belongs in a report.
|
|
926
|
+
*/
|
|
927
|
+
failedRequests: {
|
|
928
|
+
url: string;
|
|
929
|
+
status: number | null;
|
|
930
|
+
firstParty: boolean;
|
|
931
|
+
}[];
|
|
932
|
+
/**
|
|
933
|
+
* Pixels the document overflows a 375px viewport, or null when we could not
|
|
934
|
+
* measure. Zero is the answer a correct site gives.
|
|
935
|
+
*/
|
|
936
|
+
overflowAt375: number | null;
|
|
937
|
+
/** Text nodes rendering below 12px, with one example. Null = not measured. */
|
|
938
|
+
tinyText: {
|
|
939
|
+
count: number;
|
|
940
|
+
sample: string | null;
|
|
941
|
+
} | null;
|
|
942
|
+
/** Images downloaded far larger than they are drawn — the bytes a visitor
|
|
943
|
+
* pays for and never sees. */
|
|
944
|
+
oversizedImages: {
|
|
945
|
+
src: string;
|
|
946
|
+
naturalWidth: number;
|
|
947
|
+
renderedWidth: number;
|
|
948
|
+
}[];
|
|
949
|
+
};
|
|
950
|
+
|
|
951
|
+
/**
|
|
952
|
+
* The things a careful person would check with a browser and ten minutes.
|
|
953
|
+
*
|
|
954
|
+
* Every check here is a pure function of what the crawl already stored. Nothing
|
|
955
|
+
* in this file makes a request, which is the point: it can be run over every
|
|
956
|
+
* audit already in the database without touching a prospect's server, and a bug
|
|
957
|
+
* found by that replay costs nothing to fix.
|
|
958
|
+
*
|
|
959
|
+
* FOUR STATES, NOT THREE. The rest of this codebase already knows that our
|
|
960
|
+
* failed measurement must never render as the site's defect, which is why
|
|
961
|
+
* `unmeasured` exists. This file adds the state that review kept catching:
|
|
962
|
+
* `not-applicable`. A site with no `LocalBusiness` schema, no HSTS header and no
|
|
963
|
+
* RTL content must not silently PASS the checks about those — that inflates
|
|
964
|
+
* "34 of 35 passed" with checks that never ran, which is the same dishonesty as
|
|
965
|
+
* a false failure wearing nicer clothes. Both non-verdicts leave the
|
|
966
|
+
* denominator; see `tally`.
|
|
967
|
+
*
|
|
968
|
+
* THE FLOOR IS BARE HTML. A hand-written page with a title, a heading and a
|
|
969
|
+
* paragraph should pass almost all of this. A check that a careful, ordinary
|
|
970
|
+
* site fails is not measuring care, it is measuring fashion, and it makes the
|
|
971
|
+
* report an argument rather than a document. Where a bar had to be set, it is
|
|
972
|
+
* set generously and the reasoning is written down next to it.
|
|
973
|
+
*
|
|
974
|
+
* WHAT PASSES IS ONE LINE. Most of these will be green on most sites, and that
|
|
975
|
+
* is by design — they cost one row inside a collapsed section and are invisible
|
|
976
|
+
* until the day one fails, at which point it is the most useful row on the
|
|
977
|
+
* page. That is what makes a trivial check worth having, and it is the only
|
|
978
|
+
* thing that makes it worth having.
|
|
979
|
+
*/
|
|
980
|
+
type CheckStatus = "pass" | "fail" | "unmeasured" | "not-applicable";
|
|
981
|
+
type SiteCheck = {
|
|
982
|
+
key: string;
|
|
983
|
+
/** What was checked, in the reader's terms rather than ours. */
|
|
984
|
+
label: string;
|
|
985
|
+
status: CheckStatus;
|
|
986
|
+
/**
|
|
987
|
+
* What we found — the receipt, on a pass as much as on a fail. A green row
|
|
988
|
+
* saying "we looked and it is fine" is worth more when it says what it
|
|
989
|
+
* looked at.
|
|
990
|
+
*/
|
|
991
|
+
evidence: string | null;
|
|
992
|
+
/** Why it matters to them. Printed only on a fail; a cleared check needs no
|
|
993
|
+
* argument. */
|
|
994
|
+
why: string;
|
|
995
|
+
scope: Scope;
|
|
996
|
+
};
|
|
997
|
+
declare function tally(checks: SiteCheck[]): {
|
|
998
|
+
passed: number;
|
|
999
|
+
failed: number;
|
|
1000
|
+
total: number;
|
|
1001
|
+
};
|
|
1002
|
+
|
|
585
1003
|
/**
|
|
586
1004
|
* Can a visitor actually get from where they landed to a way of contacting you?
|
|
587
1005
|
*
|
|
@@ -674,6 +1092,18 @@ type PageAnchor = {
|
|
|
674
1092
|
href: string;
|
|
675
1093
|
text: string;
|
|
676
1094
|
rel: string;
|
|
1095
|
+
/** As authored, lower-cased — `_blank` on a link that opens a new tab.
|
|
1096
|
+
* Optional: absent on reports stored before it was captured, which reads as
|
|
1097
|
+
* "not measured" rather than "opens in this tab". */
|
|
1098
|
+
target?: string;
|
|
1099
|
+
/** `aria-label` as authored, empty when there is none. This is the label a
|
|
1100
|
+
* screen reader actually announces, so a link whose visible text is "Learn
|
|
1101
|
+
* more" is not necessarily a link that announces "Learn more".
|
|
1102
|
+
*
|
|
1103
|
+
* Optional for the same reason `target` is: a report stored before it was
|
|
1104
|
+
* captured has it absent everywhere, and absent must read as "we did not
|
|
1105
|
+
* look", never as "there is none". */
|
|
1106
|
+
ariaLabel?: string;
|
|
677
1107
|
};
|
|
678
1108
|
/**
|
|
679
1109
|
* What a form is FOR, inferred from its shape.
|
|
@@ -698,6 +1128,16 @@ type FormKind = "enquiry" | "subscribe" | "other";
|
|
|
698
1128
|
/** One `<form>`, in enough detail to tell an enquiry form from a newsletter box
|
|
699
1129
|
* or a search field. That distinction is the whole point: a site nobody can
|
|
700
1130
|
* actually reach must not score as though it has a conversion path. */
|
|
1131
|
+
/** One control a visitor fills in. Just the three attributes that decide
|
|
1132
|
+
* whether the form is easy to complete on a phone. */
|
|
1133
|
+
type FormField = {
|
|
1134
|
+
/** Lower-cased, defaulting to "text" for a bare `<input>` exactly as a
|
|
1135
|
+
* browser does; `textarea` and `select` carry their tag name. */
|
|
1136
|
+
type: string;
|
|
1137
|
+
name: string | null;
|
|
1138
|
+
autocomplete: string | null;
|
|
1139
|
+
required: boolean;
|
|
1140
|
+
};
|
|
701
1141
|
type FormShape = {
|
|
702
1142
|
kind: FormKind;
|
|
703
1143
|
/** As authored, or null for a form that posts to its own URL. */
|
|
@@ -711,6 +1151,9 @@ type FormShape = {
|
|
|
711
1151
|
* and this is what separates "can be contacted" from "can be searched". */
|
|
712
1152
|
hasContactField: boolean;
|
|
713
1153
|
hasSubmit: boolean;
|
|
1154
|
+
/** Per-field detail. Optional: absent on reports stored before it existed,
|
|
1155
|
+
* and absence must read as "not measured", never as "no fields". */
|
|
1156
|
+
fields?: FormField[];
|
|
714
1157
|
};
|
|
715
1158
|
type PageExtract = {
|
|
716
1159
|
title: string | null;
|
|
@@ -754,6 +1197,58 @@ type PageExtract = {
|
|
|
754
1197
|
/** `src` of each `<img>`, as authored. Same resolution note as `anchors`. */
|
|
755
1198
|
imageSrcs?: string[];
|
|
756
1199
|
forms?: FormShape[];
|
|
1200
|
+
/**
|
|
1201
|
+
* Every `<meta>` that is not `og:`/`twitter:` — those are in `social`, and
|
|
1202
|
+
* carrying them twice would double the biggest part of a persisted extract.
|
|
1203
|
+
* Keyed by lower-cased `name` or `property`, so `robots`, `generator`,
|
|
1204
|
+
* `charset` and `viewport` are all reachable by the name they are written by.
|
|
1205
|
+
*
|
|
1206
|
+
* `metaDescription` and `hasViewportMeta` remain projected separately because
|
|
1207
|
+
* older stored reports have them and nothing should have to know that
|
|
1208
|
+
* `metas.description` is the same string.
|
|
1209
|
+
*
|
|
1210
|
+
* Optional: absent on reports stored before it existed, and absence must read
|
|
1211
|
+
* as "not measured", never as "this page declares no metas".
|
|
1212
|
+
*/
|
|
1213
|
+
metas?: Record<string, string>;
|
|
1214
|
+
/**
|
|
1215
|
+
* Every `<link>` in the document, as authored.
|
|
1216
|
+
*
|
|
1217
|
+
* The elements were ALREADY collected by the extractor — only the canonical
|
|
1218
|
+
* one was ever projected onto this type — so this is a projection change
|
|
1219
|
+
* rather than a new traversal.
|
|
1220
|
+
*
|
|
1221
|
+
* Optional: absent on reports stored before it existed. Absence means "not
|
|
1222
|
+
* measured", never "this page declares no favicon".
|
|
1223
|
+
*/
|
|
1224
|
+
links?: {
|
|
1225
|
+
rel: string;
|
|
1226
|
+
href: string;
|
|
1227
|
+
hreflang?: string;
|
|
1228
|
+
type?: string;
|
|
1229
|
+
}[];
|
|
1230
|
+
/**
|
|
1231
|
+
* `src` of each `<script src>`, as authored, CAPPED — see `scriptCount` for
|
|
1232
|
+
* the true total, exactly as `anchors`/`anchorCount` do.
|
|
1233
|
+
*
|
|
1234
|
+
* These are the receipts the stack readout is built from: `/wp-content/
|
|
1235
|
+
* plugins/<name>/`, `/_next/`, `hs-scripts.com`. Inline scripts are not
|
|
1236
|
+
* collected — only ones with a `src`, because a src is an address a reader
|
|
1237
|
+
* can go and check and an inline blob is not.
|
|
1238
|
+
*/
|
|
1239
|
+
scriptSrcs?: string[];
|
|
1240
|
+
/**
|
|
1241
|
+
* URLs NAMED inside inline scripts — a different claim from a script that
|
|
1242
|
+
* is loaded, and the one that matters for a site which defers its tags.
|
|
1243
|
+
*
|
|
1244
|
+
* A page that injects `googletagmanager.com` only after the first scroll has
|
|
1245
|
+
* no analytics `src` in the DOM at crawl time. Reading that as "no analytics"
|
|
1246
|
+
* is our missing measurement reported as their defect. Absent on reports
|
|
1247
|
+
* stored before this existed, which reads as "not measured".
|
|
1248
|
+
*/
|
|
1249
|
+
inlineScriptUrls?: string[];
|
|
1250
|
+
/** True number of `<script src>` on the page, before `scriptSrcs` was capped. */
|
|
1251
|
+
scriptCount?: number;
|
|
757
1252
|
};
|
|
758
1253
|
type PageCapture = {
|
|
759
1254
|
url: string;
|
|
@@ -764,6 +1259,31 @@ type PageCapture = {
|
|
|
764
1259
|
/** Extract of the Playwright-rendered DOM (what a browser sees). */
|
|
765
1260
|
rendered: PageExtract | null;
|
|
766
1261
|
error: string | null;
|
|
1262
|
+
/**
|
|
1263
|
+
* What the axe rule set found on this page, collected in the SAME browser
|
|
1264
|
+
* pass that produced `rendered` — never a second navigation.
|
|
1265
|
+
*
|
|
1266
|
+
* Null means the rules did not run: an older stored report, a page that
|
|
1267
|
+
* failed to render, or a scan that threw. It must never read as "no
|
|
1268
|
+
* violations", which is the opposite claim.
|
|
1269
|
+
*/
|
|
1270
|
+
axe?: AxePageResult | null;
|
|
1271
|
+
/**
|
|
1272
|
+
* What the browser itself reported while this page was open — console errors,
|
|
1273
|
+
* failed requests, mobile overflow. Same pass as `rendered` and `axe`.
|
|
1274
|
+
*
|
|
1275
|
+
* Null means nothing was measured. It must never read as "nothing went
|
|
1276
|
+
* wrong", which is the opposite claim.
|
|
1277
|
+
*/
|
|
1278
|
+
vitals?: PageVitals | null;
|
|
1279
|
+
/**
|
|
1280
|
+
* What happened when we pressed this page's enquiry-form submit button.
|
|
1281
|
+
*
|
|
1282
|
+
* Present on at most ONE page per crawl, and null everywhere else — absence
|
|
1283
|
+
* means "we did not interact here", never "the form is fine". Optional for
|
|
1284
|
+
* reports stored before any of this existed.
|
|
1285
|
+
*/
|
|
1286
|
+
formProbe?: FormProbe | null;
|
|
767
1287
|
};
|
|
768
1288
|
type CrawlResult = {
|
|
769
1289
|
/** Normalized origin, e.g. "https://example.com". */
|
|
@@ -771,9 +1291,27 @@ type CrawlResult = {
|
|
|
771
1291
|
robotsTxt: string | null;
|
|
772
1292
|
/** One entry per agent in crawl.ts's ALL_AGENTS (6 AI + 2 classical). */
|
|
773
1293
|
agentAccess: RobotsAgentAccess[];
|
|
1294
|
+
/** `sample` is a capped slice of the URLs, absent on reports stored before
|
|
1295
|
+
* it existed — read absence as "not measured", never as "the sitemap is
|
|
1296
|
+
* empty". `urlCount` is the true total either way. */
|
|
774
1297
|
sitemap: {
|
|
775
1298
|
present: boolean;
|
|
776
1299
|
urlCount: number;
|
|
1300
|
+
sample?: string[];
|
|
1301
|
+
/**
|
|
1302
|
+
* True when we stopped reading before the sitemap ended, which makes
|
|
1303
|
+
* `urlCount` a FLOOR rather than a count.
|
|
1304
|
+
*
|
|
1305
|
+
* A sitemap index is followed only so far — see `MAX_SITEMAP_CHILDREN` —
|
|
1306
|
+
* and viget.com publishes 35 children holding 1,636 URLs between them. We
|
|
1307
|
+
* read the first few, counted 66, and told them 179 of their own pages were
|
|
1308
|
+
* missing from their sitemap. Our ceiling, reported as their gap, which is
|
|
1309
|
+
* the one mistake this report keeps having to be stopped from making.
|
|
1310
|
+
*
|
|
1311
|
+
* Optional: absent on reports stored before it was tracked, and absent must
|
|
1312
|
+
* read as "we do not know", never as "we read the whole thing".
|
|
1313
|
+
*/
|
|
1314
|
+
truncated?: boolean;
|
|
777
1315
|
};
|
|
778
1316
|
llmsTxt: {
|
|
779
1317
|
present: boolean;
|
|
@@ -1106,10 +1644,55 @@ type ProspectAuditResult = {
|
|
|
1106
1644
|
* single named goal rather than a generic template — see goals.ts. Optional
|
|
1107
1645
|
* for reports stored before it existed. */
|
|
1108
1646
|
goalFit?: StageResult<GoalFit>;
|
|
1647
|
+
/**
|
|
1648
|
+
* What they are running — platform, theme, plugins, host, forms, analytics.
|
|
1649
|
+
*
|
|
1650
|
+
* NOT a check and never part of any denominator: nothing in it passes or
|
|
1651
|
+
* fails. It opens the report because naming a reader's own stack back to them
|
|
1652
|
+
* answers "do these people know what they are talking about" before the first
|
|
1653
|
+
* finding. Optional for reports stored before the stage existed.
|
|
1654
|
+
*/
|
|
1655
|
+
stack?: StageResult<StackReadout>;
|
|
1656
|
+
/**
|
|
1657
|
+
* The Tier 0 battery — the things a careful person would check with a
|
|
1658
|
+
* browser and ten minutes, every one of them a pure function of the crawl.
|
|
1659
|
+
*
|
|
1660
|
+
* Four states per check, and only `pass`/`fail` count toward the denominator:
|
|
1661
|
+
* a site with no schema has not failed the schema checks, and printing
|
|
1662
|
+
* "34 of 40" where six were never applicable would be a number inflated on
|
|
1663
|
+
* our own behalf. Optional for reports stored before the stage existed.
|
|
1664
|
+
*/
|
|
1665
|
+
siteChecks?: StageResult<SiteCheck[]>;
|
|
1666
|
+
/**
|
|
1667
|
+
* The axe rule set, run against the rendered DOM.
|
|
1668
|
+
*
|
|
1669
|
+
* Named rules with named fixes, where the Lighthouse accessibility score is
|
|
1670
|
+
* one opaque number over a subset of the same rules. Optional for reports
|
|
1671
|
+
* stored before it existed — and absence means the rules did not run, never
|
|
1672
|
+
* that nothing was found.
|
|
1673
|
+
*/
|
|
1674
|
+
accessibility?: StageResult<AccessibilityResult>;
|
|
1675
|
+
/**
|
|
1676
|
+
* What the DOMAIN says — SPF, DMARC, mail servers, registration expiry.
|
|
1677
|
+
*
|
|
1678
|
+
* None of it touches their web server, and none of it is visible from any
|
|
1679
|
+
* amount of reading their HTML. Optional for reports stored before it
|
|
1680
|
+
* existed.
|
|
1681
|
+
*/
|
|
1682
|
+
dns?: StageResult<DnsFindings>;
|
|
1683
|
+
/**
|
|
1684
|
+
* What the server SERVED, as opposed to what the markup declared — the icon,
|
|
1685
|
+
* the share image, the sitemap's own URLs, and how many hops a link takes.
|
|
1686
|
+
*
|
|
1687
|
+
* The only part of the check battery that costs the prospect requests, which
|
|
1688
|
+
* is why it is capped, paced, and reports the count it made. Optional for
|
|
1689
|
+
* reports stored before it existed.
|
|
1690
|
+
*/
|
|
1691
|
+
http?: StageResult<HttpFindings>;
|
|
1109
1692
|
/** When an engine describes this business, where is it getting that from —
|
|
1110
1693
|
* each statement sorted by SOURCE, never by truth. See accuracy.ts. Optional
|
|
1111
1694
|
* for reports stored before the stage was wired in. */
|
|
1112
1695
|
accuracy?: StageResult<AccuracyResult>;
|
|
1113
1696
|
};
|
|
1114
1697
|
|
|
1115
|
-
export { type AnalyzeResult, type AnswerSpace, type AssetCheck, type BasicsCheck, type BuyerQuestion, type ChecksResult, type ConsistencyResult, type ContactAffordance, type ContactVariant, type CrawlResult, type Fix, type FormKind, type FormShape, GOAL_LABELS, type GoalFit, type GoalRequirement, type JourneyMap, type LighthouseScores, type PageAnchor, type PageCapture, type PageExtract, type PageJourney, type ProbeAnswer, type ProbedUrl, type ProbesResult, type ProspectAuditResult, type Reachability, type RobotsAgentAccess, type Scope, type Scores, type SiteGoal, type SourceCount, type StageResult, orderRequirements };
|
|
1698
|
+
export { type AccessibilityResult, type AnalyzeResult, type AnswerSpace, type AssetCheck, type AxeImpact, type AxePageResult, type AxeViolation, type BasicsCheck, type BuyerQuestion, type CheckStatus, type ChecksResult, type ConsistencyResult, type ContactAffordance, type ContactVariant, type CrawlResult, type DnsFindings, type Fix, type FormField, type FormKind, type FormProbe, type FormShape, GOAL_LABELS, type GoalFit, type GoalRequirement, type HttpFindings, type JourneyMap, LAYER_LABELS, LAYER_ORDER, type LighthouseScores, type PageAnchor, type PageCapture, type PageExtract, type PageJourney, type ProbeAnswer, type ProbedUrl, type ProbesResult, type ProspectAuditResult, type Reachability, type RobotsAgentAccess, type Scope, type Scores, type SiteCheck, type SiteGoal, type SourceCount, type StackItem, type StackLayer, type StackReadout, type StageResult, orderRequirements, tally };
|
package/dist/prospect/types.js
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
|
+
import {
|
|
2
|
+
LAYER_LABELS,
|
|
3
|
+
LAYER_ORDER,
|
|
4
|
+
tally
|
|
5
|
+
} from "../chunk-WJMPCVOR.js";
|
|
1
6
|
import {
|
|
2
7
|
GOAL_LABELS,
|
|
3
8
|
orderRequirements
|
|
4
9
|
} from "../chunk-T7ZUUOZ2.js";
|
|
10
|
+
import "../chunk-RARREDQE.js";
|
|
5
11
|
export {
|
|
6
12
|
GOAL_LABELS,
|
|
7
|
-
|
|
13
|
+
LAYER_LABELS,
|
|
14
|
+
LAYER_ORDER,
|
|
15
|
+
orderRequirements,
|
|
16
|
+
tally
|
|
8
17
|
};
|
|
9
18
|
//# sourceMappingURL=types.js.map
|