# 沙拉查词项目规范
> 架构原则、代码风格、通信协议、安全规范
---
## 1. 架构原则
### 模块职责
| 模块 | 职责 | 禁止行为 |
|------|------|----------|
| **Background** | 网络请求、数据持久化、右键菜单 | 操作DOM |
| **Content Script** | 读取页面文本、注入UI、用户交互 | 直接跨域请求 |
| **Popup** | 独立查词、快速设置、历史记录 | 访问页面DOM |
| **Options** | 配置管理、生词本、词典账号 | 操作页面内容 |
| **Shared** | 工具函数、常量、基类 | 依赖特定模块 |
### 通信规则
```
Content ↔ Background: chrome.runtime.sendMessage
Popup ↔ Background: chrome.runtime.sendMessage
Options → Background: chrome.runtime.sendMessage
```
---
## 2. 代码风格
### 命名规范
| 类型 | 规范 | 示例 |
|------|------|------|
| 文件 | 小写+连字符 | `salad-icon.js` |
| 类 | PascalCase | `DictionaryBase` |
| 函数 | camelCase+动词开头 | `getSelectionCoords()` |
| 常量 | UPPER_SNAKE_CASE | `DEFAULT_TIMEOUT` |
| 私有 | 下划线前缀 | `_handleMessage()` |
| 消息类型 | 大写+点分隔 | `DICT.SEARCH` |
### JavaScript 规范
**必须使用**:
- `const` / `let`,禁止 `var`
- 箭头函数作为回调
- 模板字符串
- 解构赋值
- 可选链 `?.`
**禁止**:
- `eval()`, `new Function()`
- `innerHTML` 插入不可信内容
- 同步的 `chrome.storage` 调用
**异步规范**:
```javascript
// ✅ async/await
async function searchWord(word) {
try {
const result = await dict.search(word);
return result;
} catch (error) {
console.error('Search failed:', error);
throw error;
}
}
```
### CSS 规范
**Shadow DOM 隔离**:
```javascript
const shadow = element.attachShadow({ mode: 'open' });
shadow.innerHTML = `
...
`;
```
**CSS 变量**:
```css
:root {
--salad-primary: #4CAF50;
--salad-bg: #ffffff;
--salad-text: #333333;
}
[data-theme="dark"] {
--salad-bg: #1a1a1a;
--salad-text: #e0e0e0;
}
```
---
## 3. 通信协议
### 消息格式
```javascript
// 请求
{
type: 'NAMESPACE.ACTION',
payload: { },
meta: { timestamp, requestId }
}
// 响应
{
type: 'NAMESPACE.ACTION_RESPONSE',
payload: { },
error: null,
meta: { requestId }
}
```
### 标准消息类型
```javascript
DICT.SEARCH / DICT.SEARCH_RESPONSE
CONFIG.GET / CONFIG.SET / CONFIG.CHANGED
WORD.ADD_FAVORITE / WORD.REMOVE_FAVORITE
CLIPBOARD.READ / CLIPBOARD.WRITE
HTTP.GET / HTTP.POST
```
### 通信封装
```javascript
// shared/messaging.js
class MessageClient {
async send(type, payload, timeout = 5000) {
return new Promise((resolve, reject) => {
// 实现:发送消息,监听响应,超时处理
});
}
}
export const messaging = new MessageClient();
```
---
## 4. 词典开发规范
### 基类定义
```javascript
export class DictionaryBase {
constructor(config = {}) {
this.name = config.name || 'Unknown';
this.icon = config.icon || '';
this.languages = config.languages || ['en', 'zh'];
}
async search(word) {
throw new Error('search() must be implemented');
}
supports(lang) {
return this.languages.includes(lang);
}
}
```
### 返回格式
```javascript
{
word: 'hello',
phonetic: '/həˈləʊ/',
meanings: [
{ partOfSpeech: 'int.', definitions: ['你好', '喂'] }
],
examples: [
{ sentence: 'Hello, world!', translation: '你好,世界!' }
],
url: 'https://...'
}
```
### 实现模板
```javascript
export class XxxDictionary extends DictionaryBase {
constructor(config = {}) {
super({ name: '词典名', icon: 'icon.png', languages: ['en', 'zh'], ...config });
}
async search(word) {
if (!word?.trim()) throw new Error('Word is empty');
const html = await messaging.send('HTTP.GET', {
url: `https://api.example.com?q=${encodeURIComponent(word)}`
});
return this.parse(html, word);
}
parse(html, word) {
const doc = new DOMParser().parseFromString(html, 'text/html');
return {
word,
phonetic: this.extractPhonetic(doc),
meanings: this.extractMeanings(doc),
examples: this.extractExamples(doc),
url: ''
};
}
}
```
---
## 5. UI 组件规范
### 组件基类
```javascript
export class ComponentBase extends HTMLElement {
constructor() {
super();
this.shadow = this.attachShadow({ mode: 'open' });
this._isVisible = false;
}
render() {
throw new Error('render() must be implemented');
}
show(x, y) {
this._isVisible = true;
this.style.display = 'block';
this.style.left = `${x}px`;
this.style.top = `${y}px`;
}
hide() {
this._isVisible = false;
this.style.display = 'none';
}
destroy() {
this.hide();
this.remove();
}
}
```
---
## 6. 存储规范
### 存储分层
```javascript
chrome.storage.local // 配置、生词本
chrome.storage.session // 临时数据
IndexedDB // 大数据量
Memory // 运行时缓存
```
### 配置结构
```javascript
const DEFAULT_CONFIG = {
version: '7.20.0',
general: {
enableSelection: true,
enableAnimation: true,
darkMode: false,
language: 'zh_CN'
},
searchMode: {
triggerMode: 'icon', // icon/direct/double/key
iconHoverSearch: false,
shortcutKeys: []
},
dictionaries: [
{ id: 'bing', enabled: true, order: 0 }
]
};
```
---
## 7. 安全规范
### XSS 防护
```javascript
// ✅ textContent
element.textContent = userInput;
// ❌ innerHTML 插入不可信内容
element.innerHTML = userInput;
// ✅ 必须使用时转义
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
```
### CSP
```json
{
"content_security_policy": {
"extension_pages": "script-src 'self'; object-src 'self'"
}
}
```
---
## 8. 版本号规范
遵循 SemVer,但 **PATCH 与验收点关联**:
```
MAJOR.MINOR.PATCH
│ │ └─ 每个任务完成 +1
│ └─ 模块完成进入下一模块 +1
└─ 正式发布 = 1
```
详见 [README.md](./README.md) 版本规则部分和 [VERSION.md](./VERSION.md)