Skip to content

chore: KaTeX math support + project cleanup - #41

Closed
one-ea wants to merge 2 commits into
mainfrom
dev
Closed

chore: KaTeX math support + project cleanup#41
one-ea wants to merge 2 commits into
mainfrom
dev

Conversation

@one-ea

@one-ea one-ea commented Apr 25, 2026

Copy link
Copy Markdown
Owner

Summary

  • KaTeX math formula support: inline $...$ and block $$...$$ rendering with code block protection
  • Project cleanup: remove orphaned .wiki-tmp submodule, unused marked from server, stray test artifacts
  • Dependency hygiene: @types/dompurify and shadcn moved to devDependencies
  • gitignore: add .playwright-mcp/ and .wiki-tmp/

@coderabbitai

coderabbitai Bot commented Apr 25, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@one-ea has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 45 minutes and 47 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 45 minutes and 47 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b31af85a-ba1f-4a88-a1ed-d753a08b0ab5

📥 Commits

Reviewing files that changed from the base of the PR and between b673444 and da229d2.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json, !**/package-lock.json
📒 Files selected for processing (7)
  • .gitignore
  • .wiki-tmp
  • client/package.json
  • client/src/globals.css
  • client/src/lib/markdown.ts
  • server/package.json
  • server/src/index.ts
📝 Walkthrough

总体概述

本 PR 重构前端导航系统为动态化,集成 KaTeX 数学表达式渲染,重新设计管理后台侧边栏布局,优化代码块样式,调整项目配置和依赖清单。涉及 15 个文件的变更,包含 UI 组件、样式、类型定义和配置文件。

变更概览

