* 清理孤立数据 * 检查所有存储的高亮和评论,移除那些在文档中找不到对应高亮文本的孤立数据 * @returns 清理的数据数量
()
| 204 | * @returns 清理的数据数量 |
| 205 | */ |
| 206 | async cleanOrphanedData(): Promise<{ removedHighlights: number; affectedFiles: number }> { |
| 207 | let removedHighlights = 0; |
| 208 | let affectedFiles = new Set<string>(); |
| 209 | |
| 210 | const allHighlights = this.repository.getAllCachedHighlights(); |
| 211 | |
| 212 | for (const [filePath, highlights] of allHighlights.entries()) { |
| 213 | const file = this.app.vault.getAbstractFileByPath(filePath); |
| 214 | if (!file || !(file instanceof TFile)) { |
| 215 | await this.repository.deleteFileHighlights(filePath); |
| 216 | affectedFiles.add(filePath); |
| 217 | removedHighlights += highlights.length; |
| 218 | continue; |
| 219 | } |
| 220 | |
| 221 | try { |
| 222 | const content = await this.app.vault.read(file); |
| 223 | const extractedHighlights = this.highlightService.extractHighlights(content, file); |
| 224 | const extractedTexts = new Set(extractedHighlights.map(h => h.text)); |
| 225 | |
| 226 | const validHighlights = highlights.filter(highlight => { |
| 227 | if (highlight.isVirtual) return true; |
| 228 | return extractedTexts.has(highlight.text); |
| 229 | }); |
| 230 | |
| 231 | if (validHighlights.length < highlights.length) { |
| 232 | removedHighlights += highlights.length - validHighlights.length; |
| 233 | affectedFiles.add(filePath); |
| 234 | |
| 235 | if (validHighlights.length === 0) { |
| 236 | await this.repository.deleteFileHighlights(filePath); |
| 237 | } else { |
| 238 | await this.repository.saveFileHighlights(filePath, validHighlights); |
| 239 | } |
| 240 | } |
| 241 | } catch { |
| 242 | // 错误处理 |
| 243 | } |
| 244 | } |
| 245 | |
| 246 | return { removedHighlights, affectedFiles: affectedFiles.size }; |
| 247 | } |
| 248 | |
| 249 | /** |
| 250 | * 处理文件重命名 |
no test coverage detected