-
Notifications
You must be signed in to change notification settings - Fork 3
/
search.tsx
128 lines (120 loc) · 4.53 KB
/
search.tsx
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
import React from 'react';
import ReactDOM from 'react-dom/client';
import { AppRenderer, requireModule, WORKSPACE_ROOT } from '@codeblitzjs/ide-core';
import '@codeblitzjs/ide-core/bundle/codeblitz.css';
import '@codeblitzjs/ide-core/languages';
let zipData: Buffer;
const zipDataPromise = (async () => {
const res = await fetch(
'http://alipay-rmsdeploy-image.cn-hangzhou.alipay.aliyun-inc.com/green-trail-test/dc85f34d-2467-436b-a0fe-092133ead0d6/demo.zip'
);
const buf = await res.arrayBuffer();
zipData = Buffer.from(new Uint8Array(buf));
})();
const fse = requireModule('fs-extra')
const path = requireModule('path')
const workspaceDir = 'log'
const workspaceFolder = path.join(WORKSPACE_ROOT, workspaceDir)
const walkWorkspace = async (dir: string, callback: (filepath: string) => Promise<boolean>) => {
const filenames: string[] = await fse.readdir(dir)
let finish = false
for (const filename of filenames) {
const filepath = path.join(dir, filename)
const stat = await fse.stat(filepath)
if (stat.isDirectory()) {
await walkWorkspace(filepath, callback)
} else {
// 排除一些非文本文件
if (!/\.(zip|jpg|png)$/.test(filepath)) {
finish = await callback(filepath)
if (finish) break
}
}
}
}
const App = () => {
return (
<div style={{ height: '100%' }}>
<AppRenderer
appConfig={{
workspaceDir,
}}
runtimeConfig={{
workspace: {
filesystem: {
fs: 'ZipFS',
options: {
zipData,
}
}
},
textSearch: {
config: {
replace: false, // 禁用替换
wordMatch: 'local', // 单词匹配用本地框架过滤
include: 'local', // 文件包含用本地框架过滤
exclude: 'local' // 文件排除用本地框架过滤
},
provideResults: (query, options, progress) => {
let maxResults = 0
return walkWorkspace(workspaceFolder, async (filepath) => {
if (maxResults > options.maxResults) return true
const content = await fse.readFile(filepath, 'utf8')
if (!content) return false;
const lines: string[] = content.split(/\r\n|\r|\n/g)
lines.forEach((line, index) => {
if (!line) return
if (maxResults > options.maxResults) return
const matches: [number, number][] = []
if (query.isRegExp) {
const regexp = new RegExp(query.pattern, `g${query.isCaseSensitive ? '' : 'i'}`)
let execArray: RegExpExecArray | null = null
while(execArray = regexp.exec(line)) {
if (!execArray) return
matches.push([ execArray.index, execArray.index + execArray[0].length ])
}
if (matches.length) {
progress.report({
path: path.relative(workspaceFolder, filepath),
lineNumber: index + 1,
preview: {
text: line,
matches,
},
})
maxResults++
}
} else {
const text = query.isCaseSensitive ? line : line.toLowerCase();
const search = query.isCaseSensitive ? query.pattern : query.pattern.toLowerCase()
let lastMatchIndex = -search.length;
while (
(lastMatchIndex = text.indexOf(search, lastMatchIndex + search.length)) !== -1
) {
matches.push([lastMatchIndex, lastMatchIndex + search.length]);
}
if (matches.length) {
progress.report({
path: path.relative(workspaceFolder, filepath),
lineNumber: index + 1,
preview: {
text: line,
matches,
},
});
maxResults++
}
}
})
return maxResults >= options.maxResults
})
}
}
}}
/>
</div>
);
};
zipDataPromise.then(() => {
ReactDOM.createRoot(document.getElementById('main')!).render(<App />);
});