内聚组 / 文件(s) 变更摘要
导航系统动态化
client/src/lib/api.ts, client/src/components/navbar.tsx, client/src/components/footer.tsx
新增 NavPage 类型和 fetchNavPages() 函数(支持缓存和错误容错),取代硬编码导航链接,动态从 /api/pages 获取已发布导航页面,删除旧的延迟动画类。
后台布局重构
client/src/components/admin-layout.tsx, client/src/pages/admin/dashboard.tsx
提取 SidebarFooter 组件,桌面端侧边栏改为固定定位左侧导航栏,移动端抽屉补充 dialog 语义,添加外链按钮;标签栏支持展开/收起,侧边栏在大屏启用粘性定位。
KaTeX 数学支持
client/src/lib/markdown.ts, client/src/globals.css, client/package.json
集成 KaTeX 库进行 LaTeX 数学表达式渲染($$...$$$...$),临时保护代码块避免冲突,扩展 DOMPurify 白名单支持 KaTeX 生成的 DOM,添加样式化的数学错误提示;更新依赖管理。
代码块样式优化
client/src/globals.css
重构代码块横向滚动行为,行号改为弹性布局分离,添加代码头部粘性定位,iOS 惯性滚动支持,移动端调整边距和圆角。
后端依赖清理
server/package.json, server/src/index.ts
移除未使用的 marked 库依赖。
配置和文档
.gitignore, opencode.json, AGENTS.md, .playwright-mcp/*, .wiki-tmp
更新 gitignore 规则(支持单点环境变量、忽略临时工具目录),新增 MCP 集成配置(GitHub、Playwright、Upstash),补充中文架构文档,清理过期的测试数据。

代码审查工作量估计

🎯 3 (Moderate) | ⏱️ ~25 分钟

关键审查点

  • 类型安全:验证新增 NavPage 类型与 API 响应的契合度,fetchNavPages() 错误处理边界
  • 响应式兼容:检查 lg:stickylg:self-start 等 Tailwind 响应式类在暗色主题下的可见性,移动端边距/圆角一致性
  • KaTeX 集成:LaTeX 表达式检测正确性,代码块保护机制完整性,DOMPurify 白名单扩展是否引入安全隐患
  • 布局交互:标签展开/收起状态管理,固定侧边栏与主内容的间距对齐,移动端 dialog 语义正确性
  • 性能useMemo 在 Navbar 中的依赖数组完整性,fetchNavPages() 缓存策略合理性

可能关联的 PR

建议标签

frontend, styles, feature

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed PR 标题符合 Conventional Commits 格式 (chore: description),清晰概括了核心改动:KaTeX 数学公式支持和项目清理,与变更集高度对应。
Description check ✅ Passed PR 描述与变更集相关,列举了主要改动项(KaTeX 支持、清理孤立文件、依赖调整、gitignore 更新),与实际代码改动对应。
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch dev

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot added frontend 前端 (React/Vite) 相关变更 backend 后端 (Hono Workers) 相关变更 styles CSS/UI 样式调整 labels Apr 25, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (5)
client/src/pages/admin/dashboard.tsx (1)

340-348: 折叠阈值与高度限制不一致(可选优化)

按钮文案 +${allTags.length - 8} 暗示折叠时展示 8 个标签,但实际通过 max-h-[64px] 控制——当标签字符长度差异较大时,可见标签数可能多于或少于 8 个,按钮里的数字会与肉眼看到的不符。如果在意可以改用基于数量的截断(allTags.slice(0, 8))或把阈值抽成常量并在两处共用。

非阻塞,按需调整即可。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/src/pages/admin/dashboard.tsx` around lines 340 - 348, The collapse
behavior is inconsistent: the button text uses 8 as the threshold but the UI
limits height via max-h-[64px], which can show a different number of tags;
update the rendering to use a consistent count-based collapse (or a shared
constant). Specifically, introduce and use a TAG_COLLAPSE_COUNT (or directly use
allTags.slice(0, 8) when !tagExpanded) so the tag list rendering and the button
text both rely on the same logic (references: allTags, tagExpanded,
setTagExpanded) and remove or keep max-h styling only as a secondary visual
clamp.
client/src/components/admin-layout.tsx (1)

65-135: 避免在组件内部声明子组件

SidebarFooterSidebarContent 在每次 AdminLayout 渲染时都会被重新创建为新的函数引用,导致 React 将其视为新的组件类型,整棵子树会被卸载/重建(丢失内部状态、破坏过渡动画、增加无谓 reconciliation 开销)。建议提到模块作用域、改为 useMemo 返回 JSX,或直接内联。

♻️ 建议改为返回 JSX 的常量(最小改动)
-  const SidebarFooter = () => (
+  const sidebarFooter = (
     <div className="border-t border-border/40 p-[12px] space-y-[2px]">
       ...
     </div>
-  );
+  );
@@
-  const SidebarContent = () => (
+  const sidebarContent = (
     <div className="flex flex-col h-full">
       ...
-      <SidebarFooter />
+      {sidebarFooter}
     </div>
   );
@@
-        <SidebarContent />
+        {sidebarContent}
@@
-            <SidebarContent />
+            {sidebarContent}

注意:若改为常量 JSX,记得把依赖(locationmobileMenuOpen 等闭包变量)的更新仍可正确触发重渲染——因为它们在父组件作用域内,正常工作。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/src/components/admin-layout.tsx` around lines 65 - 135, SidebarFooter
and SidebarContent are declared as new functions inside AdminLayout on every
render causing remounts; move them out of the AdminLayout render path by
converting them into stable values: either hoist them to module scope as JSX
constants or compute them with useMemo inside AdminLayout so their references
are stable. Ensure the hoisted/ memoized JSX still reads up-to-date values
(location, setMobileMenuOpen, navGroups, mobileMenuOpen, handleLogout) by
passing those as dependencies to useMemo or by keeping only presentational
markup hoisted and wiring interactive props (onClick handlers, dynamic classes
using isActive calculation) from AdminLayout into the JSX via props/closures.
Specifically target SidebarFooter, SidebarContent and the isActive logic that
uses location and setMobileMenuOpen.
client/src/globals.css (1)

410-426: KaTeX 样式整体良好,建议为 .math-error 补上亮色主题覆盖。

.katex-displayoverflow-x: auto + -webkit-overflow-scrolling: touch 很好地处理了长公式在窄屏下的横向滚动;.katex { font-size: 1.05em } 相对于正文 15px 约 15.75px,与代码/正文排版比例协调。

唯一的小隐患:.math-error 使用 oklch(0.65 0.2 25) 的橙红色,在暗色背景上可读性 OK,但在亮色主题的 --background: oklch(0.975 0.002 250) 上对比度偏低(约 3:1 左右)。按照该文件 [data-theme="light"] 覆写其他颜色的惯例,建议补一条亮色覆盖。

As per coding guidelines: 是否有遗漏的选择器未覆盖亮色模式

🎨 建议补充
 .prose-monolith .math-error {
   color: oklch(0.65 0.2 25);
   font-size: 13px;
 }
+
+:root[data-theme="light"] .prose-monolith .math-error {
+  color: oklch(0.45 0.22 25);
+}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/src/globals.css` around lines 410 - 426, Add a light-theme override
for the .prose-monolith .math-error rule so the error text has sufficient
contrast on the light background; locate the existing .prose-monolith
.math-error selector and add a corresponding [data-theme="light"] selector (e.g.
[data-theme="light"] .prose-monolith .math-error) that sets a darker/more
saturated color (or a theme variable like --text-danger) to meet contrast
requirements against --background: oklch(0.975 0.002 250).
client/package.json (1)

31-31: 移除 @types/dompurify,依赖 dompurify 的内置类型定义。

dompurify@^3.4.0 已内置官方 TypeScript 声明文件(dist/purify.cjs.d.ts 等),@types/dompurify@^3.0.5 现为纯 stub 包,无实际用途。保留两份类型定义可能导致冗余或不一致,建议移除该 devDependency。

♻️ 建议修改
     "@tailwindcss/vite": "^4",
-    "@types/dompurify": "^3.0.5",
     "@types/katex": "^0.16.8",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/package.json` at line 31, Remove the redundant devDependency
"@types/dompurify" from package.json because dompurify@^3.4.0 already ships
TypeScript declarations; update the dependencies/devDependencies block by
deleting the "@types/dompurify": "^3.0.5" entry and run npm/yarn install to
ensure only the built-in dompurify types are used (verify no other code imports
the stub package name).
client/src/lib/markdown.ts (1)

309-336: 考虑迁移至 marked-katex-extension,提升数学公式处理的稳健性。

当前 renderMath 通过字符串替换在 marked.parse 之前注入 KaTeX HTML,存在以下风险:

  • 代码保护不完整:仅覆盖 ``` 和 ` ` 语法,漏掉缩进代码块(4 空格/Tab)和 ~~~ 围栏,可能错误地处理其中的 $ 符号。
  • 占位符恢复脆弱:依赖 marked 对零字节的保留,这是隐式依赖,未来版本变更可能导致失效。
  • 块公式正则无边界:/$$([\s\S]+?)$$/ 未锚定行首行尾,可能跨越段落或列表边界。

marked-katex-extension (v5.1.8,兼容 marked v17.0.6) 将 $ / $$ 作为 marked 的 lexer token,由 marked 词法层统一处理冲突,在 DOMPurify 净化前生成纯净的 KaTeX HTML,无需担心代码块保护或占位符问题。现有的 DOMPurify 配置(含 iframe/video 白名单)与该方案完全兼容。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/src/lib/markdown.ts` around lines 309 - 336, The current renderMath
function (and its preserved/ph placeholder logic using preserved and ph, plus
the regex replacements for $$...$$ and $...$) is fragile and should be replaced
by integrating the marked-katex-extension: install marked-katex-extension,
import and register its KaTeX extension with marked (instead of doing regex
replacements in renderMath), remove the placeholder handling (preserved, ph) and
the manual katex.renderToString calls, and ensure the extension is applied
before DOMPurify sanitization so KaTeX HTML is produced by the lexer/parser
rather than by brittle string surgery; keep existing DOMPurify settings
unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@AGENTS.md`:
- Around line 59-63: The AGENTS.md "CI 与安全" section contains hard-coded secrets
("monolith2026" and explicit "GitHub PAT" mention); remove any plaintext
credentials from that section (delete the "monolith2026" literal and any PAT
references), rotate the exposed admin password immediately, and replace
doc-stored secrets with instructions to use environment variables or a secrets
manager (e.g., reference using .dev.vars or a proper secret store) in the "CI
与安全" text; then purge the secret from history using git filter-repo (or
equivalent) and update repository guidance to store secrets in ignored files
(e.g., .dev.vars) or secret management, plus ensure .gitignore excludes those
files.

In `@client/src/components/admin-layout.tsx`:
- Around line 149-184: The button that toggles mobile menu (onClick={() =>
setMobileMenuOpen(true)}) uses aria-controls="admin-mobile-navigation" but the
aside dialog (<aside role="dialog"> / SidebarContent) lacks that id and
aria-modal; add id="admin-mobile-navigation" to that aside and include
aria-modal="true" so the button correctly references the dialog and the dialog
exposes modal semantics to assistive tech.

In `@client/src/globals.css`:
- Around line 917-921: The mobile rule currently sets border-radius: 0 only for
:root[data-theme="light"] .prose-monolith .code-block-wrapper, leaving the
default/dark theme with 8px corners; make the behavior consistent by moving or
duplicating the mobile rule so that .prose-monolith .code-block-wrapper gets
border-radius: 0 for both themes (either remove the [data-theme="light"]
qualifier or add a matching selector for the default/dark theme such as
:root:not([data-theme="light"]) .prose-monolith .code-block-wrapper) and add a
short comment explaining the intentional cross-theme mobile styling change.

In `@client/src/lib/markdown.ts`:
- Around line 324-331: The inline math regex used in the md.replace call
(currently /(?<!\\)\$([^$\n]+?)\$/g) is too permissive and mis-parses currency
like " $100 "; update the pattern to enforce no leading/trailing spaces and
prevent a closing $ followed by a digit: replace the regex in the md.replace
invocation with /(?<!\\)\$(?!\s)([^$\n]+?)(?<!\s)\$(?!\d)/g while keeping the
existing katex.renderToString(tex.trim(), { displayMode: false, throwOnError:
false }) and the catch branch that returns `<code
class="math-error">${escapeHtml(tex)}</code>` unchanged.

In `@opencode.json`:
- Around line 4-11: The opencode.json GitHub MCP config uses Authorization:
"Bearer {env:GITHUB_TOKEN}" but the GITHUB_TOKEN env var isn't documented or
provisioned; add documentation and example files: create a .env.example showing
GITHUB_TOKEN, add a .dev.vars (or update existing local env guidance) with
instructions for local development, and update deployment/CI config (e.g.,
wrangler.toml and CI secrets) to pass GITHUB_TOKEN into the runtime so the
"github" -> "headers" -> "Authorization" entry works; reference the "github"
section and the Authorization header in opencode.json when updating docs and
deployment manifests.

---

Nitpick comments:
In `@client/package.json`:
- Line 31: Remove the redundant devDependency "@types/dompurify" from
package.json because dompurify@^3.4.0 already ships TypeScript declarations;
update the dependencies/devDependencies block by deleting the
"@types/dompurify": "^3.0.5" entry and run npm/yarn install to ensure only the
built-in dompurify types are used (verify no other code imports the stub package
name).

In `@client/src/components/admin-layout.tsx`:
- Around line 65-135: SidebarFooter and SidebarContent are declared as new
functions inside AdminLayout on every render causing remounts; move them out of
the AdminLayout render path by converting them into stable values: either hoist
them to module scope as JSX constants or compute them with useMemo inside
AdminLayout so their references are stable. Ensure the hoisted/ memoized JSX
still reads up-to-date values (location, setMobileMenuOpen, navGroups,
mobileMenuOpen, handleLogout) by passing those as dependencies to useMemo or by
keeping only presentational markup hoisted and wiring interactive props (onClick
handlers, dynamic classes using isActive calculation) from AdminLayout into the
JSX via props/closures. Specifically target SidebarFooter, SidebarContent and
the isActive logic that uses location and setMobileMenuOpen.

In `@client/src/globals.css`:
- Around line 410-426: Add a light-theme override for the .prose-monolith
.math-error rule so the error text has sufficient contrast on the light
background; locate the existing .prose-monolith .math-error selector and add a
corresponding [data-theme="light"] selector (e.g. [data-theme="light"]
.prose-monolith .math-error) that sets a darker/more saturated color (or a theme
variable like --text-danger) to meet contrast requirements against --background:
oklch(0.975 0.002 250).

In `@client/src/lib/markdown.ts`:
- Around line 309-336: The current renderMath function (and its preserved/ph
placeholder logic using preserved and ph, plus the regex replacements for
$$...$$ and $...$) is fragile and should be replaced by integrating the
marked-katex-extension: install marked-katex-extension, import and register its
KaTeX extension with marked (instead of doing regex replacements in renderMath),
remove the placeholder handling (preserved, ph) and the manual
katex.renderToString calls, and ensure the extension is applied before DOMPurify
sanitization so KaTeX HTML is produced by the lexer/parser rather than by
brittle string surgery; keep existing DOMPurify settings unchanged.

In `@client/src/pages/admin/dashboard.tsx`:
- Around line 340-348: The collapse behavior is inconsistent: the button text
uses 8 as the threshold but the UI limits height via max-h-[64px], which can
show a different number of tags; update the rendering to use a consistent
count-based collapse (or a shared constant). Specifically, introduce and use a
TAG_COLLAPSE_COUNT (or directly use allTags.slice(0, 8) when !tagExpanded) so
the tag list rendering and the button text both rely on the same logic
(references: allTags, tagExpanded, setTagExpanded) and remove or keep max-h
styling only as a secondary visual clamp.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3256d097-039c-4bb5-b3e5-ea22aff9e7e8

📥 Commits

Reviewing files that changed from the base of the PR and between f4ddfa3 and b673444.

⛔ Files ignored due to path filters (4)
  • .kilo/package-lock.json is excluded by !**/package-lock.json, !**/package-lock.json
  • .playwright-mcp/console-2026-04-19T04-35-34-885Z.log is excluded by !**/*.log
  • .playwright-mcp/page-2026-04-19T04-35-58-544Z.png is excluded by !**/*.png
  • package-lock.json is excluded by !**/package-lock.json, !**/package-lock.json
