generated from obsidianmd/obsidian-sample-plugin
-
Notifications
You must be signed in to change notification settings - Fork 7
/
cardSearch.ts
139 lines (132 loc) · 3.84 KB
/
cardSearch.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import { AnnotationWrapper } from 'annotationParse';
import { CardIDTag } from 'cardHead';
import { Notice, TFile } from 'obsidian';
import { TagParser } from 'tag';
import { Card, NewCard } from "./card";
import { getAppInstance } from 'main';
// 搜索的结果
export class SearchResult {
AllCard: Card[]
SearchName: string
constructor() {
this.AllCard = []
}
}
// 卡片搜寻器负责搜索可能的卡片
export interface cardSearcher {
search(file?: TFile, text?: string): Promise<SearchResult>
}
export function NewCardSearch(tagName?: string): cardSearcher {
return new defaultCardSearch(tagName)
}
interface elem {
all: string
start: number
end: number
content: string
heading: string
}
// 默认的卡片搜索
// 搜索标签开头的一行,到该段落结束位置,该区域的内容被视为卡片Card的内容
class defaultCardSearch implements cardSearcher {
private tagName = "Q"
private matchReg: RegExp
private qReg = /(^#Q\b.*|^#\/Q\b.*)/gm;
constructor(tagName?: string) {
}
findAllQ(text: string) {
let match;
const matches = [];
while ((match = this.qReg.exec(text)) !== null) {
matches.push({
text: match[0],
start: match.index,
end: match.index + match[0].length
});
}
return matches;
}
matchText(text: string) {
const qTags = this.findAllQ(text);
const matches: elem[] = [];
for (let i = 0; i < qTags.length; i++) {
if (qTags[i].text.startsWith('#Q')) {
if (matches.length > 0) {
if (matches[matches.length - 1].end > qTags[i].start) {
continue
}
}
let end;
if (i + 1 < qTags.length && qTags[i + 1].text.startsWith('#/Q')) {
end = qTags[i + 1].start - 1;
} else {
const nextBlankLine = text.indexOf('\n\n', qTags[i].end);
end = nextBlankLine !== -1 ? nextBlankLine : text.length;
}
const all = text.slice(qTags[i].start, end)
const content = text.slice(qTags[i].end + 1, end)
if (all.length == 0 || content.length == 0) {
continue
}
matches.push({ all: all, start: qTags[i].start, end: end, content: content, heading: qTags[i].text });
}
}
return matches;
}
async search(file?: TFile, text?: string): Promise<SearchResult> {
let result = new SearchResult()
result.SearchName = "#" + this.tagName
if (file) {
if (!text) {
result.AllCard = await this.getCardFromFile(file)
} else {
result.AllCard = this.getCardFromText(text, file)
}
} else {
result.AllCard = await this.getCardFromVaultFile()
}
return result
}
async getCardFromVaultFile(): Promise<Card[]> {
let cards: Card[] = []
const notes: TFile[] = getAppInstance().vault.getMarkdownFiles();
for (const note of notes) {
cards.push(...await this.getCardFromFile(note))
}
return cards
}
async getCardFromFile(note: TFile): Promise<Card[]> {
let cards: Card[] = []
try {
let fileText = await getAppInstance().vault.read(note)
if (fileText) {
cards = this.getCardFromText(fileText, note);
}
} catch (error) {
console.log(`[Aosr] Failed to read file: ${note.path}, error: ${error}`)
new Notice(`[Aosr] Failed to read file: ${note.path}, error: ${error}`);
}
return cards;
}
private getCardFromText(fileText: string, note: TFile): Card[] {
let cards: Card[] = []
let results = this.matchText(fileText)
let cache = getAppInstance().metadataCache.getFileCache(note)
for (let result of results) {
// 匹配注释段
let cardText = result.all;
let index = result.start || 0;
let headingtags = TagParser.parse(result.heading);
let idTag = headingtags.findTag(CardIDTag);
let blockID = idTag?.Suffix || "";
let annotation = "";
if (blockID != "") {
annotation = AnnotationWrapper.findAnnotationWrapper(fileText, blockID);
}
let content = result.content;
let card: Card = NewCard(cardText, content, annotation, blockID, index, note, cache);
cards.push(card)
}
return cards
}
}