Skip to content

chore: sync admin hardening and code scanning fixes into main - #21

Merged
one-ea merged 1 commit into
mainfrom
dev
Apr 15, 2026
Merged

chore: sync admin hardening and code scanning fixes into main#21
one-ea merged 1 commit into
mainfrom
dev

Conversation

@one-ea

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

Copy link
Copy Markdown
Owner

Summary

  • sync the latest admin module hardening from dev into main, including deployment guardrails, Pages Functions API_BASE fixes, and improved error handling across settings, analytics, comments, media, and pages
  • carry over importer and markdown safety fixes for Ghost/Hugo/Jekyll/WordPress/frontmatter/html parsing, plus route matching fixes and search/code-rendering changes that address the current code scanning warnings
  • keep documentation and deployment workflow aligned by including the Cloudflare one-click deployment script updates and related README/wiki sync already landed on dev

let j = i + 1;
while (j < lines.length && /^\s+-\s+/.test(lines[j])) {
arrayItems.push(lines[j].replace(/^\s+-\s+/, "").trim());
let nextLine = lines[j];
while (typeof nextLine === "string" && /^\s+-\s+/.test(nextLine)) {
arrayItems.push(nextLine.replace(/^\s+-\s+/, "").trim());
j++;
nextLine = lines[j];
@coderabbitai

coderabbitai Bot commented Apr 15, 2026

Copy link
Copy Markdown
📝 Walkthrough

Summary by CodeRabbit

Bug Fixes

  • 改进了搜索结果导航和关键词高亮的可靠性
  • 增强了内容解析的健壮性,更好地处理边界情况
  • 优化了视频和媒体文件的识别与加载
  • 提升了界面主题选择的一致性

Walkthrough

本次提交涉及四个文件的改进,包括搜索组件的选择逻辑与关键词高亮优化、Markdown 图像处理的 URL 规范化、YAML 前置元数据解析的防御性编程,以及管理后台主题配置逻辑的重构。

Changes

Cohort / File(s) Summary
搜索组件优化
client/src/components/search.tsx
新增 findSelectedResult() 辅助函数加强边界检查;将正则表达式高亮替换为子字符串匹配的 splitByQuery() 方法,提升类型安全性和高亮准确度。
URL 规范化与媒体检测
client/src/lib/markdown.ts
统一图像和视频元素的 href 通过 URL API 规范化处理;改用扩展名集合替代正则判断视频格式,性能更优;同步更新 Bilibili/YouTube 链接匹配逻辑。
防御性编码增强
client/src/lib/importers/frontmatter.ts
补充类型检查保护,确保 YAML 前置元数据解析器仅在数组元素为字符串时执行正则匹配,防止潜在运行时错误。
主题映射逻辑重构
client/src/pages/admin/backup.tsx
toneMap 字典查找替换为显式条件分支,消除隐式映射的不确定性,可读性更强。

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Suggested labels

frontend, bug

🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed PR 标题遵循 Conventional Commits 格式,使用 'chore' 类型,清晰总结了变更内容(管理员加固和代码扫描修复同步)。
Description check ✅ Passed PR 描述详细说明了三个主要变更方向(管理员模块加固、导入器和 markdown 安全修复、文档与部署工作流对齐),与提交的代码变更紧密相关。

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 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 bug Something isn't working frontend 前端 (React/Vite) 相关变更 labels Apr 15, 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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
client/src/lib/markdown.ts (1)

174-224: ⚠️ Potential issue | 🟠 Major

相对媒体地址被改写为 monolith.local,会导致线上图片/视频加载失败。

normalizedHref 适合作为“解析/识别”中间值,但不应直接作为最终 src 输出。当前改动会把相对路径渲染成绝对的 https://monolith.local/...renderMarkdownclient/src/pages/post.tsxclient/src/pages/dynamic-page.tsxclient/src/pages/admin/editor.tsx 都会消费用户内容,这个影响面较大。

🔧 建议修复
-  let normalizedHref = href;
+  let normalizedHref = href;
   try {
     normalizedHref = new URL(href, "https://monolith.local").toString();
   } catch {
     normalizedHref = href;
   }
@@
   if (["mp4", "webm", "ogg", "mov"].includes(mediaExtension)) {
     return `<figure class="md-figure md-video">
-      <video src="${normalizedHref}" controls playsinline preload="metadata" class="w-full rounded-lg border border-border/20 shadow-lg bg-black/5"></video>
+      <video src="${escapeHtml(href)}" controls playsinline preload="metadata" class="w-full rounded-lg border border-border/20 shadow-lg bg-black/5"></video>
       ${text ? `<figcaption>${escapeHtml(text)}</figcaption>` : ""}
     </figure>`;
   }
@@
-  return `<figure class="md-figure"><img src="${normalizedHref}" alt="${escapeHtml(text)}" loading="lazy" decoding="async" data-lazy-img${titleAttr} class="lazy-img"/>${text ? `<figcaption>${escapeHtml(text)}</figcaption>` : ""}</figure>`;
+  return `<figure class="md-figure"><img src="${escapeHtml(href)}" alt="${escapeHtml(text)}" loading="lazy" decoding="async" data-lazy-img${titleAttr} class="lazy-img"/>${text ? `<figcaption>${escapeHtml(text)}</figcaption>` : ""}</figure>`;
🤖 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 174 - 224, The code incorrectly uses
normalizedHref (which rewrites relative URLs to https://monolith.local) as the
final src; preserve href for output when the original was relative. Update the
logic around normalizedHref/videoUrl: compute a boolean (e.g., isRelative)
before/after the new URL(...) attempt (detect hrefs that do not include a scheme
or start with "//") and when rendering the <video>, <iframe> embeds, and the
final <img> use href (original) for src if isRelative is true, otherwise use
normalizedHref; keep normalizedHref for parsing/extension detection
(mediaExtension, bpxMatch, ytMatch) but ensure the emitted src attributes use
the original relative path when appropriate (affecting the
video/YouTube/Bilibili/image return blocks referencing normalizedHref).
client/src/components/search.tsx (1)

123-135: ⚠️ Potential issue | 🟠 Major

Enter 键未处理 IME 组合输入,中文输入时可能误触发跳转。

在输入法组合态(如拼音候选)按 Enter 时会走“打开结果”分支,可能打断输入流程。

🔧 建议修复
   const handleKeyDown = (e: React.KeyboardEvent) => {
+    if (e.nativeEvent.isComposing) return;
+
     if (e.key === "ArrowDown") {
       e.preventDefault();
       setSelectedIndex((prev) => Math.min(prev + 1, results.length - 1));
     } else if (e.key === "ArrowUp") {
       e.preventDefault();
       setSelectedIndex((prev) => Math.max(prev - 1, 0));
     } else if (e.key === "Enter") {
       const selected = findSelectedResult(results, selectedIndex);
       if (selected) {
         setOpen(false);
         window.location.href = `/posts/${selected.slug}`;
       }
     }
   };

As per coding guidelines client/src/components/**:审查时请关注“无障碍访问(aria 标签、键盘导航)”。

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

In `@client/src/components/search.tsx` around lines 123 - 135, The Enter key
handler in handleKeyDown triggers navigation even when the IME is composing
(e.g., Chinese pinyin), interrupting input; add an IME composition guard before
the Enter branch by checking e.nativeEvent.isComposing (or maintain an
isComposing state via onCompositionStart/onCompositionEnd) and early-return if
composing, then proceed to use findSelectedResult/results/selectedIndex to
navigate and call setOpen(false) only when not composing.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@client/src/components/search.tsx`:
- Around line 123-135: The Enter key handler in handleKeyDown triggers
navigation even when the IME is composing (e.g., Chinese pinyin), interrupting
input; add an IME composition guard before the Enter branch by checking
e.nativeEvent.isComposing (or maintain an isComposing state via
onCompositionStart/onCompositionEnd) and early-return if composing, then proceed
to use findSelectedResult/results/selectedIndex to navigate and call
setOpen(false) only when not composing.

In `@client/src/lib/markdown.ts`:
- Around line 174-224: The code incorrectly uses normalizedHref (which rewrites
relative URLs to https://monolith.local) as the final src; preserve href for
output when the original was relative. Update the logic around
normalizedHref/videoUrl: compute a boolean (e.g., isRelative) before/after the
new URL(...) attempt (detect hrefs that do not include a scheme or start with
"//") and when rendering the <video>, <iframe> embeds, and the final <img> use
href (original) for src if isRelative is true, otherwise use normalizedHref;
keep normalizedHref for parsing/extension detection (mediaExtension, bpxMatch,
ytMatch) but ensure the emitted src attributes use the original relative path
when appropriate (affecting the video/YouTube/Bilibili/image return blocks
referencing normalizedHref).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 84fd11e1-c534-4e35-b030-859cd626b150

📥 Commits

Reviewing files that changed from the base of the PR and between 3e072ed and da83463.

📒 Files selected for processing (4)
  • client/src/components/search.tsx
  • client/src/lib/importers/frontmatter.ts
  • client/src/lib/markdown.ts
  • client/src/pages/admin/backup.tsx
📜 Review details
⏰ Context from checks skipped due to timeout of 120000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: ESLint 安全扫描
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (actions)
🧰 Additional context used
📓 Path-based instructions (2)
client/src/pages/**

⚙️ CodeRabbit configuration file

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

Files:

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

⚙️ CodeRabbit configuration file

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

Files:

  • client/src/components/search.tsx
🪛 GitHub Check: ESLint
client/src/lib/importers/frontmatter.ts

[warning] 130-130: Detects "variable[key]" as a left- or right-hand assignment operand.
Variable Assigned to Object Injection Sink


[warning] 134-134: Detects "variable[key]" as a left- or right-hand assignment operand.
Generic Object Injection Sink

🔇 Additional comments (3)
client/src/pages/admin/backup.tsx (1)

602-606: 色调分支在当前调用范围内行为正确。

当前页面仅传入 orange / blue / emerald,该分支逻辑可正确映射样式,未见功能性问题。

client/src/lib/importers/frontmatter.ts (1)

111-114: 防御性类型守卫实现合理。

这两处检查能避免对非字符串执行正则匹配,提升了解析器的健壮性。

Also applies to: 130-134

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

31-58: 关键词高亮拆分实现清晰且可维护。

按片段标记后再渲染 <mark> 的方式可读性好,也避免了正则转义带来的边界问题。

Also applies to: 142-150

@one-ea
one-ea merged commit f493abd into main Apr 15, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working frontend 前端 (React/Vite) 相关变更

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants