Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
ce26ea4
chore(tooling): initialize uv project with Python 3.14
Alice39s Aug 9, 2026
28c1bb8
test(models): add pytest fixtures and data model coverage
Alice39s Aug 9, 2026
96eb093
feat(frontmatter): parse page metadata and descriptions
Alice39s Aug 9, 2026
cea2d52
feat(scanner): scan documentation trees
Alice39s Aug 9, 2026
18b6305
feat(contributing): inject contribution notices
Alice39s Aug 9, 2026
b7a2ec5
feat(docslist): render documentation cards
Alice39s Aug 9, 2026
a88e47f
feat(redirects): generate client-side redirect script
Alice39s Aug 9, 2026
7690720
feat(nav): generate ordered navigation
Alice39s Aug 9, 2026
729fb79
feat(index): render directory index pages
Alice39s Aug 9, 2026
395149f
feat(generator): orchestrate documentation generation
Alice39s Aug 9, 2026
4fb7bea
fix(redirects): tolerate invalid redirect configuration
Alice39s Aug 9, 2026
4777ba5
fix(frontmatter): skip indented description content
Alice39s Aug 9, 2026
aa53c7c
refactor(cli): centralize development and build commands
Alice39s Aug 9, 2026
1a141a2
chore(ruff): configure linting and format Python sources
Alice39s Aug 9, 2026
37980b8
chore(docs): format Markdown with mdformat
Alice39s Aug 9, 2026
955b14c
ci(actions): add uv, lint, test, and build checks
Alice39s Aug 9, 2026
b52ae57
chore(tooling): remove legacy dependency workflows
Alice39s Aug 9, 2026
4390e62
ci(actions): run checks on dev branch
Alice39s Aug 9, 2026
87c8de6
fix(cli): keep file watcher alive after generation errors
Alice39s Aug 9, 2026
e1f6e14
fix(ci): pin setup-uv to a published release
Alice39s Aug 9, 2026
3ecd9c4
fix(tooling): harden deterministic documentation builds
Alice39s Aug 9, 2026
3aba455
refactor(cli): adopt Typer command routing
Alice39s Aug 9, 2026
bc841e2
feat(cli): integrate redirect management
Alice39s Aug 9, 2026
f4b810a
feat(cli): add unified quality checks
Alice39s Aug 9, 2026
d2681e7
refactor(scripts): centralize platform launchers
Alice39s Aug 9, 2026
53053c6
fix(cli): ignore local design files in checks
Alice39s Aug 9, 2026
6534cd2
docs(tooling): document the cross-platform CLI
Alice39s Aug 9, 2026
149bdd8
ci(actions): verify launchers on all platforms
Alice39s Aug 9, 2026
e244f26
test(scripts): compare launcher roots portably
Alice39s Aug 9, 2026
6855575
fix(tooling): pin Markdown line endings
Alice39s Aug 9, 2026
b2f7588
refactor(assets): centralize documentation resources
Alice39s Aug 9, 2026
c964813
feat(images): add WebP images with compressed fallbacks
Alice39s Aug 9, 2026
8a234f7
fix(build): hide Material generator fingerprint
Alice39s Aug 9, 2026
cbcbc89
feat(build): minify generated HTML
Alice39s Aug 9, 2026
def4f10
docs(build): document the asset pipeline
Alice39s Aug 9, 2026
bb0520a
fix(build): preserve HTML attribute quotes
Alice39s Aug 9, 2026
95eb6df
docs: add repository guidelines (AGENTS.md)
Alice39s Aug 9, 2026
58fb760
chore: ignore macOS metadata files
Alice39s Aug 9, 2026
ef8e395
fix(docs): replace broken account documentation links
Alice39s Aug 9, 2026
5073c48
test(tooling): use consistent module imports
Alice39s Aug 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Keep formatter-sensitive Markdown stable across platforms.
*.md text eol=lf
46 changes: 46 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# .github/workflows/ci.yml
name: CI

on:
push:
branches: ["main", "dev"]
pull_request:

jobs:
ci:
name: ${{ matrix.os }}
runs-on: ${{ matrix.os }}
timeout-minutes: 15
permissions: {}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]

steps:
- uses: actions/checkout@v5

- name: Install uv
uses: astral-sh/setup-uv@v9.0.0
with:
enable-cache: true

- name: Sync dependencies (frozen)
run: uv sync --frozen

- name: Run quality checks
run: uv run nmteam check

- name: Verify POSIX launcher
if: runner.os != 'Windows'
run: scripts/nmteam.sh --help

