searvex-seo 1.1.1 → 1.2.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.
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +43 -0
- package/README.md +3 -2
- package/dist/analyze/audit.d.ts +23 -1
- package/dist/analyze/audit.js +77 -15
- package/dist/analyze/audit.js.map +1 -1
- package/dist/analyze/pre-launch.d.ts +24 -0
- package/dist/analyze/pre-launch.js +57 -0
- package/dist/analyze/pre-launch.js.map +1 -0
- package/dist/analyze/structured-data.d.ts +12 -1
- package/dist/analyze/structured-data.js +38 -3
- package/dist/analyze/structured-data.js.map +1 -1
- package/dist/analyze/technical.js +17 -6
- package/dist/analyze/technical.js.map +1 -1
- package/dist/cli.d.ts +165 -0
- package/dist/cli.js +166 -59
- package/dist/cli.js.map +1 -1
- package/dist/commands/ecosystem.js +2 -1
- package/dist/commands/ecosystem.js.map +1 -1
- package/dist/commands/monitor.d.ts +2 -0
- package/dist/commands/monitor.js +25 -7
- package/dist/commands/monitor.js.map +1 -1
- package/dist/commands/research.js +2 -1
- package/dist/commands/research.js.map +1 -1
- package/dist/commands/run.js +45 -28
- package/dist/commands/run.js.map +1 -1
- package/dist/core/types.d.ts +6 -0
- package/dist/core/url.d.ts +15 -0
- package/dist/core/url.js +30 -0
- package/dist/core/url.js.map +1 -1
- package/dist/crawl/crawler.d.ts +18 -0
- package/dist/crawl/crawler.js +47 -4
- package/dist/crawl/crawler.js.map +1 -1
- package/dist/crawl/sitemap.d.ts +1 -0
- package/dist/crawl/sitemap.js +4 -3
- package/dist/crawl/sitemap.js.map +1 -1
- package/dist/extract/html.d.ts +11 -2
- package/dist/extract/html.js +60 -3
- package/dist/extract/html.js.map +1 -1
- package/dist/net/fetcher.d.ts +2 -2
- package/dist/net/fetcher.js +1 -1
- package/dist/optimize/fixes.js +1 -1
- package/dist/optimize/fixes.js.map +1 -1
- package/dist/repo/ast.d.ts +2 -0
- package/dist/repo/ast.js +2 -1
- package/dist/repo/ast.js.map +1 -1
- package/dist/repo/scan.js +18 -3
- package/dist/repo/scan.js.map +1 -1
- package/dist/report/client.js +7 -3
- package/dist/report/client.js.map +1 -1
- package/dist/report/i18n.js +4 -3
- package/dist/report/i18n.js.map +1 -1
- package/dist/report/markdown.js +27 -3
- package/dist/report/markdown.js.map +1 -1
- package/dist/report/sarif.js +3 -2
- package/dist/report/sarif.js.map +1 -1
- package/dist/rules/engine.d.ts +6 -0
- package/dist/rules/engine.js +2 -0
- package/dist/rules/engine.js.map +1 -1
- package/dist/rules/implemented.js +1 -1
- package/dist/rules/implemented.js.map +1 -1
- package/dist/searvex.mjs +538 -138
- package/knowledge/rules/canonicalization.json +6 -4
- package/knowledge/rules/crawlability.json +39 -2
- package/knowledge/rules/indexability.json +6 -4
- package/knowledge/rules/performance.json +4 -3
- package/knowledge/rules/security.json +4 -3
- package/knowledge/rules/structured-data.json +11 -5
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "searvex",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Understand search, fix what matters: deterministic technical SEO + GEO audits with a sourced rule base, a bilingual (EN/TR) action-center report with root-cause groups and repair prompts, competitor research, and safe, verified code fixes with rollback.",
|
|
5
5
|
"author": { "name": "Cihan Topaç", "url": "https://github.com/cihantopac" },
|
|
6
6
|
"license": "Apache-2.0",
|
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,49 @@ All notable changes to this project are documented here. The format follows
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [1.2.0] - 2026-11-03
|
|
9
|
+
|
|
10
|
+
Trustworthy in pre-launch and embedded use. Release notes: [docs/release-notes-1.2.0.md](docs/release-notes-1.2.0.md).
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- Exit code `4`: the start URL failed at the network level (DNS, TCP, TLS). `audit`, `geo`, `monitor` and `run`
|
|
14
|
+
write their reports with `crawl.status: "unreachable"`, no site findings and `scores.notApplicable`, instead of
|
|
15
|
+
reporting `robots.unreachable` with a score. An unreachable run is never used as a monitor baseline.
|
|
16
|
+
- A target blocked by the network policy (for example a local server without `--allow-private`) is now a usage
|
|
17
|
+
error (exit `2`) with a hint.
|
|
18
|
+
- `--help` and `docs/cli.md` list the exit codes; `5` is reserved for interrupted runs (planned, not returned yet).
|
|
19
|
+
- `--site-url <url>` in URL mode (`audit`, `geo`, `monitor`, `run`): audit a local or staging build as its public
|
|
20
|
+
site. Canonical, hreflang, sitemap and link URLs on the public origin are mapped to the crawled origin, so a
|
|
21
|
+
public self-canonical no longer shows up as `canonical.cross-domain` / `canonical.noindex-conflict`, and the
|
|
22
|
+
declared sitemap is read from the build. The report records `crawl.siteUrl` and says "Audited … as …".
|
|
23
|
+
- Rule `robots.sitemap-unreachable` (low): a sitemap declared in robots.txt cannot be fetched (DNS, connection,
|
|
24
|
+
TLS or non-200). Each failing declared sitemap is reported, also when another one works; with `--site-url` the
|
|
25
|
+
evidence names where it was fetched.
|
|
26
|
+
- `--pre-launch` profile for local and staging builds. Noindex pages are evaluated as they will be once live, and
|
|
27
|
+
their noindex is listed in a **Launch checklist**. Findings of rules tagged `environment: server | launch` (HTTPS
|
|
28
|
+
and compression on the test server; noindex, disallow-all, an unreachable public sitemap) get
|
|
29
|
+
`context: "environment" | "launch-checklist"` and are excluded from the score, `--fail-on`, priorities, SARIF
|
|
30
|
+
error levels and monitor regressions. The Markdown and HTML reports have a Launch checklist section and an
|
|
31
|
+
Environment-dependent note (EN/TR). On a local or private target the CLI suggests the flag.
|
|
32
|
+
|
|
33
|
+
### Changed
|
|
34
|
+
- **Exit code for runtime errors is now `3`** (was `2`). `2` stays for usage errors. Scripts that checked
|
|
35
|
+
`== 2` for crashes must check `3`.
|
|
36
|
+
- `robots.no-sitemap` now only means no `Sitemap:` directive and no `/sitemap.xml`. A declared but failing sitemap
|
|
37
|
+
was reported as `robots.no-sitemap` before; `monitor` shows that change once as one resolved and one new finding.
|
|
38
|
+
- `geo.organization-missing` suggests Organization (company or brand) **or** ProfilePage with a Person mainEntity
|
|
39
|
+
(personal site). A heuristic personal-site signal (a name-like homepage title, no product, pricing or shop
|
|
40
|
+
pages) makes Person the primary suggestion and says so. New source: Google ProfilePage structured data.
|
|
41
|
+
- `img.dimensions-missing` no longer reports images sized in CSS: fixed width and height (or `aspect-ratio`) in the
|
|
42
|
+
inline `style`, in a simple class or id rule of the page's own `<style>`, or fixed-size utility classes
|
|
43
|
+
(`size-10`, `w-10 h-10`, `w-[40px] h-[40px]`). External stylesheets are still not fetched.
|
|
44
|
+
- Repository mode (Next.js App Router): a route inherits `robots` noindex from its layouts unless the page sets
|
|
45
|
+
its own `robots`, so `canonical.missing` and `description.missing` no longer fire on routes that are noindex
|
|
46
|
+
through a layout. The summary and Markdown report say "0 indexable: all noindex" when that is the reason.
|
|
47
|
+
Pages router: a noindex in `_app` applies to every page.
|
|
48
|
+
- `--help` lists every option, including `--timeout <ms>` (default 15000, 1000–120000) and the command options;
|
|
49
|
+
a test keeps it complete.
|
|
50
|
+
|
|
8
51
|
## [1.1.1] - 2026-11-01
|
|
9
52
|
|
|
10
53
|
Visual polish; the analysis engine, rules, evidence and CLI are unchanged. Release notes:
|
package/README.md
CHANGED
|
@@ -85,6 +85,7 @@ Then run `/searvex <url> [path]`. Requires Node.js ≥ 20.10. Full reference: [d
|
|
|
85
85
|
## What it checks
|
|
86
86
|
|
|
87
87
|
- **Technical SEO** — crawlability, indexability, canonicals, redirects, hreflang, metadata, structured data, links, performance and security signals.
|
|
88
|
+
- **Local and staging builds** — audit a build as its public site (`--site-url`) with a pre-launch profile (`--pre-launch`): test-server findings and deliberate pre-launch states go to a launch checklist instead of the score.
|
|
88
89
|
- **GEO / AI search** — AI crawler access by purpose, snippet controls, entity consistency, content clarity.
|
|
89
90
|
- **Repositories** — findings with `file:line` in framework source, plus 12 rule types fixed automatically (dry run → approval → apply → verify → rollback).
|
|
90
91
|
- **Search data, optional and read-only** — Search Console (API or CSV export) and Chrome UX Report. Without them, clicks and Core Web Vitals are shown as *not measured*, never estimated.
|
|
@@ -92,9 +93,9 @@ Then run `/searvex <url> [path]`. Requires Node.js ≥ 20.10. Full reference: [d
|
|
|
92
93
|
|
|
93
94
|
## Evidence, not claims
|
|
94
95
|
|
|
95
|
-
Status: **v1.
|
|
96
|
+
Status: **v1.2.0** ([release notes](docs/release-notes-1.2.0.md), [changelog](CHANGELOG.md)).
|
|
96
97
|
|
|
97
|
-
- **
|
|
98
|
+
- **91 rules**, each tied to an official source: 72 verified, 17 heuristic, 2 reported as unmeasurable. `searvex rules show <id>`
|
|
98
99
|
- **Tested** with unit, integration, browser and end-to-end runs; CI on Linux, macOS and Windows with Node 20, 22 and 24 ([quality report](docs/quality.md)).
|
|
99
100
|
- **Validated** on 13 public sites and 9 repositories; live Search Console and CrUX values matched the official exports.
|
|
100
101
|
- **Safe by default** — read-only, SSRF protection, robots.txt honoured, secret files never read, every change journaled with byte-for-byte rollback.
|
package/dist/analyze/audit.d.ts
CHANGED
|
@@ -18,6 +18,12 @@ export interface AuditReport {
|
|
|
18
18
|
runId: string;
|
|
19
19
|
generatedAt: string;
|
|
20
20
|
crawl: CrawlResult['stats'] & {
|
|
21
|
+
/** Website mode: `unreachable` when the start URL failed at the network level and nothing was audited. */
|
|
22
|
+
status?: 'complete' | 'unreachable';
|
|
23
|
+
/** Network error for an unreachable target. */
|
|
24
|
+
error?: string;
|
|
25
|
+
/** Public origin the crawled origin stands for (--site-url); URLs on it were mapped to the crawled origin. */
|
|
26
|
+
siteUrl?: string;
|
|
21
27
|
truncated: boolean;
|
|
22
28
|
startUrl: string;
|
|
23
29
|
robots: {
|
|
@@ -54,10 +60,20 @@ export interface AuditReport {
|
|
|
54
60
|
/** Whether JavaScript was executed for at least one page (`--render`). */
|
|
55
61
|
rendered?: boolean;
|
|
56
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* Whether a finding counts toward the score, --fail-on, affected counts and regressions: unmeasurable
|
|
65
|
+
* findings and pre-launch context findings (environment, launch checklist) never do.
|
|
66
|
+
*/
|
|
67
|
+
export declare function countsTowardScore(f: Pick<Finding, 'confidence' | 'context'>): boolean;
|
|
57
68
|
/** Distinct affected URLs/files across all non-informational findings. */
|
|
58
69
|
export declare function countAffected(findings: Array<Finding & {
|
|
59
70
|
count: number;
|
|
60
71
|
}>, affected: (ruleId: string) => string[]): number;
|
|
72
|
+
/**
|
|
73
|
+
* Indexable pages as the rules decide indexability (inventory), e.g. "2 indexable" or "0 indexable: all
|
|
74
|
+
* noindex".
|
|
75
|
+
*/
|
|
76
|
+
export declare function indexableSummary(r: Pick<AuditReport, 'inventory' | 'findings'>): string;
|
|
61
77
|
export interface Scores {
|
|
62
78
|
/** 0–100. Searvex health score: a summary of Searvex findings, NOT a search engine metric. */
|
|
63
79
|
overall: number;
|
|
@@ -65,13 +81,16 @@ export interface Scores {
|
|
|
65
81
|
method: string;
|
|
66
82
|
/** Set when there was nothing to audit (e.g. a repository without any website); `overall` is then meaningless. */
|
|
67
83
|
notApplicable?: string;
|
|
84
|
+
/** `pre-launch`: environment and launch-checklist findings were excluded (--pre-launch). */
|
|
85
|
+
profile?: 'pre-launch';
|
|
68
86
|
}
|
|
69
87
|
/** "87/100", or "n/a" when nothing could be audited. */
|
|
70
88
|
export declare function scoreLabel(s: Scores): string;
|
|
71
89
|
/**
|
|
72
90
|
* Score = 100 − Σ(weight × affected-share), where affected-share = affected pages / indexable pages
|
|
73
91
|
* (capped at 1). Site-level findings count as share 1. Heuristic findings count half.
|
|
74
|
-
* Unmeasurable findings
|
|
92
|
+
* Unmeasurable findings, and environment/launch-checklist findings of the pre-launch profile, never change
|
|
93
|
+
* the score.
|
|
75
94
|
*/
|
|
76
95
|
export declare function computeScores(findings: Array<Finding & {
|
|
77
96
|
count: number;
|
|
@@ -89,6 +108,8 @@ export interface AuditOptions {
|
|
|
89
108
|
probes?: boolean;
|
|
90
109
|
checkExternal?: boolean;
|
|
91
110
|
cruxApiKey?: string;
|
|
111
|
+
/** Pre-launch profile (--pre-launch): see `applyPreLaunch`. */
|
|
112
|
+
preLaunch?: boolean;
|
|
92
113
|
}
|
|
93
114
|
export declare function auditWebsite(url: string, options?: AuditOptions): Promise<{
|
|
94
115
|
report: AuditReport;
|
|
@@ -98,4 +119,5 @@ export declare function analyzeCrawl(result: CrawlResult, kb: KnowledgeBase, opt
|
|
|
98
119
|
probes?: boolean;
|
|
99
120
|
checkExternal?: boolean;
|
|
100
121
|
cruxApiKey?: string;
|
|
122
|
+
preLaunch?: boolean;
|
|
101
123
|
}): Promise<AuditReport>;
|
package/dist/analyze/audit.js
CHANGED
|
@@ -5,6 +5,7 @@ import { DEFAULT_POLICY } from '../net/ssrf.js';
|
|
|
5
5
|
import { extractPage } from '../extract/html.js';
|
|
6
6
|
import { FindingSink, loadKnowledge } from '../rules/engine.js';
|
|
7
7
|
import { buildContext } from './context.js';
|
|
8
|
+
import { applyPreLaunch, asLaunched, emitLaunchNoindex } from './pre-launch.js';
|
|
8
9
|
import { runContentChecks } from './content.js';
|
|
9
10
|
import { runGeoChecks } from './geo.js';
|
|
10
11
|
import { buildInventory } from './inventory.js';
|
|
@@ -12,29 +13,47 @@ import { runTechnicalChecks } from './technical.js';
|
|
|
12
13
|
import { prioritise } from './priority.js';
|
|
13
14
|
import { checkExternalLinks } from './external-links.js';
|
|
14
15
|
import { failingMetrics, queryCrux } from '../integrations/crux.js';
|
|
16
|
+
/**
|
|
17
|
+
* Whether a finding counts toward the score, --fail-on, affected counts and regressions: unmeasurable
|
|
18
|
+
* findings and pre-launch context findings (environment, launch checklist) never do.
|
|
19
|
+
*/
|
|
20
|
+
export function countsTowardScore(f) {
|
|
21
|
+
return f.confidence !== 'unmeasurable' && !f.context;
|
|
22
|
+
}
|
|
15
23
|
/** Distinct affected URLs/files across all non-informational findings. */
|
|
16
24
|
export function countAffected(findings, affected) {
|
|
17
25
|
const all = new Set();
|
|
18
26
|
for (const f of findings)
|
|
19
|
-
if (f.severity !== 'info' && f
|
|
27
|
+
if (f.severity !== 'info' && countsTowardScore(f))
|
|
20
28
|
for (const u of affected(f.ruleId))
|
|
21
29
|
if (!/\/robots\.txt$/.test(u))
|
|
22
30
|
all.add(u);
|
|
23
31
|
return all.size;
|
|
24
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Indexable pages as the rules decide indexability (inventory), e.g. "2 indexable" or "0 indexable: all
|
|
35
|
+
* noindex".
|
|
36
|
+
*/
|
|
37
|
+
export function indexableSummary(r) {
|
|
38
|
+
const total = r.inventory.pages.length;
|
|
39
|
+
const indexable = r.inventory.pages.filter((p) => p.indexable).length;
|
|
40
|
+
const noindex = r.findings.find((f) => f.ruleId === 'index.noindex')?.count ?? 0;
|
|
41
|
+
return `${indexable} indexable${indexable === 0 && total > 0 && noindex >= total ? ': all noindex' : ''}`;
|
|
42
|
+
}
|
|
25
43
|
/** "87/100", or "n/a" when nothing could be audited. */
|
|
26
44
|
export function scoreLabel(s) {
|
|
27
|
-
return s.notApplicable ? 'n/a (nothing to audit)' : `${s.overall}/100`;
|
|
45
|
+
return s.notApplicable ? 'n/a (nothing to audit)' : `${s.overall}/100${s.profile === 'pre-launch' ? ' (pre-launch profile)' : ''}`;
|
|
28
46
|
}
|
|
29
47
|
const WEIGHT = { critical: 25, high: 10, medium: 4, low: 1.5, info: 0 };
|
|
30
48
|
/**
|
|
31
49
|
* Score = 100 − Σ(weight × affected-share), where affected-share = affected pages / indexable pages
|
|
32
50
|
* (capped at 1). Site-level findings count as share 1. Heuristic findings count half.
|
|
33
|
-
* Unmeasurable findings
|
|
51
|
+
* Unmeasurable findings, and environment/launch-checklist findings of the pre-launch profile, never change
|
|
52
|
+
* the score.
|
|
34
53
|
*/
|
|
35
54
|
export function computeScores(findings, pageCount) {
|
|
36
55
|
const penalty = (fs) => fs.reduce((sum, f) => {
|
|
37
|
-
if (f
|
|
56
|
+
if (!countsTowardScore(f))
|
|
38
57
|
return sum;
|
|
39
58
|
const share = pageCount > 0 ? Math.min(1, f.count / pageCount) : 1;
|
|
40
59
|
return sum + WEIGHT[f.severity] * Math.max(share, f.severity === 'critical' ? 1 : share) * (f.confidence === 'heuristic' ? 0.5 : 1);
|
|
@@ -92,25 +111,70 @@ async function probeHostVariants(startUrl, opts, sink) {
|
|
|
92
111
|
if (!res.error && res.status === 200)
|
|
93
112
|
sink.emit('canonical.www-duplicate', { url: alt.toString(), observed: `${alt.host} and ${u.host} both return 200` });
|
|
94
113
|
}
|
|
114
|
+
function crawlSummary(result) {
|
|
115
|
+
return {
|
|
116
|
+
...result.stats,
|
|
117
|
+
status: result.unreachable ? 'unreachable' : 'complete',
|
|
118
|
+
...(result.unreachable ? { error: result.unreachable.error } : {}),
|
|
119
|
+
...(result.siteUrl ? { siteUrl: result.siteUrl } : {}),
|
|
120
|
+
truncated: result.truncated,
|
|
121
|
+
startUrl: result.startUrl,
|
|
122
|
+
robots: { url: result.robots.url, state: result.robots.state, status: result.robots.status, sitemaps: result.robots.sitemaps },
|
|
123
|
+
sitemaps: result.sitemap.sitemaps,
|
|
124
|
+
sitemapUrls: result.sitemap.urls.length,
|
|
125
|
+
sitemapIssues: result.sitemap.issues.slice(0, 100),
|
|
126
|
+
};
|
|
127
|
+
}
|
|
95
128
|
export async function auditWebsite(url, options = {}) {
|
|
96
129
|
const kb = options.kb ?? loadKnowledge();
|
|
97
130
|
const store = new RunStore(options.workspace ?? process.cwd(), options.resumeRunId ?? RunStore.newRunId('audit'));
|
|
98
131
|
const result = await crawl(url, options.crawl, store);
|
|
99
|
-
const report = await analyzeCrawl(result, kb, { ...options.crawl, probes: options.probes ?? true, checkExternal: options.checkExternal, cruxApiKey: options.cruxApiKey });
|
|
132
|
+
const report = await analyzeCrawl(result, kb, { ...options.crawl, probes: options.probes ?? true, checkExternal: options.checkExternal, cruxApiKey: options.cruxApiKey, preLaunch: options.preLaunch });
|
|
100
133
|
store.writeJson('report.json', report);
|
|
101
134
|
return { report, store };
|
|
102
135
|
}
|
|
103
136
|
export async function analyzeCrawl(result, kb, opts = {}) {
|
|
104
137
|
const sink = new FindingSink(kb);
|
|
138
|
+
const launch = opts.preLaunch ? asLaunched(result) : undefined;
|
|
139
|
+
if (launch)
|
|
140
|
+
result = launch.result;
|
|
105
141
|
const ctx = buildContext(result);
|
|
106
142
|
const netOpts = { policy: opts.policy ?? DEFAULT_POLICY, timeoutMs: opts.timeoutMs ?? 15000, userAgent: opts.userAgent ?? DEFAULT_USER_AGENT };
|
|
143
|
+
const unreachable = result.unreachable;
|
|
107
144
|
let llms;
|
|
145
|
+
if (unreachable) {
|
|
146
|
+
// Nothing was fetched, so no check can say anything about the site. Run them on a throwaway sink
|
|
147
|
+
// only to build the (empty) report sections.
|
|
148
|
+
const none = new FindingSink(kb);
|
|
149
|
+
// robots.txt was never read, so no crawler access can be stated.
|
|
150
|
+
const geo = { ...runGeoChecks(ctx, none), bots: [] };
|
|
151
|
+
const content = runContentChecks(ctx, none);
|
|
152
|
+
return {
|
|
153
|
+
tool: { name: 'searvex', version: SEARVEX_VERSION, rulesVersion: kb.version },
|
|
154
|
+
mode: 'website',
|
|
155
|
+
target: result.startUrl,
|
|
156
|
+
runId: result.runId,
|
|
157
|
+
generatedAt: new Date().toISOString(),
|
|
158
|
+
crawl: crawlSummary(result),
|
|
159
|
+
inventory: buildInventory(ctx),
|
|
160
|
+
findings: [],
|
|
161
|
+
geo,
|
|
162
|
+
content,
|
|
163
|
+
scores: { ...computeScores([], 1), notApplicable: `target unreachable (${unreachable.error})` },
|
|
164
|
+
measurement: { verified: 0, heuristic: 0, unmeasurable: 0 },
|
|
165
|
+
limitations: [`The start URL could not be reached (${unreachable.error}); no page was fetched, so this report contains no findings about the site. Check the URL, DNS, the network or the server, then run the audit again.`],
|
|
166
|
+
affectedUrls: 0,
|
|
167
|
+
rendered: false,
|
|
168
|
+
};
|
|
169
|
+
}
|
|
108
170
|
if (opts.probes !== false) {
|
|
109
171
|
await probeHostVariants(result.startUrl, netOpts, sink);
|
|
110
172
|
await probeLocaleAdaptive(result.startUrl, netOpts, sink);
|
|
111
173
|
llms = await probeLlmsTxt(result.origin, netOpts);
|
|
112
174
|
}
|
|
113
175
|
runTechnicalChecks(ctx, sink);
|
|
176
|
+
if (launch)
|
|
177
|
+
emitLaunchNoindex(ctx, launch.noindex, sink);
|
|
114
178
|
const geo = runGeoChecks(ctx, sink, llms);
|
|
115
179
|
const content = runContentChecks(ctx, sink);
|
|
116
180
|
let externalLinks;
|
|
@@ -134,12 +198,18 @@ export async function analyzeCrawl(result, kb, opts = {}) {
|
|
|
134
198
|
const inventory = buildInventory(ctx);
|
|
135
199
|
const findings = sink.findings();
|
|
136
200
|
prioritise(findings, (id) => sink.affected(id), ctx);
|
|
201
|
+
if (opts.preLaunch)
|
|
202
|
+
applyPreLaunch(findings, kb);
|
|
137
203
|
const limitations = [
|
|
138
204
|
'Website mode sees only publicly reachable pages; it has no access to real traffic, rankings, Search Console or analytics data unless an integration is configured.',
|
|
139
205
|
'Response times are single-location lab samples, not Core Web Vitals field data.',
|
|
140
206
|
];
|
|
141
207
|
if (result.truncated)
|
|
142
208
|
limitations.unshift(`Crawl stopped at the page limit with ${result.stats.queuedRemaining} URLs still queued; site-level findings (duplicates, hreflang return links) are based on the crawled subset, and orphan pages are not reported (pages that were not crawled may link to them). Raise --max-pages for a complete picture.`);
|
|
209
|
+
if (launch)
|
|
210
|
+
limitations.push(`Pre-launch profile (--pre-launch): the site is audited as it will be once live. ${launch.noindex.size ? `${launch.noindex.size} noindex page(s) were evaluated as indexable; their noindex is in the launch checklist. ` : ''}Findings that depend on the test server (environment) or on a deliberate pre-launch state (launch checklist) are listed separately and excluded from the score and --fail-on.`);
|
|
211
|
+
if (result.siteUrl)
|
|
212
|
+
limitations.push(`Audited ${result.origin} as ${result.siteUrl} (--site-url): canonical, hreflang, sitemap and link URLs on ${result.siteUrl} were checked against the crawled pages at ${result.origin}; the public site itself was not fetched.`);
|
|
143
213
|
if (!opts.checkExternal)
|
|
144
214
|
limitations.push('Outbound links were not checked (use --check-external).');
|
|
145
215
|
if (!result.pages.some((p) => p.rendered))
|
|
@@ -150,20 +220,12 @@ export async function analyzeCrawl(result, kb, opts = {}) {
|
|
|
150
220
|
target: result.startUrl,
|
|
151
221
|
runId: result.runId,
|
|
152
222
|
generatedAt: new Date().toISOString(),
|
|
153
|
-
crawl:
|
|
154
|
-
...result.stats,
|
|
155
|
-
truncated: result.truncated,
|
|
156
|
-
startUrl: result.startUrl,
|
|
157
|
-
robots: { url: result.robots.url, state: result.robots.state, status: result.robots.status, sitemaps: result.robots.sitemaps },
|
|
158
|
-
sitemaps: result.sitemap.sitemaps,
|
|
159
|
-
sitemapUrls: result.sitemap.urls.length,
|
|
160
|
-
sitemapIssues: result.sitemap.issues.slice(0, 100),
|
|
161
|
-
},
|
|
223
|
+
crawl: crawlSummary(result),
|
|
162
224
|
inventory,
|
|
163
225
|
findings,
|
|
164
226
|
geo,
|
|
165
227
|
content,
|
|
166
|
-
scores: computeScores(findings, Math.max(1, ctx.indexable.length)),
|
|
228
|
+
scores: { ...computeScores(findings, Math.max(1, ctx.indexable.length)), ...(opts.preLaunch ? { profile: 'pre-launch' } : {}) },
|
|
167
229
|
measurement: {
|
|
168
230
|
verified: findings.filter((f) => f.confidence === 'verified').length,
|
|
169
231
|
heuristic: findings.filter((f) => f.confidence === 'heuristic').length,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/analyze/audit.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/analyze/audit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { Finding } from '../core/types.js';
|
|
2
|
+
import type { CrawlResult } from '../crawl/crawler.js';
|
|
3
|
+
import type { FindingSink, KnowledgeBase } from '../rules/engine.js';
|
|
4
|
+
import { type SiteContext } from './context.js';
|
|
5
|
+
/**
|
|
6
|
+
* Pre-launch profile (--pre-launch): the site is audited as it will be once it goes live.
|
|
7
|
+
*
|
|
8
|
+
* - Pages that are noindex now (meta robots or X-Robots-Tag, often set on purpose before launch) are
|
|
9
|
+
* evaluated as indexable, so every check that only runs on indexable pages still runs and the score's
|
|
10
|
+
* page base is not collapsed to zero. Their noindex is reported as a launch-checklist item instead.
|
|
11
|
+
* - Findings of rules tagged `environment: server` (the test server) or `launch` (a deliberate pre-launch
|
|
12
|
+
* state) get a `context` and leave the score, --fail-on, the priorities and monitor regressions.
|
|
13
|
+
*/
|
|
14
|
+
export interface LaunchView {
|
|
15
|
+
/** The crawl with noindex directives removed. */
|
|
16
|
+
result: CrawlResult;
|
|
17
|
+
/** Noindex directives per URL, as crawled. */
|
|
18
|
+
noindex: Map<string, string[]>;
|
|
19
|
+
}
|
|
20
|
+
export declare function asLaunched(result: CrawlResult): LaunchView;
|
|
21
|
+
/** Report the noindex that `asLaunched` removed, as the technical checks would have (launch checklist). */
|
|
22
|
+
export declare function emitLaunchNoindex(ctx: SiteContext, noindex: Map<string, string[]>, sink: FindingSink): void;
|
|
23
|
+
/** Mark findings of environment-tagged rules; they are kept and shown separately. */
|
|
24
|
+
export declare function applyPreLaunch(findings: Finding[], kb: KnowledgeBase): void;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { factsOf, isNoindex, isSelfCanonical, resolveRecord, robotsDirectives } from './context.js';
|
|
2
|
+
const NOINDEX = new Set(['noindex', 'none']);
|
|
3
|
+
function strip(d) {
|
|
4
|
+
// "none" = noindex, nofollow: keep the nofollow part.
|
|
5
|
+
return d.flatMap((x) => (x === 'none' ? ['nofollow'] : NOINDEX.has(x) ? [] : [x]));
|
|
6
|
+
}
|
|
7
|
+
function stripData(d) {
|
|
8
|
+
if (!d)
|
|
9
|
+
return d;
|
|
10
|
+
return { ...d, metaRobots: strip(d.metaRobots), botRobots: Object.fromEntries(Object.entries(d.botRobots).map(([k, v]) => [k, strip(v)])) };
|
|
11
|
+
}
|
|
12
|
+
export function asLaunched(result) {
|
|
13
|
+
const noindex = new Map();
|
|
14
|
+
const pages = result.pages.map((p) => {
|
|
15
|
+
if (!isNoindex(p))
|
|
16
|
+
return p;
|
|
17
|
+
noindex.set(p.url, [...new Set(robotsDirectives(p, ['googlebot', 'bingbot']))]);
|
|
18
|
+
return {
|
|
19
|
+
...p,
|
|
20
|
+
xRobots: strip(p.xRobots),
|
|
21
|
+
xRobotsByBot: Object.fromEntries(Object.entries(p.xRobotsByBot).map(([k, v]) => [k, strip(v)])),
|
|
22
|
+
data: stripData(p.data),
|
|
23
|
+
rendered: stripData(p.rendered),
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
return { result: { ...result, pages }, noindex };
|
|
27
|
+
}
|
|
28
|
+
/** Report the noindex that `asLaunched` removed, as the technical checks would have (launch checklist). */
|
|
29
|
+
export function emitLaunchNoindex(ctx, noindex, sink) {
|
|
30
|
+
for (const p of ctx.pages) {
|
|
31
|
+
const directives = noindex.get(p.url);
|
|
32
|
+
if (!directives || !factsOf(p) || p.status !== 200 || p.redirects.length)
|
|
33
|
+
continue;
|
|
34
|
+
sink.emit('index.noindex', { url: p.url, observed: directives.join(', ') });
|
|
35
|
+
if (p.inSitemap)
|
|
36
|
+
sink.emit('index.noindex-in-sitemap', { url: p.url });
|
|
37
|
+
}
|
|
38
|
+
for (const p of ctx.htmlPages) {
|
|
39
|
+
const canonical = factsOf(p)?.canonical;
|
|
40
|
+
if (!canonical || isSelfCanonical(p))
|
|
41
|
+
continue;
|
|
42
|
+
const target = resolveRecord(ctx, canonical);
|
|
43
|
+
if (target && !target.blockedByRobots && target.status === 200 && !target.redirects.length && noindex.has(target.url))
|
|
44
|
+
sink.emit('canonical.target-noindex', { url: p.url, observed: canonical });
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/** Mark findings of environment-tagged rules; they are kept and shown separately. */
|
|
48
|
+
export function applyPreLaunch(findings, kb) {
|
|
49
|
+
for (const f of findings) {
|
|
50
|
+
const env = kb.rules.get(f.ruleId)?.environment;
|
|
51
|
+
if (!env)
|
|
52
|
+
continue;
|
|
53
|
+
f.context = env === 'server' ? 'environment' : 'launch-checklist';
|
|
54
|
+
delete f.priority;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=pre-launch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pre-launch.js","sourceRoot":"","sources":["../../src/analyze/pre-launch.ts"],"names":[],"mappings":"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"}
|
|
@@ -23,5 +23,16 @@ export interface SdIssue {
|
|
|
23
23
|
docs: string;
|
|
24
24
|
}
|
|
25
25
|
export declare function validateNode(n: Node): SdIssue | null;
|
|
26
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Heuristic personal-site signal for the Organization-or-Person suggestion: the homepage title starts with a
|
|
28
|
+
* name-like phrase (2–3 capitalised words, no company words) and no page looks commercial.
|
|
29
|
+
*/
|
|
30
|
+
export declare function personalSiteSignal(homepageTitle: string | null | undefined, pageUrls: string[]): {
|
|
31
|
+
personal: boolean;
|
|
32
|
+
reason: string;
|
|
33
|
+
};
|
|
34
|
+
export declare function checkStructuredData(url: string, f: PageData, sink: FindingSink, isHomepage: boolean, signal?: {
|
|
35
|
+
personal: boolean;
|
|
36
|
+
reason: string;
|
|
37
|
+
}): void;
|
|
27
38
|
export {};
|
|
@@ -66,11 +66,46 @@ export function validateNode(n) {
|
|
|
66
66
|
}
|
|
67
67
|
return null;
|
|
68
68
|
}
|
|
69
|
-
|
|
69
|
+
/** Paths that indicate a business site (products, plans, a shop). */
|
|
70
|
+
const COMMERCIAL_PATH = /\/(pricing|prices|plans|products?|shop|store|cart|checkout|buy|fiyat(lar)?|urun(ler)?|magaza|sepet)(\/|$|\.)/i;
|
|
71
|
+
const ORG_WORDS = /\b(inc|ltd|llc|gmbh|corp|co|company|studio|studios|agency|labs?|group|team|solutions|software|technologies|a\.?ş|ltd\.?\s*şti)\b\.?/i;
|
|
72
|
+
/**
|
|
73
|
+
* Heuristic personal-site signal for the Organization-or-Person suggestion: the homepage title starts with a
|
|
74
|
+
* name-like phrase (2–3 capitalised words, no company words) and no page looks commercial.
|
|
75
|
+
*/
|
|
76
|
+
export function personalSiteSignal(homepageTitle, pageUrls) {
|
|
77
|
+
const name = (homepageTitle ?? '').split(/\s+[|·•—–:-]\s+/)[0].trim();
|
|
78
|
+
const word = "\\p{Lu}\\p{Ll}+(?:[-'’]\\p{Lu}?\\p{Ll}+)*\\.?";
|
|
79
|
+
const nameLike = new RegExp(`^${word}(?:\\s${word}){1,2}$`, 'u').test(name) && !ORG_WORDS.test(name);
|
|
80
|
+
const commercial = pageUrls.find((u) => {
|
|
81
|
+
try {
|
|
82
|
+
return COMMERCIAL_PATH.test(new URL(u).pathname);
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
if (!nameLike)
|
|
89
|
+
return { personal: false, reason: 'homepage title does not start with a personal name' };
|
|
90
|
+
if (commercial)
|
|
91
|
+
return { personal: false, reason: `commercial page ${commercial}` };
|
|
92
|
+
return { personal: true, reason: `homepage title starts with a name ("${name}") and no product, pricing or shop pages` };
|
|
93
|
+
}
|
|
94
|
+
function organizationMissing(url, observed, sink, signal) {
|
|
95
|
+
if (signal?.personal) {
|
|
96
|
+
sink.emit('geo.organization-missing', { url, observed: `${observed} — looks like a personal site (heuristic: ${signal.reason}): add ProfilePage with a Person mainEntity` }, {
|
|
97
|
+
message: 'The homepage has no Person / ProfilePage markup, and the site looks personal (heuristic). Google uses ProfilePage structured data for a page about a single person; Organization markup applies when the site represents a company or brand.',
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
sink.emit('geo.organization-missing', { url, observed: `${observed} — add Organization (company or brand) or ProfilePage with a Person mainEntity (personal site)` });
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
export function checkStructuredData(url, f, sink, isHomepage, signal) {
|
|
70
105
|
if (!f.jsonLd.length && !f.microdataTypes.length) {
|
|
71
106
|
sink.emit('sd.none', { url });
|
|
72
107
|
if (isHomepage)
|
|
73
|
-
|
|
108
|
+
organizationMissing(url, 'no structured data on homepage', sink, signal);
|
|
74
109
|
return;
|
|
75
110
|
}
|
|
76
111
|
const allTypes = new Set(f.microdataTypes);
|
|
@@ -102,7 +137,7 @@ export function checkStructuredData(url, f, sink, isHomepage) {
|
|
|
102
137
|
// A personal site describes a Person (often on a ProfilePage); Organization markup does not apply there.
|
|
103
138
|
const personal = allTypes.has('Person') || allTypes.has('ProfilePage');
|
|
104
139
|
if (isHomepage && !personal && !['Organization', 'Corporation', 'OnlineStore', 'OnlineBusiness', 'NGO', 'EducationalOrganization', 'GovernmentOrganization', ...LOCAL_BUSINESS_SUBTYPES].some((t) => allTypes.has(t))) {
|
|
105
|
-
|
|
140
|
+
organizationMissing(url, `types present: ${[...allTypes].join(', ') || 'none'}`, sink, signal);
|
|
106
141
|
}
|
|
107
142
|
}
|
|
108
143
|
//# sourceMappingURL=structured-data.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"structured-data.js","sourceRoot":"","sources":["../../src/analyze/structured-data.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"structured-data.js","sourceRoot":"","sources":["../../src/analyze/structured-data.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { normalizeUrl, sameSite } from '../core/url.js';
|
|
1
|
+
import { mapOrigin, normalizeUrl, originMap, sameSite } from '../core/url.js';
|
|
2
2
|
import { factsOf, isNoindex, isSelfCanonical, resolveRecord, robotsDirectives } from './context.js';
|
|
3
|
-
import { checkStructuredData } from './structured-data.js';
|
|
3
|
+
import { checkStructuredData, personalSiteSignal } from './structured-data.js';
|
|
4
4
|
import { detectLanguage, detectShortLanguage, primaryTag } from './language.js';
|
|
5
5
|
/** ISO 639-1 codes (complete list) used to validate hreflang. */
|
|
6
6
|
const ISO639_1 = new Set('aa ab ae af ak am an ar as av ay az ba be bg bh bi bm bn bo br bs ca ce ch co cr cs cu cv cy da de dv dz ee el en eo es et eu fa ff fi fj fo fr fy ga gd gl gn gu gv ha he hi ho hr ht hu hy hz ia id ie ig ii ik io is it iu ja jv ka kg ki kj kk kl km kn ko kr ks ku kv kw ky la lb lg li ln lo lt lu lv mg mh mi mk ml mn mr ms mt my na nb nd ne ng nl nn no nr nv ny oc oj om or os pa pi pl ps pt qu rm rn ro ru rw sa sc sd se sg si sk sl sm sn so sq sr ss st su sv sw ta te tg th ti tk tl tn to tr ts tt tw ty ug uk ur uz ve vi vo wa wo xh yi yo za zh zu'.split(' '));
|
|
@@ -51,8 +51,19 @@ export function runTechnicalChecks(ctx, sink) {
|
|
|
51
51
|
if (/^\s*crawl-delay\s*:/im.test(crawl.robots.raw))
|
|
52
52
|
sink.emit('robots.crawl-delay-ignored', { url: crawl.robots.url, observed: (/^\s*crawl-delay\s*:.*$/im.exec(crawl.robots.raw) ?? [''])[0].trim() });
|
|
53
53
|
}
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
// A declared sitemap that cannot be fetched is not a missing sitemap. Declared URLs on the --site-url origin
|
|
55
|
+
// were fetched at the crawled origin.
|
|
56
|
+
const smMap = originMap(crawl.siteUrl, crawl.origin);
|
|
57
|
+
const smIssues = new Map(crawl.sitemap.issues.map((i) => [i.sitemap, i.message]));
|
|
58
|
+
for (const declared of new Set(crawl.robots.sitemaps)) {
|
|
59
|
+
const fetched = mapOrigin(declared, smMap);
|
|
60
|
+
const failed = smIssues.get(fetched);
|
|
61
|
+
if (failed !== undefined && !crawl.sitemap.sitemaps.includes(fetched)) {
|
|
62
|
+
sink.emit('robots.sitemap-unreachable', { url: declared, observed: `${failed}${fetched !== declared ? ` (fetched at ${fetched})` : ''}` });
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (!crawl.sitemap.sitemaps.length && !crawl.robots.sitemaps.length)
|
|
66
|
+
sink.emit('robots.no-sitemap', { url: crawl.robots.url, observed: 'No Sitemap directive; /sitemap.xml not available' });
|
|
56
67
|
// ---- start URL ----
|
|
57
68
|
const start = ctx.byUrl.get(crawl.startUrl);
|
|
58
69
|
if (start && !start.blockedByRobots && (start.error || start.status >= 400)) {
|
|
@@ -176,7 +187,7 @@ export function runTechnicalChecks(ctx, sink) {
|
|
|
176
187
|
sink.emit('img.alt-missing', { url: p.url, observed: `${noAlt.length} image(s), e.g. ${noAlt[0].src.slice(0, 120)}` });
|
|
177
188
|
const noDim = f.images.filter((i) => i.src && (!i.width || !i.height) && !i.sizedByLayout);
|
|
178
189
|
if (noDim.length)
|
|
179
|
-
sink.emit('img.dimensions-missing', { url: p.url, observed: `${noDim.length} image(s) without width/height attributes` });
|
|
190
|
+
sink.emit('img.dimensions-missing', { url: p.url, observed: `${noDim.length} image(s) without width/height attributes or a fixed size in inline CSS (external stylesheets are not checked)` });
|
|
180
191
|
// Links
|
|
181
192
|
const uncrawlable = f.links.filter((l) => l.uncrawlable && l.text);
|
|
182
193
|
if (uncrawlable.length)
|
|
@@ -232,7 +243,7 @@ export function runTechnicalChecks(ctx, sink) {
|
|
|
232
243
|
if (selfCanon && !noindex)
|
|
233
244
|
checkHreflang(ctx, p.url, f, sink);
|
|
234
245
|
// Structured data
|
|
235
|
-
checkStructuredData(p.url, f, sink, p === ctx.homepage);
|
|
246
|
+
checkStructuredData(p.url, f, sink, p === ctx.homepage, p === ctx.homepage ? personalSiteSignal(f.title, ctx.htmlPages.map((x) => x.url)) : undefined);
|
|
236
247
|
}
|
|
237
248
|
for (const [title, urls] of titleMap)
|
|
238
249
|
if (urls.length > 1)
|