From 0d6840abb6eb06baa02a704d9f04bec4bbc4aaf2 Mon Sep 17 00:00:00 2001 From: sfw222 <2452042683@qq.com> Date: Fri, 19 Jun 2026 22:53:36 +0800 Subject: [PATCH 1/3] Initial commit: PrometheusDocs crawler with local modifications --- .gitignore | 16 + AGENTS.md | 32 + README.md | 189 ++ crawler_config.template.json | 19 + crawler_verse.json | 19 + docs_crawler.py | 3151 ++++++++++++++++++++++++++++++++++ image/1.png | Bin 0 -> 117854 bytes image/2.png | Bin 0 -> 101359 bytes run_crawler.bat | 113 ++ tests/test_docs_crawler.py | 388 +++++ 10 files changed, 3927 insertions(+) create mode 100644 .gitignore create mode 100644 AGENTS.md create mode 100644 README.md create mode 100644 crawler_config.template.json create mode 100644 crawler_verse.json create mode 100644 docs_crawler.py create mode 100644 image/1.png create mode 100644 image/2.png create mode 100644 run_crawler.bat create mode 100644 tests/test_docs_crawler.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..36ef842 --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +__pycache__/ +*.py[cod] +*.pyo + +# Local/generated workspace +.site_sync/ +.site_sync*/ +.moyu_sync/ +.omx/ +.playwright-mcp/ + +# Local runtime config (use template file for repo) +crawler_config.json + +# Local temporary configs +tmp_*.json diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..946c51d --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,32 @@ +# Repository Guidelines + +## Project Purpose +This repository is a **generic documentation crawler**: + +1. Crawl a target docs site and store markdown files. +2. Build a local HTML viewer with sidebar navigation + markdown content panel. + +## Main Files +- `docs_crawler.py`: core CLI (init / crawl / build-site / run / status / preview) +- `crawler_config.json`: target site and runtime settings +- `run_crawler.bat`: one-click Windows entrypoint +- `tests/test_docs_crawler.py`: unit tests + +## Output Workspace +Generated data is written to `.site_sync/` (configurable): +- `source_md/` +- `manifests/source_manifest.json` +- `source_site/index.html` +- `reports/` + +## Development Commands +```powershell +python docs_crawler.py --config crawler_config.json run +python docs_crawler.py --config crawler_config.json preview --port 8777 +python -m unittest discover -s tests -p "test_*.py" -v +``` + +## Style +- Python 3.10+ +- PEP 8, 4 spaces +- Keep changes focused and reversible diff --git a/README.md b/README.md new file mode 100644 index 0000000..9ca63d3 --- /dev/null +++ b/README.md @@ -0,0 +1,189 @@ +# 通用文档爬虫(Generic Docs Crawler) + +一个面向文档站离线化的 Python 工具: +**抓取源站文档 → 输出 Markdown → 构建本地 HTML 文档站(左侧导航 + 右侧正文)**。 + +--- + +## 功能特性 + +- 支持抓取常见文档站(VitePress / Docusaurus 结构) +- 支持多文档根路径自动识别(如 `/guide`、`/components`) +- 支持“根路径 404,但叶子文档可访问”的站点结构 +- 导航结构尽量贴近源站层级(一级/二级) +- 详细日志与保活输出(当前阶段、URL、进度、速率、ETA) +- 一键预览本地 HTML 文档站 +- 输出标准 Markdown 目录,便于后续二次加工 + +--- + +## 适用场景 + +- 文档站离线备份 +- 内网镜像阅读 +- 文档迁移与归档 +- 导航结构和正文内容对照审查 + +--- + +## 界面截图 + +### 源网站 + +![源网站截图](image/1.png) + +### 本地预览站 + +![本地预览截图](image/2.png) + +--- + +## 环境要求 + +- Python 3.10+ +- Windows PowerShell(推荐)或 CMD + +--- + +## 快速开始 + +### 1) 准备配置 + +仓库内提供模板配置:`crawler_config.template.json`。 + +```powershell +Copy-Item crawler_config.template.json crawler_config.json +``` + +编辑 `crawler_config.json`(关键字段): + +- `target.base_url`:目标站点域名(例如 `https://docs.example.com`) +- `target.seed_path`:入口路径(通常留空) +- `target.docs_root`:文档根路径(可留空) + +> `crawler_config.json` 已加入 `.gitignore`,默认不提交到仓库。 + +--- + +### 2) 一键运行(BAT) + +```powershell +run_crawler.bat +``` + +菜单: + +- `1` 抓取并构建站点 +- `2` 预览本地站点 +- `3` 查看状态 +- `0` 退出 + +--- + +### 3) 命令行运行(Python) + +```powershell +# 初始化工作目录 +python docs_crawler.py --config crawler_config.json init + +# 仅抓取 +python docs_crawler.py --config crawler_config.json crawl + +# 仅构建本地站点 +python docs_crawler.py --config crawler_config.json build-site --menu-mode nav + +# 抓取 + 构建(推荐) +python docs_crawler.py --config crawler_config.json run + +# 本地预览 +python docs_crawler.py --config crawler_config.json preview --port 8777 +``` + +--- + +## docs_root 配置说明(重要) + +### 方案 A:手动指定单根路径 + +```json +"docs_root": "/guide" +``` + +适合你明确知道文档主路径时使用。 + +### 方案 B:留空自动识别(推荐) + +```json +"docs_root": "" +``` + +程序会自动探测多个文档根路径并合并抓取。 +也兼容如下情况: + +- `/components/` 返回 404 +- 但 `/components/xxx.html` 可访问(会自动纳入抓取) + +--- + +## 输出目录结构 + +默认输出到 `.site_sync/`: + +- `source_md/`:抓取后的 Markdown 源文件 +- `manifests/source_manifest.json`:抓取清单 +- `source_site/index.html`:本地预览入口 +- `source_site/docs/...`:预览站点引用的 md 文件 +- `reports/`:抓取/构建报告 + +--- + +## 常用参数 + +- `--max-docs N`:仅抓取前 N 篇(调试时非常有用) +- `--menu-mode nav`:仅保留导航中出现的文档(推荐) +- `--menu-mode all`:展示所有抓取到的文档 + +示例: + +```powershell +python docs_crawler.py --config crawler_config.json run --max-docs 20 +``` + +--- + +## 排错建议 + +### 1) 预览页面空白/无正文 + +按顺序执行: + +```powershell +python docs_crawler.py --config crawler_config.json run +python docs_crawler.py --config crawler_config.json preview --port 8777 +``` + +浏览器使用 `Ctrl + F5` 强制刷新。 + +### 2) 导航层级不对或标题异常 + +- 先执行一次完整 `run`,不要只 `preview` +- 确认使用了最新构建产物(`source_site/index.html`) + +### 3) 控制台中文乱码 + +Windows 下建议在 UTF-8 终端运行,或使用 PowerShell 7。 + +--- + +## 测试 + +```powershell +python -m unittest discover -s tests -p "test_*.py" -v +``` + +--- + +## 项目定位 + +本项目聚焦于“**文档抓取 + 本地文档站生成**”两件事, +不绑定特定产品,不依赖登录态,适合作为通用文档镜像工具的基础版本。 diff --git a/crawler_config.template.json b/crawler_config.template.json new file mode 100644 index 0000000..c9df0ec --- /dev/null +++ b/crawler_config.template.json @@ -0,0 +1,19 @@ +{ + "target": { + "base_url": "https://docs.example.com", + "seed_path": "", + "docs_root": "" + }, + "workspace": ".site_sync", + "crawler": { + "timeout_seconds": 30, + "http_retries": 3, + "retry_backoff_seconds": 1.5, + "continue_on_doc_error": true, + "max_docs": 0 + }, + "site": { + "output_dir": "source_site", + "menu_mode": "nav" + } +} diff --git a/crawler_verse.json b/crawler_verse.json new file mode 100644 index 0000000..6051798 --- /dev/null +++ b/crawler_verse.json @@ -0,0 +1,19 @@ +{ + "target": { + "base_url": "https://verselang.github.io/book/", + "seed_path": "", + "docs_root": "/book/" + }, + "workspace": "F:/Docs/.site_sync_verse", + "crawler": { + "timeout_seconds": 30, + "http_retries": 3, + "retry_backoff_seconds": 1.5, + "continue_on_doc_error": true, + "max_docs": 0 + }, + "site": { + "output_dir": "source_site", + "menu_mode": "nav" + } +} \ No newline at end of file diff --git a/docs_crawler.py b/docs_crawler.py new file mode 100644 index 0000000..081a444 --- /dev/null +++ b/docs_crawler.py @@ -0,0 +1,3151 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +Generic documentation crawler. + +What it does: +1) Crawl docs pages from a configurable docs site and save markdown files. +2) Build a local HTML viewer with left navigation + right markdown panel. + +No product-specific rewriting or brand-coupled behavior. +""" + +from __future__ import annotations + +import argparse +import datetime as dt +import html +import http.server +import json +import os +import re +import shutil +import socket +import socketserver +import sys +import threading +import time +import traceback +import urllib.error +import urllib.parse +import urllib.request +from pathlib import Path +from typing import Dict, List, Optional, Sequence, Tuple + +DEFAULT_CONFIG_PATH = "crawler_config.json" + + +# ----------------------------- +# basic io helpers +# ----------------------------- +def now_iso() -> str: + return dt.datetime.now().astimezone().isoformat() + + +def now_hms() -> str: + return dt.datetime.now().strftime("%H:%M:%S") + + +def log(message: str) -> None: + text = f"[{now_hms()}] {message}" + try: + print(text, flush=True) + except UnicodeEncodeError: + enc = getattr(sys.stdout, "encoding", None) or "utf-8" + safe = text.encode(enc, errors="replace").decode(enc, errors="replace") + print(safe, flush=True) + + +def ensure_dir(path: Path) -> None: + path.mkdir(parents=True, exist_ok=True) + + +def load_json(path: Path, default): + if not path.exists(): + return default + try: + return json.loads(path.read_text(encoding="utf-8")) + except Exception: + return default + + +def save_json(path: Path, data) -> None: + ensure_dir(path.parent) + path.write_text(json.dumps(data, ensure_ascii=False, indent=2) + "\n", encoding="utf-8") + + +def write_text(path: Path, text: str) -> None: + ensure_dir(path.parent) + path.write_text(text, encoding="utf-8") + + +def copy_file(src: Path, dst: Path) -> bool: + if not src.exists(): + return False + ensure_dir(dst.parent) + shutil.copy2(src, dst) + return True + + +class ProgressHeartbeat: + """ + Periodically prints progress heartbeat so users can see the program is alive. + """ + + def __init__(self, name: str, interval_seconds: int = 8) -> None: + self.name = name + self.interval_seconds = max(3, int(interval_seconds)) + self._lock = threading.Lock() + self._stop = threading.Event() + self._thread: Optional[threading.Thread] = None + self._state = { + "phase": "初始化", + "step": "-", + "url": "-", + "done": 0, + "total": 0, + "last_touch": time.time(), + "started_at": time.time(), + } + + def start(self) -> "ProgressHeartbeat": + self._thread = threading.Thread(target=self._run, name=f"heartbeat-{self.name}", daemon=True) + self._thread.start() + return self + + def stop(self) -> None: + self._stop.set() + if self._thread and self._thread.is_alive(): + self._thread.join(timeout=1.5) + + def update( + self, + *, + phase: Optional[str] = None, + step: Optional[str] = None, + url: Optional[str] = None, + done: Optional[int] = None, + total: Optional[int] = None, + ) -> None: + with self._lock: + if phase is not None: + self._state["phase"] = phase + if step is not None: + self._state["step"] = step + if url is not None: + self._state["url"] = url + if done is not None: + self._state["done"] = int(done) + if total is not None: + self._state["total"] = int(total) + self._state["last_touch"] = time.time() + + def _run(self) -> None: + while not self._stop.wait(self.interval_seconds): + with self._lock: + phase = self._state["phase"] + step = self._state["step"] + url = self._state["url"] + done = int(self._state["done"]) + total = int(self._state["total"]) + idle = int(time.time() - float(self._state["last_touch"])) + started_at = float(self._state["started_at"]) + percent = 0.0 if total <= 0 else (done / total) * 100 + elapsed = max(0.001, time.time() - started_at) + speed = done / elapsed # docs/sec + speed_min = speed * 60 + remain = max(0, total - done) + eta_seconds = int(remain / speed) if speed > 0 else -1 + eta_text = "-" if eta_seconds < 0 else f"{eta_seconds}s" + log( + f"[保活] 阶段={phase} 进度={done}/{total} ({percent:.1f}%) " + f"速度={speed_min:.2f} docs/min ETA={eta_text} " + f"当前={step} 空闲={idle}s URL={url}" + ) + + +def progress_bar(done: int, total: int, width: int = 28) -> str: + if total <= 0: + return "[----------------------------] 0.0%" + ratio = max(0.0, min(1.0, done / total)) + filled = int(ratio * width) + bar = "█" * filled + "-" * (width - filled) + return f"[{bar}] {ratio * 100:5.1f}%" + + +def log_progress_line(prefix: str, done: int, total: int, started_at: float) -> None: + elapsed = max(0.001, time.time() - started_at) + speed = done / elapsed + speed_min = speed * 60 + remain = max(0, total - done) + eta_seconds = int(remain / speed) if speed > 0 else -1 + eta_text = "-" if eta_seconds < 0 else f"{eta_seconds}s" + bar = progress_bar(done, total) + log(f"{prefix} {bar} {done}/{total} 速度={speed_min:.2f} docs/min ETA={eta_text}") + + +def sanitize_segment(text: str, fallback: str = "uncategorized") -> str: + name = (text or "").strip() + if not name: + return fallback + name = re.sub(r'[\\/:*?"<>|]+', "_", name) + name = re.sub(r"\s+", "", name) + return name.strip("._") or fallback + + +def slug_to_source_filename(slug: str) -> str: + safe = re.sub(r"[^a-zA-Z0-9_\-/\.]+", "-", slug.strip("/")) + safe = safe.replace("/", "__") + if not safe: + safe = "index" + return f"{safe}.source.md" + + +def build_doc_source_url(base_url: str, docs_root: str, slug: str) -> str: + root = "/" + (docs_root or "/docs").strip("/") + s = (slug or "").strip("/") + if s in {"", "index"}: + return urllib.parse.urljoin(base_url, root.rstrip("/") + "/") + return urllib.parse.urljoin(base_url, f"{root.rstrip('/')}/{s}") + + +# ----------------------------- +# http / parse helpers +# ----------------------------- +def build_doc_source_url_with_meta(base_url: str, docs_root: str, slug: str, meta: Optional[dict] = None) -> str: + m = meta or {} + source_path = (m.get("source_path") or "").strip() + if source_path: + return urllib.parse.urljoin(base_url, source_path) + source_root = (m.get("source_root") or docs_root or "/docs").strip() or "/docs" + return build_doc_source_url(base_url, source_root, slug) + + +def make_source_path(docs_root: str, rel_slug: str) -> str: + root = "/" + (docs_root or "/docs").strip("/") + rel = (rel_slug or "").strip("/") + if rel in {"", "index"}: + return root.rstrip("/") + "/" + return f"{root.rstrip('/')}/{rel}" + + +def make_compound_slug(docs_root: str, rel_slug: str, multi_root: bool) -> str: + rel = (rel_slug or "").strip("/") or "index" + if not multi_root: + return rel + root_tag = (docs_root or "/docs").strip("/") or "docs" + return f"{root_tag}/{rel}" + + +def make_route_candidates(rel_slug: str, slug: str) -> List[str]: + candidates: List[str] = [] + for raw in [rel_slug or "", slug or ""]: + s = raw.strip("/").lower() + if not s: + continue + for x in [s, s.rstrip("/"), s.removesuffix(".html")]: + if x and x not in candidates: + candidates.append(x) + if "index" not in candidates: + candidates.append("index") + return candidates + + +def http_get_text( + url: str, + timeout: int = 30, + retries: int = 3, + backoff_seconds: float = 1.5, +) -> str: + req = urllib.request.Request(url, headers={"User-Agent": "DocsCrawler/1.0"}) + retries = max(1, int(retries)) + last_error: Optional[Exception] = None + for attempt in range(1, retries + 1): + t0 = time.time() + log(f"[HTTP] 请求开始 attempt={attempt}/{retries} timeout={timeout}s url={url}") + try: + with urllib.request.urlopen(req, timeout=timeout) as resp: + raw = resp.read() + elapsed = time.time() - t0 + log(f"[HTTP] 请求成功 status={getattr(resp, 'status', '?')} bytes={len(raw)} 耗时={elapsed:.2f}s url={url}") + return raw.decode("utf-8", errors="replace") + except (urllib.error.URLError, TimeoutError, socket.timeout) as e: + last_error = e + if attempt >= retries: + break + sleep_seconds = float(backoff_seconds) * attempt + elapsed = time.time() - t0 + log(f"[HTTP][WARN] 请求失败 attempt={attempt}/{retries} 耗时={elapsed:.2f}s url={url} err={e}") + log(f"[HTTP][WARN] 等待重试 sleep={sleep_seconds:.1f}s") + time.sleep(sleep_seconds) + except Exception: + raise + raise RuntimeError(f"request failed after {retries} retries: {url} | {last_error}") + + +def infer_category_number(text: str) -> Optional[int]: + m = re.match(r"^\s*(\d+)(?:\.\d+)?", text or "") + if not m: + return None + try: + return int(m.group(1)) + except Exception: + return None + + +def pick_attr_value(m: Optional[re.Match], start_idx: int = 1) -> str: + if not m: + return "" + end = (m.lastindex or 0) + 1 + for i in range(start_idx, end): + val = m.group(i) + if val: + return val + return "" + + +def strip_tags(text: str) -> str: + return html.unescape(re.sub(r"<[^>]+>", "", text or "")).strip() + + +def normalize_docs_href(href: str, docs_root: str = "/docs") -> str: + docs_root = "/" + docs_root.strip("/") + p = urllib.parse.urlparse(href or "") + path = p.path or "" + if not path.startswith(docs_root + "/"): + return "" + return path[len(docs_root) + 1 :].strip("/") + + +def _looks_like_docs_html(page_html: str, docs_root: str) -> bool: + text = page_html or "" + if not text: + return False + markers = [ + "theme-doc-sidebar-item", + "VPSidebar", + "VPDoc", + "vitepress", + "docusaurus", + ] + if any(m.lower() in text.lower() for m in markers): + return True + docs_root = "/" + (docs_root or "/docs").strip("/") + # Check for relative or absolute links under docs_root (quoted or unquoted) + escaped = re.escape(docs_root) + if re.search(rf'href=(?:"|\')?(?:https?://[^/]+)?{escaped}/', text, re.I): + return True + # Last-resort: accept any page with |\s*\s*|$))', + re.S, + ) + + categories: Dict[str, dict] = {} + slug_to_category: Dict[str, str] = {} + slug_titles: Dict[str, str] = {} + ordered_keys: List[str] = [] + + for idx, m in enumerate(item_re.finditer(seed_html or "")): + cls = m.group("class") or "" + body = m.group("body") or "" + + a_match = re.search( + r"]*href=(?:\"([^\"]+)\"|'([^']+)'|([^\s>]+))[^>]*>(?P.*?)", + body, + re.S, + ) + href = pick_attr_value(a_match, 1).strip() + if not href: + continue + + a_body = a_match.group("a_body") if a_match else body + title_match = re.search(r"]*title=(?:\"([^\"]+)\"|'([^']+)'|([^\s>]+))", a_body, re.S) + title = html.unescape(pick_attr_value(title_match, 1)).strip() or strip_tags(a_body) + if not title: + continue + + rel = normalize_docs_href(href, docs_root=docs_root) + if not rel: + continue + + number = infer_category_number(title) + order = number if number is not None else (1000 + idx) + + if "theme-doc-sidebar-item-category-level-1" in cls and rel.startswith("category/"): + key = f"cat:{rel[len('category/'):]}" + categories[key] = { + "key": key, + "label": title, + "order": order, + "number": number, + "folder": sanitize_segment(title), + "kind": "category", + } + ordered_keys.append(key) + continue + + if "theme-doc-sidebar-item-link-level-1" in cls and not rel.startswith("category/"): + slug = rel + key = f"doc:{slug}" + categories[key] = { + "key": key, + "label": title, + "order": order, + "number": number, + "folder": sanitize_segment(title), + "kind": "doc", + } + ordered_keys.append(key) + slug_to_category[slug] = key + slug_titles[slug] = title + + # unique keep order + seen = set() + ordered: List[str] = [] + for k in ordered_keys: + if k in seen: + continue + seen.add(k) + ordered.append(k) + + result = { + "categories": categories, + "slug_to_category": slug_to_category, + "slug_titles": slug_titles, + "ordered_keys": ordered, + } + if categories or slug_to_category: + return result + + # fallback: VitePress sidebar + vitepress = _extract_sidebar_structure_vitepress(seed_html, docs_root=docs_root) + if (vitepress.get("categories") or {}) or (vitepress.get("slug_to_category") or {}): + return vitepress + + # fallback: generic link extraction (MkDocs, plain HTML, etc.) + generic = _extract_sidebar_structure_generic(seed_html, docs_root=docs_root) + if (generic.get("categories") or {}) or (generic.get("slug_to_category") or {}): + return generic + return result + + +def parse_doc_entries_from_category_page(page_html: str, docs_root: str = "/docs") -> List[Tuple[str, str]]: + """ + Parse second-level sidebar entries from category page. + + Important: do NOT parse all links in page body, otherwise article internal links + will pollute navigation and make level-2 menu differ from source site. + """ + out: List[Tuple[str, str]] = [] + seen = set() + docs_root_norm = "/" + docs_root.strip("/") + + # Prefer explicit sidebar level-2 link items. + sidebar_re = re.compile( + r'theme-doc-sidebar-item-link-level-2[^>]*>\s*]*href=(?:"([^"]+)"|\'([^\']+)\'|([^\s>]+))[^>]*>' + r'(?:\s*]*title=(?:"([^"]+)"|\'([^\']+)\'|([^\s>]+))[^>]*>)?', + re.S | re.I, + ) + for m in sidebar_re.finditer(page_html or ""): + href = (m.group(1) or m.group(2) or m.group(3) or "").strip() + if not href: + continue + p = urllib.parse.urlparse(href) + path = (p.path or "").rstrip("/") + if path == docs_root_norm.rstrip("/"): + rel = "index" + else: + rel = normalize_docs_href(href, docs_root=docs_root) + if not rel or rel.startswith("category/"): + continue + label = html.unescape((m.group(4) or m.group(5) or m.group(6) or "").strip()) + if not label: + label = rel + key = (rel, label) + if key in seen: + continue + seen.add(key) + out.append((rel, label)) + + if out: + return out + + # Fallback for non-Docusaurus or unexpected structures. + a_re = re.compile( + r"]*href=(?:\"([^\"]+)\"|'([^']+)'|([^\s>]+))[^>]*>(?P.*?)", + re.S | re.I, + ) + for m in a_re.finditer(page_html or ""): + href = (m.group(1) or m.group(2) or m.group(3) or "").strip() + if not href: + continue + p = urllib.parse.urlparse(href) + path = (p.path or "").rstrip("/") + if path == docs_root_norm.rstrip("/"): + rel = "index" + else: + rel = normalize_docs_href(href, docs_root=docs_root) + if not rel or rel.startswith("category/"): + continue + label = strip_tags(m.group("body") or "") + if not label: + continue + key = (rel, label) + if key in seen: + continue + seen.add(key) + out.append((rel, label)) + return out + + +def parse_doc_slugs_from_sitemap(xml_text: str, docs_root: str = "/docs") -> List[str]: + out: List[str] = [] + seen = set() + docs_root = "/" + docs_root.strip("/") + for url in re.findall(r"(.*?)", xml_text or "", re.I | re.S): + u = url.strip() + if not u: + continue + p = urllib.parse.urlparse(u) + path = (p.path or "").rstrip("/") + if path == docs_root: + # Site home page is also a doc page (common in MkDocs) + if "index" not in seen: + seen.add("index") + out.append("index") + continue + if not path.startswith(docs_root + "/"): + continue + rel = path[len(docs_root) + 1 :].strip("/") + if not rel or rel.startswith("category/"): + continue + if rel in seen: + continue + seen.add(rel) + out.append(rel) + return out + + +def html_to_markdown(article_html: str) -> str: + text = article_html or "" + + # remove script/style + text = re.sub(r"<(script|style)\b[^>]*>.*?", "", text, flags=re.I | re.S) + + # code blocks first + code_blocks: List[str] = [] + + def _extract_code(m: re.Match) -> str: + raw = m.group(1) or "" + raw = re.sub(r"^\s*]*>|\s*$", "", raw, flags=re.I | re.S) + raw = re.sub(r"<[^>]+>", "", raw) + raw = html.unescape(raw) + raw = raw.strip("\n") + code_blocks.append(raw) + return f"\n@@CODEBLOCK_{len(code_blocks)-1}@@\n" + + text = re.sub(r"]*>(.*?)", _extract_code, text, flags=re.I | re.S) + + # links + text = re.sub( + r"]*href=(?:\"([^\"]+)\"|'([^']+)'|([^\s>]+))[^>]*>(.*?)", + lambda m: f"[{strip_tags(m.group(4) or '')}]({(m.group(1) or m.group(2) or m.group(3) or '').strip()})", + text, + flags=re.I | re.S, + ) + + # headings + for n in range(6, 0, -1): + text = re.sub( + rf"]*>(.*?)", + lambda m, lv=n: "\n" + ("#" * lv) + " " + strip_tags(m.group(1) or "") + "\n", + text, + flags=re.I | re.S, + ) + + # simple blocks + text = re.sub(r"]*>(.*?)", lambda m: "\n> " + strip_tags(m.group(1) or "") + "\n", text, flags=re.I | re.S) + text = re.sub(r"]*>(.*?)", lambda m: "\n- " + strip_tags(m.group(1) or ""), text, flags=re.I | re.S) + + # tables: convert to markdown + def _table_to_markdown(table_html: str) -> str: + """Convert HTML table to markdown table.""" + rows: List[List[str]] = [] + for tr in re.finditer(r"]*>(.*?)", table_html, re.I | re.S): + cells: List[str] = [] + for cell in re.finditer(r"]*>(.*?)", tr.group(1), re.I | re.S): + cells.append(strip_tags(cell.group(1) or "")) + rows.append(cells) + if not rows: + return "" + max_cols = max(len(r) for r in rows) + # Normalize: pad short rows + for r in rows: + while len(r) < max_cols: + r.append("") + # Build markdown + lines: List[str] = [] + # Header row + first = rows[0] + lines.append("| " + " | ".join(first) + " |") + # Separator + lines.append("| " + " | ".join(["---"] * max_cols) + " |") + # Data rows + for r in rows[1:]: + lines.append("| " + " | ".join(r) + " |") + return "\n" + "\n".join(lines) + "\n" + + text = re.sub(r"]*>(.*?)
", lambda m: _table_to_markdown(m.group(0)), text, flags=re.I | re.S) + + text = re.sub(r"<(p|div|section|article|main)[^>]*>", "\n", text, flags=re.I) + text = re.sub(r"", "\n", text, flags=re.I) + text = re.sub(r"", "\n", text, flags=re.I) + + # inline emphasis + text = re.sub(r"<(strong|b)[^>]*>(.*?)", lambda m: f"**{strip_tags(m.group(2) or '')}**", text, flags=re.I | re.S) + text = re.sub(r"<(em|i)[^>]*>(.*?)", lambda m: f"*{strip_tags(m.group(2) or '')}*", text, flags=re.I | re.S) + text = re.sub(r"]*>(.*?)", lambda m: f"`{strip_tags(m.group(1) or '')}`", text, flags=re.I | re.S) + + # strip leftovers + text = strip_tags(text) + + # restore code blocks + for idx, code in enumerate(code_blocks): + marker = f"@@CODEBLOCK_{idx}@@" + text = text.replace(marker, f"```\n{code}\n```") + + # cleanup + lines = [ln.rstrip() for ln in text.replace("\r\n", "\n").split("\n")] + out: List[str] = [] + blank = False + for ln in lines: + if not ln.strip(): + if not blank: + out.append("") + blank = True + continue + out.append(ln) + blank = False + return "\n".join(out).strip() + "\n" + + +def extract_doc_from_html(page_html: str, slug: str) -> Tuple[str, str]: + article_match = re.search(r"]*>(.*?)", page_html or "", re.I | re.S) + article_html = article_match.group(1) if article_match else "" + + title = "" + if article_html: + h1 = re.search(r"]*>(.*?)", article_html, re.I | re.S) + if h1: + title = strip_tags(h1.group(1)) + + if not title: + doc_title = re.search(r"]*>(.*?)", page_html or "", re.I | re.S) + title = strip_tags(doc_title.group(1)) if doc_title else "" + + if not title: + title = slug + + body_md = html_to_markdown(article_html or page_html or "") + return title, body_md + + +def build_source_markdown(title: str, source_url: str, body_markdown: str) -> str: + lines = [ + f"# {title}", + "", + f"> Source: `{source_url}`", + "", + body_markdown.strip(), + "", + ] + return "\n".join(lines) + + +def parse_script_src_urls(page_html: str, base_url: str) -> List[str]: + out: List[str] = [] + seen: set[str] = set() + if not page_html: + return out + for m in re.finditer(r"]*\bsrc\s*=\s*(\"([^\"]+)\"|'([^']+)'|([^\s>]+))", page_html, re.I | re.S): + src = (m.group(2) or m.group(3) or m.group(4) or "").strip() + if not src: + continue + full = urllib.parse.urljoin(base_url, src) + if full in seen: + continue + seen.add(full) + out.append(full) + return out + + +def is_thin_body_markdown(body_markdown: str) -> bool: + text = body_markdown or "" + cleaned = re.sub(r"\s+", "", text) + non_empty_lines = [ln.strip() for ln in text.splitlines() if ln.strip()] + heading_count = len(re.findall(r"^\s*#{1,6}\s+", text, re.M)) + list_count = len(re.findall(r"^\s*[-*]\s+", text, re.M)) + + if len(cleaned) < 280: + return True + if len(non_empty_lines) <= 8 and any(token in text for token in ["本页总览", "官方广告"]): + return True + if heading_count <= 1 and list_count == 0 and len(cleaned) < 800: + return True + return False + + +def decode_js_string(raw: str) -> str: + s = raw or "" + try: + return _normalize_unicode_brace_escapes(json.loads(f"\"{s}\"")) + except Exception: + if "\\" not in s: + return _normalize_unicode_brace_escapes(s) + try: + return _normalize_unicode_brace_escapes(bytes(s, "utf-8").decode("unicode_escape")) + except Exception: + return _normalize_unicode_brace_escapes(s) + + +def _normalize_unicode_brace_escapes(text: str) -> str: + s = text or "" + return re.sub(r"\\u\{([0-9a-fA-F]{1,6})\}", lambda m: chr(int(m.group(1), 16)), s) + + +def _scan_js_value(text: str, start: int) -> Tuple[str, int]: + i = start + depth_paren = depth_brace = depth_bracket = 0 + in_str = False + quote = "" + escaped = False + + while i < len(text): + ch = text[i] + if in_str: + if escaped: + escaped = False + elif ch == "\\": + escaped = True + elif ch == quote: + in_str = False + i += 1 + continue + + if ch in ("'", '"'): + in_str = True + quote = ch + i += 1 + continue + + if ch == "(": + depth_paren += 1 + elif ch == ")": + if depth_paren > 0: + depth_paren -= 1 + elif ch == "{": + depth_brace += 1 + elif ch == "}": + if depth_brace > 0: + depth_brace -= 1 + elif ch == "[": + depth_bracket += 1 + elif ch == "]": + if depth_bracket > 0: + depth_bracket -= 1 + elif ch == "," and depth_paren == 0 and depth_brace == 0 and depth_bracket == 0: + return text[start:i].strip(), i + elif ch in "}" and depth_paren == 0 and depth_brace == 0 and depth_bracket == 0: + return text[start:i].strip(), i + i += 1 + return text[start:].strip(), len(text) + + +def _find_balanced(text: str, start: int, opener: str, closer: str) -> Tuple[str, int]: + if start < 0 or start >= len(text) or text[start] != opener: + return "", -1 + i = start + 1 + depth = 1 + in_str = False + quote = "" + escaped = False + while i < len(text): + ch = text[i] + if in_str: + if escaped: + escaped = False + elif ch == "\\": + escaped = True + elif ch == quote: + in_str = False + i += 1 + continue + if ch in ("'", '"'): + in_str = True + quote = ch + i += 1 + continue + if ch == opener: + depth += 1 + elif ch == closer: + depth -= 1 + if depth == 0: + return text[start : i + 1], i + i += 1 + return "", -1 + + +def _split_top_level_commas(text: str) -> List[str]: + out: List[str] = [] + i = 0 + start = 0 + depth_paren = depth_brace = depth_bracket = 0 + in_str = False + quote = "" + escaped = False + while i < len(text): + ch = text[i] + if in_str: + if escaped: + escaped = False + elif ch == "\\": + escaped = True + elif ch == quote: + in_str = False + i += 1 + continue + if ch in ("'", '"'): + in_str = True + quote = ch + i += 1 + continue + if ch == "(": + depth_paren += 1 + elif ch == ")": + depth_paren = max(0, depth_paren - 1) + elif ch == "{": + depth_brace += 1 + elif ch == "}": + depth_brace = max(0, depth_brace - 1) + elif ch == "[": + depth_bracket += 1 + elif ch == "]": + depth_bracket = max(0, depth_bracket - 1) + elif ch == "," and depth_paren == 0 and depth_brace == 0 and depth_bracket == 0: + part = text[start:i].strip() + if part: + out.append(part) + start = i + 1 + i += 1 + tail = text[start:].strip() + if tail: + out.append(tail) + return out + + +def _extract_prop_expr(obj_text: str, prop_name: str) -> str: + marker = prop_name + ":" + idx = obj_text.find(marker) + if idx < 0: + return "" + start = idx + len(marker) + val, _ = _scan_js_value(obj_text, start) + return val.strip() + + +def _strip_js_quote(expr: str) -> str: + s = (expr or "").strip() + if len(s) >= 2 and ((s[0] == '"' and s[-1] == '"') or (s[0] == "'" and s[-1] == "'")): + return decode_js_string(s[1:-1]) + return s + + +def _parse_js_template_literal(expr: str) -> str: + s = (expr or "").strip() + if not (len(s) >= 2 and s[0] == "`" and s[-1] == "`"): + return s + body = s[1:-1] + body = body.replace("\\`", "`") + body = body.replace("\\${", "${") + body = body.replace("\\r\\n", "\n").replace("\\n", "\n").replace("\\r", "\n") + try: + decoded = bytes(body, "utf-8").decode("unicode_escape") + return _normalize_unicode_brace_escapes(decoded) + except Exception: + return _normalize_unicode_brace_escapes(body) + + +def _parse_mdx_inline(expr: str) -> str: + e = (expr or "").strip() + if not e: + return "" + if e.startswith('"') and e.endswith('"'): + return decode_js_string(e[1:-1]) + if e.startswith("'") and e.endswith("'"): + return decode_js_string(e[1:-1]) + if e.startswith("`") and e.endswith("`"): + return _parse_js_template_literal(e) + if e.startswith("[") and e.endswith("]"): + inner = e[1:-1].strip() + parts = _split_top_level_commas(inner) + return "".join(_parse_mdx_inline(p) for p in parts) + comp_m = re.search(r"\(([A-Za-z_$][A-Za-z0-9_$]*)\.([A-Za-z0-9_]+)\s*,\{", e) + if not comp_m: + return "" + comp = comp_m.group(2) + obj_start = e.find("{", comp_m.end() - 1) + obj_text, _ = _find_balanced(e, obj_start, "{", "}") + if not obj_text: + return "" + body = obj_text[1:-1] + child_expr = _extract_prop_expr(body, "children") + child_text = _parse_mdx_inline(child_expr) if child_expr else "" + + if comp == "strong": + return f"**{child_text}**" + if comp == "del": + return f"~~{child_text}~~" + if comp == "code": + return f"`{child_text}`" + if comp == "a": + href = _extract_prop_expr(body, "href").strip().strip('"').strip("'") + if href: + label = child_text or href + return f"[{label}]({href})" + return child_text + if comp == "img": + src = _extract_prop_expr(body, "src").strip().strip('"').strip("'") + alt = _extract_prop_expr(body, "alt").strip().strip('"').strip("'") + if src: + return f"![{alt}]({src})" + return alt + return child_text + + +def _parse_mdx_code_expr(expr: str) -> Tuple[str, str]: + e = (expr or "").strip() + comp_m = re.search(r"\(([A-Za-z_$][A-Za-z0-9_$]*)\.code\s*,\{", e) + if not comp_m: + return "", "" + obj_start = e.find("{", comp_m.end() - 1) + obj_text, _ = _find_balanced(e, obj_start, "{", "}") + if not obj_text: + return "", "" + body = obj_text[1:-1] + class_expr = _extract_prop_expr(body, "className") + child_expr = _extract_prop_expr(body, "children") + lang = "" + class_text = _strip_js_quote(class_expr) + m_lang = re.search(r"language-([a-zA-Z0-9_+\-#]+)", class_text) + if m_lang: + lang = m_lang.group(1) + + code = _parse_mdx_inline(child_expr) if child_expr else "" + code = (code or "").replace("\r\n", "\n").replace("\r", "\n").rstrip("\n") + return lang, code + + +def _mdx_component_and_body(expr: str) -> Tuple[str, str]: + e = (expr or "").strip() + comp_m = re.search(r"\(([A-Za-z_$][A-Za-z0-9_$]*)\.([A-Za-z0-9_]+)\s*,\{", e) + if not comp_m: + return "", "" + comp = comp_m.group(2) + obj_start = e.find("{", comp_m.end() - 1) + obj_text, _ = _find_balanced(e, obj_start, "{", "}") + if not obj_text: + return "", "" + return comp, obj_text[1:-1] + + +def _parse_table_cells(expr: str) -> List[str]: + e = (expr or "").strip() + if not e: + return [] + if e.startswith("[") and e.endswith("]"): + out: List[str] = [] + inner = e[1:-1].strip() + for part in _split_top_level_commas(inner): + out.extend(_parse_table_cells(part)) + return out + + comp, body = _mdx_component_and_body(e) + if not comp: + txt = _parse_mdx_inline(e).strip() + return [txt] if txt else [] + child_expr = _extract_prop_expr(body, "children") + if comp in {"th", "td"}: + return [_parse_mdx_inline(child_expr).strip()] + if comp in {"tr", "thead", "tbody", "table"}: + return _parse_table_cells(child_expr) + return [] + + +def _parse_table_rows(expr: str) -> List[List[str]]: + e = (expr or "").strip() + if not e: + return [] + if e.startswith("[") and e.endswith("]"): + rows: List[List[str]] = [] + inner = e[1:-1].strip() + for part in _split_top_level_commas(inner): + rows.extend(_parse_table_rows(part)) + return rows + + comp, body = _mdx_component_and_body(e) + if not comp: + return [] + child_expr = _extract_prop_expr(body, "children") + if comp == "tr": + cells = _parse_table_cells(child_expr) + return [cells] if cells else [] + if comp in {"thead", "tbody", "table"}: + return _parse_table_rows(child_expr) + return [] + + +def _parse_mdx_block_expr(expr: str, out_lines: List[str]) -> None: + e = (expr or "").strip() + if not e: + return + if e.startswith('"') and e.endswith('"'): + text = decode_js_string(e[1:-1]).strip() + if text: + out_lines.append(text) + return + if e.startswith("'") and e.endswith("'"): + text = decode_js_string(e[1:-1]).strip() + if text: + out_lines.append(text) + return + if e.startswith("[") and e.endswith("]"): + inner = e[1:-1].strip() + for part in _split_top_level_commas(inner): + _parse_mdx_block_expr(part, out_lines) + return + + comp_m = re.search(r"\(([A-Za-z_$][A-Za-z0-9_$]*)\.([A-Za-z0-9_]+)\s*,\{", e) + if not comp_m: + return + comp = comp_m.group(2) + obj_start = e.find("{", comp_m.end() - 1) + obj_text, _ = _find_balanced(e, obj_start, "{", "}") + if not obj_text: + return + body = obj_text[1:-1] + child_expr = _extract_prop_expr(body, "children") + title_expr = _extract_prop_expr(body, "title") + title = _parse_mdx_inline(title_expr) if title_expr else "" + + if comp in {"h1", "h2", "h3", "h4", "h5", "h6"}: + lv = int(comp[1]) + head = _parse_mdx_inline(child_expr) + if head: + out_lines.append(f"{'#' * lv} {head}") + out_lines.append("") + return + if comp == "p": + text = _parse_mdx_inline(child_expr) + if text: + out_lines.append(text) + out_lines.append("") + return + if comp == "blockquote": + text = _parse_mdx_inline(child_expr) + if text: + out_lines.append(f"> {text}") + out_lines.append("") + return + if comp == "pre": + lang, code = _parse_mdx_code_expr(child_expr) + if code: + out_lines.append(f"```{lang}".rstrip()) + out_lines.extend(code.split("\n")) + out_lines.append("```") + out_lines.append("") + return + if comp == "li": + text = _parse_mdx_inline(child_expr) + if text: + out_lines.append(f"- {text}") + return + if comp in {"ul", "ol"}: + _parse_mdx_block_expr(child_expr, out_lines) + out_lines.append("") + return + if comp == "table": + rows = _parse_table_rows(child_expr) + rows = [r for r in rows if any((c or "").strip() for c in r)] + if rows: + col_count = max(len(r) for r in rows) + normalized = [r + [""] * (col_count - len(r)) for r in rows] + header = normalized[0] + out_lines.append("| " + " | ".join((c or "").strip() for c in header) + " |") + out_lines.append("| " + " | ".join(["---"] * col_count) + " |") + for row in normalized[1:]: + out_lines.append("| " + " | ".join((c or "").strip() for c in row) + " |") + out_lines.append("") + return + if comp == "admonition": + body_text = _parse_mdx_inline(child_expr) + if title: + out_lines.append(f"> [!TIP] {title}") + if body_text: + out_lines.append(f"> {body_text}") + out_lines.append("") + return + + # fallback + text = _parse_mdx_inline(child_expr) + if text: + out_lines.append(text) + out_lines.append("") + + +def parse_chunk_to_markdown(chunk_js: str, source_url: str, fallback_title: str) -> Tuple[str, str]: + title = fallback_title + slug_hint = "" + module_scan_text = chunk_js or "" + meta_match = re.search(r"JSON\.parse\('([^']+)'\)", chunk_js) + if meta_match: + raw = meta_match.group(1) + meta_json = decode_js_string(raw) + try: + meta = json.loads(meta_json) + if isinstance(meta, dict) and meta.get("title"): + title = str(meta.get("title")) + if isinstance(meta, dict) and isinstance(meta.get("id"), str): + slug_hint = str(meta.get("id")) + except Exception: + pass + + meta_pos = meta_match.start() + module_match = None + for m in re.finditer(r"(\d+)\([^)]*\)\{", chunk_js or ""): + if m.start() < meta_pos: + module_match = m + else: + break + if module_match: + brace_idx = (chunk_js or "").find("{", module_match.end() - 1) + module_body, _ = _find_balanced(chunk_js or "", brace_idx, "{", "}") + if module_body: + module_scan_text = module_body[1:-1] + + def _extract_from_function_block(fn_block: str) -> List[str]: + out: List[str] = [] + children_anchor = fn_block.find("children:[") + if children_anchor < 0: + return out + arr_start = fn_block.find("[", children_anchor) + if arr_start < 0: + return out + arr_text, _ = _find_balanced(fn_block, arr_start, "[", "]") + if not arr_text: + return out + items = _split_top_level_commas(arr_text[1:-1]) + for item in items: + _parse_mdx_block_expr(item, out) + return out + + def _find_function_blocks(js_text: str) -> List[str]: + blocks: List[str] = [] + for m in re.finditer(r"function\s+([A-Za-z_$][A-Za-z0-9_$]*)\s*\(", js_text): + brace_idx = js_text.find("{", m.end()) + if brace_idx < 0: + continue + body, _ = _find_balanced(js_text, brace_idx, "{", "}") + if not body: + continue + blocks.append(js_text[m.start() : brace_idx] + body) + return blocks + + candidate_lines: List[List[str]] = [] + default_fn_name = "" + m_default = re.search(r"default:\(\)=>\s*([A-Za-z_$][A-Za-z0-9_$]*)", module_scan_text or "") + if m_default: + default_fn_name = m_default.group(1) + + for fn_block in _find_function_blocks(module_scan_text or ""): + if "children:[" not in fn_block: + continue + lines = _extract_from_function_block(fn_block) + if lines: + score = len("\n".join(lines)) + if default_fn_name and re.search(rf"function\s+{re.escape(default_fn_name)}\s*\(", fn_block): + score += 300 + if slug_hint and slug_hint in fn_block: + score += 120 + candidate_lines.append((score, lines)) + + body_lines: List[str] = [] + if candidate_lines: + candidate_lines.sort(key=lambda x: x[0], reverse=True) + body_lines = candidate_lines[0][1] + + merged: List[str] = [] + prev_blank = True + for ln in body_lines: + s = (ln or "").strip() + if not s: + if not prev_blank: + merged.append("") + prev_blank = True + continue + merged.append(s) + prev_blank = False + + body_markdown = "\n".join(merged).strip() + if not body_markdown: + body_markdown = "(无法从页面静态 HTML 提取到完整正文。)" + return title, build_source_markdown(title=title, source_url=source_url, body_markdown=body_markdown) + + +def parse_main_route_chunk_map(main_js: str) -> Dict[str, str]: + """ + Return slug -> chunk id map (numeric webpack chunk id). + """ + route_map: Dict[str, str] = {} + pat = re.compile( + r'(?:\"?[a-f0-9]+\"?)\s*:\s*\[\(\)=>(?P.*?)\s*,\s*"@site/docs/(?P[^"]+?)\.(?:mdx|md)"\s*,', + re.I | re.S, + ) + for m in pat.finditer(main_js or ""): + loader = m.group("loader") or "" + ids = re.findall(r'n\.e\("([0-9]+)"\)', loader) + if not ids: + continue + chunk_id = ids[-1] + doc_path = (m.group("doc") or "").strip("/") + if not doc_path: + continue + slug = doc_path.lower() + if slug == "index": + route_map["index"] = chunk_id + elif slug.endswith("/index"): + route_map[slug[:-6]] = chunk_id + route_map[slug] = chunk_id + else: + route_map[slug] = chunk_id + return route_map + + +def parse_runtime_chunk_url_map(runtime_js: str, base_url: str) -> Dict[str, str]: + """ + Return chunk_id -> full chunk url. + """ + out: Dict[str, str] = {} + text = runtime_js or "" + idx = text.find("n.u=") + if idx < 0: + return out + + first_obj_start = text.find("{", idx) + if first_obj_start < 0: + return out + first_obj_text, first_obj_end = _find_balanced(text, first_obj_start, "{", "}") + if not first_obj_text: + return out + second_obj_start = text.find("{", first_obj_end + 1) + if second_obj_start < 0: + return out + second_obj_text, _ = _find_balanced(text, second_obj_start, "{", "}") + if not second_obj_text: + return out + + names = dict(re.findall(r'([0-9]+)\s*:\s*["\']([^"\']+)["\']', first_obj_text)) + hashes = dict(re.findall(r'([0-9]+)\s*:\s*["\']([^"\']+)["\']', second_obj_text)) + for chunk_id, h in hashes.items(): + if not h: + continue + name = names.get(chunk_id) or chunk_id + out[chunk_id] = urllib.parse.urljoin(base_url, f"/assets/js/{name}.{h}.js") + return out + + +# ----------------------------- +# workspace / config +# ----------------------------- +def default_config() -> dict: + return { + "target": { + "base_url": "https://docs.example.com", + "seed_path": "", + "docs_root": "", + }, + "workspace": ".site_sync", + "crawler": { + "timeout_seconds": 30, + "http_retries": 3, + "retry_backoff_seconds": 1.5, + "continue_on_doc_error": True, + "max_docs": 0, + }, + "site": { + "output_dir": "source_site", + "menu_mode": "nav" + } + } + + +def workspace_paths(config: dict) -> dict: + ws = Path(config.get("workspace") or ".site_sync").resolve() + return { + "ws": ws, + "raw": ws / "raw", + "source_md": ws / "source_md", + "manifests": ws / "manifests", + "reports": ws / "reports", + "state": ws / "state" / "state.json", + "source_manifest": ws / "manifests" / "source_manifest.json", + "source_site": ws / (config.get("site", {}).get("output_dir") or "source_site"), + } + + +def ensure_workspace(paths: dict) -> None: + for key in ["ws", "raw", "source_md", "manifests", "reports", "state"]: + p = paths[key] + ensure_dir(p if key != "state" else p.parent) + + +# ----------------------------- +# crawl +# ----------------------------- +def _collect_sidebar_meta_for_root( + *, + base_url: str, + docs_root: str, + seed_html: str, + timeout: int, + retries: int, + backoff: float, +) -> dict: + sidebar = extract_sidebar_structure(seed_html, docs_root=docs_root) + categories: Dict[str, dict] = dict(sidebar.get("categories") or {}) + ordered_keys: List[str] = list(sidebar.get("ordered_keys") or []) + slug_titles: Dict[str, str] = dict(sidebar.get("slug_titles") or {}) + slug_order: Dict[str, int] = dict(sidebar.get("slug_order") or {}) + slug_meta: Dict[str, dict] = {} + + for slug, key in (sidebar.get("slug_to_category") or {}).items(): + c = categories.get(key) or {} + doc_order = slug_order.get(slug) if slug_order.get(slug) is not None else c.get("order", 9999) + slug_meta[slug] = { + "title": slug_titles.get(slug) or c.get("label") or slug, + "category_key": key, + "category_order": c.get("order", 9999), + "category_label": c.get("label") or "Uncategorized", + "category_folder": c.get("folder") or sanitize_segment(c.get("label") or "Uncategorized"), + "doc_order": doc_order, + } + + for key in ordered_keys: + c = categories.get(key) or {} + if c.get("kind") != "category": + continue + cat_slug = key[len("cat:") :] if key.startswith("cat:") else "" + if not cat_slug: + continue + cat_url = urllib.parse.urljoin(base_url, f"{docs_root.rstrip('/')}/category/{cat_slug}") + try: + page_html = http_get_text(cat_url, timeout=timeout, retries=retries, backoff_seconds=backoff) + except Exception: + continue + entries = parse_doc_entries_from_category_page(page_html, docs_root=docs_root) + for idx, (slug, label) in enumerate(entries): + slug_meta[slug] = { + "title": label or slug, + "category_key": key, + "category_order": c.get("order", 9999), + "category_label": c.get("label") or "Uncategorized", + "category_folder": c.get("folder") or sanitize_segment(c.get("label") or "Uncategorized"), + "doc_order": idx, + } + + # Build a reverse lookup from seed HTML: relative slug -> link text + slug_title_from_html: Dict[str, str] = {} + a_re = re.compile( + r']*href=(?:"([^"]+)"|\'([^\']+)\'|([^\s>]+))[^>]*>(?P.*?)', + re.S | re.I, + ) + for m in a_re.finditer(seed_html or ""): + href = (m.group(1) or m.group(2) or m.group(3) or "").strip() + if not href or href.startswith("#") or href.startswith("javascript:"): + continue + rel = normalize_docs_href(href, docs_root=docs_root) + if not rel: + continue + link_text = strip_tags(m.group("body") or "") + if link_text and rel not in slug_title_from_html: + slug_title_from_html[rel] = link_text + + try: + sitemap_url = urllib.parse.urljoin(base_url, "sitemap.xml") + sitemap_xml = http_get_text(sitemap_url, timeout=timeout, retries=1, backoff_seconds=0) + for slug in parse_doc_slugs_from_sitemap(sitemap_xml, docs_root=docs_root): + # Prefer title from HTML link text, then sidebar, fall back to slug + html_title = slug_title_from_html.get(slug) or slug_title_from_html.get(slug.rstrip("/")) + best_title = html_title or slug_titles.get(slug) or slug_titles.get(slug.rstrip("/")) or slug + slug_meta.setdefault( + slug, + { + "title": best_title, + "category_key": "uncategorized", + "category_order": 9999, + "category_label": "Uncategorized", + "category_folder": "uncategorized", + "doc_order": 10**9, + }, + ) + # Also update title if sitemap gave a better one than sidebar + existing = slug_meta.get(slug) + if existing and html_title and existing.get("title") == slug: + existing["title"] = html_title + except Exception: + pass + + return { + "categories": categories, + "ordered_keys": ordered_keys, + "slug_meta": slug_meta, + } + + +def collect_sidebar_meta(config: dict) -> dict: + target = config.get("target", {}) if isinstance(config.get("target"), dict) else {} + crawler = config.get("crawler", {}) if isinstance(config.get("crawler"), dict) else {} + base_url = (target.get("base_url") or "").strip() + configured_docs_root = (target.get("docs_root") or "").strip() + seed_path = target.get("seed_path", "") + timeout = int(crawler.get("timeout_seconds", 30) or 30) + retries = int(crawler.get("http_retries", 3) or 3) + backoff = float(crawler.get("retry_backoff_seconds", 1.5) or 1.5) + + if not base_url: + raise ValueError("target.base_url is required") + + seed_url = urllib.parse.urljoin(base_url, seed_path) + seed_html = "" + try: + seed_html = http_get_text(seed_url, timeout=timeout, retries=retries, backoff_seconds=backoff) + except Exception: + seed_html = "" + + docs_roots, root_home_html_map = resolve_docs_roots( + base_url=base_url, + configured_docs_root=configured_docs_root, + seed_html=seed_html, + timeout=timeout, + retries=retries, + backoff=backoff, + ) + + multi_root_mode = (not configured_docs_root) and len(docs_roots) > 1 + categories: Dict[str, dict] = {} + ordered_keys: List[str] = [] + slug_meta: Dict[str, dict] = {} + + for root_index, docs_root in enumerate(docs_roots): + root_html = root_home_html_map.get(docs_root) or seed_html + root_data = _collect_sidebar_meta_for_root( + base_url=base_url, + docs_root=docs_root, + seed_html=root_html, + timeout=timeout, + retries=retries, + backoff=backoff, + ) + + root_tag = sanitize_segment(docs_root.strip("/") or f"docs{root_index + 1}", fallback=f"docs{root_index + 1}") + category_key_map: Dict[str, str] = {} + + for old_key, category in (root_data.get("categories") or {}).items(): + new_key = old_key if not multi_root_mode else f"root:{docs_root.strip('/')}:{old_key}" + category_key_map[old_key] = new_key + new_category = dict(category or {}) + new_category["key"] = new_key + if multi_root_mode: + new_category["folder"] = sanitize_segment(f"{root_tag}_{new_category.get('folder') or new_category.get('label') or 'uncategorized'}") + categories[new_key] = new_category + + for old_key in (root_data.get("ordered_keys") or []): + mapped = category_key_map.get(old_key) or old_key + if mapped not in ordered_keys: + ordered_keys.append(mapped) + + for rel_slug, meta in (root_data.get("slug_meta") or {}).items(): + compound_slug = make_compound_slug(docs_root, rel_slug, multi_root_mode) + old_category_key = (meta or {}).get("category_key") or "uncategorized" + mapped_category_key = category_key_map.get(old_category_key, old_category_key) + mapped_category = categories.get(mapped_category_key) or {} + source_path = make_source_path(docs_root, rel_slug) + slug_meta[compound_slug] = { + "title": (meta or {}).get("title") or rel_slug, + "category_key": mapped_category_key, + "category_order": (meta or {}).get("category_order", 9999), + "category_label": (meta or {}).get("category_label") or mapped_category.get("label") or "Uncategorized", + "category_folder": mapped_category.get("folder") or (meta or {}).get("category_folder") or "uncategorized", + "doc_order": (meta or {}).get("doc_order", 10**9), + "source_root": docs_root, + "source_path": source_path, + "route_keys": make_route_candidates(rel_slug, compound_slug), + } + + primary_docs_root = docs_roots[0] if docs_roots else ("/" + (configured_docs_root or "docs").strip("/")) + return { + "base_url": base_url, + "docs_root": primary_docs_root, + "docs_roots": docs_roots, + "multi_root_mode": multi_root_mode, + "categories": categories, + "ordered_keys": ordered_keys, + "slug_meta": slug_meta, + } + +def crawl_once(config: dict, max_docs: int = 0) -> dict: + paths = workspace_paths(config) + ensure_workspace(paths) + + target = config.get("target", {}) if isinstance(config.get("target"), dict) else {} + crawler = config.get("crawler", {}) if isinstance(config.get("crawler"), dict) else {} + base_url = (target.get("base_url") or "").strip() + docs_root = (target.get("docs_root") or "").strip() + timeout = int(crawler.get("timeout_seconds", 30) or 30) + retries = int(crawler.get("http_retries", 3) or 3) + backoff = float(crawler.get("retry_backoff_seconds", 1.5) or 1.5) + continue_on_doc_error = bool(crawler.get("continue_on_doc_error", True)) + + if not base_url: + raise ValueError("target.base_url is required") + + heartbeat = ProgressHeartbeat("crawl", interval_seconds=8).start() + heartbeat.update(phase="读取源站导航", step="collect_sidebar_meta", url=base_url) + sidebar = collect_sidebar_meta(config) + docs_root = (sidebar.get("docs_root") or docs_root).strip() or docs_root + slug_meta: Dict[str, dict] = sidebar.get("slug_meta", {}) + + route_chunk_map: Dict[str, str] = {} + chunk_url_map: Dict[str, str] = {} + chunk_text_cache: Dict[str, str] = {} + try: + heartbeat.update(phase="分析页面脚本", step="discover_bundles", url=urllib.parse.urljoin(base_url, docs_root)) + discover_url = urllib.parse.urljoin(base_url, docs_root) + discover_html = http_get_text(discover_url, timeout=timeout, retries=retries, backoff_seconds=backoff) + script_urls = parse_script_src_urls(discover_html, base_url) + runtime_js_url = next((u for u in script_urls if "/assets/js/runtime~main." in u), "") + main_js_url = next((u for u in script_urls if "/assets/js/main." in u), "") + log(f"[*] 脚本发现:runtime={runtime_js_url or '-'}") + log(f"[*] 脚本发现:main={main_js_url or '-'}") + + if main_js_url: + heartbeat.update(step="load_main_bundle", url=main_js_url) + main_js = http_get_text(main_js_url, timeout=timeout, retries=retries, backoff_seconds=backoff) + route_chunk_map = parse_main_route_chunk_map(main_js) + log(f"[*] 路由块映射数量:{len(route_chunk_map)}") + else: + log("[!] 未找到 main bundle,文档正文回退能力将受限。") + + if runtime_js_url: + heartbeat.update(step="load_runtime_bundle", url=runtime_js_url) + runtime_js = http_get_text(runtime_js_url, timeout=timeout, retries=retries, backoff_seconds=backoff) + chunk_url_map = parse_runtime_chunk_url_map(runtime_js, base_url) + log(f"[*] 资源块映射数量:{len(chunk_url_map)}") + else: + log("[!] 未找到 runtime bundle,文档正文回退能力将受限。") + except Exception as bundle_error: + log(f"[!] 分析页面脚本失败,继续使用 HTML 抽取:{bundle_error}") + + slugs = list(slug_meta.keys()) + slugs.sort( + key=lambda s: ( + int((slug_meta.get(s) or {}).get("category_order", 9999)), + int((slug_meta.get(s) or {}).get("doc_order", 10**9)), + s, + ) + ) + + requested_max = int(max_docs or crawler.get("max_docs", 0) or 0) + if requested_max > 0: + slugs = slugs[:requested_max] + + log(f"[*] 开始抓取:target={base_url} docs_root={docs_root}") + log(f"[*] 待处理文档数:{len(slugs)}") + + prev_manifest = load_json(paths["source_manifest"], default={}) + prev_docs = {x.get("slug"): x for x in (prev_manifest.get("docs") or []) if x.get("slug")} + + docs_payload: List[dict] = [] + changed_slugs: List[str] = [] + failed: List[str] = [] + + total = len(slugs) + crawl_started_at = time.time() + for idx, slug in enumerate(slugs, start=1): + m = slug_meta.get(slug) or {} + source_url = build_doc_source_url_with_meta(base_url, docs_root, slug, m) + heartbeat.update(phase="抓取文档", step=slug, url=source_url, done=idx - 1, total=total) + log(f"[{idx}/{total}] 开始抓取 slug={slug}") + log(f" URL={source_url}") + doc_t0 = time.time() + try: + page_html = http_get_text(source_url, timeout=timeout, retries=retries, backoff_seconds=backoff) + title, body_md = extract_doc_from_html(page_html, slug) + if not title or title.strip() == slug: + title = m.get("title") or slug + + markdown = build_source_markdown(title=title, source_url=source_url, body_markdown=body_md) + + if is_thin_body_markdown(body_md): + route_keys = m.get("route_keys") if isinstance(m.get("route_keys"), list) else [] + if not route_keys: + slug_key = (slug or "").strip("/").lower() or "index" + route_keys = [slug_key, slug_key.rstrip("/"), slug_key.removesuffix(".html")] + chunk_id = "" + for rk in route_keys: + rk_key = (rk or "").strip("/").lower() + if not rk_key: + continue + chunk_id = route_chunk_map.get(rk_key) or route_chunk_map.get(rk_key.rstrip("/")) + if chunk_id: + break + if chunk_id: + chunk_url = chunk_url_map.get(chunk_id) + if chunk_url: + log(f" [回退] HTML 内容偏薄,尝试 JS 块提取 slug={slug} chunk_id={chunk_id}") + chunk_js = chunk_text_cache.get(chunk_url) + if chunk_js is None: + chunk_js = http_get_text(chunk_url, timeout=timeout, retries=retries, backoff_seconds=backoff) + chunk_text_cache[chunk_url] = chunk_js + chunk_title, chunk_markdown = parse_chunk_to_markdown(chunk_js, source_url, title) + if len(chunk_markdown) > int(len(markdown) * 1.20): + markdown = chunk_markdown + title = chunk_title or title + log(f" [回退成功] slug={slug} 使用 JS 块正文,长度 {len(markdown)}") + else: + log(f" [回退跳过] slug={slug} JS 块内容未明显提升,保留 HTML 抽取结果") + else: + log(f" [回退跳过] slug={slug} 找到 chunk_id={chunk_id},但无 chunk URL 映射") + else: + log(f" [回退跳过] slug={slug} 未找到对应 chunk_id") + + source_file = slug_to_source_filename(slug) + write_text(paths["source_md"] / source_file, markdown) + + source_hash = str(abs(hash(markdown))) + prev_hash = str((prev_docs.get(slug) or {}).get("source_hash", "")) + if source_hash != prev_hash: + changed_slugs.append(slug) + + docs_payload.append( + { + "slug": slug, + "title": title, + "category_key": m.get("category_key") or "uncategorized", + "category_label": m.get("category_label") or "Uncategorized", + "category_order": m.get("category_order", 9999), + "category_folder": m.get("category_folder") or "uncategorized", + "source_file": source_file, + "source_url": source_url, + "source_hash": source_hash, + "updated_at": now_iso(), + } + ) + heartbeat.update(done=idx, total=total) + elapsed = time.time() - doc_t0 + log(f" [完成] slug={slug} title={title} 耗时={elapsed:.2f}s") + if idx % 5 == 0 or idx == total: + log_progress_line(" [抓取进度]", idx, total, crawl_started_at) + log(f" [统计] 成功={len(docs_payload)} 失败={len(failed)}") + except Exception as e: + failed.append(f"{slug}: {e}") + heartbeat.update(done=idx, total=total) + elapsed = time.time() - doc_t0 + log(f" [失败] slug={slug} 耗时={elapsed:.2f}s err={e}") + if idx % 5 == 0 or idx == total: + log_progress_line(" [抓取进度]", idx, total, crawl_started_at) + log(f" [统计] 成功={len(docs_payload)} 失败={len(failed)}") + if continue_on_doc_error: + continue + raise + + heartbeat.update(phase="写入清单与报告", step="source_manifest", url="-", done=total, total=total) + + now_slugs = {d["slug"] for d in docs_payload} + removed_docs = [ + { + "slug": d.get("slug"), + "title": d.get("title") or d.get("slug"), + "category_label": d.get("category_label") or "Uncategorized", + "source_file": d.get("source_file") or "", + } + for d in (prev_manifest.get("docs") or []) + if (d.get("slug") and d.get("slug") not in now_slugs) + ] + + manifest = { + "generated_at": now_iso(), + "seed_url": urllib.parse.urljoin(base_url, target.get("seed_path", "")), + "counts": { + "total_docs": len(docs_payload), + "changed_docs": len(changed_slugs), + "removed_docs": len(removed_docs), + "failed_docs": len(failed), + }, + "changed_docs": changed_slugs, + "removed_docs": removed_docs, + "docs": docs_payload, + } + save_json(paths["source_manifest"], manifest) + + state = { + "version": "1.0", + "last_run": now_iso(), + "pipeline": "crawl-only", + "target": { + "base_url": base_url, + "docs_root": docs_root, + "docs_roots": sidebar.get("docs_roots") or [docs_root], + }, + "counts": manifest["counts"], + } + save_json(paths["state"], state) + + report_lines = [ + "# Crawl Report", + "", + f"- generated_at: `{manifest['generated_at']}`", + f"- target: `{base_url}`", + f"- docs_root: `{docs_root}`", + f"- total_docs: `{manifest['counts']['total_docs']}`", + f"- changed_docs: `{manifest['counts']['changed_docs']}`", + f"- removed_docs: `{manifest['counts']['removed_docs']}`", + f"- failed_docs: `{manifest['counts']['failed_docs']}`", + "", + ] + if failed: + report_lines += ["## Failed", ""] + [f"- {x}" for x in failed] + write_text(paths["reports"] / "crawl-report.md", "\n".join(report_lines).rstrip() + "\n") + + result = { + "processed": len(slugs), + "changed": len(changed_slugs), + "removed": len(removed_docs), + "failed": len(failed), + "source_manifest": str(paths["source_manifest"]), + "source_dir": str(paths["source_md"]), + "failed_docs": failed, + } + log(f"[*] 抓取阶段结束 processed={result['processed']} changed={result['changed']} removed={result['removed']} failed={result['failed']}") + heartbeat.stop() + return result + + +# ----------------------------- +# site build +# ----------------------------- +def title_sort_key(title: str) -> tuple: + text = (title or "").strip() + m = re.match(r"^(\d+(?:\.\d+)*)", text) + if not m: + return (1, [10**9], text.lower()) + nums = [int(x) for x in m.group(1).split(".")] + return (0, nums, text.lower()) + + +# Mapping from English sidebar link texts to Chinese +_SIDEBAR_TITLE_MAP = { + "index": "目录索引", + "Overview": "概览", + "Expressions": "表达式", + "Primitives types": "基础类型", + "Containers types": "容器类型", + "Operators": "运算符", + "Mutability": "可变性", + "Functions": "函数", + "Control Flow": "控制流", + "Failure": "失败系统", + "Structs & Enums": "结构体与枚举", + "Classes & Interfaces": "类与接口", + "Type System": "类型系统", + "Access Specifiers": "访问说明符", + "Effects": "效应系统", + "Concurrency": "并发", + "Live Variables": "活跃变量", + "Modules and Paths": "模块与路径", + "Persistable Types": "持久化类型", + "Code Evolution": "代码演进", + "📚 Concept Index": "📚 概念索引", + "VerseSyntaxValidation": "Verse 语法验证", +} + + +def _post_process_sidebar_titles(payload: dict, paths: dict) -> None: + """Translate sidebar doc titles from English to Chinese.""" + categories = payload.get("categories") or [] + source_md = paths["source_md"] + for cat in categories: + for doc in (cat.get("docs") or []): + old_title = doc.get("title") or "" + slug = doc.get("slug") or "" + # Try explicit map first + new_title = _SIDEBAR_TITLE_MAP.get(old_title) or _SIDEBAR_TITLE_MAP.get(slug) + # Fallback: read first # heading from source .md + if not new_title: + src_file = doc.get("source_file") or "" + src_path = source_md / src_file + if src_path.exists(): + first_line = src_path.read_text(encoding="utf-8").split("\n")[0].strip() + if first_line.startswith("# "): + t = first_line[2:].strip() + if t and not t.startswith("来源") and not t.startswith("Source"): + new_title = t + if new_title and new_title != old_title: + doc["title"] = new_title + + +def build_site_data(docs: Sequence[dict], sidebar_meta: dict, strict_nav: bool = True) -> List[dict]: + grouped: Dict[str, dict] = {} + categories_meta: Dict[str, dict] = sidebar_meta.get("categories") or {} + slug_meta: Dict[str, dict] = sidebar_meta.get("slug_meta") or {} + + for item in docs: + slug = item.get("slug") or "" + if not slug: + continue + + doc_meta = slug_meta.get(slug) or {} + if strict_nav and not doc_meta: + continue + + category_key = doc_meta.get("category_key") or item.get("category_key") or "uncategorized" + category = categories_meta.get(category_key) or {} + label = category.get("label") or doc_meta.get("category_label") or item.get("category_label") or "Uncategorized" + folder = sanitize_segment(category.get("folder") or doc_meta.get("category_folder") or item.get("category_folder") or "uncategorized") + order = doc_meta.get("category_order") if isinstance(doc_meta.get("category_order"), int) else item.get("category_order") + + if category_key not in grouped: + grouped[category_key] = { + "key": category_key, + "label": label, + "folder": folder, + "order": order if isinstance(order, int) else 9999, + "docs": [], + } + + rel_path = f"docs/{folder}/{slug}.md" + grouped[category_key]["docs"].append( + { + "slug": slug, + "title": doc_meta.get("title") or item.get("title") or slug, + "source_url": item.get("source_url") or "", + "source_file": item.get("source_file") or "", + "rel_path": rel_path, + "doc_order": doc_meta.get("doc_order") if isinstance(doc_meta.get("doc_order"), int) else 10**9, + } + ) + + if strict_nav: + for key, c in categories_meta.items(): + if c.get("kind") != "category": + continue + if key in grouped: + continue + label = c.get("label") or "Uncategorized" + grouped[key] = { + "key": key, + "label": label, + "folder": sanitize_segment(c.get("folder") or label), + "order": c.get("order") if isinstance(c.get("order"), int) else 9999, + "docs": [], + } + + categories = list(grouped.values()) + categories.sort(key=lambda x: (x.get("order", 9999), str(x.get("label") or ""))) + for cat in categories: + cat["docs"].sort(key=lambda d: (d.get("doc_order", 10**9), title_sort_key(d.get("title") or d.get("slug") or ""))) + return categories + + +def build_index_html(site_payload: dict) -> str: + payload_json = json.dumps(site_payload, ensure_ascii=False) + template = """ + + + + + Docs Viewer + + + +
Docs Viewer
loading...
+
+ +
Select a document from the left panel.
+
+ + + + + +""" + return template.replace("__SITE_DATA_JSON__", payload_json) + + +def build_site(config: dict, menu_mode: Optional[str] = None) -> dict: + paths = workspace_paths(config) + ensure_workspace(paths) + + manifest = load_json(paths["source_manifest"], default={}) + docs = manifest.get("docs") or [] + if not docs: + return {"ok": False, "message": f"empty manifest: {paths['source_manifest']}"} + + desired_mode = (menu_mode or config.get("site", {}).get("menu_mode") or "nav").strip().lower() + strict_nav = desired_mode != "all" + log(f"[*] 开始构建站点:menu_mode={'nav(仅导航)' if strict_nav else 'all(全部)'}") + heartbeat = ProgressHeartbeat("build_site", interval_seconds=8).start() + heartbeat.update(phase="构建目录树", step="build_site_data", url="-") + + sidebar = collect_sidebar_meta(config) + categories = build_site_data(docs=docs, sidebar_meta=sidebar, strict_nav=strict_nav) + + site_root = paths["source_site"] + docs_root = site_root / "docs" + ensure_dir(docs_root) + + copied = 0 + missing: List[str] = [] + total_docs = sum(len(cat.get("docs") or []) for cat in categories) + log(f"[*] 站点目录统计:分类={len(categories)} 文档={total_docs}") + build_started_at = time.time() + copied_attempt = 0 + for cat in categories: + folder = sanitize_segment(cat.get("folder") or cat.get("label") or "uncategorized") + for doc in cat.get("docs") or []: + copied_attempt += 1 + heartbeat.update( + phase="复制文档到站点目录", + step=doc.get("slug") or "-", + url=doc.get("source_url") or "-", + done=copied_attempt - 1, + total=total_docs, + ) + source_file = doc.get("source_file") or "" + if not source_file: + missing.append(doc.get("slug") or "") + continue + src = paths["source_md"] / source_file + dst = docs_root / folder / f"{doc.get('slug')}.md" + if copy_file(src, dst): + copied += 1 + else: + missing.append(doc.get("slug") or "") + heartbeat.update(done=copied_attempt, total=total_docs) + if copied_attempt % 10 == 0 or copied_attempt == total_docs: + log_progress_line(" [构建进度]", copied_attempt, total_docs, build_started_at) + log(f" [统计] 复制成功={copied} 缺失={len(missing)}") + + manifest_slugs = {d.get("slug") for d in docs if d.get("slug")} + included_slugs = {d.get("slug") for c in categories for d in (c.get("docs") or []) if d.get("slug")} + excluded_slugs = sorted([s for s in manifest_slugs if s not in included_slugs]) + + payload = { + "generated_at": now_iso(), + "menu_mode": "nav" if strict_nav else "all", + "counts": { + "manifest_docs": len(manifest_slugs), + "categories": len(categories), + "docs": sum(len(c.get("docs") or []) for c in categories), + "excluded_docs": len(excluded_slugs), + "copied_docs": copied, + "missing_docs": len(missing), + }, + "categories": categories, + } + + heartbeat.update(phase="写入站点文件", step="site_manifest + index.html", url="-", done=total_docs, total=total_docs) + save_json(site_root / "site_manifest.json", payload) + # Post-process: translate sidebar titles using source .md headings + _post_process_sidebar_titles(payload, paths) + save_json(site_root / "site_manifest.json", payload) + write_text(site_root / "index.html", build_index_html(payload)) + + lines = [ + "# Site Build Report", + "", + f"- generated_at: `{payload['generated_at']}`", + f"- output_dir: `{site_root}`", + f"- menu_mode: `{payload['menu_mode']}`", + f"- manifest_docs: `{payload['counts']['manifest_docs']}`", + f"- menu_docs: `{payload['counts']['docs']}`", + f"- hidden_docs: `{payload['counts']['excluded_docs']}`", + f"- copied_docs: `{payload['counts']['copied_docs']}`", + f"- missing_docs: `{payload['counts']['missing_docs']}`", + "", + f"- entry: `{site_root / 'index.html'}`", + ] + if excluded_slugs: + lines += ["", "## Hidden Slugs", ""] + [f"- `{s}`" for s in excluded_slugs[:300]] + if missing: + lines += ["", "## Missing Slugs", ""] + [f"- `{s}`" for s in missing[:300]] + write_text(paths["reports"] / "site-build-report.md", "\n".join(lines).rstrip() + "\n") + heartbeat.stop() + log( + f"[*] 构建阶段结束 categories={payload['counts']['categories']} " + f"menu_docs={payload['counts']['docs']} hidden={payload['counts']['excluded_docs']} missing={payload['counts']['missing_docs']}" + ) + + return { + "ok": True, + "site_root": str(site_root), + "index_html": str(site_root / "index.html"), + "site_manifest": str(site_root / "site_manifest.json"), + "counts": payload["counts"], + "menu_mode": payload["menu_mode"], + } + + +# ----------------------------- +# command handlers +# ----------------------------- +def cmd_init(args) -> int: + cfg_path = Path(args.config) + if cfg_path.exists() and not args.force: + print(f"[!] config exists: {cfg_path}. use --force to overwrite") + return 1 + + save_json(cfg_path, default_config()) + cfg = load_json(cfg_path, default={}) + paths = workspace_paths(cfg) + ensure_workspace(paths) + print(f"[+] initialized: {cfg_path}") + print(f"- workspace: {paths['ws']}") + return 0 + + +def cmd_crawl(args) -> int: + cfg = load_json(Path(args.config), default={}) + if not cfg: + print(f"[!] invalid config: {args.config}") + return 1 + result = crawl_once(cfg, max_docs=int(args.max_docs or 0)) + log("[+] 抓取命令完成") + for k in ["processed", "changed", "removed", "failed", "source_dir", "source_manifest"]: + log(f"- {k}: {result.get(k)}") + if result.get("failed_docs"): + log("- failed_docs:") + for x in result["failed_docs"][:50]: + log(f" - {x}") + return 0 if (result.get("failed", 0) == 0) else 2 + + +def cmd_build_site(args) -> int: + cfg = load_json(Path(args.config), default={}) + if not cfg: + print(f"[!] invalid config: {args.config}") + return 1 + result = build_site(cfg, menu_mode=args.menu_mode) + if not result.get("ok"): + print(f"[!] {result.get('message')}") + return 1 + log("[+] 站点构建命令完成") + log(f"- site_root: {result['site_root']}") + log(f"- index_html: {result['index_html']}") + log(f"- site_manifest: {result['site_manifest']}") + log(f"- menu_mode: {result['menu_mode']}") + log(f"- counts: {result['counts']}") + return 0 + + +def cmd_run(args) -> int: + cfg = load_json(Path(args.config), default={}) + if not cfg: + print(f"[!] invalid config: {args.config}") + return 1 + + log("[*] 阶段 1/2:抓取文档") + crawl_result = crawl_once(cfg, max_docs=int(args.max_docs or 0)) + log("[*] 阶段 2/2:构建本地站点") + site_result = build_site(cfg, menu_mode=args.menu_mode) + + log("[+] 任务执行完成") + log(f"- crawl: processed={crawl_result.get('processed')} changed={crawl_result.get('changed')} failed={crawl_result.get('failed')}") + if not site_result.get("ok"): + log(f"- site: failed: {site_result.get('message')}") + return 2 + log(f"- site: index={site_result.get('index_html')} menu_mode={site_result.get('menu_mode')}") + return 0 if crawl_result.get("failed", 0) == 0 else 2 + + +def cmd_status(args) -> int: + cfg = load_json(Path(args.config), default={}) + if not cfg: + print(f"[!] invalid config: {args.config}") + return 1 + paths = workspace_paths(cfg) + state = load_json(paths["state"], default={}) + manifest = load_json(paths["source_manifest"], default={}) + + print("Docs Crawler Status") + print(f"- last_run: {state.get('last_run')}") + print(f"- target: {((state.get('target') or {}).get('base_url'))}") + print(f"- docs_root: {((state.get('target') or {}).get('docs_root'))}") + print(f"- total_docs: {(manifest.get('counts') or {}).get('total_docs', 0)}") + print(f"- changed_docs: {(manifest.get('counts') or {}).get('changed_docs', 0)}") + print(f"- removed_docs: {(manifest.get('counts') or {}).get('removed_docs', 0)}") + print(f"- workspace: {paths['ws']}") + print(f"- source_dir: {paths['source_md']}") + print(f"- source_manifest: {paths['source_manifest']}") + print(f"- site_dir: {paths['source_site']}") + return 0 + + +def cmd_export(args) -> int: + cfg = load_json(Path(args.config), default={}) + if not cfg: + print(f"[!] invalid config: {args.config}") + return 1 + paths = workspace_paths(cfg) + + manifest = load_json(paths["source_manifest"], default={}) + docs = manifest.get("docs") or [] + if not docs: + print(f"[!] no crawled docs found. Run 'crawl' first.") + return 1 + + raw_url = (cfg.get("target", {}).get("base_url") or "").rstrip("/") + parsed = urllib.parse.urlparse(raw_url) + host_parts = (parsed.hostname or "").split(".") + # Pick the most specific non-TLD part: e.g. "verselang" from "verselang.github.io" + domain_name = host_parts[0] if host_parts else "" + path_segs = [s for s in parsed.path.split("/") if s] + # If the last path segment is a generic doc root name, use domain instead + generic_paths = {"book", "docs", "guide", "manual", "api", "reference"} + last_seg = path_segs[-1] if path_segs else "" + if last_seg and last_seg.lower() not in generic_paths: + site_name = last_seg + elif domain_name: + site_name = domain_name + else: + site_name = last_seg or "docs" + + export_dir = paths["ws"] / "export" + ensure_dir(export_dir) + + html = _build_export_html(docs, paths["source_md"], site_name) + out_path = export_dir / f"{site_name}.html" + write_text(out_path, html) + + print(f"[+] Exported: {out_path} ({len(docs)} docs)") + return 0 + + +def _build_export_html(docs: List[dict], source_md_dir: Path, site_name: str) -> str: + """Build a single self-contained HTML with all doc content inlined.""" + # Group by category + cats_ordered: List[dict] = [] + cats_seen: Dict[str, int] = {} + for d in docs: + cat_label = d.get("category_label") or "Uncategorized" + if cat_label not in cats_seen: + cats_seen[cat_label] = len(cats_ordered) + cats_ordered.append({"label": cat_label, "docs": []}) + cats_ordered[cats_seen[cat_label]]["docs"].append(d) + + # Load markdown content for each doc + for cat in cats_ordered: + for doc in cat["docs"]: + src_file = doc.get("source_file") or "" + src_path = source_md_dir / src_file + if src_path.exists(): + content = src_path.read_text(encoding="utf-8") + doc["_content"] = content + # Extract h1 from markdown to use as sidebar title + m = re.match(r"^#\s+(.+)$", content, re.M) + if m: + doc["title"] = m.group(1).strip() + else: + doc["_content"] = f"# {doc.get('title', doc.get('slug', ''))}\n\n(Source file not found: {src_file})" + doc["title"] = doc.get("title") or doc.get("slug", "") + + payload = { + "site_name": site_name, + "generated_at": now_iso(), + "count": len(docs), + "categories": cats_ordered, + } + payload_json = json.dumps(payload, ensure_ascii=False) + + return f""" + + + + +{html.escape(site_name)} - Docs Export + + + +
{html.escape(site_name)}
{len(docs)} docs | generated {now_iso()}
+
+ +
Select a document from the left panel.
+
+ + + +""" + + +def _kill_process_on_port(port: int) -> bool: + """Kill any Python process listening on the given port. + Returns True if a preview process was killed.""" + import subprocess, signal + killed = False + try: + out = subprocess.run( + ["cmd", "/c", f"netstat -ano | findstr :{port}"], + capture_output=True, text=True, timeout=5 + ) + lines = out.stdout.strip().splitlines() + if not lines: + return False + for line in lines: + parts = line.split() + if len(parts) < 5: + continue + local_addr = parts[1] + if not local_addr.endswith(f":{port}"): + continue + pid_str = parts[-1] + try: + pid = int(pid_str) + except ValueError: + continue + if pid == 0 or pid == 4: + continue + # Only kill if the process is Python (our preview server) + try: + tasklist_out = subprocess.run( + ["cmd", "/c", f"tasklist /FI \"PID eq {pid}\" /FO CSV /NH"], + capture_output=True, text=True, timeout=3 + ) + except Exception: + continue + if "python" not in tasklist_out.stdout.lower(): + log(f"[!] Port {port} is used by a non-Python process (PID={pid}), skipping.") + continue + try: + os.kill(pid, signal.SIGTERM) + killed = True + log(f"[*] Killed preview process PID={pid} on port {port}") + except Exception: + pass + except Exception: + pass + return killed + + +def cmd_preview(args) -> int: + cfg = load_json(Path(args.config), default={}) + if not cfg: + print(f"[!] invalid config: {args.config}") + return 1 + paths = workspace_paths(cfg) + site_dir = paths["source_site"] + index_file = site_dir / "index.html" + if not index_file.exists(): + print(f"[!] site not built yet: {index_file}") + return 1 + + port = int(args.port or 8777) + killed = _kill_process_on_port(port) + if killed: + import time as _time + _time.sleep(0.5) + + print(f"[*] preview: http://127.0.0.1:{port}/index.html") + os.chdir(site_dir) + handler = http.server.SimpleHTTPRequestHandler + with socketserver.TCPServer(("127.0.0.1", port), handler) as httpd: + httpd.serve_forever() + + +def build_parser() -> argparse.ArgumentParser: + p = argparse.ArgumentParser(description="Generic docs crawler and local site builder") + p.add_argument("--config", default=DEFAULT_CONFIG_PATH, help="config file path") + + sub = p.add_subparsers(dest="command", required=True) + + sp_init = sub.add_parser("init", help="initialize config and workspace") + sp_init.add_argument("--force", action="store_true", help="overwrite existing config") + sp_init.set_defaults(func=cmd_init) + + sp_crawl = sub.add_parser("crawl", help="crawl docs and write markdown files") + sp_crawl.add_argument("--max-docs", type=int, help="process only first N docs") + sp_crawl.set_defaults(func=cmd_crawl) + + sp_build = sub.add_parser("build-site", help="build local HTML viewer from markdown files") + sp_build.add_argument("--menu-mode", choices=["nav", "all"], help="nav=sidebar docs only, all=all crawled docs") + sp_build.set_defaults(func=cmd_build_site) + + sp_run = sub.add_parser("run", help="crawl and then build site") + sp_run.add_argument("--max-docs", type=int, help="process only first N docs") + sp_run.add_argument("--menu-mode", choices=["nav", "all"], help="nav=sidebar docs only, all=all crawled docs") + sp_run.set_defaults(func=cmd_run) + + sp_status = sub.add_parser("status", help="show status") + sp_status.set_defaults(func=cmd_status) + + sp_preview = sub.add_parser("preview", help="serve local site") + sp_preview.add_argument("--port", type=int, default=8777) + sp_preview.set_defaults(func=cmd_preview) + + sp_export = sub.add_parser("export", help="export single self-contained HTML file") + sp_export.set_defaults(func=cmd_export) + + return p + + +def main(argv: Optional[List[str]] = None) -> int: + parser = build_parser() + args = parser.parse_args(argv) + try: + return int(args.func(args) or 0) + except Exception as e: + print(f"[!] {e}") + traceback.print_exc() + return 2 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/image/1.png b/image/1.png new file mode 100644 index 0000000000000000000000000000000000000000..ea249a6a7345972171fd8de720d7f97439e24b75 GIT binary patch literal 117854 zcmb@uWmHye*EV_~3JB5y(gFfXOLup7hjfE>v=N_Q(HF(UeHI5XftYm>{2`bJFgdlcs_SF6?0>-)kaWYi!~S#UxfaRPq?iLWkEB zRSxD_YnC>#>gHOL%Q-X_$v>*p^I5S2(O*V?&VwVCc>aXw6V*Hq%~up<-X|H&2f3-I z^LB%^Y+}3-2B6xSoNLJRX;H0fHGxNlC4({QPjCT?`Bi`V~`* zPt%|v+yrpE(0?!TCi54}$dyU$S+f;FNS1c`_%V%TtLX3V9>1nd^>%m5g>a+uuiCmu zOCvoQ`tR=!rSp1lqj6EaVg7T@+bJXBzQ{xng7cqK5XL7^Cjb331ot?Ce-B;~l>c!z zB$)UA`;Bo@T;MsEhuv$o`HEz*y%G`2!SM! zVoDg$t0@dVF_TwUr-2c(|3hjCUl4RD~YP@s53~b9(e~(uDz1ti4>Er68q1x8s)eiPYNs>kO9`*lo zGb7~B%_Ld!f~kq`8{GfiGW7b-^n-cfEi1mpBL6*!^Uq_lv$Mfw=JEXZ;>Rg_U(AIf zhjtvNQaY~HE@#~3_u!u&sG6Ev6ij;Dv%4*SgRCLdtypg5Ob5=mb$w0qZLE`$d~C*?s?$#c^$}>JcNW5N@Wr(My6~#Vgwj()noQ1tDKJXI`)6_ zI8q=Rvv0i@$ZPZZgk2XHld2ajO}G&WMpJv(WgHWez}vK!&=ao)awE--s_>u;PW3l?9a0h)75j5^RKv zz7Z1Q|HK=X*z0wD8Xp{7)#xFC*jHl(4-b!qhNjcx9-o*fk~#eC+l%624fo@K$P|Lo z{9Kqrs8&B2?`e;b@`dixdimNSi&WteYy)NYcOt{OgG=$R zxm7qrCL=K37m>1WS8W~G@T6B3n3AP)_f_7$+}_z?x_|n(UW<3+FX7SABY{{|oRDkM zgtnxOY`tJl7KRJ&l~}Wlmn2j1>NlgNriO<00RQ;?d0#spuc~Qlr$j2ukh$0} zi5WrDP3t0dT*~<)*8U_Q139?Mz{@J%J)$;*px7l(@tIWq`$+9#NMmdrQ6N8y+rqCtt90Hv~r{CKk$KIh~MlUtWiV zjg8G>HS1_^pGLe6ktLs+no_D}*^X|8^v5Qe&MZ04zz1>yJhnG-D9v% zZsQ-@O%NHll>o#2_`1zubiFdwyOY?MnEmOh zu9=yOq4Z3|_d3p@FEKE-QRQxTuTsT4z>PmqM;*Vqz~=fZ)l-4Q0wF^9jB6!3&lBcW41IG+HIB zJceTh4rbhKQlzxBq1RF2$;n#s^2Cwd^z`&*gpQVDs{*F0(-bw)!-mvbuwsbziGP6I)|8cDz&SQCK9f zx4C)P&!VHIQ4`i}Q1A2*AA6BAoCABP+cs7O*)Cs+b5?hR@1>%BnLW}a7^bRfXuJo7 z@jLYC@dDcLAgDIG|@sj=IT20Ff-nkt-WQ>zK{ z#mc~7h*#ljj*6zHEihY?ldRCtK-b)^j+OEincXip=IWiyxATF3H!R4XW0U2g=p6?2 zHn5RNeSD~`y-j2}c>0tor`mY%et)eOK3qgbCX`eHQ+5VO@%s8Y4NbBT@o7?5z9FIAUj~@MwwX8}(Y-;$;({+4c@>k!1a{r$BjTs`pOM3A&9cFy^$I z2Q0@5NXOER2dzXxl0MpO^%+$tD2%wC@8--_h-V51!@ZaV7FR`b#UnB{)>v1UC|X>I zIJ~4}Kas_HG%qX+v+l;$_SlexAFg)SF@@C=mws<6W%Z_Qd2}o9rQZMNmHU6Q{AgD9z;Y$e1V7vM?@8)EEe#iB!9@Bz0qMu z`Qa|sL|^}oCe?0CQC+>x%j<1)%E9XDXq7n@R_uV&{;cIpb#O`wfzqq%tr26b`Z^T; z-{2V0!NhouOvue_x2`BPh`6Zl4PoTPm$V$yVS`Am&{y5Oiq-5@+R7Q5@-ERykBZjO zaDXlXw(j<1&_j~!WT&+G`gDYd5r>+XnEs8y0no?YU5lG@2TT91bUwYZ%g*2#dv@SN zjE#)A+%NOI9y}2}X`7l>+&#LOE=|+(qoSgoKC`T>u111W&A4=YLrO}@csdz`MJp15 zS27^>rZjb~$?d?9sI9NeEfh)FqF-}~q}wIwvh!ztu$o8USiV4%&Cc>dII=CNV5!iA zr#3VPw%o-VR1EP-=cFF5s;dbn*oO(L@s|_jp_wv+x2`_l)HsU}iF|(95j!3<6tBEr zDco1>!-Xsg9J5lk(@B&Wd$p5%fFtq=Lts&HR*^e@-ABh+#Q&wqSbK0EktzOUgVxzC zboJvTFc>p4Gd8ueTJ_acmNQ@3T@M$RHUO zv$8sqSK;F|*p23)Rv{goB-WeA{k%HC>I@~6fO`%SJ1e*L%5cr(-XC>-w6jQUB=5%6D=sc>b90mK)e8_V;{QFp|%e&X_?oZVdzJ;ipd zP*7OI`DX0RI8kd}@{o{_$jBfUyl07R*6%7|von%|GJ*NRmpig8w;0^JX3JVPHN{4) zuF7;slK+PLo=<%m_(YuGoTOd74DAY?-ZJ_xvnL)IaX<# z4k>78rmD;b!2-LUZuaPv0mn+n?fw$Sm5Pfixpyt()saxMr$=Q~FO3HU1sVa5Cq2b> zovP;VGJRO<136}9r7Tzj6OXzy0LqlOGylZIScuwtcSdA*&SW`> z4)1R^QoV|ci<_^_8f-Hg8}Dwf?8b|4iWPE0kdV%qQi(WhPdXW}U+ggBONo~d&byyW z=Du6FVI7N*P$cwy{;(Uo)9@oWUbs9|Fcj(OzE{@F+>V_}iVvX|sl5a7gI_Il-m8|$hBFAwS!En}#-xrT#;8D^q7s{_ zc`-Fz=bO5Kr=>OL_0WidfguHFdurF!gjdvV`hay(6 zY<%wMG0N#;WF+l+Ey2Jr0tJ2j?&0YCoM3H_OPnTFAvjn1u2EkEF0vb>OTPvNkY3#0 z4QKiQ8$ci5H&Lns`}FpBwOc_z0GgV*7+Cg&2A7>!9Zz|eNQ#%3ARfG0YV!e_YvXi4 zi5B2_=P*~SQFC_cjE6+d%uK_~Y_-&SaC5##9owtZJb(f3i_2o=0RoEXXv2PqhmI~D z=M%DK<3R#wnA4k!g+m{oc9l|X1#2mw?#Os>TpwRYq3D^I98T!m?C$QqgeFBZb##;# z6YC!2DeV~?q@|(Zwpq4!b?rRa7z_&ZAr5~_wF`oeD~Xs(b8~YnOiUvqBRT7}{5@b{ zcwA5YJM=Ixp4V8-rNqZG>35F0Hb8yuj7?4Ty0DrpH$d!O=7$VMasn(_(GgxK z$wN2Y-RPio7~e@9@_2@_Ec#s$tlRU$Z7o^|EAR0<{ItyIPR^XrM!7Gn=z7ET z)s+=vmK8@p^O~MOWMc|>PqV*UP)5dj>h4GXORwOk%TSQC_lR5AVIse41e0D5oUF&8 z9J5>K6xqVq#}9|hJr`R*Lp{#iK32zINUN$}u)C;Kz}J#-I_Lz-vweA_pveE$uMHLM zDF~PgXZ?B-UIqw)z$r~VB7$I{`N3N}YM_6uRJDx#^#>co4$>_7tybUO>x+Y$k4qP$ zxD6oE0G2K2+qe6T)X1KedYJI2Q&x8N9K+sn^8Bx8cob8mic_0CwcX@0_r-5h3jKuw z1v47mkfoDY?^nBUEgms~LRVj&Y7lEccyPiTmuLVk3Xr|>nuzPidP zdc=WG7STaRl$PfWW!;rY`iK!BosVX3L8q*HD=SXe*| zW}PpSDW88@F-TDo*8Ty24X*C@%SZM)4JO~v4hK`RWpQ(I$Y^NB8hvR-3ROZYjN9@Y zm{Pgi#^FYwFBcyb)tCVvhT2WG=@x$^yti^9I_D)Se;hMjF%m}kmt6K!m4`le&l29( zCSyHKJvjZNN)~ErQ(#RkO-#PquE`XuSE0cNd0rXz`yyb0C~a@N*j!chGLl?IBpBzt zVGoNW83X(E^>kJ9-ke)lL5~P3T%hNJ$H-j0O{&NF7SLM0%wenf29J#aEtLuFAWRP# zE!3-(P@aQ1x1UqB_)M$)iMJ(MTH~cUnT5Uiy7xez*xA2I=U(j3jZ9D1dAM!-`n4$% zdY}1ZC_mrSc;GfOJ6p)N8Uf)M&qIU!+6$05^V}{@Gm0 z50`6HSW1eVA$^f5)qJy8=%-IDV};>66R>l24#vBa??*9o4^t$>#Hz~6i%L$@zX%ip zo$WCw$H81A6C{p7ryiIgl&(JU(NT`I?6tGHt2#0H?2W=-Sp+i>w{6-*=JT@C*NV+G zm6pf{MZ129p=sYxn*6qqukawj(TKY))@r?KXmC!{r6~SpHD0?oU(85np^=zaP7rSC z?DULqZ0ZgK+LF>5&!i&*? zsdOcW_@yZor#l<1E(r$HMF?c5U6Rw7E-p@9Iq~DmRQBoBCg4+p236c@L; z&OF(X-OI9Y+1W7{`i-g=3K?lWUtU$9_LYBzhJ{5Eahdwso&pJvM9(o*tHk6TJ^pzd zsZ4h4c)G0Gdit7%hEzzoG=hgPP31OL6|qD4%wmi=4a_M~yyQb>1uZqy)b8(Z>d0kM3=IvD@!8vd{tO!&B=I@j*>JqD(zHDu zaopps_2SW%kttOvO?mdr*C#B7dQZK|>}t6qsI|4c1Fb{v=zOo-N^9@qDBd{+%Vg&>WW#|Eb?R+nJWqE&NwSk_AiO6SjdmBWo&oDeNgE|0=qEsTx zVlioqgjAe&hL+0dVrFW(w7L1~1D&Rpn~<=uP9x6N`gmf8UUsgrZ1*t8)k%B~oi$|! zWui-ch<)M`5*)Wj!-X@arl$e2ht5C0KV1o6g{g`S+uEX@+!Ch)ZAFI=B>be{;NUe| zm%Dig-wHb1Q%>!wLcQ&6TY#<0$)Q#;i!x0+I;`z;mpPub(KNc*JJ^)3G&c4yob?fk zEZ8TUoP6X6VZ4z)yw=Lyi@jnUCKS>1)V;}mSl$;Fbap!!Bp+BfU@k+5MBy(_>2A1F zc3>LG=xj1!c>lp3mY}=oyUU%9Zt5-P?=X~zBUZ1)2W6?@cOeK`PKTGxb4kq>apuRz zmo7eCh2J$pG5rdK;D)PrK3MY-Byu>Iot&q}DU+;A?X-~jtQx3rkF2cB90dB0{30-l z4h69I$=Q0>BnHp6+q{04{eWwxt1MILlxs-+M&+TDhV#jK*!Ps~RezB$hFpbd1xku4 zy1aaEUk)U(orUr^D#ep%7Rqp&*4wOHU!8c-(b0v8XJgT7PyMjDBTr?#eexB6a_wC_ zcuZzKAl~XHWsQPv?@`17o6YR7oi#gK{z^HOyQJRHa;E+wEm9#7U?s-!w>03g#&BVyVGdoo$H_=430!+6pCoatvp^>aS?z1mnQ$v0?b7V;26R8R%jUfGGU>VYz;t3@h| zZ}_ID;~eNgoEp)rGm;NH>DfG9#D`?pfz zctjxBTt!HNaOS%vpV)4L8ta8dr&9O#o!X6c3Q(IM3IraOAhh0kfe$BGSvIURyF*f1 zdZ4EV!~^L@C8dLz`>}P`Vj?2N;{A*`!P2EfP}O+J19=`T=+3FCs;YuQT7~;2Mn;%H z*;@Li@hGkKIJNddgEK0$b3dFf&()rf@H|)J0_h>e zGi-Tfb+mKG?V+3==NWw~aqX2me;*uCdryBMN7c{8ib)RQ`oRYF!#E$56FxhY(+Ilf z@80;R*19+@o1tcmWe1J4h_u4EiS(>*hP9&QyLu(KxH4riW1+zw3>tPx-`b1~l=6HA z<(dBZ8Jr=Q<{y2D`uy@M`id&3l2gWU%4;aLRF2Q0YUX#r{t~O03w~=LDJvY2Y5pKw{>(=4 zwXEW*tf`7Yk%~5ryjl>ZGLx6fp?0GIRZNWR+tHB~ITb<*W&GW-!mi;=azEsY2+=nn zND%N?$^vFxv}l0~-j^R!LZR1ce5*i1S1v=Sv(SN5uw6nG-4K0V}hul}VxY(~Yb90-WZ&_@ zs_Ke3$A?R8oxz1+{^`a25#0vU)9k{+U!kBRqE&p-hD|sLSV-5{&OE9TH4bhr2=O=^ zdsj49>G_rqoY6weo0^7+FC_jJs~1O&ss-_D*%k{Y}Z`tNo@8E?{vYM_%**dAK)n?q*%-Wk~h z_kD9H;7%1)m3(owuud`(Z;_Jopf_D@C2-E|kM6K_f6ibo+`i7Wt>O{?YYR3Hj)neI1S%E@uIx2W)1Jl*i5-ZuGvY!Rw zZMO^@%y=o?kHuzq9%lKpa3<42GiRL^`qKk_MjaM`yfs}e+i`HrM3O%!BS|Wp;YAS| z0g#N}zqE9)(lnC7nD^nZ%}LSQ4FFAwP$oiLn*famXo{Scw{|*e3h6VPbX5LR?Td(V zkgLBi#fYsMOITKK>RYT*vQoJgqTZ2!BLW~itm2fE+-H(Ko8zBE+a=W}C5k;JvZV>1 zdum?7kM3yibmN|o7GlTtQd6LbXJhm%JUVh5Mmh=#*S4?JpjPDNRm1J!YHVmo>9wl3 ziZ!7m7amryn{KMC9HR(fC*M#qGfPO;T8pOc<#IhGbP#(Fv|fA#;ms5G7mt`#?vZ23 zgF$;^ctgMEsL|WzvSoS)qbdT$2|Iu^oE;oEF8*8sn3;yUy1Y3Q7AE}p{+y2D8;gY| z{Mg>Anwp8RHBQglxNd{(t)sj%cb%rbkB;|QLI{*@ZZm}{3IOJtsj|x;ZiuDPs`^fM zFj;1SZHRzyqE=y~*-TJj*h}bjSG6!)R#jW8mdIQTG$cAHX?J@%QaBS}$`Y|9AdUd8 zU+%7($1Uc1S1m9(c@E^Q&JE@6V>=W2%$C!RC+o@Sbt!UG5XfIHfPkMYgBK{J2n!nl zeFfRebQP|HN8n;x+Xp)ChuIU58`^Dn78Yv}k#I9H?cLwO24USy*apV3gmk{Nf3>~T zPU1u7QtWr`6v7=BE8>qCB%LHoMMYVf9`>q<<*WPk9qkvYIG17Q>LtgO1 z>DJ)x&Do9Z^YCj>o!ZFnhy%`m3AfpRH_eM3Y|k5;D^Hh7*Gk{td0z!EG8d1WC1RD6 zV`jV)IQdnuqlwI|ti+#%gAxF!|CG{8CM70<;+823i^G>3kUs(R=Mezf+FAlpH^y=v z+qI-=rLmY_u@v0Wk=yu?Ut7ug&b>JOND3?arLq^NneR+Wc@S?`G4TR-E#0Z*H+Ckb zc$2J7NxkKj@83@nSStcAR$*s`h7Qlnn*@o6$7$+Kn5g$U#*1gLsIObv^uPOceJBVY z9Gv;Cdy>Rf@$xK+G~&95SM*t0a4;h7KB{8x@Gue45|0_jo7GZmh8*RKB(S5li@bSy zHI_34F+)$i*#WwfcArzZ{h;x?mIC>zdRHqH{kKWwdwpRtGVUffVDLuOK)J-8os0HB zN=z&uIe8CQJ~$%F=}JeZ1CXvZOT^q>UTvgiXK^AUH;ZP5>v(Cke4uN(wRN`GZR}6{ z5*ZP(x2JJ`GFaOcn)(87v!vX;CpXmCv%W1GXzc@&OJYX7uf40dZ_s5SPb{ip}2o}gf2x=1`K)t=t(E}hcEbL7PK1XN! ztZLn9F1WkFJw7}kAt&3{%h%g}dz6U#zQwxP@)dJmZ)ayh?^u8T8V`V3mpgjd+1Y7z zn(XZ@v__oKt2fWLNQm38Nv3z+8$Lr0O>yDH6P`hB-5XA9T+2jB<%dU|;QyNp3#m_$L z?iLRY6`eOeDAYmw=w7d;K3#v?TKt_@Z+#Jg(P#|op1;2pCry%z zb@%c}e{a`v&-M#Lz~ryvCQ>D?`+ypY5| zYO`!8{B(l8$=-_eP3Uj9~-s|&cX1Rr!!FYxsaTlwZ>i%-WAW+=5-5y;~ zwAun$CA-JC5NyvWPz5D7`iz;6xfo13hzr?EVDm5g+U7YJB1IzK+fOXoTPHbeb^ zksWJYM~9w6PIBx88QFSH3?@JWt$K7k6651Nj{_784D2;$Jw&?37d%)rh{M}EI}HsC z95)wtH(0Fit`X1NG8Umv##B}g=7TxBxH&mE{H}*B$9m=mt>1iyA9*f0#+-);b@udwdkzj9L+hM6&B8nd4N6GqR z5ifQ3C=~4tDEy)V?eVWTZf1L-BF~A~9iekw*@pshc$6ykU?kO;y`%gE?U^-daZ(%; zX|e8)nNN4oU*)lWSl_Ri*2>R}9Na$sVoy2fTgb)4X$;Vd%10Q#Vje}$OAytdq!`AY zv?kZr58sWW8j3+EI#x%4swY<-Isqjj`Od6A0Rz#gCb*yuXDD#UZq2rDbi@`o8J3zB z#m4pa_N>pJThr320Q?BT9?O-^pCBWstwmHOSX=&`Z9Xx;;k0i$+#1-n^p--T{)auA z=k4q0OUYyf(#pBY>(hPro%1#<+Hwj)dZzcg^Nn1QYW>eNL2M8@6DgUOR0$6oqWU8u0O`gbV9RVxe zc^V&dYwG|xDXB~>f6)Fe)Mg24T~`o`W^5#4P708C%sXZReB ziyv9f;&dAc)opCLL71!Eajjd zNS>Ml)F#=@DZ*h(+=q!oA==&$gWuRXQ}s+|-yqzKfU`p=c^Y3(sGvFfVff1REe%a) zl@C~6h%70R-$<<;d4S;U;gVN;yqb%PwIFf0B1LwHc(#1FXcVAkdX5vHimkK9oKV<$rLU(02^hvE7HWG^G{lw=gH|vCto9G3_=j$n9`u; zqoIOU%qPg-kbZ_2PW=8uii-r|Tx!Fb)X>1m?;jE(O|rq)yLP<1toJF+zu?^;DxfU3 zU)vS{lmU+|D(WR!WXGDVy+bV?5`dwGw*U!X-~(M{W#y)Q9eXqjsHDOpJo5$X_smz% zCg2aLtykCuPYEpV{Cp<6`QetOdf&Fxt6sEenYKM6la0t@H8UO4YS z5d{L_q9P0KR9Y0ccD*u9ZSltJtUMPqP(If)1=JM*0RcO^3MU9>4zO zik|7B@`G4Zaa$(}_JHWW1j)Z_N|V*KvozhMwZ9ZsZ<-$00%>ho5*g!8b-wy&^)c!`7vH zMTJ@TKZv463Nql=+#i7z(Hsa9Hw5fNu!#A&&`KcR1@G$?TmyvE$HU~qqmFoYf(^w) z2$%YM(mNEX^)F@f&*wDM|Il^8XK&%xk8IX|51daB#(#eXkNd+N{rB_#+KqIHu1_Eb z^}D-CIVn%v1^fE@6I>se(0>j@7$_5O_1CZA{yibf^Eh7jEKo5_{Lf{Fp9BE6cacO0 zPze9W$u?r3f`soVpmAz`bWmH_1Zm7JWB&KY^EvB60d#nw;8*)#<~i*~JB(*9|9Q_M z^h-iQ9YYR!z{>si`2WEt{v$j8J}3B*h`dOmbd6b6>>lJ;nTfw=BEm5}9P-~EwR6w6 zhkW?uNWO9a>3Uc8e^IX?9bH{2Qz1Zf|8x8=6Q50R{_=zWdH&^3P|QmEiu;KG3KePO z^OvqL{R*Q!=j|r?*=CWcvN$G!W^FQq#lVUn*ZdcmNbj6roI{69D#3RC^8ok7$7I{j z-;e+`5Z}+VWl7%xj;Lnbg}PoJS4%T{ zz)tT@)*cMv>SKiu;mZWHRnB7uGjRQTx%UOkBXQGJOg~~Gge>V_X@~II zJz{ZOqe)Q7=NnX|y)qc}H)O86Bt9sx7oUPT|1lkp2J~?hkJnk=NF7cIWfh>|RS?Vi z{6qK$X6cdrKT5o_SrovbgQCZfSJOXJt!~C!=<4D;p5>t^UfIT&N|2CD`|rGd-h3u| z8JOS-O#YDQq($;SLc{wEltKY9LW&Ck0&!M3IyzFS9>Mh>`}a0rCguKL`TSJ;z+?vPb1qiD($Q;pZ@5Y)|xIHX1nUMCcmegalAiv zqZO$d(7|7u8aHkI=XEb1`SlPSUNP~}DF)Ng>dgMQ?I%NGUCPuPI@MeT{Xf0cS8A_p z$eFF@UAd)pS#=)<#2mk=*EKg0I-c)cNnAIWL)2ZWx21oS2tH{NEvlp)@JI?fa{RP9 zYi!dEAa(hOGf}s8LWG+#oa_C+JI7n`$7nd~G_tdsub%sjIv#&Y4SfNRZ9Fq-SMa4z z;r;|U3ymNC%KejSFcg!%&hgGh0Nh`5&3p3s(QyB~>9OzIm4h|H$C7pHo>B3wyIazi z5*^=qW{1pKY9>h3?9QQARl`zWAWcnf@dD2(Kb?)T%)(G34ujkzZ$wB~#Glho@yh@2 zDlB?{y?=aY;oUdFuSq(dpWv5!QY;XWPOiryDKQ!bmW{`mm6HYs`%1SVr7e1`RUh}4 z#ieyjzK_g(`$0xP|B4MjSJLIA#}AX_J^ za@(Ek231G3TKb=(igQAdsaz6jwYGa$I_}(h?R5O2Mn>xeN}rmVxGA7a_~8H-bJzs& z4u~>0<{v*jO8C&3vZCf_dFmjh>!N?WzlH!;MrHqEb&OG2>l=-ZjHQ#F)|2;p^lnqj z;WWZj{QMbYic>0VDI5m<9p2oC?>{+xSY;fV%MaLi+zCR0c**lF!g^4&?N8<~U;VXY z&we*sdxFbsF;(Yq0}|_~lQh7jRizpq87ai$ixGVT^b&;q*;+KQ8yi@g+qSAym_&ja z8Z!$EGPPe+sc5KPeq`OnLCXMTQUrMTS1({FgM#FY1rRES{G?JLUfY4f=4^gfTmdz@Li3%%2+zGzL72`J1p({}o@*E+9DMipws zs1{Esb9E?fL0u4tP%#J_0ITkFd&~n2Uh&7&$jHiY=7XM|6~LZ!jg9Ng#_HTImH~|q zkH=G-EV8!l{B|psw63l$kl_s}*ZGMCs4l(2YXDsi9OmOiY1071jiWal2PBKCs;Z5? zcs8&r;i8o$au6Z|kOl*Cf4$=!Hjb+zS>*86=_lwL0E4@)jmRf==#@oBcXR})z!3#< z%jZ}2lm#kUu_tpoA9{cLMuizvWz-MPoT#O!Sm}A!*&AC5nxdeg@3JMZ&bP-h-=$bX zyq*58M&ps4jy!I)BeP6TBDT*jP>#Wh=(6B!Y%;w1RJ7uGa?VXTW257^>NS_&pV*B2 zK%MdRMz_+AP_~TpWV6A>Ey6rWvt9gvVt~!wWwgAhinC~2TGe6L%n$=XHR!jVHRrn` zo1bm)=I@L;v}-ll3Q9hVd8TF7O^gC>{nL+%goJ^Xwp6QL=4JN)0N5pBrHuzuBxJnA z#)f|N^-;WgH&tVOvDDTjoyzTYv>d(E*7(x+<42P!_p9Hjp6YC7qlW;p+}_-j-D9zy zzhCk@sI01jhW>&?$UUALN*Sv`paTe9TyD&LUB-Q@-RLAFnE<;)Cwv$htIF*;MMJya znXWonYP%Uo;R01eA`ub4qm?dh_qdPux4zwxFoNh6=|$>*j~1@%biFD2R#jAAQeb@ic+~ z{1Fij4tWA^M?9XE?Zr=U*hKjv4|U8&D|8)oE>8$D-RXkN4HO-HCa7#93g4+07wJLm z%;r%;RS9-eio+p_<}DqDF+oHBc_M@#a2Akg6mka+uiV!lm6|k>y=wqPXYU1}&X6HX%X3L6^~S%@jNr;|C#NJNkhW@}fvBmMHx@Ls@t5hek&UE=Uffa(J_ zdRGWOpaVBuo85v6Mt1S7vTl7}2^*Z^M7X zAmYM+NsBYqk=MY+Qqi#dG*+bphoPrjZ_r0e))f7s2+v!YVvTR#>QLJz+t$tZH{qj+ z>`#u4&W?^=1MDRo_oH}_1QWgCX?{&lKi%0`r$p)2KSvuZjQd`1(jT?$_~fLmjrJMr z0jtY#-|1GQQr+6>D%?{c3ucWs6rLw!gOihS!kPG-&a2&##)&Ks^JV%s5BCz+3lEs` zYBNAiYHMqW<=!Xu5A?c4rleR|T1q{eIy*b#%@<*7f04+P_Z`{O*%+GRWiJ0fQ$ zry^o8LgPcGUU7fTR#(f+lN~x7kp^PM_ap%C0^$~vl5%u+aT5IP z#Te)F6 z+VNT;Ai~($+p~IH?*elJ5audiiyT}EfYm4Xy980Egi7BhtEDJ2aJW!~P98 ze`We22MdJP6FRW3UUUN7Fba!V@uRI-VP+2G_S;Povwd!T7PVc^1rdMqB}fd`=W zi5i3yo>Fi}$H!Ff-m!uCr3;8OG>Vv+M$;Cug4T|7*-C?M8T$BdZA*PgY*h-mNZUNT z5bukppcVJA-42o#E}OlX_Q{{26mJq2`(iPDocHZV+z z-;g4S%xT7{AzB;tuYSBezMh*JL-)!s_B%ih zGl%?#$*$1u*O8ipC z*APY)Ky{16M2ZvKGbq4|g4Z@aQo^M~K`6geiq1`&uGKT$2}fwUAoj^36s$wq?{~OY`=JZ&eVl|*+rhZI31$- zz2T_sp9}-?_;MnmQLjOd!oj;9GxMnTb{86ROJ+l64{nO(6`&fzo0{aGmR1qdmT{f97y*BpANuwo!;E&-dP({ic6kF!QB8|C(M zrDj5z#ohu|=cUW7a%#Tm0Pk*c$(gG@EqY7uX9X&cO9R|uCLbv4Vg{rKIT^cBA!%Bk zUW>~PWtJ|ib3{(4d>%J)gSmcoJ{SO}zH7aOySXBXMw3cP5af~coCy7iij1=x8hPs2 zCvK_B*O0XCqd^!#r6`Vd+uBF_$#1~o^*}v+mfPfj$QN|=dZQ|X(TmVLU~TUBoS&?!SZJdJcgk4^q* z6$R}S6oe4DrDI{dlj8gbLGSt+jTQz`CK7e(1lbz{P5eNdAnOO_buZo9z+mCVbt`oS zPW>||A&FkpW|-Rqj53$*Kn2slSEa0X>*G^R$X@K_wjUc$O3aPfh!20kRk?OP);k;Y zO09nmla?eT{sWgXvV-J&G$t~cug`q@ke!^IWW;c3`#IU@JqbU%6wnBHdr`PE9-X_7 zkW1NYg1DMvqpOm$kEPtu-6}+=UPf|=-81XOCa7pbGIO-Ks&mFvI5<^{4a6OBWA}+? zpA@ETo_EXcnJwLWh)zy!Hdk9ryX{&2nzreygu?m8{SWZ*cIXkr?1$kYk5o+33@za(T}O6}Jr8`SnyTzBE&1fj6rDi|rGliC z=P9JQJ#a*t6CFF`>L7LjY1~aHNsGet7>b;c+C_5py6EJ%SV@i#N>Bg-*;FG-A!=Y@ zf%ZR;7~u)wo6G{e|7 zmUmW}x*mvb*-S9*Td2(#KV#EcmzjdBe`T4sLvLk$u8pO164n}M$W5&5=2kIQOIaf% zvQd{eB8Q3PCXnp;S1X1zAMwPP_Mx(PI_dt zpAk7cq_f=dKUsD~inNGYEV5iG| z56~pkoC{}X-^$C-z9KN1@)-J+4&8V?6>xIp4l^OzY@yXuvVhNaXQ?KloSkJ-=C8{3 z>iMO6>mp770z<`R0hgJljTJV=Q z9uFLN5QbDqywGY$yo9+Pi@3KKU7-EmERJi&3+*1It)tF-%j+Y)88_^DoMAC>s^4xs8bh_RQ(kDKN_kQ3W=9nEovCwXa+&U(`R>hF6&qW_ zPc>gmghvm`5@M1xZ~lHwUVtu=i&IKWq*0N!Mrl)-IbH*)z*|w?_Mmghm&7sQgs0Zq*CbcSK7_SJCj=7pFHn zzrq+2$1Osni_IGO9oSr5+0git8o!!0x2c&8)oqWd&N$f+4VNh)FV)dZR({7?9{f9R zLYzNv9OEYrgQMfP$u-nsG7C+ne0QxDGxi!nEa%a^`7_~GUD;nwWOCt~yMQ?S@kmq4_*?r0ZV-)GBR4Elugw`1l$#Gc_-eoAZ7f zgS2XIhNIazoPfY{c)}^E+EMMO%nz9m(04$5X&@972-su>Mn=Kd47Ob%VW26j%DS}f zHOg2ExEO{28}btt4uIHzLkw&Pc+1b598c^a(B3N&n(~Ty*UrO(OQ`q$&JQFaGn1;6 zb?=@Gf&A2Q7fy~XARyofG%4=S)+UC9iTY-poFF*vPVTKRbb|cI_Ant(M}<3dSuwC1 z0&(~GFMdy01ZukOo+&BXV?=;%n0$A4$IpMCz58-?Cv2m&g6 z_#FH>GO6zCeLS?*cfq-ZwkBo_g2Zw+JX|Wh0f*DBrwVO z?9ZDpDZT{+Ocm=Yq8^+Afze1kNBC!h#UBGgh`Py3&PB(|^BSqEz}H@P=w92nU1Tt6 z4kWrTcTTwhS-@bWdD4Yi5*Eba=}iy_fy*+Bo{^E)<#4;G{?N3`xAx3)ysUX|cQ?X$ zIW&~b`9eW^CaGNY#?;V|?bZjFqhmDd^z`#D{-Bn!;baLFso1siozlzYQuD@akm$c; z>()!vLiPlKvm>qhD=XW*@6(fl**H0U?T?-=(r(mk z_SUd}WIOg*#IGg?2(U?n|9c0|?9E^CW`qkd6vRhN))fC)$SZ1qPfd>hEL8NVI6ak) zyl=d2MW1{l`IZ|o3CqzT=)oj}tEw6`t%XkV>7*eLtzBJZRjM~2)#|je@s`}vM-tli zt_KW6Gl~EG9tdOw=k|X=x+nQ-$U|GPMF~uy%azoF_WoZd9us;Vam}yC6^jk6oO}kO zt~%QKy%GdU#ZTmD!~TJ-`h|vREr=x-Q59UxueWKV@g4EOuh;YbhItG#1t)tok$PEH z9x+drW`=nfgi7P2c68J-mQ<^BfCWNd!ojP9V~#adqmaqz&Z`AQy2kGVLR_^h*zvSk zq%BR2PYD`(dR^XC^UYWS#Pkdbr$M-nT@9rX5wV|H*?2?$5CvCxk zHp<2FQ0V;P;y5Y~0-4Omqm|_*&ALgva&x&UEv|u#j9X52^Si_x1E$}H?nlh$OH9b3 zHyOKWUadt1TMr-lW8*J+r_n^pOJmp`bpn%xzC8J!-eB+ZEA?>AvzM11B*ICGdR{-~ z+ywh`7sYq4rz`$C9U)D{U34n7HLDa@P{q`cmVu(q{o$k-aESA-XMl27&wil9uJaEPB+ zBxnqN{x{wZ_iq{}>j|>R_!H)wXDdt)Pzxn`47u9Ekx7lO2pKhrOoq-)M0bGBr-+No zZz~(D%j>He1$Ow94xKnN!{zbL-T~P`!_y~`Ss|r!!4yRl4d+d13_a-iN)bmE(esV@ z_u)ufaBXN>-Yv-ZI|!DVRGxR>Kl+E44Ni)!R+o2=zS&N4i7c$loo@*71)g=K7Y|}c zc)Vf+#VYoem$6l~<3;0zS9h4W|K5Nl<|+z>1=-?`pdjmJb~T=scGpef-#6cH+F)G| zAY8xyD_*dx_*iN^cj2|JQ|xh7;Zv^wSo6ObaJdO)fJuUInM9S_hYq9tl3JUcm%@$z zYCf3R-}miFlI#88$hWZlCIn6Fu^rPC=Nm7xAUdr(eYsRJdHu2U&MwzZ9M1M<8%_@wzV@>8AUA4*m9&sO;onlXWiF-p?`0pJeRp(!&}I8#$R(U3UY=q<_Z&w zRT+$!u_J8wX`dV9k%%6>zJQe*4{g8pN{4AZ35h!YN%~>mbX=p4MQasvs?y4aWS(Ba z-U0)R$;K8nWb1BN6iv@$LUe`4>H;0K+T|)2W8GjUwa?BXKQ^Y();elNA)*jk+`w^D zg+)rzZ{LEC85bcQV}C`DBq_~IP*qx74$n5Kn`fZ1{*Objv%J(7i>Ro98jz{Q zZrdoMkk2iK<~aukZe-xO76elLD>gQk)9fwa+@_`lHCt;NnRYAmmCVzvCUZ&cLKL>c|zp;oKcH!=+fJt z-CW;fokU|viABn(EtEth9Y$^QlS3sWZ&3^%Hqow-x0BLLT2#TvlJ`zPF^#{}sw$lO zbUN;?{Y5=>)RKg(W{TuceBgL2?(lEqnTj#)riU%n4l!y*x{J$MB6C4vx-S*cOWz?g zq$Y;woEQpFP|zT-(J@dvA17*RP^8{1iwfYO6U2|Jca@6MmWtZYOgXVOyi_O&2sNTv z%F>tcjV{~HCpx@3SDP7^ZE*#E>B^-FYD?rS?d{zcBchnH4i2I!%_Lp6YF;=T-7vRs zKmP5ZQMzDP`$5e~lqc~OwSMcj@A2`I03Qtv4Sn(PIXOA;e`{--j%!a6xEhH$KUWSM z6&USKudiRlFfeFS)2O?;7+BfLTz1oL%*u)Z$MhpGwv=7SBM13b`kBDq)W)JYLu^*` zd?T1u&PNX4d&$*^2s|ofwipK#m>2>E%OW)9JGx3o^B-s?(^cdI9t28tsLpBR-5xxz z-kmv95zTz$!d2V+d2!^e!>8xN{DukMstZPuUzp$R5Qg0Hcn1)Sz5hj2WK8*l;w6{5 z3csC`dndKVX6uDKTd(cpK#PZ!vk%SKnJSFa&aq;#=&pK*?z)CI+0`Asp;+!loJg8W za1(n`lFA7CCZYnK-h#J-;*red3`Wz9^zIHTv92Kz!vaSU!=6wZTxYnV#&Ed3;!oY?3+bM4zcI0LgAAizx{QwK>4%>Q zJ_w64upldhCiiRnDykG9=)PyT5__Jpq_K4W>g$Og35PE6I__xb&`7fS8?j90-d-&@ zneD`#YRt=Mjnp8b%x76fdX>zIhL!#*MFK3eJD(qq zMsAUs8!6H!qavY-Ab#4U^t=O^9pNr!-I+`c|7vt-MoNCs^QR^7ENy}z&8hjKsgL)mX`U9{btExLW?8^#k~vIFnup^mL8YMV3hA_H(XB7 zHJ(rP<#XjvPitX4@}VE#+#-+<@Fi^*sCWFOfNABlMIIAjj2|5tkr;tna&NLXfiA2p zLz%S#IUoBqz!qAT93c7`&N!({RLK()R#0L_`U7+@B*oWQ(!UGOF3pv zX;ln066pgJG~8t>H%0TEg{#;c)@PpO4pgk$)0*_Oj`eK6jXNY(UY)?OmjTU4_8-95 zMB0F;X0~!L;=XZ(b9Gi$mM_?N?_&1{Cns6Dy1K$b-$~I=HF{kA`SVg*@sZE@xvQR@ z_DV_cU#tOvRDG@?9lM&8!ok^oTVSk0W^A#|J(K;lOkw`2n&l_`ef~dfL!s(^bR!|A z(yvYZw;S+dIb~Au*P;tf#zVn!>Tu$e5|k`kQ_+=tX+#4jW2VY@ZvIi)4J1IAElAXq z?KSkXeR*D1JW-R=ik$ni{+y+&$AS;RCr@43ZzL(JB^K`1vav42!%8Eh03H;JO7-F9 zz>*6T-lPkUnah4#^F~zM_QGhuuate0L`tBd=K0h>jZ0H!N`cT9|MPBKIy!m!kPE`B zEXKwd^1dk)iRH|Fnbh)8!!P805YJlaEc`xy-~f`7UvY47MB;!k3gu=HNG97-K3Lz)Yqykc$Fp>fD~aAMu;<;mBlcInDQ zr8PLk=4)IAFn9MZvnAtFGA7jcuX_E_UqAEd1;q4?MNPvn84j7aTS$3@_zUb7v9S*b za-`%w(7rMySZvWOwd|_(j>ROcC}HMPo@+dwB8stiW`ay8Ix^TiOyZH2jqooIJJHxA zP*ZVMS@``(uz^i6atWo6Jc+^G3xfX9&@ibLNWY>MSrp&kDrCT+ql1Peu{vGR%cRSQ z{ORaYATX_%*pED%DG;bVD(Fk+PVD2N|MfZ^8v;S3FyMpu-stqm;bM^`>2zH?fXnP{ zNyEa%Mt(Tw*~tme7q@`W2N}oJR>&uzs2J941%X^UyCP7?lF0}SGu7NNL2|7ni192@ zY3GUm;OeTwg!&I3dQD)cvsGr6Q|R%UG+AxEi*c^LVE(+^(>{kU-@I$XNUeOrL$em` zkof|?WdJunYoeSY=Y;?*wV|w^lq8{fx(WjwUF?7j>qlMRmgOx?!Cz}W^VMSBzP{n* zu>1Y>pJ!BnC8B3jtjp+5A2#e^H)>Kg$TEnuw_g9e7(x>5gm!X$F(x5n8DS9?@;*J` z0_rNLd;Yw(hLI{Z&tG|r4@GLrgdbh9lbB!0ImGqOAKwhEqE$E@BTX3_CQ( zQw0>;B_yP!Q7m!n4j~?%Z%uwDFtMv>tGCe_l0G(cXKuH7n_-w zZouIox><{~q_9Tvl5|uSxE=g=Cv`1HZ=HniN!XwZnI0D`Z?kl<*=r2^SXRK;X&=zkIrJp z)jw5}R_(Ib#*iP-6d2 zPXBnuf=>sn`zsxnt#&jirV4OQPk35=BgHX`Y;VsIen<|MQAR7vs9|I{(sgtu{b5V^byJ zTfz?42E{Af{MKHSjQJqnPX*8X4aTS!#L{Q;1X7L#LF2JWn@s5S#8Jz)T5hS6VRu?* z@%8y)ND$Y|dTCt*KpON~^Bh^jYpm)+h^FLbds2mvN~@}|C?SS$Dq|XjqPM7Olo0>a zu44?$DVLFz#bp=k6$v#;GE%JDY8ig@Yn4vq>M23d_#o%U%Kcoy(Vhq9qaUa=kj^mx zn_jXSc)XdvKb}^3szt|C@udt?#oOTPq|#XcXQN`AeJ>i{4?Q!?(VLE$+ZOn>+vd%z zDjY}R){-9s6EI=cvA8!5OmEepkKf~vi#&pS7CgFu(G45`f1gO#nu9$hySRwIKH|nm z6+qayvb+prSLM1Q{!`wc$W(<#M@RXtFD?!adEmdNuEF2K*g8hkq}q6{LkkFdNH$9i zV-Wm8DC+@SEbqdODt5O-@S}^9SS%;&yFu9tm@=Z0=AL;$9@75-pB>)RCry>mSROVS zkZs;g#ZZ5xsX3|*%&5L&oR20~pUscmFnQL~@W_3|@z!EH>zQl^0vI9pWUlTk zlaELY9WKSzcfp@L%;yaJ)+?iQ*_0>MTY^a2Q1XlR!0Or{pRRfn7HxnpNufqG5(p5r zCF&*dAj*EYnBiR_x7BA*Q+&8d1ol(ajF#c*4YH?CK})!8zqhioTY!)u2a$(^gN5de z&D9(ev%38Bfs3;v?dq3HfMx5m5(yUZd6YLyJvUcwf021(mRtgjp@W-AN%IIRGV3`t z=K2A0W+z5Ho%m3?rlX1gKb0Fm-(n-33U~9JG%#;0UMferlNCTChB;62^)fOZX~=A7 z<2Ulz$~2tVp~1$wM1DtAM{GSc9-$G8&^Uv`3rhU+AAZ>G$l0t+5KtN zeI60o$H8l=|NvZQ{u8BF`h1y1;t- zl@vHWacYk`KnZX&SOq?7-L^kJx@UoWaNwNRiY&w3+r--&S#hcv_IU@FJgoS5AcrFW zuy0lU%F5deYMU%Zj-E#>>V>VX4LU>)4iw4zTgB_M{lC1)ArQX*jkH2o05`c+e#jNh zzy`xJ5UbtEhGMV88S$myn)-8_G?@)Hendxg1G3cftYIp(TfbY*38l<)6H&^B114-n znT-5t6;I;$==rNO{t%fPoiW=Vc0i+3=%KYbZZXP@hCT`GaD(me#J-(7-U${KcOk+@ z%BrJ|PELo1^dMwhZ}G!>)OIf!Ow$`Q2j_`;2)yeg*#uVd+2snuUk(DWNqGNAO%Rd` zeEvuFf#{t2|M2qG`X&a%;Y%ueeMxeCfZ*?Yh{wT&lRSdFJXAldRm`Nuo^euJ52Vj* z!Z_kmIeT@oqa&Vhbng1Uo1sC>QgZFQ{>z*Q_X1;$c*`-WyW~PS`p56UNm$8RA-wsX zZ0tU*nJjX3@9T%=wQi|A2FcTRdm-jJ1=*-L^_PPD{-A5%^;IQs(|C3y7s>XNl^#{Y z?OuK|`=(I0%IGumj}N=?@%qe8_8)GT7Z{KBXyBw>`XY_rf6Ea3FL49~#1T{}u7sDe z`8R%&Wgeb#F*DuRZ}S5DJ~3Dx8v`<;C$~nLY9cr;V=TN_vLjXz@4oBLWoM(2o_-oR zRdp7|-tW(I?LnF2_2rBOm>jW$s@ZIm>Dvi))bD3)2NI&LKk-7tQo9op?3zUK6%29K z2}obRl9b1h?7$I&Ij6Ne6U(uFnDj-6A|*8Jxm#|_bBS+t8QMUKi@qi`Zuk9Qntuh2 z;-4~1hZj-i@Yb1A7~$lg;v#>OCGbm$>g$UtSc{(RC7vUMMHTQ&mRD?fBi@=%Z_R^m zN&lD1szw6803E6zAT^KUrZ_=xQwiS-SU)7@ln#d@q-0}5gD`#tA&1rj=kO9=<~^r7 zaExUuuVvF*Y3n`P&y@ z(~spZ3kZQf`ZpMlaft9k-kZK1AXJ-jbse4V3mH`YmH9qX!8!{Gt7UiTr5jVX#KG5bK+=@C>5^BL+3DCCEkDe z=zV&y0toh^3#A`*bLcNiDZl<&)qecPs_nsP0@Zw4nB9_ZO;{p{ib-C*kp#bzO}DE? zd;(AxPdw9TG5&L3)vwA3r4PhTzPhPfu8yaWyQeVlxJ$fwKK8u(Lhf+av(0PKhhFJ=wK6rS& zTdHd#qM|@kiuZos1O$}9ol&uxjrCQS3c3EJmw=28&4v8@nHn2ALB#e(RDWx7TqRgF zJTj68c)fVn)^Cr~UQHRls}k+*d<_VDz>EB)MC$76wcHNux~S1szV28|NJ!(^P0xpb zP7FW{-9mt+zv_G3{px5WJ5SmBR%)o7llN^m6KPE&FUm9p4hKnvQiU4VfoBrmPO0tp zf>s9*vhL8?d7fG!!8K^)KrhjOtT(3=5+VaDDOQ79( zwa86NJ36R{|Mcm9sIp`u9G!DFG7J6(VWvkUpPLA%oKD4&=kK0+?CO^&aDl`J=(B2c z>&}Cf5|%rjeE8Sv?Z}gvlV)RAA$1wprW9dO(a#^luPDUu^QG@Md^hc*HQT)>*GGea zLJrDeuh^^QW<{tzb1L^>K+pfAo0OF7)y$P9?4B!-7>O-h9E}17-~}}Z#MunLgh#0= zDJ%EJaY+!JAEHhr$mJPM4r**NI!iLDTH`Dl1gz%1EOtfN|CxSBq7d%oher$g)S)Mg zr=UP!28jIT=Bg8kAzK)3XNUFf7tW|A!N9;M7nmf(lOpba znaIi>^Y!q+R$J+#2N`eGS06*QJzyXM1y*SIz~^QJX8C|t^KQHMLpn;z!EhM(MPO?B z`$Ll4Pfvgs0D*Wx(oIhnMHmd`=2kzITwBYB|2IW4D_d$YbLHQj{MzgM{CwK&=t$~w zoo@5&w%mr;%iZul0YL-)(wayQbTr-uEmMeX~PxhASH&d9v-∨<`*?C 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
VGd_D=0f9U$zS`C@!W8EI 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

-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 z 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 P7hkBWJOfrLy?FOumd=L+ literal 0 HcmV?d00001 diff --git a/image/2.png b/image/2.png new file mode 100644 index 0000000000000000000000000000000000000000..d8f3b9ae9033f83a57a88e635af1d9f8e1abcc85 GIT binary patch literal 101359 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 literal 0 HcmV?d00001 diff --git a/run_crawler.bat b/run_crawler.bat new file mode 100644 index 0000000..b586e63 --- /dev/null +++ b/run_crawler.bat @@ -0,0 +1,113 @@ +@echo off +setlocal EnableExtensions EnableDelayedExpansion +chcp 65001 >nul 2>&1 +cd /d "%~dp0" +set "PYTHONUNBUFFERED=1" + +set "CFG=%1" +if "%CFG%"=="" call :pick_config + +if "%CFG%"=="" exit /b 0 +if not exist "%CFG%" ( + echo [!] Config not found: %CFG% + pause + goto :eof +) + +:menu +cls +echo ============================= +echo Docs Crawler Menu [config: %CFG%] +echo ============================= +echo 1. Crawl and Build Site +echo 2. Preview Site (port 8777) +echo 3. Show Status +echo 4. Export Single HTML +echo 5. Switch Config +echo 0. Exit +echo. +set "CHOOSE=" +set /p CHOOSE=Select: + +if "%CHOOSE%"=="1" call :do_crawl & goto menu +if "%CHOOSE%"=="2" call :do_preview & goto menu +if "%CHOOSE%"=="3" call :do_status & goto menu +if "%CHOOSE%"=="4" call :do_export & goto menu +if "%CHOOSE%"=="5" call :pick_config & if "%CFG%"=="" exit /b 0 & goto menu +if "%CHOOSE%"=="0" exit /b 0 + +echo Invalid choice, try again. +timeout /t 1 >nul 2>&1 +goto menu + +:pick_config +setlocal EnableDelayedExpansion +set "IDX=0" +cls +echo ============================= +echo Select Config File +echo ============================= +echo. +for %%f in (crawler*.json) do ( + set /a IDX+=1 + set "CFG_!IDX!=%%f" + echo !IDX!. %%f +) +if !IDX! equ 0 ( + echo No crawler*.json files found in %CD% + pause + endlocal & set "CFG=" + exit /b +) +echo. +echo 0. Cancel +echo. +set "PICK=" +set /p PICK=Select number: + +if "!PICK!"=="" ( + endlocal & set "CFG=" + exit /b +) +if "!PICK!"=="0" ( + endlocal & set "CFG=" + exit /b +) + +set "CHOSEN=" +for /l %%i in (1,1,!IDX!) do ( + if "!PICK!"=="%%i" set "CHOSEN=!CFG_%%i!" +) + +if "!CHOSEN!"=="" ( + echo Invalid choice. + pause + endlocal & set "CFG=" + exit /b +) + +endlocal & set "CFG=%CHOSEN%" +exit /b + +:do_crawl +echo [*] Crawling and building... +python docs_crawler.py --config "%CFG%" run +if errorlevel 1 echo [!] Run completed with warnings (see above). +pause +exit /b + +:do_preview +echo [*] Starting preview server... +python docs_crawler.py --config "%CFG%" preview --port 8777 +exit /b + +:do_status +python docs_crawler.py --config "%CFG%" status +pause +exit /b + +:do_export +echo [*] Exporting single HTML file... +python docs_crawler.py --config "%CFG%" export +pause +exit /b diff --git a/tests/test_docs_crawler.py b/tests/test_docs_crawler.py new file mode 100644 index 0000000..6e628d9 --- /dev/null +++ b/tests/test_docs_crawler.py @@ -0,0 +1,388 @@ +import unittest + +import docs_crawler + + +class TestDocsCrawler(unittest.TestCase): + def test_extract_sidebar_structure(self): + html = """ +

  • + 2. Getting Started +
  • + + """ + data = docs_crawler.extract_sidebar_structure(html, docs_root="/docs") + self.assertIn("cat:get-start", data["categories"]) + self.assertIn("doc:about", data["categories"]) + self.assertEqual(data["slug_to_category"]["about"], "doc:about") + + def test_parse_doc_entries_from_category_page(self): + html = """ + 2.1 Intro + 2.2 Setup + Category + """ + entries = docs_crawler.parse_doc_entries_from_category_page(html, docs_root="/docs") + self.assertIn(("intro", "2.1 Intro"), entries) + self.assertIn(("setup", "2.2 Setup"), entries) + self.assertNotIn(("category/get-start", "Category"), entries) + + def test_parse_doc_entries_prefers_sidebar_level2(self): + html = """ + + + + """ + entries = docs_crawler.parse_doc_entries_from_category_page(html, docs_root="/docs") + self.assertIn(("index", "1.1 Intro"), entries) + self.assertIn(("author", "1.2 Author"), entries) + self.assertNotIn(("should-not-appear", "Random Body Link"), entries) + + def test_html_to_markdown_basic(self): + html = """ +

    Section

    +

    Hello World.

    +
    • One
    • Two
    +
    print("ok")
    + """ + md = docs_crawler.html_to_markdown(html) + self.assertIn("## Section", md) + self.assertIn("**World**", md) + self.assertIn("- One", md) + self.assertIn('print("ok")', md) + self.assertIn("```", md) + + def test_build_site_data_strict_nav(self): + docs = [ + { + "slug": "about", + "title": "about", + "category_key": "cat:get-start", + "category_label": "2. Getting Started", + "category_order": 2, + "category_folder": "2.GettingStarted", + "source_file": "about.source.md", + "source_url": "https://example.com/docs/about", + }, + { + "slug": "internal-only", + "title": "internal-only", + "category_key": "uncategorized", + "category_label": "Uncategorized", + "category_order": 9999, + "category_folder": "uncategorized", + "source_file": "internal-only.source.md", + "source_url": "https://example.com/docs/internal-only", + }, + ] + sidebar_meta = { + "categories": { + "cat:get-start": { + "key": "cat:get-start", + "label": "2. Getting Started", + "order": 2, + "folder": "2.GettingStarted", + "kind": "category", + } + }, + "slug_meta": { + "about": { + "title": "2.1 About", + "category_key": "cat:get-start", + "category_order": 2, + "category_label": "2. Getting Started", + "category_folder": "2.GettingStarted", + "doc_order": 1, + } + }, + } + categories = docs_crawler.build_site_data(docs, sidebar_meta=sidebar_meta, strict_nav=True) + slugs = [d["slug"] for c in categories for d in c.get("docs", [])] + self.assertIn("about", slugs) + self.assertNotIn("internal-only", slugs) + + def test_workspace_paths_default(self): + paths = docs_crawler.workspace_paths({"workspace": ".site_sync"}) + self.assertTrue(str(paths["source_manifest"]).endswith("site_sync\\manifests\\source_manifest.json")) + + def test_build_doc_source_url(self): + self.assertEqual( + docs_crawler.build_doc_source_url("https://example.com", "/guide", "index"), + "https://example.com/guide/", + ) + self.assertEqual( + docs_crawler.build_doc_source_url("https://example.com", "/guide", "intro.html"), + "https://example.com/guide/intro.html", + ) + + def test_parse_main_route_chunk_map_supports_promise_all_and_unquoted_key(self): + snippet = """ + 3427cf63:[()=>n.e("7750").then(n.bind(n,3622)),"@site/docs/author.mdx",3622], + "2f23d45f":[()=>Promise.all([n.e("4014"),n.e("7964")]).then(n.bind(n,6006)),"@site/docs/cordon-attributes.mdx",6006], + """ + result = docs_crawler.parse_main_route_chunk_map(snippet) + self.assertEqual(result.get("author"), "7750") + self.assertEqual(result.get("cordon-attributes"), "7964") + + def test_parse_runtime_chunk_url_map(self): + snippet = ( + 'n.u=e=>"assets/js/"+(({7750:"3427cf63",7964:"2f23d45f"})[e]||e)' + '+"."+({7750:"bc220ec9",7964:"792f24ee"})[e]+".js"' + ) + result = docs_crawler.parse_runtime_chunk_url_map(snippet, "https://example.com") + self.assertEqual(result.get("7750"), "https://example.com/assets/js/3427cf63.bc220ec9.js") + self.assertEqual(result.get("7964"), "https://example.com/assets/js/2f23d45f.792f24ee.js") + + def test_parse_chunk_to_markdown(self): + chunk = ( + "var x=JSON.parse('{\"title\":\"1.2 关于作者\"}');" + "function u(e){return(0,n.jsxs)(n.Fragment,{children:[" + "(0,n.jsx)(n.h2,{id:\"name\",children:\"网名\"})," + "(0,n.jsxs)(n.ul,{children:[" + "(0,n.jsx)(n.li,{children:\"百小僧\"})," + "(0,n.jsx)(n.li,{children:\"MonkSoul\"})" + "]})" + "]})}" + ) + title, md = docs_crawler.parse_chunk_to_markdown(chunk, "https://example.com/docs/author", "author") + self.assertEqual(title, "1.2 关于作者") + self.assertIn("## 网名", md) + self.assertIn("- 百小僧", md) + self.assertIn("- MonkSoul", md) + + def test_parse_chunk_to_markdown_code_fence(self): + chunk = ( + "var x=JSON.parse('{\"title\":\"示例\"}');" + "function u(e){return(0,n.jsxs)(n.Fragment,{children:[" + "(0,n.jsx)(n.pre,{children:(0,n.jsx)(n.code,{className:\"language-cs\",children:\"var a = 1;\\r\\nConsole.WriteLine(a);\"})})" + "]})}" + ) + _, md = docs_crawler.parse_chunk_to_markdown(chunk, "https://example.com/docs/demo", "demo") + self.assertIn("```cs", md) + self.assertIn("var a = 1;", md) + self.assertIn("Console.WriteLine(a);", md) + self.assertIn("```", md) + + def test_parse_chunk_to_markdown_table(self): + chunk = ( + "var x=JSON.parse('{\"title\":\"表格页\"}');" + "function u(e){return(0,n.jsxs)(n.Fragment,{children:[" + "(0,n.jsxs)(n.table,{children:[" + "(0,n.jsx)(n.thead,{children:(0,n.jsxs)(n.tr,{children:[" + "(0,n.jsx)(n.th,{children:\"名称\"}),(0,n.jsx)(n.th,{children:\"说明\"})]})})," + "(0,n.jsx)(n.tbody,{children:(0,n.jsxs)(n.tr,{children:[" + "(0,n.jsx)(n.td,{children:\"Foo\"}),(0,n.jsx)(n.td,{children:\"Bar\"})]})})" + "]})" + "]})}" + ) + _, md = docs_crawler.parse_chunk_to_markdown(chunk, "https://example.com/docs/table", "table") + self.assertIn("| 名称 | 说明 |", md) + self.assertIn("| --- | --- |", md) + self.assertIn("| Foo | Bar |", md) + + def test_candidate_docs_roots_from_seed_html(self): + html = """ + Guide + Button + Docs + """ + roots = docs_crawler._candidate_docs_roots_from_seed_html(html, "/docs") + self.assertIn("/docs", roots) + self.assertIn("/guide", roots) + self.assertIn("/components", roots) + + + def test_resolve_docs_root_uses_single_probe_retry(self): + calls = [] + + original = docs_crawler.http_get_text + + def fake_get(url, timeout=30, retries=3, backoff_seconds=1.5): + calls.append((url, retries, backoff_seconds)) + if url.endswith('/docs/'): + raise RuntimeError('404') + if url.endswith('/guide/'): + return '' + raise RuntimeError('unexpected url') + + docs_crawler.http_get_text = fake_get + try: + root, html = docs_crawler.resolve_docs_root( + base_url='https://example.com', + configured_docs_root='/docs', + seed_html='Guide', + timeout=30, + retries=3, + backoff=1.5, + ) + finally: + docs_crawler.http_get_text = original + + self.assertEqual(root, '/guide') + self.assertIn('VPSidebar', html) + self.assertGreaterEqual(len(calls), 2) + self.assertEqual(calls[0][1], 1) + self.assertEqual(calls[1][1], 1) + + def test_extract_sidebar_structure_vitepress(self): + html = """ + + """ + data = docs_crawler.extract_sidebar_structure(html, docs_root="/guide") + self.assertTrue(data["categories"]) + self.assertIn("introduce.html", data["slug_to_category"]) + self.assertIn("router.html", data["slug_to_category"]) + self.assertEqual(data.get("slug_titles", {}).get("introduce.html"), "介绍") + self.assertEqual(data.get("slug_titles", {}).get("router.html"), "路由") + + def test_resolve_docs_roots_when_docs_root_empty(self): + calls = [] + original = docs_crawler.http_get_text + + def fake_get(url, timeout=30, retries=3, backoff_seconds=1.5): + calls.append((url, retries)) + if url == "https://example.com/docs/": + raise RuntimeError("404") + if url == "https://example.com/guide/": + return '' + if url == "https://example.com/components/": + return '' + raise RuntimeError(f"unexpected url: {url}") + + docs_crawler.http_get_text = fake_get + try: + roots, html_map = docs_crawler.resolve_docs_roots( + base_url="https://example.com", + configured_docs_root="", + seed_html='GuideComponents', + timeout=30, + retries=3, + backoff=1.5, + ) + finally: + docs_crawler.http_get_text = original + + self.assertIn("/guide", roots) + self.assertIn("/components", roots) + self.assertEqual(html_map["/guide"], '') + self.assertEqual(html_map["/components"], '') + self.assertTrue( + all( + retry == 1 + for url, retry in calls + if url.endswith("/docs/") or url.endswith("/guide/") or url.endswith("/components/") + ) + ) + + def test_resolve_docs_roots_supports_leaf_when_root_404(self): + original = docs_crawler.http_get_text + + def fake_get(url, timeout=30, retries=3, backoff_seconds=1.5): + if url == "https://example.com/docs/": + raise RuntimeError("404") + if url == "https://example.com/components/": + raise RuntimeError("404") + if url == "https://example.com/guide/": + return '' + if url == "https://example.com/components/proTable.html": + return '' + raise RuntimeError(f"unexpected url: {url}") + + docs_crawler.http_get_text = fake_get + try: + roots, _ = docs_crawler.resolve_docs_roots( + base_url="https://example.com", + configured_docs_root="", + seed_html='GuideProTable', + timeout=30, + retries=3, + backoff=1.5, + ) + finally: + docs_crawler.http_get_text = original + + self.assertIn("/guide", roots) + self.assertIn("/components", roots) + + def test_collect_sidebar_meta_multi_root(self): + original = docs_crawler.http_get_text + + seed_html = 'GuideComponents' + guide_html = ( + '' + ) + components_html = ( + '' + ) + + def fake_get(url, timeout=30, retries=3, backoff_seconds=1.5): + if url == "https://example.com": + return seed_html + if url == "https://example.com/docs/": + raise RuntimeError("404") + if url == "https://example.com/guide/": + return guide_html + if url == "https://example.com/components/": + return components_html + if url == "https://example.com/sitemap.xml": + raise RuntimeError("404") + raise RuntimeError(f"unexpected url: {url}") + + docs_crawler.http_get_text = fake_get + try: + meta = docs_crawler.collect_sidebar_meta( + { + "target": { + "base_url": "https://example.com", + "seed_path": "", + "docs_root": "", + }, + "crawler": { + "timeout_seconds": 30, + "http_retries": 3, + "retry_backoff_seconds": 1.5, + }, + } + ) + finally: + docs_crawler.http_get_text = original + + self.assertTrue(meta.get("multi_root_mode")) + self.assertIn("/guide", meta.get("docs_roots", [])) + self.assertIn("/components", meta.get("docs_roots", [])) + self.assertIn("guide/introduce.html", meta.get("slug_meta", {})) + self.assertIn("components/button.html", meta.get("slug_meta", {})) + self.assertEqual( + meta["slug_meta"]["components/button.html"]["source_path"], + "/components/button.html", + ) + self.assertEqual(meta["slug_meta"]["guide/introduce.html"]["title"], "介绍") + self.assertEqual(meta["slug_meta"]["components/button.html"]["title"], "Button") + + +if __name__ == "__main__": + unittest.main() From 450cc58730fbcb7fe1badb4b80f761f5e3aece99 Mon Sep 17 00:00:00 2001 From: sfw222 <2452042683@qq.com> Date: Fri, 19 Jun 2026 22:57:15 +0800 Subject: [PATCH 2/3] Add crawler_verse.json to gitignore --- .gitignore | 1 + crawler_verse.json | 19 ------------------- 2 files changed, 1 insertion(+), 19 deletions(-) delete mode 100644 crawler_verse.json diff --git a/.gitignore b/.gitignore index 36ef842..adc5504 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ __pycache__/ # Local runtime config (use template file for repo) crawler_config.json +crawler_verse.json # Local temporary configs tmp_*.json diff --git a/crawler_verse.json b/crawler_verse.json deleted file mode 100644 index 6051798..0000000 --- a/crawler_verse.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "target": { - "base_url": "https://verselang.github.io/book/", - "seed_path": "", - "docs_root": "/book/" - }, - "workspace": "F:/Docs/.site_sync_verse", - "crawler": { - "timeout_seconds": 30, - "http_retries": 3, - "retry_backoff_seconds": 1.5, - "continue_on_doc_error": true, - "max_docs": 0 - }, - "site": { - "output_dir": "source_site", - "menu_mode": "nav" - } -} \ No newline at end of file From 22b9d6e8a8c3e9299ceb2eff0d26cbde52d179c8 Mon Sep 17 00:00:00 2001 From: sfw222 <2452042683@qq.com> Date: Sun, 21 Jun 2026 10:24:55 +0800 Subject: [PATCH 3/3] docs: update README with new features (MkDocs, dark mode, export, multi-config) --- README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9ca63d3..7e50c1e 100644 --- a/README.md +++ b/README.md @@ -7,12 +7,14 @@ ## 功能特性 -- 支持抓取常见文档站(VitePress / Docusaurus 结构) +- 支持抓取常见文档站(VitePress / Docusaurus / MkDocs 结构) - 支持多文档根路径自动识别(如 `/guide`、`/components`) - 支持“根路径 404,但叶子文档可访问”的站点结构 - 导航结构尽量贴近源站层级(一级/二级) +- 侧边栏标题自动中文化(覆盖常见技术术语) - 详细日志与保活输出(当前阶段、URL、进度、速率、ETA) -- 一键预览本地 HTML 文档站 +- 一键预览本地 HTML 文档站(支持暗色/亮色模式) +- 支持将抓取结果导出为单个自包含 HTML 文件 - 输出标准 Markdown 目录,便于后续二次加工 --- @@ -74,8 +76,10 @@ run_crawler.bat 菜单: - `1` 抓取并构建站点 -- `2` 预览本地站点 +- `2` 预览本地站点(含暗色模式切换) - `3` 查看状态 +- `4` 导出单文件 HTML +- `5` 切换配置文件(`crawler*.json`) - `0` 退出 ---