📒 Files selected for processing (16)
  • .gitignore
  • .playwright-mcp/page-2026-04-19T04-35-40-096Z.yml
  • .playwright-mcp/page-2026-04-19T04-35-49-532Z.yml
  • .wiki-tmp
  • AGENTS.md
  • client/package.json
  • client/src/components/admin-layout.tsx
  • client/src/components/footer.tsx
  • client/src/components/navbar.tsx
  • client/src/globals.css
  • client/src/lib/api.ts
  • client/src/lib/markdown.ts
  • client/src/pages/admin/dashboard.tsx
  • opencode.json
  • server/package.json
  • server/src/index.ts
💤 Files with no reviewable changes (5)
  • .playwright-mcp/page-2026-04-19T04-35-49-532Z.yml
  • server/package.json
  • .playwright-mcp/page-2026-04-19T04-35-40-096Z.yml
  • .wiki-tmp
  • server/src/index.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (5)
client/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

DOMPurify must sanitize Markdown rendered output with whitelist allowing iframe/video embeds

Files:

  • client/src/lib/api.ts
  • client/src/pages/admin/dashboard.tsx
  • client/src/lib/markdown.ts
  • client/src/components/navbar.tsx
  • client/src/components/footer.tsx
  • client/src/components/admin-layout.tsx
