|
# retoor <retoor@molodetz.nl>
|
|
|
|
from __future__ import annotations
|
|
|
|
from collections import defaultdict
|
|
|
|
from .base import (
|
|
MEDIUM,
|
|
LOW,
|
|
INFO,
|
|
Check,
|
|
SiteContext,
|
|
site_check,
|
|
)
|
|
|
|
CATEGORY = "crosspage"
|
|
|
|
|
|
def _duplicates(site: SiteContext, dom_key: str) -> dict:
|
|
groups: dict[str, list] = defaultdict(list)
|
|
for page in site.pages:
|
|
value = (page.dom.get(dom_key, "") or "").strip().lower()
|
|
if value:
|
|
groups[value].append(page.url)
|
|
return {value: urls for value, urls in groups.items() if len(urls) > 1}
|
|
|
|
|
|
@site_check
|
|
def duplicate_titles(site: SiteContext) -> Check:
|
|
if len(site.pages) < 2:
|
|
return None
|
|
dupes = _duplicates(site, "title")
|
|
passed = not dupes
|
|
return Check(
|
|
"crosspage.duplicate_titles",
|
|
CATEGORY,
|
|
"Unique page titles",
|
|
"pass" if passed else "warn",
|
|
MEDIUM,
|
|
value="unique" if passed else f"{len(dupes)} duplicated title(s)",
|
|
recommendation="" if passed else "Give every page a distinct <title>.",
|
|
details={"duplicates": {k: v for k, v in list(dupes.items())[:10]}},
|
|
)
|
|
|
|
|
|
@site_check
|
|
def duplicate_descriptions(site: SiteContext) -> Check:
|
|
if len(site.pages) < 2:
|
|
return None
|
|
dupes = _duplicates(site, "metaDescription")
|
|
passed = not dupes
|
|
return Check(
|
|
"crosspage.duplicate_descriptions",
|
|
CATEGORY,
|
|
"Unique meta descriptions",
|
|
"pass" if passed else "warn",
|
|
LOW,
|
|
value="unique" if passed else f"{len(dupes)} duplicated description(s)",
|
|
recommendation="" if passed else "Write a distinct meta description for every page.",
|
|
details={"duplicates": {k: v for k, v in list(dupes.items())[:10]}},
|
|
)
|
|
|
|
|
|
@site_check
|
|
def hreflang_usage(site: SiteContext) -> Check:
|
|
annotated = [p for p in site.pages if p.dom.get("hreflang")]
|
|
if not annotated:
|
|
return None
|
|
return Check(
|
|
"crosspage.hreflang",
|
|
CATEGORY,
|
|
"Hreflang annotations",
|
|
INFO,
|
|
INFO,
|
|
value=f"{len(annotated)} page(s) declare hreflang",
|
|
details={
|
|
"pages": {p.url: p.dom.get("hreflang") for p in annotated[:5]},
|
|
},
|
|
)
|