diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..5cd4978 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Keep formatter-sensitive Markdown stable across platforms. +*.md text eol=lf diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..e089a38 --- /dev/null +++ b/.github/workflows/ci.yml @@ -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 diff --git a/.gitignore b/.gitignore index 58e672f..eaf5c88 100644 --- a/.gitignore +++ b/.gitignore @@ -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 @@ -131,4 +128,12 @@ dmypy.json # nmTeam Doc Generator /generated /cache -/mkdocs.yml \ No newline at end of file +/mkdocs.yml + +# uv / ruff +.ruff_cache/ + +# Local design and implementation artifacts +/docs/superpowers/ + +.DS_Store \ No newline at end of file diff --git a/.mdformat.toml b/.mdformat.toml new file mode 100644 index 0000000..4d9e26f --- /dev/null +++ b/.mdformat.toml @@ -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 等开关,在此追加配置项。 diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..6324d40 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.14 diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..2d2b6a5 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,146 @@ +# 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) +``` + +构建后还有一步:`stage_markdown_copies()` 把 `cache/` 下每个 `.md` 复制到 `site/` +同路径(如 `site/nmbot-telegram/mcp.md`),作为每页的 Markdown 版本,供 +`/llms.txt` 链接、“复制 Markdown”按钮、View-as-Markdown 菜单项与 AI 打开 +菜单。 + +`generate()`(`src/nmteam_support/generator.py`)编排的完整链路: + +1. 清空重建 `cache/` +1. `scanner.scan_docs()` 递归扫描 `docs/` 得到文档树(`SKIP_DIRS`/`INTERNAL_DIRS` 过滤) +1. 写入处理后的页面(非 index.md 注入贡献提示,`contributing.py`) +1. `index.py` 为每目录生成 `index.md`(自动 generated 标记 + docsList 卡片,`docslist.py` 渲染 HTML) +1. `image_pipeline.py` 用 PIL 为 assets 中每张 PNG/JPEG 生成 `.webp` 兄弟文件(质量 80;PNG 另出 256 色有损 fallback) +1. `nav.py` 生成 nav YAML,`template.py` 替换 `mkdocs-template.yml` 的 `# NAV_ARIA_START`/`# NAV_ARIA_END` 标记块写入 `mkdocs.yml` +1. `redirects.py` 读 `redirects.json` 生成 `cache/assets/js/redirects.js` +1. `llms.py` 用扫描树 + 模板 `site_url` 生成 `cache/llms.txt`(llmstxt.org 规范:H1 + blockquote + H2 分节链接,链接指向 `.md` 版本;非 md 文件会被 mkdocs 原样拷到 `site/llms.txt`) +1. copytree 到 `generated/`,交给 `mkdocs build --strict` + +**图片双层管线**(关键机制):生成期 `image_pipeline.py` 产出同名 `.webp` 兄弟文件;渲染期 `markdown_images.py`(mkdocs 扩展,注册在 mkdocs-template.yml 的 markdown_extensions 中)把本地栅格图 `` 改写为 WebP-first ``,靠同名 `.webp` 约定对接。外部 URL 不下载不镜像。Markdown 中仍写普通图片语法。 + +`mkdocs.yml`、`cache/`、`generated/`、`site/` 均为生成产物(gitignore),**永远不要手改**;配置改 `mkdocs-template.yml`,nav 由脚本生成。 + +## Key Directories + +| 路径 | 用途 | +| --------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `src/nmteam_support/` | 工具链包(16 个模块,见 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)、`assets/js/`(AI 工具脚本 `ai-tools.js`,随构建 stage 到生成站) | +| `overrides/` | mkdocs `custom_dir`:`main.html` 覆写 site_meta 移除主题版本号;`partials/actions.html` 追加 Fumadocs 风格文章操作区(复制 Markdown + GitHub / Markdown / Perplexity / Grok / ChatGPT / Claude Web / Claude Desktop / Claude Code / OpenAI Codex / Cursor 打开菜单);`.icons/ai/` 存放菜单品牌图标 | +| `scripts/` | 三平台薄启动器(`nmteam.sh` / `nmteam.ps1` / `nmteam.bat`) | +| `tests/` | pytest 测试(17 个文件 + 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/, + # 再 stage 每页 .md 副本到 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: ` 排序;`index.md` 可用 `hide_docs_list: true` 与 `hide: [navigation]`。 +- 常用 `!!! note` / `!!! warning` / `!!! success` / `!!! faq` admonition 与 `??? question` 折叠块;表格(对齐列 `:---`);步骤用有序列表。 +- 付费功能用 `` 行内徽标(样式 `assets/styles/plus.css`,远程 svg);智能功能可用 `nmbot-intelligence-icon`。 +- **图片一律绝对路径引用 `/assets/images/...`**(不要用相对 `./img/`),构建时自动产出 WebP 优先 ``;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 `` | +| `src/nmteam_support/llms.py` | `render_llms_txt()` 从扫描树生成 `/llms.txt`(llmstxt.org 规范;链接指向各页 `.md` 版本) | +| `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 版本号 | +| `overrides/partials/actions.html` | 覆盖 material actions partial:保留编辑/查看按钮,追加复制 Markdown 按钮与十项文章打开菜单 | +| `assets/js/ai-tools.js` | 文章操作交互:复制当前页 Markdown、菜单开关、外部点击/Escape 关闭、开发模式提示,以及八种 AI 服务的页面 URL 深链 | +| `assets/styles/ai-tools.css` | 文章操作按钮组与半透明弹层样式,适配明暗主题和窄屏 | + +## 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_.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 等)。 +- `test_llms.py` 覆盖 llms.txt 生成(标题/摘要/分节/.md 链接/base_url/空树);`test_generator.py` 覆盖 llms.txt 落盘与 `stage_markdown_copies` 镜像 cache。 +- 输入构造分级: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_.py` 行为测试即可。 +- CI 在 ubuntu/macos/windows 三平台跑全量 check;提交前本地至少跑 `uv run nmteam check`。 diff --git a/README.md b/README.md index b8a4608..63372f6 100644 --- a/README.md +++ b/README.md @@ -1,67 +1,150 @@ # 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 开发服务器() +- 监听 `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 色有损量化 + +Markdown 中仍使用普通图片语法,构建工具会自动输出 WebP +优先的 `` 元素。外部 URL 不会被下载或镜像。 + +## AI 支持 + +站点面向语言模型提供以下能力: -# 或使用便捷脚本 -.\dev.ps1 build +- `/llms.txt`:按 [llmstxt.org](https://llmstxt.org/) 规范生成的站点索引, + 每个链接指向页面的 Markdown 版本。 +- 每页 Markdown 版本:`nmteam build` 时在每个页面旁生成同路径的 `.md` 文件 + (如 `/nmbot-telegram/mcp.md`)。 +- 页面顶部的文章操作区(首页不显示):**复制 Markdown** 直接复制当前页面 + 原文;**使用[品牌图标]打开** 菜单提供 GitHub 源文件、Markdown 版本, + 以及 Perplexity、Grok、ChatGPT、Claude Web、Claude Desktop、 + Claude Code、OpenAI Codex、Cursor 八种 AI 打开方式。 + +注意:`llms.txt` 与 `.md` 版本由 `nmteam build` 输出到 `site/`;开发模式 +(`nmteam dev`)下复制和 View as Markdown 会提示先构建,AI 操作仍可通过 +当前页面 URL 打开。 + +### 其他命令 + +```bash +uv run nmteam generate # 仅重新生成文档结构 +uv run nmteam clean # 清理 cache/、generated/ 和 site/ +uv run nmteam serve # 预览 site/(.md 以 text/plain; charset=utf-8 提供) +uv run nmteam --help # 显示完整命令帮助 ``` -构建过程会: -1. 运行 `generate.py` 生成文档结构 -2. 执行 `mkdocs build` 生成静态站点到 `site/` 目录 +`nmteam serve` 默认监听 `127.0.0.1:8124`,可用 `--port` / `--bind` +调整。与裸 `python -m http.server` 不同,它把 `.md` 文件的 +`Content-Type` 显式设为 `text/plain; charset=utf-8`(Python 3.13+ 的 +`mimetypes` 会把 `.md` 判为 `text/markdown`,部分客户端会下载而非内联 +显示),保证每页 Markdown 版本在任何浏览器中都能直接阅读。 + +## 平台启动器 + +直接运行 `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 上提出问题并贡献文档。 diff --git a/docs/img/icons/doc.svg b/assets/icons/doc.svg similarity index 100% rename from docs/img/icons/doc.svg rename to assets/icons/doc.svg diff --git a/docs/img/icons/folder.svg b/assets/icons/folder.svg similarity index 100% rename from docs/img/icons/folder.svg rename to assets/icons/folder.svg diff --git a/docs/nmbot-telegram/img/add_as_admin_step_1.png b/assets/images/nmbot/add_as_admin_step_1.png similarity index 100% rename from docs/nmbot-telegram/img/add_as_admin_step_1.png rename to assets/images/nmbot/add_as_admin_step_1.png diff --git a/docs/nmbot-telegram/img/add_as_admin_step_2.png b/assets/images/nmbot/add_as_admin_step_2.png similarity index 100% rename from docs/nmbot-telegram/img/add_as_admin_step_2.png rename to assets/images/nmbot/add_as_admin_step_2.png diff --git a/docs/nmbot-telegram/img/add_to_admin_step_1.png b/assets/images/nmbot/add_to_admin_step_1.png similarity index 100% rename from docs/nmbot-telegram/img/add_to_admin_step_1.png rename to assets/images/nmbot/add_to_admin_step_1.png diff --git a/docs/nmbot-telegram/img/add_to_admin_step_2.png b/assets/images/nmbot/add_to_admin_step_2.png similarity index 100% rename from docs/nmbot-telegram/img/add_to_admin_step_2.png rename to assets/images/nmbot/add_to_admin_step_2.png diff --git a/docs/nmbot-telegram/img/add_to_admin_step_3.png b/assets/images/nmbot/add_to_admin_step_3.png similarity index 100% rename from docs/nmbot-telegram/img/add_to_admin_step_3.png rename to assets/images/nmbot/add_to_admin_step_3.png diff --git a/docs/nmbot-telegram/img/add_to_admin_step_4.png b/assets/images/nmbot/add_to_admin_step_4.png similarity index 100% rename from docs/nmbot-telegram/img/add_to_admin_step_4.png rename to assets/images/nmbot/add_to_admin_step_4.png diff --git a/docs/nmbot-telegram/img/add_to_admin_step_5.png b/assets/images/nmbot/add_to_admin_step_5.png similarity index 100% rename from docs/nmbot-telegram/img/add_to_admin_step_5.png rename to assets/images/nmbot/add_to_admin_step_5.png diff --git a/docs/nmbot-telegram/img/doc cover.png b/assets/images/nmbot/doc cover.png similarity index 100% rename from docs/nmbot-telegram/img/doc cover.png rename to assets/images/nmbot/doc cover.png diff --git a/docs/nmbot-telegram/img/doc start intro.png b/assets/images/nmbot/doc start intro.png similarity index 100% rename from docs/nmbot-telegram/img/doc start intro.png rename to assets/images/nmbot/doc start intro.png diff --git a/docs/nmbot-telegram/img/doc start panel.png b/assets/images/nmbot/doc start panel.png similarity index 100% rename from docs/nmbot-telegram/img/doc start panel.png rename to assets/images/nmbot/doc start panel.png diff --git a/docs/nmbot-telegram/img/doc start telegram.png b/assets/images/nmbot/doc start telegram.png similarity index 100% rename from docs/nmbot-telegram/img/doc start telegram.png rename to assets/images/nmbot/doc start telegram.png diff --git a/docs/nmbot-telegram/img/interaction_example.png b/assets/images/nmbot/interaction_example.png similarity index 100% rename from docs/nmbot-telegram/img/interaction_example.png rename to assets/images/nmbot/interaction_example.png diff --git a/docs/nmbot-telegram/img/interaction_example2.png b/assets/images/nmbot/interaction_example2.png similarity index 100% rename from docs/nmbot-telegram/img/interaction_example2.png rename to assets/images/nmbot/interaction_example2.png diff --git a/docs/nmbot-telegram/img/interaction_example3.png b/assets/images/nmbot/interaction_example3.png similarity index 100% rename from docs/nmbot-telegram/img/interaction_example3.png rename to assets/images/nmbot/interaction_example3.png diff --git a/docs/nmbot-telegram/img/interaction_example4.png b/assets/images/nmbot/interaction_example4.png similarity index 100% rename from docs/nmbot-telegram/img/interaction_example4.png rename to assets/images/nmbot/interaction_example4.png diff --git a/docs/nmbot-telegram/img/launch_panel_from_any_chat.png b/assets/images/nmbot/launch_panel_from_any_chat.png similarity index 100% rename from docs/nmbot-telegram/img/launch_panel_from_any_chat.png rename to assets/images/nmbot/launch_panel_from_any_chat.png diff --git a/docs/nmbot-telegram/img/launch_panel_from_chat_corner.png b/assets/images/nmbot/launch_panel_from_chat_corner.png similarity index 100% rename from docs/nmbot-telegram/img/launch_panel_from_chat_corner.png rename to assets/images/nmbot/launch_panel_from_chat_corner.png diff --git a/docs/nmbot-telegram/img/mcp/mcp-config-page.png b/assets/images/nmbot/mcp/mcp-config-page.png similarity index 100% rename from docs/nmbot-telegram/img/mcp/mcp-config-page.png rename to assets/images/nmbot/mcp/mcp-config-page.png diff --git a/docs/nmbot-telegram/img/mcp/mcp-create-token-dialog.png b/assets/images/nmbot/mcp/mcp-create-token-dialog.png similarity index 100% rename from docs/nmbot-telegram/img/mcp/mcp-create-token-dialog.png rename to assets/images/nmbot/mcp/mcp-create-token-dialog.png diff --git a/docs/nmbot-telegram/img/mcp/mcp-entry.png b/assets/images/nmbot/mcp/mcp-entry.png similarity index 100% rename from docs/nmbot-telegram/img/mcp/mcp-entry.png rename to assets/images/nmbot/mcp/mcp-entry.png diff --git a/docs/nmbot-telegram/img/mcp/mcp-token-created-dialog.png b/assets/images/nmbot/mcp/mcp-token-created-dialog.png similarity index 100% rename from docs/nmbot-telegram/img/mcp/mcp-token-created-dialog.png rename to assets/images/nmbot/mcp/mcp-token-created-dialog.png diff --git a/docs/nmbot-telegram/img/mcp/mcp-vscode-command-palette.png b/assets/images/nmbot/mcp/mcp-vscode-command-palette.png similarity index 100% rename from docs/nmbot-telegram/img/mcp/mcp-vscode-command-palette.png rename to assets/images/nmbot/mcp/mcp-vscode-command-palette.png diff --git a/docs/nmbot-telegram/img/mcp/mcp-vscode-user-config.png b/assets/images/nmbot/mcp/mcp-vscode-user-config.png similarity index 100% rename from docs/nmbot-telegram/img/mcp/mcp-vscode-user-config.png rename to assets/images/nmbot/mcp/mcp-vscode-user-config.png diff --git a/docs/nmbot-telegram/img/nmartchat_panel_enablechat.png b/assets/images/nmbot/nmartchat_panel_enablechat.png similarity index 100% rename from docs/nmbot-telegram/img/nmartchat_panel_enablechat.png rename to assets/images/nmbot/nmartchat_panel_enablechat.png diff --git a/docs/nmbot-telegram/img/nmartchat_regadmin.png b/assets/images/nmbot/nmartchat_regadmin.png similarity index 100% rename from docs/nmbot-telegram/img/nmartchat_regadmin.png rename to assets/images/nmbot/nmartchat_regadmin.png diff --git a/docs/nmbot-telegram/img/reply-channel_eg.png b/assets/images/nmbot/reply-channel_eg.png similarity index 100% rename from docs/nmbot-telegram/img/reply-channel_eg.png rename to assets/images/nmbot/reply-channel_eg.png diff --git a/docs/nmbot-telegram/img/update-pictures/nmBot plus.png b/assets/images/nmbot/update-pictures/nmBot plus.png similarity index 100% rename from docs/nmbot-telegram/img/update-pictures/nmBot plus.png rename to assets/images/nmbot/update-pictures/nmBot plus.png diff --git a/docs/nmbot-telegram/img/update-pictures/nmbot-2312-christmas.jpg b/assets/images/nmbot/update-pictures/nmbot-2312-christmas.jpg similarity index 100% rename from docs/nmbot-telegram/img/update-pictures/nmbot-2312-christmas.jpg rename to assets/images/nmbot/update-pictures/nmbot-2312-christmas.jpg diff --git a/docs/nmbot-telegram/img/update-pictures/nmbot-2401-winter.jpg b/assets/images/nmbot/update-pictures/nmbot-2401-winter.jpg similarity index 100% rename from docs/nmbot-telegram/img/update-pictures/nmbot-2401-winter.jpg rename to assets/images/nmbot/update-pictures/nmbot-2401-winter.jpg diff --git a/docs/nmbot-telegram/img/update-pictures/nmbot-2402-spring-festival.jpg b/assets/images/nmbot/update-pictures/nmbot-2402-spring-festival.jpg similarity index 100% rename from docs/nmbot-telegram/img/update-pictures/nmbot-2402-spring-festival.jpg rename to assets/images/nmbot/update-pictures/nmbot-2402-spring-festival.jpg diff --git a/docs/nmbot-telegram/img/update-pictures/nmbot-2408.png b/assets/images/nmbot/update-pictures/nmbot-2408.png similarity index 100% rename from docs/nmbot-telegram/img/update-pictures/nmbot-2408.png rename to assets/images/nmbot/update-pictures/nmbot-2408.png diff --git a/docs/nmbot-telegram/img/update-pictures/nmbot-2409.png b/assets/images/nmbot/update-pictures/nmbot-2409.png similarity index 100% rename from docs/nmbot-telegram/img/update-pictures/nmbot-2409.png rename to assets/images/nmbot/update-pictures/nmbot-2409.png diff --git a/docs/nmbot-telegram/img/update-pictures/nmbot-2410.png b/assets/images/nmbot/update-pictures/nmbot-2410.png similarity index 100% rename from docs/nmbot-telegram/img/update-pictures/nmbot-2410.png rename to assets/images/nmbot/update-pictures/nmbot-2410.png diff --git a/docs/nmbot-telegram/img/update-pictures/nmbot-2412.png b/assets/images/nmbot/update-pictures/nmbot-2412.png similarity index 100% rename from docs/nmbot-telegram/img/update-pictures/nmbot-2412.png rename to assets/images/nmbot/update-pictures/nmbot-2412.png diff --git a/docs/nmbot-telegram/img/update-pictures/nmbot-2501.png b/assets/images/nmbot/update-pictures/nmbot-2501.png similarity index 100% rename from docs/nmbot-telegram/img/update-pictures/nmbot-2501.png rename to assets/images/nmbot/update-pictures/nmbot-2501.png diff --git a/docs/nmbot-telegram/img/update-pictures/nmbot-2502.png b/assets/images/nmbot/update-pictures/nmbot-2502.png similarity index 100% rename from docs/nmbot-telegram/img/update-pictures/nmbot-2502.png rename to assets/images/nmbot/update-pictures/nmbot-2502.png diff --git a/docs/nmbot-telegram/img/update-pictures/nmbot-2503.png b/assets/images/nmbot/update-pictures/nmbot-2503.png similarity index 100% rename from docs/nmbot-telegram/img/update-pictures/nmbot-2503.png rename to assets/images/nmbot/update-pictures/nmbot-2503.png diff --git a/docs/nmbot-telegram/img/update-pictures/nmbot-2504.png b/assets/images/nmbot/update-pictures/nmbot-2504.png similarity index 100% rename from docs/nmbot-telegram/img/update-pictures/nmbot-2504.png rename to assets/images/nmbot/update-pictures/nmbot-2504.png diff --git a/docs/nmbot-telegram/img/update-pictures/nmbot-2505.png b/assets/images/nmbot/update-pictures/nmbot-2505.png similarity index 100% rename from docs/nmbot-telegram/img/update-pictures/nmbot-2505.png rename to assets/images/nmbot/update-pictures/nmbot-2505.png diff --git a/docs/nmbot-telegram/img/update-pictures/nmbot-2506.png b/assets/images/nmbot/update-pictures/nmbot-2506.png similarity index 100% rename from docs/nmbot-telegram/img/update-pictures/nmbot-2506.png rename to assets/images/nmbot/update-pictures/nmbot-2506.png diff --git a/docs/nmbot-telegram/img/update-pictures/nmbot-2507.png b/assets/images/nmbot/update-pictures/nmbot-2507.png similarity index 100% rename from docs/nmbot-telegram/img/update-pictures/nmbot-2507.png rename to assets/images/nmbot/update-pictures/nmbot-2507.png diff --git a/docs/nmbot-telegram/img/update-pictures/nmbot-2508.png b/assets/images/nmbot/update-pictures/nmbot-2508.png similarity index 100% rename from docs/nmbot-telegram/img/update-pictures/nmbot-2508.png rename to assets/images/nmbot/update-pictures/nmbot-2508.png diff --git a/docs/nmbot-telegram/img/update-pictures/nmbot-2509.png b/assets/images/nmbot/update-pictures/nmbot-2509.png similarity index 100% rename from docs/nmbot-telegram/img/update-pictures/nmbot-2509.png rename to assets/images/nmbot/update-pictures/nmbot-2509.png diff --git a/docs/nmbot-telegram/img/update-pictures/nmbot-2510.png b/assets/images/nmbot/update-pictures/nmbot-2510.png similarity index 100% rename from docs/nmbot-telegram/img/update-pictures/nmbot-2510.png rename to assets/images/nmbot/update-pictures/nmbot-2510.png diff --git a/docs/nmbot-telegram/img/update-pictures/nmbot-2511.png b/assets/images/nmbot/update-pictures/nmbot-2511.png similarity index 100% rename from docs/nmbot-telegram/img/update-pictures/nmbot-2511.png rename to assets/images/nmbot/update-pictures/nmbot-2511.png diff --git a/docs/nmbot-telegram/img/update-pictures/nmbot-2512.png b/assets/images/nmbot/update-pictures/nmbot-2512.png similarity index 100% rename from docs/nmbot-telegram/img/update-pictures/nmbot-2512.png rename to assets/images/nmbot/update-pictures/nmbot-2512.png diff --git a/docs/img/keyword-reply-edit.png b/assets/images/shared/keyword-reply-edit.png similarity index 100% rename from docs/img/keyword-reply-edit.png rename to assets/images/shared/keyword-reply-edit.png diff --git a/docs/img/keyword-reply-limit.png b/assets/images/shared/keyword-reply-limit.png similarity index 100% rename from docs/img/keyword-reply-limit.png rename to assets/images/shared/keyword-reply-limit.png diff --git a/docs/img/nmteam-support-background.jpg b/assets/images/shared/nmteam-support-background.jpg similarity index 100% rename from docs/img/nmteam-support-background.jpg rename to assets/images/shared/nmteam-support-background.jpg diff --git a/docs/img/nmteam_account_register.png b/assets/images/shared/nmteam_account_register.png similarity index 100% rename from docs/img/nmteam_account_register.png rename to assets/images/shared/nmteam_account_register.png diff --git a/docs/img/spam faq.png b/assets/images/shared/spam faq.png similarity index 100% rename from docs/img/spam faq.png rename to assets/images/shared/spam faq.png diff --git a/assets/js/ai-tools.js b/assets/js/ai-tools.js new file mode 100644 index 0000000..68b6e1a --- /dev/null +++ b/assets/js/ai-tools.js @@ -0,0 +1,250 @@ +// Fumadocs-style page actions menu. +(function () { + "use strict"; + + var ENDPOINTS = { + perplexity: "https://www.perplexity.ai/search?q=", + grok: "https://grok.com/?q=", + chatgpt: "https://chatgpt.com/?prompt=", + claude: "https://claude.ai/new?q=", + "claude-desktop": "claude://claude.ai/new?q=", + "claude-code": "https://claude.ai/code/new?q=", + codex: "codex://new?prompt=", + cursor: "https://cursor.com/link/prompt?text=", + }; + + var CLAUDE_CODE_REPOSITORY = "nm-Team/Support"; + var CLAUDE_CODE_BRANCH = "main"; + + function mdUrl(raw) { + if (!raw) { + return "/index.md"; + } + return "/" + raw.replace(/\/+$/, "") + ".md"; + } + + function pageUrl(raw) { + return location.origin + "/" + (raw || ""); + } + + function providerPrompt(url) { + return ( + "请阅读以下 nmTeam 帮助文档,并依据原文回答我接下来的问题;" + + "若文档未提及,请如实说明:\n\n" + + url + ); + } + + function providerUrl(provider, prompt) { + var url = ENDPOINTS[provider] + encodeURIComponent(prompt); + if (provider === "chatgpt") { + return url + "&hints=search"; + } + if (provider === "claude-code") { + return ( + url + + "&repo=" + + encodeURIComponent(CLAUDE_CODE_REPOSITORY) + + "&branch=" + + encodeURIComponent(CLAUDE_CODE_BRANCH) + ); + } + return url; + } + + function setOpen(box, open, restoreFocus) { + var trigger = box.querySelector(".ai-tools__trigger"); + var menu = box.querySelector(".ai-tools__menu"); + box.classList.toggle("is-open", open); + trigger.setAttribute("aria-expanded", String(open)); + menu.hidden = !open; + if (!open && restoreFocus) { + trigger.focus(); + } + } + + function showMarkdownUnavailable() { + window.alert( + "Markdown 版本在构建产物中提供。请先运行 `uv run nmteam build`," + + "或使用其他打开方式。" + ); + } + + function showCopyFailed() { + window.alert("无法复制 Markdown,请稍后重试。"); + } + + function copyWithSelection(text) { + var textarea = document.createElement("textarea"); + textarea.value = text; + textarea.setAttribute("readonly", ""); + textarea.style.position = "fixed"; + textarea.style.opacity = "0"; + document.body.appendChild(textarea); + textarea.select(); + + var copied = document.execCommand("copy"); + textarea.remove(); + if (!copied) { + return Promise.reject(new Error("Copy command failed")); + } + return Promise.resolve(); + } + + function copyText(text) { + if (navigator.clipboard && navigator.clipboard.writeText) { + return navigator.clipboard.writeText(text).catch(function () { + return copyWithSelection(text); + }); + } + return copyWithSelection(text); + } + + function setCopyState(button, copied) { + button.querySelector(".ai-tools__copy-icon--idle").hidden = copied; + button.querySelector(".ai-tools__copy-icon--success").hidden = !copied; + button.querySelector(".ai-tools__copy-label").textContent = copied + ? "已复制" + : "复制 Markdown"; + } + + function wireCopy(button, md, availability) { + var resetTimer; + + button.addEventListener("click", function () { + button.disabled = true; + availability + .then(function (available) { + if (!available) { + showMarkdownUnavailable(); + return null; + } + return fetch(md); + }) + .then(function (response) { + if (!response) { + return null; + } + var contentType = response.headers.get("Content-Type") || ""; + if (!response.ok || contentType.indexOf("html") !== -1) { + throw new Error("Markdown is unavailable"); + } + return response.text(); + }) + .then(function (markdown) { + if (markdown === null) { + return; + } + return copyText(markdown).then(function () { + window.clearTimeout(resetTimer); + setCopyState(button, true); + resetTimer = window.setTimeout(function () { + setCopyState(button, false); + }, 1800); + }); + }) + .catch(showCopyFailed) + .then(function () { + button.disabled = false; + }); + }); + } + + function wireMarkdown(link, md) { + var availability = fetch(md, { method: "HEAD" }) + .then(function (response) { + var contentType = response.headers.get("Content-Type") || ""; + return response.ok && contentType.indexOf("html") === -1; + }) + .catch(function () { + return false; + }) + .then(function (available) { + link.dataset.rawAvailable = String(available); + return available; + }); + + link.href = md; + link.addEventListener("click", function (event) { + if (link.dataset.rawAvailable === "true") { + return; + } + + event.preventDefault(); + if (link.dataset.rawAvailable === "false") { + showMarkdownUnavailable(); + return; + } + + var target = window.open("about:blank", "_blank"); + if (target) { + target.opener = null; + } + availability.then(function (available) { + if (available && target) { + target.location.replace(md); + return; + } + if (target) { + target.close(); + } + showMarkdownUnavailable(); + }); + }); + + return availability; + } + + function wireMenu(box) { + var trigger = box.querySelector(".ai-tools__trigger"); + var copy = box.querySelector(".ai-tools__copy"); + var menu = box.querySelector(".ai-tools__menu"); + var raw = box.getAttribute("data-md-url") || ""; + var markdown = menu.querySelector('[data-ai="markdown"]'); + var md = mdUrl(raw); + var prompt = providerPrompt(pageUrl(raw)); + var availability = wireMarkdown(markdown, md); + + wireCopy(copy, md, availability); + [ + "perplexity", + "grok", + "chatgpt", + "claude", + "claude-desktop", + "claude-code", + "codex", + "cursor", + ].forEach(function (provider) { + menu.querySelector('[data-ai="' + provider + '"]').href = + providerUrl(provider, prompt); + }); + + trigger.addEventListener("click", function () { + setOpen(box, menu.hidden, false); + }); + + menu.addEventListener("click", function (event) { + if (event.target.closest(".ai-tools__item")) { + setOpen(box, false, false); + } + }); + + document.addEventListener("click", function (event) { + if (!menu.hidden && !box.contains(event.target)) { + setOpen(box, false, false); + } + }); + + document.addEventListener("keydown", function (event) { + if (event.key === "Escape" && !menu.hidden) { + event.preventDefault(); + setOpen(box, false, true); + } + }); + } + + document.addEventListener("DOMContentLoaded", function () { + document.querySelectorAll(".ai-tools").forEach(wireMenu); + }); +})(); diff --git a/assets/styles/ai-tools.css b/assets/styles/ai-tools.css new file mode 100644 index 0000000..7d6580e --- /dev/null +++ b/assets/styles/ai-tools.css @@ -0,0 +1,258 @@ +/* Fumadocs-style page actions menu. */ +.ai-tools { + position: relative; + z-index: 1; + display: inline-flex; + flex-wrap: wrap; + align-items: center; + justify-content: flex-end; + gap: 8px; + float: right; + margin: 0 0 12px 12px; +} + +.ai-tools__copy, +.ai-tools__trigger { + display: inline-flex; + align-items: center; + justify-content: center; + min-height: 36px; + gap: 7px; + padding: 7px 11px; + font: inherit; + font-size: 13px; + font-weight: 600; + line-height: 20px; + color: var(--md-default-fg-color); + background: var(--md-default-bg-color); + border: 1px solid var(--md-default-fg-color--lightest); + border-radius: 6px; + cursor: pointer; + transition: background-color 120ms ease, border-color 120ms ease; +} + +.ai-tools__copy:hover, +.ai-tools__trigger:hover, +.ai-tools.is-open .ai-tools__trigger { + background: var(--md-default-fg-color--lightest); + border-color: var(--md-default-fg-color--lighter); +} + +.ai-tools__copy:focus-visible, +.ai-tools__trigger:focus-visible, +.ai-tools__item:focus-visible { + outline: 2px solid var(--md-accent-fg-color); + outline-offset: 2px; +} + +.ai-tools__copy:disabled { + cursor: wait; + opacity: 0.65; +} + +.ai-tools__copy-icon { + display: inline-flex; + flex: 0 0 auto; + width: 16px; + height: 16px; + color: var(--md-default-fg-color--light); +} + +.ai-tools__copy-icon--success { + color: var(--md-accent-fg-color); +} + +.ai-tools__copy-icon[hidden] { + display: none; +} + +.ai-tools__copy-icon svg { + width: 100%; + height: 100%; + fill: currentcolor; +} + +.ai-tools__provider-icons { + display: inline-flex; + align-items: center; + padding-left: 1px; +} + +.ai-tools__provider-icon { + display: inline-flex; + flex: 0 0 auto; + width: 16px; + height: 16px; + padding: 1px; + background: var(--md-default-bg-color); + border-radius: 4px; + box-shadow: 0 0 0 1px var(--md-default-bg-color); +} + +.ai-tools__provider-icon + .ai-tools__provider-icon { + margin-left: -4px; +} + +.ai-tools__provider-icon svg { + width: 100%; + height: 100%; +} + +.ai-tools__provider-icon--github svg { + fill: currentcolor; +} + +.ai-tools__chevron, +.ai-tools__item-icon, +.ai-tools__external { + display: inline-flex; + align-items: center; + justify-content: center; + flex: 0 0 auto; +} + +.ai-tools__chevron { + width: 15px; + height: 15px; + color: var(--md-default-fg-color--light); + transition: transform 140ms ease; +} + +.ai-tools.is-open .ai-tools__chevron { + transform: rotate(180deg); +} + +.ai-tools__menu { + position: absolute; + top: calc(100% + 6px); + right: 0; + display: grid; + width: 248px; + max-width: calc(100vw - 32px); + max-height: min(70vh, 420px); + overflow-y: auto; + padding: 8px; + color: var(--md-default-fg-color); + background: color-mix(in srgb, var(--md-default-bg-color) 88%, transparent); + -webkit-backdrop-filter: blur(16px) saturate(135%); + backdrop-filter: blur(16px) saturate(135%); + border: 1px solid var(--md-default-fg-color--lightest); + border-radius: 12px; + box-shadow: 0 16px 40px color-mix(in srgb, #000 22%, transparent); +} + +.ai-tools__menu[hidden] { + display: none; +} + +.md-typeset .ai-tools__item { + display: grid; + grid-template-columns: 18px minmax(0, 1fr) 16px; + align-items: center; + gap: 10px; + position: relative; + min-height: 32px; + padding: 6px 8px; + font-size: 14px; + line-height: 20px; + color: var(--md-default-fg-color); + border-radius: 8px; + text-decoration: none; + transition: color 100ms ease, background-color 100ms ease; +} + +.md-typeset .ai-tools__item:hover { + color: var(--md-default-fg-color); + background: var(--md-default-fg-color--lightest); +} + +.md-typeset .ai-tools__item--group-start { + margin-top: 5px; +} + +.md-typeset .ai-tools__item--group-start::before { + content: ""; + position: absolute; + top: -3px; + right: 8px; + left: 8px; + border-top: 1px solid var(--md-default-fg-color--lightest); +} + +.ai-tools__item-icon { + width: 18px; + height: 18px; +} + +.ai-tools__label { + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.ai-tools__external { + width: 16px; + height: 16px; + color: var(--md-default-fg-color--light); +} + +.ai-tools__chevron svg, +.ai-tools__item-icon:not(.ai-tools__item-icon--brand) svg, +.ai-tools__external svg { + width: 100%; + height: 100%; + fill: currentcolor; +} + +.ai-tools__item-icon--brand svg { + width: 100%; + height: 100%; +} + +@media (max-width: 48em) { + .md-content__inner { + display: flex; + flex-direction: column; + } + + .md-content__inner > h1 { + order: -1; + } + + .md-content__inner > .ai-tools { + order: 0; + float: none; + flex-wrap: nowrap; + width: 100%; + justify-content: flex-start; + margin: 0 0 16px; + } + + .ai-tools__copy, + .ai-tools__trigger { + flex: 0 1 auto; + background: transparent; + border-color: var(--md-default-fg-color--light); + } + + .md-content__inner > :not(h1):not(.ai-tools) { + order: 1; + } +} + +@media (max-width: 44.984375em) { + .ai-tools { + flex-wrap: wrap; + gap: 6px; + margin-right: 4px; + } + + .ai-tools__copy, + .ai-tools__trigger { + gap: 5px; + padding-right: 8px; + padding-left: 8px; + font-size: 12px; + } +} diff --git a/assets/styles/base.css b/assets/styles/base.css new file mode 100644 index 0000000..33766da --- /dev/null +++ b/assets/styles/base.css @@ -0,0 +1,10 @@ +/* Global anchor-link smooth scrolling. */ +html { + scroll-behavior: smooth; +} + +@media (prefers-reduced-motion: reduce) { + html { + scroll-behavior: auto; + } +} diff --git a/docs/docsList.css b/assets/styles/docsList.css similarity index 90% rename from docs/docsList.css rename to assets/styles/docsList.css index 2b7344d..a1c9c76 100644 --- a/docs/docsList.css +++ b/assets/styles/docsList.css @@ -40,11 +40,11 @@ } .docsList .docsItem .icon.doc { - background-image: url(img/icons/doc.svg); + background-image: url(/assets/icons/doc.svg); } .docsList .docsItem .icon.folder { - background-image: url(img/icons/folder.svg); + background-image: url(/assets/icons/folder.svg); } .docsList .docsItem .text .description { diff --git a/docs/plus.css b/assets/styles/plus.css similarity index 100% rename from docs/plus.css rename to assets/styles/plus.css diff --git a/dev.bat b/dev.bat deleted file mode 100644 index f77841d..0000000 --- a/dev.bat +++ /dev/null @@ -1,20 +0,0 @@ -@echo off -REM nmTeam Documentation Development Script -REM Windows 批处理脚本 - -echo nmTeam Documentation Manager -echo. - -if "%1"=="" ( - echo 用法: dev.bat [command] - echo. - echo 可用命令: - echo dev 启动开发模式 - echo build 构建静态站点 - echo clean 清理生成文件 - echo install 安装依赖 - echo. - goto :eof -) - -python manage.py %* diff --git a/dev.ps1 b/dev.ps1 deleted file mode 100644 index 81f116e..0000000 --- a/dev.ps1 +++ /dev/null @@ -1,35 +0,0 @@ -# nmTeam Documentation Management PowerShell Script -# Enable UTF-8 encoding -[Console]::OutputEncoding = [System.Text.Encoding]::UTF8 -$OutputEncoding = [System.Text.Encoding]::UTF8 - -param( - [Parameter(Position=0)] - [string]$Command = "", - [Parameter(ValueFromRemainingArguments=$true)] - [string[]]$RemainingArgs -) - -Write-Host "nmTeam Documentation Manager" -ForegroundColor Cyan -Write-Host "" - -if ($Command -eq "" -or $Command -eq "help") { - Write-Host "用法: .\dev.ps1 " -ForegroundColor Yellow - Write-Host "" - Write-Host "可用命令:" -ForegroundColor Green - Write-Host " dev 启动开发模式 (文件监听 + 热更新)" -ForegroundColor White - Write-Host " build 构建静态站点 (生成文档 + 构建)" -ForegroundColor White - Write-Host " clean 清理生成的文件" -ForegroundColor White - Write-Host " install 安装依赖包" -ForegroundColor White - Write-Host " help 显示帮助信息" -ForegroundColor White - Write-Host "" - Write-Host "示例:" -ForegroundColor Yellow - Write-Host " .\dev.ps1 dev # 启动开发服务器" -ForegroundColor Gray - Write-Host " .\dev.ps1 build # 构建生产版本" -ForegroundColor Gray - Write-Host " .\dev.ps1 clean # 清理临时文件" -ForegroundColor Gray - exit 0 -} - -# 执行 Python 脚本 -$arguments = @($Command) + $RemainingArgs -& python manage.py $arguments diff --git a/dev.sh b/dev.sh deleted file mode 100644 index 0d9968c..0000000 --- a/dev.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash -# nmTeam Documentation Development Script -# Unix/Linux shell script - -echo "nmTeam Documentation Manager" -echo - -if [ $# -eq 0 ]; then - echo "用法: ./dev.sh [command]" - echo - echo "可用命令:" - echo " dev 启动开发模式" - echo " build 构建静态站点" - echo " clean 清理生成文件" - echo " install 安装依赖" - echo - exit 0 -fi - -python manage.py "$@" diff --git a/docs/about.md b/docs/about.md index 24152bf..326b531 100644 --- a/docs/about.md +++ b/docs/about.md @@ -5,11 +5,13 @@ index: 200 --- ## nmTeam 帮助文档 + nmTeam 帮助文档由 nmTeam 成员和社区志愿者共同编辑。 您可以在 [GitHub](https://github.com/nm-Team/Support) 上参与贡献此文档。 ## 贡献者 + + \ No newline at end of file + diff --git a/docs/assets/js/redirects.js b/docs/assets/js/redirects.js deleted file mode 100644 index 2b724cd..0000000 --- a/docs/assets/js/redirects.js +++ /dev/null @@ -1,20 +0,0 @@ -// 简单的客户端重定向脚本 -(function () { - // 重定向映射 - const redirects = { - '/nmbot-telegram/about-panel/': '/nmbot-telegram/panel/', - }; - - // 获取当前路径 - const currentPath = window.location.pathname; - - // 检查是否需要重定向 - for (const oldPath in redirects) { - if (currentPath === oldPath || currentPath.startsWith(oldPath)) { - const newPath = redirects[oldPath]; - // 执行重定向 - window.location.replace(newPath); - break; - } - } -})(); diff --git a/docs/contact-us/contact-support.md b/docs/contact-us/contact-support.md index d14b9d1..85e1670 100644 --- a/docs/contact-us/contact-support.md +++ b/docs/contact-us/contact-support.md @@ -4,6 +4,7 @@ description: 了解如何联系 nmTeam 支持获取帮助。 --- # 联系 nmTeam 支持 + 我们欢迎您联系 nmTeam 支持获取帮助。我们的支持团队将尽力为您提供帮助。 ## 联系 nmTeam 支持前,请注意 @@ -11,26 +12,29 @@ description: 了解如何联系 nmTeam 支持获取帮助。 - nmTeam 帮助文档中包含许多常见问题的解答。提出问题前,请先查阅帮助文档,并尝试使用搜索功能查找有关您的问题的解答。 - 如果您在使用 nmTeam 产品时遇到问题,请尽量提供详细的信息,以便我们更快地为您解决问题。 - nmTeam 支持包括志愿者和员工。 -我们的支持团队会尽力为您提供帮助,但无法保证能够解决所有问题。 + 我们的支持团队会尽力为您提供帮助,但无法保证能够解决所有问题。 - 联系 nmTeam 支持时,请尽量使用英文或中文。 -我们的支持团队会尽量使用您提供的语言回复您。 + 我们的支持团队会尽量使用您提供的语言回复您。 - 联系 nmTeam 时请保持礼貌。我们的支持团队会尽力为您提供帮助,但不接受任何形式的辱骂或威胁。 -若您的行为不当,我们将拒绝为您提供帮助。 + 若您的行为不当,我们将拒绝为您提供帮助。 - 由于 nmTeam 支持团队的业务繁忙,我们可能无法立即回复您的问题。 -请耐心等待,我们会尽快回复您。 -有时我们会在不回复的情况下解决您的问题,因此您可以在提交问题后等待一段时间查看您的问题是否已解决。 + 请耐心等待,我们会尽快回复您。 + 有时我们会在不回复的情况下解决您的问题,因此您可以在提交问题后等待一段时间查看您的问题是否已解决。 - nmTeam 支持团队不会要求您提供 nmTeam 账号的密码或其他敏感信息。 -请勿向任何人提供您的 nmTeam 账号密码或其他敏感信息。 + 请勿向任何人提供您的 nmTeam 账号密码或其他敏感信息。 - 由于 nmTeam 支持团队在多个平台上均提供帮助,我们建议您尽可能在遇到问题的平台上联系 nmTeam 支持。 -例如,如果您在 nmBot Telegram 中遇到问题,请在 Telegram 中联系 nmTeam 支持,以便我们更快地为您解决问题。 + 例如,如果您在 nmBot Telegram 中遇到问题,请在 Telegram 中联系 nmTeam 支持,以便我们更快地为您解决问题。 ## 联系 nmTeam 支持 + 您可以通过以下方式联系 nmTeam 支持: ### 电子邮件支持 + 您可以通过电子邮件联系 nmTeam 支持。 请发送邮件至 [support@nmteam.xyz](mailto:support@nmteam.xyz)。 ### Telegram 支持 + 您可以在 Telegram 中联系 nmTeam 支持。 我们的 Telegram 账号是 [@nmteamsupportbot](https://t.me/nmteamsupportbot)。 diff --git a/docs/contact-us/index.md b/docs/contact-us/index.md index 738e0ed..0eb11e8 100644 --- a/docs/contact-us/index.md +++ b/docs/contact-us/index.md @@ -5,4 +5,5 @@ index: 100 --- # 联系 nmTeam -了解如何联系 nmTeam,包括在社交网站上关注我们,或联系 nmTeam 支持获取帮助。 \ No newline at end of file + +了解如何联系 nmTeam,包括在社交网站上关注我们,或联系 nmTeam 支持获取帮助。 diff --git a/docs/contact-us/social-media.md b/docs/contact-us/social-media.md index e290b4a..1e11412 100644 --- a/docs/contact-us/social-media.md +++ b/docs/contact-us/social-media.md @@ -4,13 +4,16 @@ description: 了解如何在社交媒体上关注 nmTeam,获取最新消息和 --- # 社交媒体上的 nmTeam + 您可以在社交媒体上关注 nmTeam,获取最新消息和帮助。 ## Twitter + 您可以在 Twitter 上关注 nmTeam,获取最新消息和帮助。 我们的 Twitter 账号是 [@nmnmfun](https://twitter.com/nmnmfun)。 ## Telegram + 您可以订阅 nmTeam Newsroom 频道,获取 nmTeam 的最新消息。 我们的 Telegram 频道是 [@nmteamnewsroom](https://t.me/nmteamnewsroom)。 @@ -21,5 +24,6 @@ nmTeam Development Channel 是极客和铁粉观测 nmTeam 最新产品开发动 nmTeam Development Channel 是 [@nmteampush](https://t.me/nmteampush)。 ## Discord + 您可以加入 nmTeam Discord 服务器,与其他用户交流。 我们的 Discord 服务器是 [nmTeam](https://discord.gg/kRegqfMx)。 diff --git a/docs/index.md b/docs/index.md index dfe7c8a..7bc6ea2 100644 --- a/docs/index.md +++ b/docs/index.md @@ -12,11 +12,11 @@ hide: 在此获取 nmTeam 旗下产品的支持。 - + ## 产品和服务 - + @@ -32,7 +32,7 @@ hide: - + ## 关于帮助文档 @@ -48,9 +48,12 @@ nmTeam 帮助文档由 nmTeam 成员和社区志愿者共同编辑。您可以 访问 [nmTeam 官网](https://nmteam.xyz)了解 nmTeam 的最新动态和产品信息。 - +
在此获取 nmTeam 旗下产品的支持。