client/src/pages/**

⚙️ CodeRabbit configuration file

client/src/pages/**: 页面级组件。审查时请关注: 1. 数据加载和错误处理是否完善 2. SEO 相关(页面标题、meta 标签) 3. 导航和路由是否正确

Files:

  • client/src/pages/admin/dashboard.tsx
client/src/components/**

⚙️ CodeRabbit configuration file

client/src/components/**: 这是 React 前端组件目录。审查时请关注: 1. 是否同时兼容暗色和亮色主题(检查 CSS 变量和 data-theme) 2. 响应式布局是否完整(移动端/平板/桌面端) 3. 无障碍访问(aria 标签、键盘导航) 4. 组件是否保持单一职责

Files:

  • client/src/components/navbar.tsx
  • client/src/components/footer.tsx
  • client/src/components/admin-layout.tsx
.gitignore

📄 CodeRabbit inference engine (AGENTS.md)

package-lock.json must never be added to .gitignore

Files:

  • .gitignore
client/src/globals.css

⚙️ CodeRabbit configuration file

client/src/globals.css: 全局样式和 CSS 变量系统。审查时请关注: 1. [data-theme="light"] 和默认暗色主题的变量是否配对 2. OKLCH 色值的明度/色度是否合理 3. 是否有遗漏的选择器未覆盖亮色模式

Files:

  • client/src/globals.css
🧠 Learnings (6)
📓 Common learnings
Learnt from: CR
Repo: one-ea/Monolith

Timestamp: 2026-04-25T02:24:16.009Z
Learning: Use `npm run deploy:cloudflare` for one-command deployment, strictly forbidden to manually run `wrangler pages deploy`
Learnt from: CR
Repo: one-ea/Monolith

Timestamp: 2026-04-25T02:24:16.009Z
Learning: Must deploy `dist` directory from `client/` directory, otherwise Pages Functions will be omitted
Learnt from: CR
Repo: one-ea/Monolith

Timestamp: 2026-04-25T02:24:16.009Z
Learning: CI 'Sync Worker secrets' step must inject ADMIN_PASSWORD / JWT_SECRET via `wrangler secret put`
Learnt from: CR
Repo: one-ea/Monolith

Timestamp: 2026-04-25T02:24:16.009Z
Learning: When D1 migration markers are out of sync, manually `INSERT INTO d1_migrations` to resolve
Learnt from: CR
Repo: one-ea/Monolith

Timestamp: 2026-04-25T02:24:16.009Z
Learning: Use deployment unique URLs when validating Cloudflare CDN behavior due to short-lived caching
Learnt from: CR
Repo: one-ea/Monolith

Timestamp: 2026-04-25T02:24:16.009Z
Learning: Production branch is `main` (auto-deployed by Cloudflare Pages); development happens on `dev` branch; strictly forbidden to push directly to main
Learnt from: CR
Repo: one-ea/Monolith

Timestamp: 2026-04-25T02:24:16.009Z
Learning: Main branch requires 1 approval + linear history + status checks before merging
Learnt from: CR
Repo: one-ea/Monolith

Timestamp: 2026-04-25T02:24:16.009Z
Learning: Preferred workflow: dev development → commit → push → PR → squash merge to main → deploy
📚 Learning: 2026-04-21T14:30:39.825Z
Learnt from: CR
Repo: one-ea/Monolith PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-21T14:30:39.825Z
Learning: Applies to client/src/**/*.{ts,tsx} : Use DOMPurify to sanitize Markdown rendered output with whitelist allowing iframe/video embeds

Applied to files:

  • client/src/lib/markdown.ts
📚 Learning: 2026-04-21T14:30:39.825Z
Learnt from: CR
Repo: one-ea/Monolith PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-21T14:30:39.825Z
Learning: Applies to client/functions/tsconfig.json : Pages Functions `tsconfig.json` must independently import `cloudflare/workers-types` to avoid DOM type conflicts with the main project

Applied to files:

  • client/package.json
📚 Learning: 2026-04-21T14:30:39.825Z
Learnt from: CR
Repo: one-ea/Monolith PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-21T14:30:39.825Z
Learning: Frontend uses Vite 6, React 19, Tailwind CSS v4, shadcn/ui, and wouter for routing

Applied to files:

  • client/package.json
  • client/src/components/navbar.tsx
  • client/src/components/footer.tsx
📚 Learning: 2026-04-21T14:30:39.825Z
Learnt from: CR
Repo: one-ea/Monolith PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-21T14:30:39.825Z
Learning: Applies to .gitignore : `package-lock.json` must never be added to `.gitignore`

Applied to files:

  • .gitignore
📚 Learning: 2026-04-21T14:30:39.825Z
Learnt from: CR
Repo: one-ea/Monolith PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-21T14:30:39.825Z
Learning: Applies to client/src/**/*.{css,tsx} : Use OKLCH color space for dual theme system with dark theme (Slate & Cyan) and light theme variants

Applied to files:

  • client/src/globals.css
🪛 LanguageTool
AGENTS.md