- name: Verify PowerShell launcher
if: runner.os == 'Windows'
shell: pwsh
run: .\scripts\nmteam.ps1 --help

- name: Verify Batch launcher
if: runner.os == 'Windows'
shell: cmd
run: scripts\nmteam.bat --help
13 changes: 9 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,6 @@ target/
profile_default/
ipython_config.py

# pyenv
.python-version

# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
Expand Down Expand Up @@ -131,4 +128,12 @@ dmypy.json
# nmTeam Doc Generator
/generated
/cache
/mkdocs.yml
/mkdocs.yml

# uv / ruff
.ruff_cache/

# Local design and implementation artifacts
/docs/superpowers/

.DS_Store
11 changes: 11 additions & 0 deletions .mdformat.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# mdformat 配置:仓库根目录,适用于 docs/ 下所有 .md 文件
# 插件(mdformat-mkdocs、mdformat-front-matters)通过 entry point 自动启用,
# 因此 admonition、content tabs、YAML frontmatter 均受保护,无需 extensions 列表。
wrap = "keep"
number = false
end_of_line = "lf"
validate = true

[plugin.mkdocs]
# 保持 mdformat-mkdocs 默认行为(4 空格列表缩进、admonition 保护);
# 如后续需要 --align-semantic-breaks-in-lists 等开关,在此追加配置项。
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.14
133 changes: 133 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# Repository Guidelines

## Project Overview

nmTeam Support 官方支持文档站(https://support.nmteam.xyz)的构建工具链。纯文档 + Python 工具链仓库:内容为简体中文,覆盖 nmBot(Telegram 机器人)及其 Plus / Intelligence 产品线;工具链负责扫描 `docs/` 与 `assets/`,自动生成 mkdocs 目录结构(nav)、各目录 `index.md`、图片 WebP 优化与重定向脚本,再用 `mkdocs-material` 构建静态站。

本项目是 main 分支旧版(单文件 `generate.py`/`manage.py`/`redirects_manager.py` + `runtime.txt` 3.7 + pip)的现代化重构:**uv 管理、Python 3.14+、`src/` 包结构、Typer CLI、pytest 测试、ruff/mdformat 检查、三平台 CI**。

## Architecture & Data Flow

数据流(四输入 → 生成 → 构建):

```
docs/ (markdown 源) ─┐
assets/ (images/icons/styles 母版) ─┤
mkdocs-template.yml ─┤ generate() → cache/ ─copytree→ generated/ (mkdocs docs_dir) → mkdocs build --strict → site/
redirects.json ──────┘ (含生成的 assets/js/redirects.js)
```

`generate()`(`src/nmteam_support/generator.py`)编排的完整链路:

1. 清空重建 `cache/`
2. `scanner.scan_docs()` 递归扫描 `docs/` 得到文档树(`SKIP_DIRS`/`INTERNAL_DIRS` 过滤)
3. 写入处理后的页面(非 index.md 注入贡献提示,`contributing.py`)
4. `index.py` 为每目录生成 `index.md`(自动 generated 标记 + docsList 卡片,`docslist.py` 渲染 HTML)
5. `image_pipeline.py` 用 PIL 为 assets 中每张 PNG/JPEG 生成 `.webp` 兄弟文件(质量 80;PNG 另出 256 色有损 fallback)
6. `nav.py` 生成 nav YAML,`template.py` 替换 `mkdocs-template.yml` 的 `# NAV_ARIA_START`/`# NAV_ARIA_END` 标记块写入 `mkdocs.yml`
7. `redirects.py` 读 `redirects.json` 生成 `cache/assets/js/redirects.js`
8. copytree 到 `generated/`,交给 `mkdocs build --strict`

**图片双层管线**(关键机制):生成期 `image_pipeline.py` 产出同名 `.webp` 兄弟文件;渲染期 `markdown_images.py`(mkdocs 扩展,注册在 mkdocs-template.yml 的 markdown_extensions 中)把本地栅格图 `<img>` 改写为 WebP-first `<picture>`,靠同名 `.webp` 约定对接。外部 URL 不下载不镜像。Markdown 中仍写普通图片语法。

`mkdocs.yml`、`cache/`、`generated/`、`site/` 均为生成产物(gitignore),**永远不要手改**;配置改 `mkdocs-template.yml`,nav 由脚本生成。

## Key Directories

| 路径 | 用途 |
|---|---|
| `src/nmteam_support/` | 工具链包(15 个模块,见 Important Files) |
| `docs/` | **真实文档源**(唯一需要手工编辑的内容位置) |
| `docs/nmbot-telegram/` | 产品中枢:`panel/`、`plus/`、`legal/`、`group/`、`faq/`、`business/`、`tools/`、`nmbot-intelligence/`、`credit/`、`update-log/`(`YYYY-MM.md` 月度日志)、`mcp/` |
| `docs/contact-us/`、`docs/nmteam-account/` | 其他产品线 |
| `docs/superpowers/` | 本地设计与实现工件(plans/specs),**已 gitignore,勿提交** |
| `assets/images/` | 图片母版:`shared/`(站级共享)、`nmbot/`(含 `mcp/`、`update-pictures/` 子目录);`assets/icons/`(SVG)、`assets/styles/`(CSS) |
| `overrides/` | mkdocs `custom_dir`,`main.html` 覆写 site_meta 移除主题版本号 |
| `scripts/` | 三平台薄启动器(`nmteam.sh` / `nmteam.ps1` / `nmteam.bat`) |
| `tests/` | pytest 测试(15 个文件 + conftest.py) |
| `cache/`、`generated/`、`site/`、`mkdocs.yml` | 生成产物,勿手改勿提交 |

## Development Commands

```bash
uv sync # 安装依赖(按 .python-version 3.14 自动管理 Python)
uv run nmteam install # 同上,CLI 封装
uv run nmteam dev # 生成文档结构 + mkdocs serve http://127.0.0.1:8000,
# 监听 docs/、assets/、mkdocs-template.yml 变化自动重生成 + 热更新
uv run nmteam build # generate() + mkdocs build --strict → site/
uv run nmteam generate # 仅重新生成文档结构
uv run nmteam clean # 清理 cache/ generated/ site/
uv run nmteam check # 全部质量检查(见下)
uv run nmteam redirects list|add "/old/" "/new/"|remove "/old/"
uv run nmteam --help
```

平台启动器(定位仓库根后原样透传参数,无业务逻辑):`scripts/nmteam.sh dev`、`.\scripts\nmteam.ps1 dev`、`scripts\nmteam.bat dev`。

**质量检查**(`nmteam check`,CI 同样执行):
```bash
uv run ruff check .
uv run ruff format --check .
uv run pytest
uv run mdformat --check README.md docs/
uv run nmteam build # 内部为 mkdocs build --strict,严格模式会因警告失败
```

## Code Conventions & Common Patterns

Python(`src/nmteam_support/`):

- Python 3.14+(`pyproject.toml` `requires-python = ">=3.14"`,`.python-version` = 3.14)。
- CLI 用 **Typer**(`cli.py`,命令树 + `QUALITY_COMMANDS` 编排),不用 argparse。
- 核心模型用 `frozen dataclass`(`models.py`:`PageMetadata`/`DocEntry`);类型标注齐全(`typing`)。
- ruff 约束:`line-length = 100`(`E501` ignore)、`target py314`、`select = E,F,I,UP,B,SIM,W,C4,RUF`、`isort known-first-party = nmteam_support`、双引号、空格缩进。
- 错误处理显式:如 `redirects.py` 对损坏的 `redirects.json` 抛 `RedirectConfigError`(绝不静默清空覆盖,管理命令不写坏文件)。
- 依赖注入轻量:`GeneratorOptions`/`default_options` 传参,函数式模块(scanner/frontmatter/nav/docslist 等),无重 OOP。

Markdown 文档(`docs/`):

- front matter 用 YAML:`title` + `description`(description 供列表卡片);可选 `index: <int>` 排序;`index.md` 可用 `hide_docs_list: true` 与 `hide: [navigation]`。
- 常用 `!!! note` / `!!! warning` / `!!! success` / `!!! faq` admonition 与 `??? question` 折叠块;表格(对齐列 `:---`);步骤用有序列表。
- 付费功能用 `<nmbot-plus-icon></nmbot-plus-icon>` 行内徽标(样式 `assets/styles/plus.css`,远程 svg);智能功能可用 `nmbot-intelligence-icon`。
- **图片一律绝对路径引用 `/assets/images/...`**(不要用相对 `./img/`),构建时自动产出 WebP 优先 `<picture>`;logo 等品牌资源用外部 URL(websiteres.nmteam.xyz)。
- 更新日志:`docs/nmbot-telegram/update-log/YYYY-MM.md`,标题 `# nmBot YYYY 年 M 月更新`,`## 日期 时间` + `### 问题修复` / `### 新功能` 列表;配图放 `assets/images/nmbot/update-pictures/nmbot-YYMM.png`。
- Markdown 由 **mdformat** 统一格式(`.mdformat.toml`:wrap=keep、LF 行尾;插件 mdformat-mkdocs + mdformat-front-matters 保护 admonition 与 front matter,不需要手写 extensions 列表)。

## Important Files

| 文件 | 职责 |
|---|---|
| `src/nmteam_support/cli.py` | Typer 入口 `main`;install/dev/generate/build/clean/check + redirects 子命令 |
| `src/nmteam_support/generator.py` | `generate()` 端到端编排 + `GeneratorOptions`/`default_options` |
| `src/nmteam_support/scanner.py` | 递归扫描 docs/ 树,SKIP_DIRS/INTERNAL_DIRS 过滤 |
| `src/nmteam_support/frontmatter.py` | frontmatter 解析(title/description/index/flag) |
| `src/nmteam_support/index.py` + `docslist.py` | 每目录 index.md 生成 + docsList 卡片 HTML |
| `src/nmteam_support/nav.py` + `template.py` | nav YAML 生成;NAV_ARIA 标记块替换写 mkdocs.yml |
| `src/nmteam_support/contributing.py` | 非 index.md 注入贡献提示 admonition |
| `src/nmteam_support/redirects.py` | redirects.json 管理(损坏保护)+ redirects.js 生成 |
| `src/nmteam_support/image_pipeline.py` + `markdown_images.py` | PIL 生成 .webp 兄弟文件;mkdocs 扩展包 WebP-first `<picture>` |
| `src/nmteam_support/models.py` | `PageMetadata`/`DocEntry` frozen dataclass |
| `pyproject.toml` | 包元数据、依赖、入口、pytest/ruff/hatchling 配置 |
| `uv.lock` | 锁定依赖(mkdocs 1.6.1、mkdocs-material 9.7.7、mkdocs-minify-plugin 0.8.0、pillow 12.3.0、typer 0.27.1、pytest 9.1.1、ruff 0.16.2、mdformat 1.0.0 等) |
| `mkdocs-template.yml` | mkdocs 配置模板(material zh 黄色双 palette、minify 插件、custom_dir overrides、`nmteam_support.markdown_images` 扩展、NAV_ARIA 标记) |
| `redirects.json` | 顶层 `redirects` 对象:`{旧路径带斜杠: 新路径}` |
| `.github/workflows/ci.yml` | 三 OS 矩阵 CI(push main/dev + PR):uv sync --frozen → nmteam check → 验证三个启动器 |
| `.mdformat.toml` | mdformat 配置(wrap=keep、LF) |
| `overrides/main.html` | 移除 meta 中 mkdocs-material 版本号 |

## Runtime/Tooling Preferences

- **uv** 为唯一包管理器(`uv sync`,lockfile `uv.lock`);Python 由 uv 按 `.python-version`(3.14)自动管理,不手动装。
- 构建后端 **hatchling**;无 Node/npm 组件。
- 强制检查:**ruff**(lint + format)+ **mdformat** + **pytest** + **mkdocs strict build**,全部由 `uv run nmteam check` 一键执行,CI 三平台门禁。
- gitattributes:`*.md` 强制 LF。
- 许可证 MIT(Copyright 2022 nmTeam)。

## Testing & QA

- **pytest**(dev 组 `pytest>=9.0`),配置在 pyproject.toml:`testpaths = ["tests"]`、`pythonpath = ["src"]`、`addopts = "-ra"`。
- 测试约定:`tests/` 单层目录,每个模块一个 `test_<module>.py`(test_cli、test_generator、test_scanner、test_frontmatter、test_nav、test_index、test_docslist、test_contributing、test_redirects、test_image_pipeline、test_markdown_images、test_models、test_scripts、test_build_config 等)。
- 输入构造分级:conftest 的 `docs_dir` fixture(tmp_path 构造最小 docs 树,含 index/hide_docs_list/hide frontmatter)→ `tmp_path` 手写单文件 → 全流程 generate 集成。**不依赖真实 docs/ 内容**。
- CLI 测试用 `typer.testing.CliRunner` + monkeypatch;启动器测试用 subprocess + 假 uv 脚本。
- **无覆盖率门槛**(无 pytest-cov、CI 无 coverage 步骤)——新增功能时给模块补 `test_<module>.py` 行为测试即可。
- CI 在 ubuntu/macos/windows 三平台跑全量 check;提交前本地至少跑 `uv run nmteam check`。
139 changes: 99 additions & 40 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,67 +1,126 @@
# Support
[**nmTeam 支持**](https://support.nmteam.xyz)官方网站。使用 `mkdocs-material` 进行构建。

# 快速开始
[**nmTeam 支持**](https://support.nmteam.xyz)官方网站。使用 `mkdocs-material` 构建;项目由 `uv` 初始化并管理依赖,通过 Typer 提供统一的跨平台命令行入口。

## 安装依赖
```bash
# 方式1: 使用管理脚本自动安装
python manage.py install
## 环境要求

- Python 3.14+(由 `uv` 按 `.python-version` 自动管理)
- [uv](https://docs.astral.sh/uv/)(`curl -LsSf https://astral.sh/uv/install.sh | sh`)

## 快速开始

# 方式2: 手动安装
pip install -r requirements.txt
### 安装依赖

```bash
uv sync
```

## 开发模式 (推荐)
也可以使用统一 CLI:

```bash
# 启动开发服务器 (支持热更新)
python manage.py dev
uv run nmteam install
```

# 或使用便捷脚本 (Windows)
.\dev.ps1 dev
dev.bat dev
### 开发模式

# 或使用便捷脚本 (Linux/macOS)
./dev.sh dev
```bash
uv run nmteam dev
```

开发模式会:
- 自动生成文档结构
- 启动 MkDocs 开发服务器 (http://127.0.0.1:8000)
- 监听 `docs/` 目录文件变化并自动重新生成
- 支持热更新,修改后自动刷新页面

## 构建生产版本
- 自动生成文档结构(`cache/`、`generated/`、`mkdocs.yml`)
- 启动 MkDocs 开发服务器(<http://127.0.0.1:8000>)
- 监听 `docs/`、`assets/` 和 MkDocs 模板变化并自动重新生成,浏览器热更新

### 构建生产版本

```bash
# 构建静态站点
python manage.py build
uv run nmteam build
```

构建结果输出到 `site/` 目录。

最终 HTML 会由 `mkdocs-minify-plugin` 压缩;生成器元标签仅保留 MkDocs
版本,不暴露主题及其版本。

## 静态资源

仓库内资源统一存放在:

- `assets/images/`:PNG、JPEG 图片母版
- `assets/icons/`:SVG 图标
- `assets/styles/`:站点样式

文档使用 `/assets/...` 引用这些资源。生成文档时,每张 PNG 或 JPEG
图片会同时产生:

- WebP 优先版本:质量 80
- 原格式 fallback:JPEG 使用质量 80;PNG 使用 256 色有损量化

# 或使用便捷脚本
.\dev.ps1 build
Markdown 中仍使用普通图片语法,构建工具会自动输出 WebP
优先的 `<picture>` 元素。外部 URL 不会被下载或镜像。

### 其他命令

```bash
uv run nmteam generate # 仅重新生成文档结构
uv run nmteam clean # 清理 cache/、generated/ 和 site/
uv run nmteam --help # 显示完整命令帮助
```

构建过程会:
1. 运行 `generate.py` 生成文档结构
2. 执行 `mkdocs build` 生成静态站点到 `site/` 目录
## 平台启动器

直接运行 `uv run nmteam` 是推荐方式。`scripts/` 也提供不包含业务逻辑的薄启动器;它们会自动定位仓库根目录并原样传递参数。

=== "Linux / macOS"

```bash
scripts/nmteam.sh dev
```

=== "PowerShell"

```powershell
.\scripts\nmteam.ps1 dev
```

=== "Windows Batch"

```batch
scripts\nmteam.bat dev
```

## 质量检查

一条命令运行 Ruff lint、Ruff format check、pytest、mdformat 和 MkDocs strict build:

## 其他命令
```bash
# 清理生成的文件
python manage.py clean
uv run nmteam check
```

也可以单独运行:

# 查看帮助
python manage.py help
```bash
uv run ruff check .
uv run ruff format --check .
uv run pytest
uv run mdformat --check README.md docs/
uv run nmteam build
```

# 传统部署方式
以上检查由 CI(`.github/workflows/ci.yml`)自动执行。

## 重定向管理

如果你更喜欢传统的分步操作:
```bash
uv run nmteam redirects list
uv run nmteam redirects add "/old-path/" "/new-path/"
uv run nmteam redirects remove "/old-path/"
```

- 安装依赖 `pip install -r requirements.txt`
- 启动本地服务器 `python -m mkdocs serve`
- 构建生成目录 `python generate.py`
- 构建静态界面 `python -m mkdocs build`
管理命令不会用空配置覆盖损坏的 `redirects.json`;修复配置后再重试即可。

# 贡献
## 贡献

欢迎您在 GitHub 上提出问题并贡献文档。
File renamed without changes
File renamed without changes
File renamed without changes
Loading