mirror of
https://github.com/zadam/trilium.git
synced 2026-03-23 00:33:47 +01:00
refactor: add plan and package
This commit is contained in:
parent
6f5c618bcd
commit
c7980f42fe
216
.agents/migration_plan_autocomplete.md
Normal file
216
.agents/migration_plan_autocomplete.md
Normal file
@ -0,0 +1,216 @@
|
||||
# Migration Plan: `autocomplete.js` → `@algolia/autocomplete-js`
|
||||
|
||||
> Issue: https://github.com/TriliumNext/Trilium/issues/5134
|
||||
>
|
||||
> 目标:将旧的 `autocomplete.js@0.38.1`(jQuery 插件)迁移到 `@algolia/autocomplete-js`(独立组件)
|
||||
|
||||
---
|
||||
|
||||
## 当前状态总览
|
||||
|
||||
### 两个库的架构差异
|
||||
| | 旧 `autocomplete.js` | 新 `@algolia/autocomplete-js` |
|
||||
|---|---|---|
|
||||
| 模式 | jQuery 插件,**增强已有 `<input>`** | 独立组件,**传入容器 `<div>`,自己创建 `<input>`** |
|
||||
| 初始化 | `$el.autocomplete(config, [datasets])` | `autocomplete({ container, getSources, ... })` 返回 `api` |
|
||||
| 操作 | `$el.autocomplete("open"/"close"/"val")` | `api.setIsOpen()`, `api.setQuery()`, `api.refresh()` |
|
||||
| 销毁 | `$el.autocomplete("destroy")` | `api.destroy()` |
|
||||
| 事件 | jQuery 事件 `autocomplete:selected` | `onSelect` 回调、`onStateChange` 回调 |
|
||||
| DOM | 增强已有 input,添加 `.aa-input` 类 | 替换容器内容为自己的 DOM(`.aa-Form`、`.aa-Panel` 等) |
|
||||
|
||||
### 关键迁移原则
|
||||
1. **不使用 wrapper/适配层**,直接在各 service 中调用 `autocomplete()` API
|
||||
2. 消费者代码需要适配:传入容器 `<div>` 而非 `<input>`,通过 API/回调读写值
|
||||
3. 增量迁移:每个使用点独立迁移,逐一验证
|
||||
|
||||
### 涉及的功能区域
|
||||
1. **属性名称自动补全** — `attribute_autocomplete.ts` → `attribute_detail.ts`、`RelationMap.tsx`
|
||||
2. **标签值自动补全** — `attribute_autocomplete.ts` → `attribute_detail.ts`
|
||||
3. **笔记搜索自动补全** — `note_autocomplete.ts` → `NoteAutocomplete.tsx`、`attribute_detail.ts`
|
||||
4. **关闭弹出窗口** — `dialog.ts`、`entrypoints.ts`、`tab_manager.ts`
|
||||
5. **CKEditor 提及** — 不使用 autocomplete.js,**无需迁移**
|
||||
|
||||
---
|
||||
|
||||
## 迁移步骤
|
||||
|
||||
### Step 0: 安装新依赖 ✅ 完成
|
||||
**文件变更:**
|
||||
- `apps/client/package.json` — 添加 `@algolia/autocomplete-js@1.19.6`,暂时保留 `autocomplete.js`
|
||||
|
||||
**验证方式:**
|
||||
- ✅ 新依赖安装成功
|
||||
|
||||
---
|
||||
|
||||
### Step 1: 迁移属性名称自动补全
|
||||
**文件变更:**
|
||||
- `apps/client/src/services/attribute_autocomplete.ts` — `initAttributeNameAutocomplete()` 改为直接调用 `autocomplete()`
|
||||
- `apps/client/src/widgets/attribute_widgets/attribute_detail.ts` — 属性名称输入框从 `<input>` 改为 `<div>` 容器,调整值读写
|
||||
- `apps/client/src/widgets/type_widgets/relation_map/RelationMap.tsx` — 关系名输入调整
|
||||
|
||||
**说明:**
|
||||
属性名称补全是最简单的场景。变更模式:
|
||||
1. HTML 模板中的 `<input class="attr-input-name">` → `<div class="attr-input-name-container"></div>`
|
||||
2. `initAttributeNameAutocomplete()` 接收容器元素,调用 `autocomplete({ container, getSources })`
|
||||
3. 消费者通过返回的 `api` 对象(或回调)获取选中的值
|
||||
4. 为 `autocomplete-js` 生成的 `<input>` 添加 `form-control` 等样式类
|
||||
|
||||
**验证方式:**
|
||||
- 打开一个笔记 → 点击属性面板 → 点击属性名称输入框 → 应能看到自动补全的属性名称列表
|
||||
- 选择一个名称后,值应正确填入
|
||||
|
||||
---
|
||||
|
||||
### Step 2: 迁移标签值自动补全
|
||||
**文件变更:**
|
||||
- `apps/client/src/services/attribute_autocomplete.ts` — `initLabelValueAutocomplete()` 改为直接调用 `autocomplete()`
|
||||
- `apps/client/src/widgets/attribute_widgets/attribute_detail.ts` — 标签值输入框同步调整
|
||||
|
||||
**说明:**
|
||||
与 Step 1 类似,但标签值补全有一个特殊点:每次 focus 都会重新初始化(因为属性名可能变了,需要重新获取可选值列表)。
|
||||
|
||||
**验证方式:**
|
||||
- 打开属性面板 → 输入一个标签名 → 切换到值输入框 → 应能看到该标签的已有值列表
|
||||
|
||||
---
|
||||
|
||||
### Step 3: 迁移笔记搜索自动补全核心
|
||||
**文件变更:**
|
||||
- `apps/client/src/services/note_autocomplete.ts` — `initNoteAutocomplete()` 改为直接调用 `autocomplete()`
|
||||
|
||||
**说明:**
|
||||
这是迁移中最复杂的部分,`initNoteAutocomplete()` 包含:
|
||||
- 复杂的 source 函数(带防抖、IME 处理)
|
||||
- 自定义 suggestion 模板(图标、路径高亮)
|
||||
- 多种选择类型分发(笔记、外部链接、命令)
|
||||
- `autocomplete("val", ...)` 等操作性 API 调用
|
||||
- 附带的辅助按钮(清除、最近笔记、全文搜索、跳转按钮)
|
||||
|
||||
消费者通过自定义 jQuery 事件(`autocomplete:noteselected` 等)接收结果,需要保持这些事件或改为回调。
|
||||
|
||||
**验证方式:**
|
||||
- 搜索栏 → 输入笔记名称 → 应能看到搜索结果
|
||||
- 选择结果 → 应正确跳转到对应笔记
|
||||
- 命令面板(`>` 前缀)正常工作
|
||||
- 中文输入法不应中途触发搜索
|
||||
- Shift+Enter 全文搜索、Ctrl+Enter 搜索笔记
|
||||
|
||||
---
|
||||
|
||||
### Step 4: 迁移辅助函数
|
||||
**文件变更:**
|
||||
- `apps/client/src/services/note_autocomplete.ts` — `clearText`, `setText`, `showRecentNotes` 等函数
|
||||
|
||||
**说明:**
|
||||
这些函数使用旧库的操作 API(`$el.autocomplete("val", value)` 等),需要改为新库的 `api.setQuery()` / `api.setIsOpen()` / `api.refresh()`。
|
||||
|
||||
**验证方式:**
|
||||
- 最近笔记按钮 → 下拉菜单正常打开
|
||||
- 清除按钮 → 输入框被清空
|
||||
- Shift+Enter → 触发全文搜索
|
||||
|
||||
---
|
||||
|
||||
### Step 5: 迁移 `NoteAutocomplete.tsx` (React/Preact 组件)
|
||||
**文件变更:**
|
||||
- `apps/client/src/widgets/react/NoteAutocomplete.tsx` — 传入容器 `<div>`,管理 `api` 生命周期
|
||||
|
||||
**验证方式:**
|
||||
- 关系属性的目标笔记选择正常工作
|
||||
- `noteId` 和 `text` props 的动态更新正确
|
||||
|
||||
---
|
||||
|
||||
### Step 6: 迁移"关闭弹窗"逻辑 + `attribute_detail.ts` 引用
|
||||
**文件变更:**
|
||||
- `apps/client/src/services/dialog.ts` — 替换 `$(".aa-input").autocomplete("close")`
|
||||
- `apps/client/src/components/entrypoints.ts` — 替换 `$(".aa-input").autocomplete("close")`
|
||||
- `apps/client/src/components/tab_manager.ts` — 替换 `$(".aa-input").autocomplete("close")`
|
||||
- `apps/client/src/widgets/attribute_widgets/attribute_detail.ts` — 更新 `.algolia-autocomplete` 选择器
|
||||
|
||||
**说明:**
|
||||
需要一个全局的"关闭所有 autocomplete"机制。方案:维护一个全局 `Set<AutocompleteApi>`,在各处调用时遍历关闭。可以放在 `note_autocomplete.ts` 中导出。
|
||||
|
||||
**验证方式:**
|
||||
- autocomplete 弹窗打开时切换标签页 → 弹窗自动关闭
|
||||
- autocomplete 弹窗打开时打开对话框 → 弹窗自动关闭
|
||||
- 点击 autocomplete 下拉菜单时属性面板不应关闭
|
||||
|
||||
---
|
||||
|
||||
### Step 7: 更新 CSS 样式
|
||||
**文件变更:**
|
||||
- `apps/client/src/stylesheets/style.css`(第 895-961 行)
|
||||
|
||||
**说明:**
|
||||
新库使用的 CSS 类名:
|
||||
- `.aa-Autocomplete` — 容器
|
||||
- `.aa-Form` — 搜索表单(含 input)
|
||||
- `.aa-Input` — 输入框
|
||||
- `.aa-Panel` — 下拉面板
|
||||
- `.aa-List` — 列表
|
||||
- `.aa-Item` — 列表项
|
||||
- `.aa-Item[aria-selected="true"]` — 选中项
|
||||
|
||||
**验证方式:**
|
||||
- 下拉菜单样式正常(亮色/暗色模式)
|
||||
- 选中项高亮正确
|
||||
|
||||
---
|
||||
|
||||
### Step 8: 更新类型声明
|
||||
**文件变更:**
|
||||
- `apps/client/src/types.d.ts` — 移除 `AutoCompleteConfig`、`AutoCompleteArg`、jQuery `.autocomplete()` 方法
|
||||
|
||||
**验证方式:**
|
||||
- TypeScript 编译无错误
|
||||
|
||||
---
|
||||
|
||||
### Step 9: 移除旧库和 Polyfill
|
||||
**文件变更:**
|
||||
- `apps/client/package.json` — 移除 `"autocomplete.js": "0.38.1"`
|
||||
- `apps/client/src/desktop.ts` — 移除 `import "autocomplete.js/index_jquery.js";`
|
||||
- `apps/client/src/mobile.ts` — 移除 `import "autocomplete.js/index_jquery.js";`
|
||||
- `apps/client/src/runtime.ts` — 移除 jQuery polyfill
|
||||
- `apps/client/src/index.ts` — 移除 jQuery polyfill
|
||||
|
||||
**验证方式:**
|
||||
- 完整回归测试
|
||||
- 构建无错误
|
||||
|
||||
---
|
||||
|
||||
### Step 10: 更新 E2E 测试
|
||||
**文件变更:**
|
||||
- `apps/server-e2e/src/support/app.ts`
|
||||
- `apps/server-e2e/src/layout/split_pane.spec.ts`
|
||||
|
||||
**验证方式:**
|
||||
- E2E 测试全部通过
|
||||
|
||||
---
|
||||
|
||||
## 依赖关系图
|
||||
|
||||
```
|
||||
Step 0 (安装新库) ✅
|
||||
├── Step 1 (属性名称 autocomplete) ← 最简单,优先迁移
|
||||
├── Step 2 (标签值 autocomplete)
|
||||
├── Step 3 (笔记搜索 autocomplete 核心) ← 最复杂
|
||||
│ ├── Step 4 (辅助函数)
|
||||
│ └── Step 5 (React 组件)
|
||||
├── Step 6 (关闭弹窗 + attribute_detail 引用)
|
||||
└── Step 7 (CSS 样式)
|
||||
└── Step 8 (类型声明)
|
||||
└── Step 9 (移除旧库) ← 最后执行
|
||||
└── Step 10 (E2E 测试)
|
||||
```
|
||||
|
||||
## 风险点
|
||||
1. **消费者代码需要改动**:新库要求传入容器而非 input,消费者需要调整 HTML 模板和值的读写方式。
|
||||
2. **自定义事件兼容性**:旧库通过 jQuery 事件与外部交互,新库使用回调,`attribute_detail.ts` 等消费者中的事件监听需要更新。
|
||||
3. **IME 输入处理**:新库原生支持 `ignoreCompositionEvents` 选项,但需要验证行为是否与旧的手动处理一致。
|
||||
4. **CSS 类名变化**:多处代码通过 `.aa-input`、`.algolia-autocomplete` 定位元素,需要统一更新为新的 `.aa-*` 类名。
|
||||
5. **全局关闭机制**:旧代码通过 `$(".aa-input").autocomplete("close")` 关闭所有实例,新库需要手动维护实例注册表。
|
||||
@ -16,6 +16,7 @@
|
||||
"circular-deps": "dpdm -T src/**/*.ts --tree=false --warning=false --skip-dynamic-imports=circular"
|
||||
},
|
||||
"dependencies": {
|
||||
"@algolia/autocomplete-js": "1.19.6",
|
||||
"@excalidraw/excalidraw": "0.18.0",
|
||||
"@fullcalendar/core": "6.1.20",
|
||||
"@fullcalendar/daygrid": "6.1.20",
|
||||
|
||||
35049
pnpm-lock.yaml
generated
35049
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user