[grammar] ~41-~41: Ensure spelling is correct
Context: ....gitignore - CI "Sync Worker secrets" 步骤通过 wrangler secret put 注入 ADMIN_PASSWORD...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🪛 markdownlint-cli2 (0.22.1)
AGENTS.md

[warning] 7-7: Spaces inside emphasis markers

(MD037, no-space-in-emphasis)

🔇 Additional comments (11)
client/src/lib/api.ts (1)

115-130: LGTM!

复用 fetchJsonWithCache + 失败回退空数组的写法稳健,类型定义清晰。sortOrder 字段虽然定义但前端未参与排序,假定服务端已按该字段排好序,这一约定建议在后端接口处保持一致即可。

client/src/components/navbar.tsx (1)

22-35: LGTM!

动态导航链接的派生方式(fixedStart + 动态页面 + fixedEnd)清晰,useMemo 依赖正确。顺带移除基于 index 的 delay-${i+1} 也合理——Tailwind v4 的 JIT 无法扫描到这种字符串拼接的类名,原本的延迟动画其实并不会生效。

Also applies to: 74-89

client/src/components/footer.tsx (1)

18-39: LGTM!

fetchNavPages() 内部已对失败做了空数组兜底,这里直接 .then(setNavPages) 不会引发未捕获的 Promise,简洁可靠。flex-wrap + gap-x/gap-y 对窄屏友好,主题 token 使用一致。

opencode.json (1)

23-34: 指令文件路径与 .gitignore 冲突。

所有指令文件位于 .agents/memory_bank/ 下,但 .gitignore 第 37 行将整个 .agents/ 目录加入忽略列表。这将导致这些指令文件无法被 Git 跟踪,OpenCode MCP 无法读取项目规则。

需要调整 .gitignore 规则以保留指令文件,或将指令文件移至可跟踪的目录。

.gitignore (2)

48-57: 优秀的文档实践!

注释部分明确列出了必须跟踪的关键文件(如 package-lock.jsonclient/functions/、部署脚本等),并说明了原因。这符合编码规范,且能有效避免团队成员误操作。

根据编码规范:package-lock.json 必须被跟踪,当前配置正确遵守了该规则。


37-37: .gitignore 设置正确,无需修改。

.agents/ 目录设计用于存储本地 AI 工具的敏感信息(密码、PAT、个人偏好等),因此被正确地加入忽略列表。opencode.jsonAGENTS.md 中的引用仅作为本地开发配置,而非 Git 跟踪的依赖。此外,package-lock.json 已正确地被保护,不在忽略列表中,符合编码指南要求。

AGENTS.md (2)

1-10: 项目概览清晰准确。

技术栈描述与实际使用的 React 19、Tailwind CSS v4 等版本一致,架构说明简洁明了。


37-42: 部署规则完整覆盖关键要点。

文档准确记录了项目的部署铁律,与学习库中的规则完全一致:

  • 使用 npm run deploy:cloudflare 一键部署
  • client/ 目录部署以保留 Pages Functions
  • package-lock.json 必须跟踪
  • CI 通过 wrangler secret put 注入密钥

根据学习库:必须使用一键部署命令,严禁手动运行 wrangler pages deploy

client/package.json (1)

19-19: 依赖调整整体合理。

  • katex@^0.16.45@types/katex@^0.16.8 对应,当前 npm 上 katex 最新即 0.16.45,类型包最新为 0.16.8,版本匹配。
  • shadcn 作为 CLI 工具(client/src/globals.css 通过 @import "shadcn/tailwind.css" 在构建期使用),下放到 devDependencies 符合其用途,生产 bundle 不会被拉入。

Also applies to: 32-32, 40-40

client/src/lib/markdown.ts (1)

348-366: KaTeX/MathML 白名单扩展看起来合理。

保留了原有 iframe/video/source/figure/figcaption 以满足 B 站/YouTube 嵌入与懒加载需求,MathML 标签(math/mrow/mi/mo/mn/msup/...)与 KaTeX 常用属性(mathvariant/displaystyle/columnalign/...)均为渲染输出所需,且未放开危险属性(如 hrefxlink:href、事件处理器)。符合 client/src/**/*.{ts,tsx} 的 DOMPurify 白名单放行 iframe/video 的约束。

As per coding guidelines: DOMPurify must sanitize Markdown rendered output with whitelist allowing iframe/video embeds.

client/src/globals.css (1)

598-612: 代码块横向滚动重构方案正确,z-index 层级也合理。

.code-header / .code-title-barposition: sticky; left: 0; z-index: 5,配合 .line-numberposition: sticky; left: 0; z-index: 10,再把 .code-line 改为 display: flex + .line-content { flex: 1; min-width: 0; white-space: pre },可以让内容撑开 wrapper、横向滚动时行号与顶栏始终可见,逻辑自洽。移动端对 .line-number 宽度(22px)与 .has-line-numbers pre 左 padding(8px)同步缩减也匹配得当。

Also applies to: 684-687, 719-757

Comment thread AGENTS.md
Comment on lines +59 to +63
## CI 与安全
- 仓库:`https://github.com/one-ea/Monolith`
- GitHub PAT:已配置在 system_config.md
- 后台密码:`monolith2026`
- 分支保护:main 需要 1 人审批 + 线性历史 + 状态检查 No newline at end of file

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🚨 严重安全漏洞:文档中硬编码了管理员密码。

第 62 行直接暴露了后台管理密码 monolith2026。此文件已被 Git 跟踪,密码将永久保留在仓库历史中,即使后续删除也无法彻底清除。

安全风险:

  • 任何能访问仓库的人都能看到管理员密码
  • 即使仓库是私有的,这也违反了安全最佳实践
  • 第 61 行提到的 GitHub PAT 也不应在文档中提及具体位置

必须立即:

  1. 从文档中删除所有敏感凭据(密码、PAT、token 等)
  2. 更改后台管理密码
  3. 使用环境变量或密钥管理系统存储凭据
  4. 考虑使用 git filter-repo 从 Git 历史中清除已提交的密码
🔒 建议的修复方案
 ## CI 与安全
 - 仓库:`https://github.com/one-ea/Monolith`
