wechat-markdown-editor / INTERVIEW_GUIDE.md
duqing2026's picture
Enhance: Add Toolbar, Notion Theme, Pangu spacing, and Interview Guide
4167172
# 面试指南:微信公众号 Markdown 编辑器 (WeChat Markdown Editor)
> 本文档旨在辅助你理解项目核心架构与技术难点,以便在面试中流利作答。
## 1. 项目概述 (Project Overview)
**一句话介绍**
这是一个基于 Web 的 Markdown 编辑器,专注于解决微信公众号排版繁琐、代码展示不友好以及外链限制等痛点。它能够将 Markdown 实时渲染为适配微信公众号样式的 HTML,支持一键复制发布。
**核心价值**
- **效率提升**:让技术博主专注于写作,而非排版。
- **样式定制**:通过 CSS 变量实现多主题切换(如 Notion 风格),满足不同审美。
- **平台适配**:针对微信环境的特殊限制(如外链、代码块)做了专门处理。
## 2. 技术架构 (Technical Architecture)
虽然项目看似简单,但其架构设计体现了**轻量化****关注点分离**的思想。
- **后端 (Backend)**: Python Flask
- **角色**:主要作为静态资源服务器(Static File Server)。
- **优势**:轻量、部署简单(配合 Docker/Gunicorn),易于后续扩展(如增加账号系统或云端存储)。
- **前端 (Frontend)**: Vue 3 + Tailwind CSS
- **Vue 3**:利用 Composition API (`setup`, `ref`, `computed`) 管理编辑器状态(源码、预览 HTML、主题设置)。
- **Tailwind CSS**:快速构建现代化的 UI 界面,提高开发效率。
- **核心引擎**: Markdown-it + Highlight.js
- **渲染**:在浏览器端实时将 Markdown 解析为 HTML AST,再渲染为 DOM。
- **高亮**:自动检测代码语言并应用高亮样式。
## 3. 核心难点与解决方案 (Key Challenges & Solutions)
面试中如果被问到“项目中遇到的最大困难是什么”,可以从以下几点回答:
### 难点 1:微信公众号的样式兼容性 (Style Adaptation)
**问题**:微信公众号后台编辑器过滤掉了许多外部 CSS,且对某些 HTML 标签(如 `h1`, `blockquote`)的默认样式支持不一致。
**解决方案**
- **内联样式模拟**:虽然没有使用内联样式库(如 juice),但我通过精心设计的 CSS 选择器(`#preview-content h1` 等)确保复制到剪贴板的内容带有所需的样式信息。微信编辑器在粘贴富文本时会保留大部分计算后的样式。
- **自定义 CSS 变量**:使用 `:root``data-theme` 属性实现主题切换。这样只需修改变量值,无需重写大量 CSS 规则。
### 难点 2:外链处理 (External Links)
**问题**:微信公众号文章除白名单外,不支持普通外部超链接,导致文章中的参考链接无法点击。
**解决方案**
- **自定义 Renderer**:利用 `markdown-it` 的插件机制,重写 `link_open``link_close` 规则。
- **脚注转换**:在渲染过程中,将所有外链收集到一个 `footnotes` 数组中。渲染结束后,在文章底部自动追加一个“引用链接”列表,并将正文中的链接转换为上标索引(如 `[1]`)。
### 难点 3:富文本一键复制 (Rich Text Copy)
**问题**:普通的 `navigator.clipboard.writeText` 只能复制纯文本,无法保留颜色和排版。
**解决方案**
- **Range API**: 创建一个 `Range` 对象选中预览区域的 DOM 节点。
- **Selection API**: 将 `Range` 添加到当前的 `Selection` 中。
- **execCommand**: 使用 `document.execCommand('copy')`(虽然标准标记为过时,但在处理“富文本复制”场景下,它仍然是兼容性最好、最可靠的方案)。
### 难点 4:同步滚动 (Sync Scroll)
**问题**:左侧 Markdown 源码和右侧渲染后的 HTML 高度不一致,如何实现精准的同步滚动?
**解决方案**
- **百分比映射**:计算当前滚动条位置占总可滚动高度的百分比 (`scrollTop / (scrollHeight - clientHeight)`),并将此百分比应用到另一侧。
- **防抖动 (Debounce/Lock)**:为了防止“循环触发”滚动事件(左滚带动右,右滚又带动左),设置了一个 `isScrolling` 标志位,在滚动触发时锁定,滚动结束后(通过 `setTimeout`)释放。
### 难点 5:中英文自动空格 (Pangu Spacing)
**问题**:为了提升排版美感,中英文之间应该有空格(如 "Hello你好" -> "Hello 你好")。
**解决方案**
- **正则替换**:前端实现了一个轻量级的替换逻辑。
- `text.replace(/([\u4e00-\u9fa5])([a-zA-Z0-9])/g, '$1 $2')`:中文后跟英文/数字。
- `text.replace(/([a-zA-Z0-9])([\u4e00-\u9fa5])/g, '$1 $2')`:英文/数字后跟中文。
## 4. 为什么做这个项目?
- **自我驱动**:作为一个技术人员,我经常写技术博客。现有的工具要么收费,要么功能太复杂,我希望有一个**轻量、可控、隐私安全(纯本地渲染)**的工具。
- **技术实践**:我想通过这个项目深入理解前端的**文本处理****DOM 操作**,同时实践 Vue 3 的 Composition API。