-- GitHub PAT:已配置在 system_config.md
-- 后台密码:`monolith2026`
+- GitHub PAT:通过环境变量 `GITHUB_TOKEN` 配置
+- 后台密码:通过环境变量 `ADMIN_PASSWORD` 配置(参考 `.env.example`)
 - 分支保护:main 需要 1 人审批 + 线性历史 + 状态检查

同时,在部署后立即更改管理员密码,并将新密码存储在 .dev.vars(已被 .gitignore 忽略)中。

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
## CI 与安全
- 仓库:`https://github.com/one-ea/Monolith`
- GitHub PAT:已配置在 system_config.md
- 后台密码:`monolith2026`
- 分支保护:main 需要 1 人审批 + 线性历史 + 状态检查
## CI 与安全
- 仓库:`https://github.com/one-ea/Monolith`
- GitHub PAT:通过环境变量 `GITHUB_TOKEN` 配置
- 后台密码:通过环境变量 `ADMIN_PASSWORD` 配置(参考 `.env.example`
- 分支保护:main 需要 1 人审批 + 线性历史 + 状态检查
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@AGENTS.md` around lines 59 - 63, The AGENTS.md "CI 与安全" section contains
hard-coded secrets ("monolith2026" and explicit "GitHub PAT" mention); remove
any plaintext credentials from that section (delete the "monolith2026" literal
and any PAT references), rotate the exposed admin password immediately, and
replace doc-stored secrets with instructions to use environment variables or a
secrets manager (e.g., reference using .dev.vars or a proper secret store) in
the "CI 与安全" text; then purge the secret from history using git filter-repo (or
equivalent) and update repository guidance to store secrets in ignored files
(e.g., .dev.vars) or secret management, plus ensure .gitignore excludes those
files.

Comment on lines +149 to 184
<aside
role="dialog"
aria-label="导航菜单"
className="relative flex flex-col w-[260px] max-w-[80vw] h-full bg-background shadow-2xl animate-in slide-in-from-left"
>
<SidebarContent />
</aside>
</div>
)}

{/* Main Content */}
<main className="flex-1 flex flex-col min-w-0">
{/* Mobile Header */}
<header className="md:hidden sticky top-0 z-40 flex items-center justify-between px-4 h-14 border-b bg-background/80 backdrop-blur-md">
<div className="flex items-center gap-2 font-semibold">
<div className="w-6 h-6 rounded bg-foreground text-background flex items-center justify-center text-xs font-bold">M</div>
<span>Admin</span>
<main className="md:ml-[240px] min-h-screen overflow-y-auto">
<header className="md:hidden sticky top-0 z-40 flex items-center justify-between px-[16px] h-[52px] border-b border-border/40 bg-background/80 backdrop-blur-md shrink-0">
<div className="flex items-center gap-[8px] font-semibold text-[14px]">
<div className="w-[24px] h-[24px] rounded bg-foreground text-background flex items-center justify-center text-[11px] font-bold">M</div>
<span>Admin</span>
</div>
<div className="flex items-center gap-2">
<div className="flex items-center gap-[4px]">
<ThemeToggle />
<a
href="/"
target="_blank"
rel="noopener noreferrer"
className="p-[6px] text-muted-foreground/50 hover:text-foreground transition-colors"
aria-label="查看站点"
>
<ExternalLink className="w-[16px] h-[16px]" />
</a>
<button
onClick={() => setMobileMenuOpen(true)}
className="p-2 -mr-2 text-muted-foreground hover:text-foreground"
aria-label="打开后台导航菜单"
aria-expanded={mobileMenuOpen}
className="p-[6px] text-muted-foreground/50 hover:text-foreground transition-colors"
aria-label="打开导航菜单"
aria-expanded={mobileMenuOpen}
aria-controls="admin-mobile-navigation"
>
<Menu className="w-5 h-5" />
<Menu className="w-[18px] h-[18px]" />
</button>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

aria-controls 指向不存在的元素

第 181 行的 aria-controls="admin-mobile-navigation" 引用了一个 id,但抽屉 <aside role="dialog">(第 149-153 行)并没有设置该 id,屏幕阅读器无法通过该属性建立按钮与受控区域的关联。同时建议为 dialog 补充 aria-modal="true" 以明确模态语义。

🛡️ 建议修复
           <aside
             role="dialog"
+            id="admin-mobile-navigation"
+            aria-modal="true"
             aria-label="导航菜单"
             className="relative flex flex-col w-[260px] max-w-[80vw] h-full bg-background shadow-2xl animate-in slide-in-from-left"
           >
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<aside
role="dialog"
aria-label="导航菜单"
className="relative flex flex-col w-[260px] max-w-[80vw] h-full bg-background shadow-2xl animate-in slide-in-from-left"
>
<SidebarContent />
</aside>
</div>
)}
{/* Main Content */}
<main className="flex-1 flex flex-col min-w-0">
{/* Mobile Header */}
<header className="md:hidden sticky top-0 z-40 flex items-center justify-between px-4 h-14 border-b bg-background/80 backdrop-blur-md">
<div className="flex items-center gap-2 font-semibold">
<div className="w-6 h-6 rounded bg-foreground text-background flex items-center justify-center text-xs font-bold">M</div>
<span>Admin</span>
<main className="md:ml-[240px] min-h-screen overflow-y-auto">
<header className="md:hidden sticky top-0 z-40 flex items-center justify-between px-[16px] h-[52px] border-b border-border/40 bg-background/80 backdrop-blur-md shrink-0">
<div className="flex items-center gap-[8px] font-semibold text-[14px]">
<div className="w-[24px] h-[24px] rounded bg-foreground text-background flex items-center justify-center text-[11px] font-bold">M</div>
<span>Admin</span>
</div>
<div className="flex items-center gap-2">
<div className="flex items-center gap-[4px]">
<ThemeToggle />
<a
href="/"
target="_blank"
rel="noopener noreferrer"
className="p-[6px] text-muted-foreground/50 hover:text-foreground transition-colors"
aria-label="查看站点"
>
<ExternalLink className="w-[16px] h-[16px]" />
</a>
<button
onClick={() => setMobileMenuOpen(true)}
className="p-2 -mr-2 text-muted-foreground hover:text-foreground"
aria-label="打开后台导航菜单"
aria-expanded={mobileMenuOpen}
className="p-[6px] text-muted-foreground/50 hover:text-foreground transition-colors"
aria-label="打开导航菜单"
aria-expanded={mobileMenuOpen}
aria-controls="admin-mobile-navigation"
>
<Menu className="w-5 h-5" />
<Menu className="w-[18px] h-[18px]" />
</button>
<aside
role="dialog"
id="admin-mobile-navigation"
aria-modal="true"
aria-label="导航菜单"
className="relative flex flex-col w-[260px] max-w-[80vw] h-full bg-background shadow-2xl animate-in slide-in-from-left"
>
<SidebarContent />
</aside>
</div>
)}
<main className="md:ml-[240px] min-h-screen overflow-y-auto">
<header className="md:hidden sticky top-0 z-40 flex items-center justify-between px-[16px] h-[52px] border-b border-border/40 bg-background/80 backdrop-blur-md shrink-0">
<div className="flex items-center gap-[8px] font-semibold text-[14px]">
<div className="w-[24px] h-[24px] rounded bg-foreground text-background flex items-center justify-center text-[11px] font-bold">M</div>
<span>Admin</span>
</div>
<div className="flex items-center gap-[4px]">
<ThemeToggle />
<a
href="/"
target="_blank"
rel="noopener noreferrer"
className="p-[6px] text-muted-foreground/50 hover:text-foreground transition-colors"
aria-label="查看站点"
>
<ExternalLink className="w-[16px] h-[16px]" />
</a>
<button
onClick={() => setMobileMenuOpen(true)}
className="p-[6px] text-muted-foreground/50 hover:text-foreground transition-colors"
aria-label="打开导航菜单"
aria-expanded={mobileMenuOpen}
aria-controls="admin-mobile-navigation"
>
<Menu className="w-[18px] h-[18px]" />
</button>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/src/components/admin-layout.tsx` around lines 149 - 184, The button
that toggles mobile menu (onClick={() => setMobileMenuOpen(true)}) uses
aria-controls="admin-mobile-navigation" but the aside dialog (<aside
role="dialog"> / SidebarContent) lacks that id and aria-modal; add
id="admin-mobile-navigation" to that aside and include aria-modal="true" so the
button correctly references the dialog and the dialog exposes modal semantics to
assistive tech.

Comment thread client/src/globals.css
Comment on lines +917 to +921
@media (max-width: 768px) {
:root[data-theme="light"] .prose-monolith .code-block-wrapper {
border-radius: 0;
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

暗/亮主题移动端圆角不对称。

当前移动端 border-radius: 0 只写在 [data-theme="light"] 分支下(line 918),而默认暗色主题下 .prose-monolith .code-block-wrapper 在小屏下仍保持 8px 圆角。两个主题在同一断点下的视觉表现不一致,如果这是有意的平铺移动体验,应两者都设为 0;如果仅希望亮色下去掉圆角也需在注释中说明理由。

As per coding guidelines: [data-theme="light"] 和默认暗色主题的变量是否配对

🎨 建议方案(两主题一致去圆角)
-@media (max-width: 768px) {
-  :root[data-theme="light"] .prose-monolith .code-block-wrapper {
-    border-radius: 0;
-  }
-}
+@media (max-width: 768px) {
+  .prose-monolith .code-block-wrapper {
+    border-radius: 0;
+  }
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@media (max-width: 768px) {
:root[data-theme="light"] .prose-monolith .code-block-wrapper {
border-radius: 0;
}
}
`@media` (max-width: 768px) {
.prose-monolith .code-block-wrapper {
border-radius: 0;
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/src/globals.css` around lines 917 - 921, The mobile rule currently
sets border-radius: 0 only for :root[data-theme="light"] .prose-monolith
.code-block-wrapper, leaving the default/dark theme with 8px corners; make the
behavior consistent by moving or duplicating the mobile rule so that
.prose-monolith .code-block-wrapper gets border-radius: 0 for both themes
(either remove the [data-theme="light"] qualifier or add a matching selector for
the default/dark theme such as :root:not([data-theme="light"]) .prose-monolith
.code-block-wrapper) and add a short comment explaining the intentional
cross-theme mobile styling change.

Comment on lines +324 to +331
// u884cu5185u516cu5f0fuff1a$...$uff08u907fu514du5339u914du8d27u5e01u7b26u53f7u5982 $100uff09
md = md.replace(/(?<!\\)\$([^$\n]+?)\$/g, (_, tex) => {
try {
return katex.renderToString(tex.trim(), { displayMode: false, throwOnError: false });
} catch {
return `<code class="math-error">${escapeHtml(tex)}</code>`;
}
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

What is the standard regex heuristic used by Pandoc or markdown-it-texmath to distinguish inline $...$math from currency like$100 and $200?

💡 Result:

The standard regex heuristic used by Pandoc (with the tex_math_dollars extension enabled) to distinguish inline $...$ math from currency like $100 and $200 is as follows: For inline math $...$: - The opening $ must be immediately followed by a non-space character. - The closing $ must be immediately preceded by a non-space character and must not be immediately followed by a digit. This prevents sequences like $20,000 and $30,000 from being parsed as math, while allowing legitimate math like $x+y$, $\alpha$, and $100/2$. Pandoc's Markdown reader is parser-based (not purely regex), but implements these exact rules as described in the official documentation. The rules are enforced during parsing of inline content. markdown-it-texmath (dollars mode) uses a similar heuristic via regex: /$((?:[^\r\n\t\f\v \\])|(?:\S.*?[^\r\n\t\f\v \\]))$/gy (simplified: requires non-space and non-backslash immediately adjacent to delimiters), which achieves comparable behavior by avoiding spaces next to $ and handling escapes, though it does not explicitly check for a following digit on the closing $.

Citations:


🏁 Script executed:

cat -n client/src/lib/markdown.ts | sed -n '305,375p'

Repository: one-ea/Monolith

Length of output: 3584


行内公式正则未遵循标准防护规则,注释与实现不符。

第 325 行的正则 /(?<!\\)\$([^$\n]+?)\$/g 只检查开头 $ 前不是反斜杠,但无法避免货币符号。对于 价格 $100 和 $200 的对比,非贪婪匹配会将 $100 和 $ 作为公式分界,捕获 100 和 交给 KaTeX,结果错误且吞掉后续 $200 前的 $

标准做法(Pandoc、markdown-it-texmath)要求:

  • $ 后紧跟非空白字符
  • $ 前为非空白字符
  • $ 后不是数字

建议调整为:/(?<!\\)\$(?!\s)([^$\n]+?)(?<!\s)\$(?!\d)/g

DOMPurify 的白名单配置已正确支持 iframe/video 嵌入和 MathML/KaTeX 标签(包括 span、math、mrow 等必要元素),符合防 XSS 要求。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/src/lib/markdown.ts` around lines 324 - 331, The inline math regex
used in the md.replace call (currently /(?<!\\)\$([^$\n]+?)\$/g) is too
permissive and mis-parses currency like " $100 "; update the pattern to enforce
no leading/trailing spaces and prevent a closing $ followed by a digit: replace
the regex in the md.replace invocation with
/(?<!\\)\$(?!\s)([^$\n]+?)(?<!\s)\$(?!\d)/g while keeping the existing
katex.renderToString(tex.trim(), { displayMode: false, throwOnError: false })
and the catch branch that returns `<code
class="math-error">${escapeHtml(tex)}</code>` unchanged.

Comment thread opencode.json
Comment on lines +4 to +11
"github": {
"type": "remote",
"url": "https://api.githubcopilot.com/mcp/",
"headers": {
"Authorization": "Bearer {env:GITHUB_TOKEN}"
},
"enabled": true
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# 检查 GITHUB_TOKEN 在仓库中的配置情况

echo "=== 检查工作流中的 GITHUB_TOKEN 使用 ==="
rg -n 'GITHUB_TOKEN' .github/workflows/

echo -e "\n=== 检查 wrangler.toml 中的环境变量 ==="
rg -n 'GITHUB_TOKEN' wrangler.toml 2>/dev/null || echo "wrangler.toml 中未找到"

echo -e "\n=== 检查 .env.example 中的示例配置 ==="
rg -n 'GITHUB_TOKEN' .env.example 2>/dev/null || echo ".env.example 中未找到"

Repository: one-ea/Monolith

Length of output: 573


🏁 Script executed:

#!/bin/bash
# 检查所有可能的环境变量配置文件

echo "=== 查找 .dev.vars 文件 ==="
find . -name ".dev.vars" -o -name ".dev.vars*" 2>/dev/null | head -20

echo -e "\n=== 查找 opencode.json 并显示内容 ==="
find . -name "opencode.json" 2>/dev/null | head -5
cat opencode.json 2>/dev/null | head -40

echo -e "\n=== 查找所有 .env 相关文件 ==="
find . -name ".env*" -type f 2>/dev/null | grep -v node_modules | head -20

echo -e "\n=== 检查 wrangler.toml 配置 ==="
cat wrangler.toml 2>/dev/null | head -50

echo -e "\n=== 查找 GITHUB_TOKEN 的其他出现位置 ==="
rg 'GITHUB_TOKEN|GITHUB_.*TOKEN' -g '!node_modules' -l 2>/dev/null | head -20

Repository: one-ea/Monolith

Length of output: 1288


环境变量 GITHUB_TOKEN 缺少配置文档和部署设置。

opencode.json 中 GitHub MCP 端点使用 {env:GITHUB_TOKEN} 进行认证,但该环境变量未在以下位置配置或文档化:

  • .env.example 或文档说明所需的环境变量
  • .dev.vars 文件用于本地开发环境
  • wrangler.toml 未配置此变量
  • 仅在 .github/workflows/dependabot-auto-merge.yml 中被 GitHub Actions 使用

建议:

  1. 添加 .env.example 或 README 文档说明 GITHUB_TOKEN 的配置
  2. 确保部署流程(wrangler 配置或 CI/CD)能正确传递此环境变量
  3. 为本地开发补充 .dev.vars 配置指南
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@opencode.json` around lines 4 - 11, The opencode.json GitHub MCP config uses
Authorization: "Bearer {env:GITHUB_TOKEN}" but the GITHUB_TOKEN env var isn't
documented or provisioned; add documentation and example files: create a
.env.example showing GITHUB_TOKEN, add a .dev.vars (or update existing local env
guidance) with instructions for local development, and update deployment/CI
config (e.g., wrangler.toml and CI secrets) to pass GITHUB_TOKEN into the
runtime so the "github" -> "headers" -> "Authorization" entry works; reference
the "github" section and the Authorization header in opencode.json when updating
docs and deployment manifests.

one-ea added 2 commits April 25, 2026 02:36
Critical/High:
- Sanitize custom_header/footer through DOMPurify before injection,
  forbid inline scripts, only allow external script src (fixes #1)
- Add security headers: X-Content-Type-Options, X-Frame-Options,
  Referrer-Policy, Permissions-Policy, HSTS (fixes #5)
- Remove authorEmail from public comment API, use DiceBear avatars
  based on nickname instead of Gravatar hash (fixes #2, #14)
- Add login rate limiting: 5 attempts per 15 min per IP (fixes #3)
- Reflect request Origin in CORS instead of wildcard (fixes #4)
- Add SSRF protection for WebDAV backup and image localization:
  only allow https://, block private/internal IPs (fixes #6, #13)
- Filter javascript: URIs in markdown link renderer (fixes #7)

Medium:
- Replace hardcoded reaction salt with REACTION_SALT env var (fixes #9)
- Add .env.* to .gitignore, remove .env.production from tracking (fixes #10)
- Disable source maps in production build (fixes #11)
- Remove infrastructure details from health endpoint (fixes #15)
- feat: KaTeX math formula rendering ($...$ inline, $$...$$ block)
- fix: protect code blocks from KaTeX parsing
- chore: remove orphaned .wiki-tmp submodule
- chore: remove unused marked import/dep from server
- chore: move @types/dompurify, shadcn to devDependencies
- chore: add .playwright-mcp/, .wiki-tmp/ to .gitignore
- chore: delete stray test artifacts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend 后端 (Hono Workers) 相关变更 frontend 前端 (React/Vite) 相关变更 styles CSS/UI 样式调整

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant