dsh-locator 0.4.1 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/README-es.md +162 -0
- package/README-hi.md +162 -0
- package/README-pt.md +162 -0
- package/README.en.md +257 -0
- package/README.md +172 -142
- package/bin/darwin-arm64/indexd +0 -0
- package/bin/darwin-x64/indexd +0 -0
- package/bin/linux-arm64/indexd +0 -0
- package/bin/linux-x64/indexd +0 -0
- package/bin/win32-arm64/indexd.exe +0 -0
- package/bin/win32-x64/indexd.exe +0 -0
- package/client.js +192 -55
- package/docs/assets/architecture.svg +68 -0
- package/docs/assets/panel-en.png +0 -0
- package/docs/assets/panel-zh.png +0 -0
- package/lib/http.d.ts.map +1 -1
- package/lib/http.js +27 -1
- package/lib/http.js.map +1 -1
- package/lib/reveal.d.ts +5 -3
- package/lib/reveal.d.ts.map +1 -1
- package/lib/reveal.js +19 -17
- package/lib/reveal.js.map +1 -1
- package/package.json +7 -3
- package/src/http.ts +25 -1
- package/src/reveal.ts +17 -15
- package/README-zh.md +0 -226
package/client.js
CHANGED
|
@@ -100,10 +100,135 @@ window.__ModuleLoader__.load({
|
|
|
100
100
|
})
|
|
101
101
|
const data = await response.json().catch(() => null)
|
|
102
102
|
if (!response.ok || data === null) throw new Error('HTTP ' + response.status)
|
|
103
|
-
if (data.ok === false) throw new Error(typeof data.error === 'string' ? data.error : '
|
|
103
|
+
if (data.ok === false) throw new Error(typeof data.error === 'string' ? data.error : 'request failed')
|
|
104
104
|
return data
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
+
|
|
108
|
+
// ── i18n ────────────────────────────────────────────────────────────────
|
|
109
|
+
const STRINGS = {
|
|
110
|
+
en: {
|
|
111
|
+
placeholder: 'Search file names or paths… e.g. ext:pdf size:>10mb dm:thisweek path:src !tmp',
|
|
112
|
+
searchLabel: 'Search files', dialog: 'Local file search', closeTitle: 'Close (Esc)', closeLabel: 'Close',
|
|
113
|
+
filesOnly: 'Files only', dirsOnly: 'Directories only', statusLoading: 'Reading index status…',
|
|
114
|
+
status: 'Index {entries} entries · {mode} · {roots} roots', live: 'live', snapshot: 'snapshot', usn: 'USN',
|
|
115
|
+
sortTitle: 'Click to change sorting', name: 'Name', size: 'Size', mtime: 'Modified', path: 'Path',
|
|
116
|
+
dirBadge: 'DIR', fileBadge: 'FILE', loading: 'Searching…', errorPrefix: 'Search failed: ', empty: 'No matching files',
|
|
117
|
+
results: '{total} results', showing: 'showing first {n}', indexing: 'indexing, results may be incomplete',
|
|
118
|
+
copied: 'Path copied', revealed: 'Revealed in file manager', opened: 'Opened', inserted: 'Inserted @file',
|
|
119
|
+
insertFailed: 'Insert failed; @file copied', footer: '↑↓ select · Enter copy · Ctrl+O open · Ctrl+Enter insert @file · double-click reveal · Esc close',
|
|
120
|
+
launcher: 'Local file search (Ctrl+Shift+F)',
|
|
121
|
+
justNow: 'just now', minutesAgo: '{n} min ago', hoursAgo: '{n} h ago',
|
|
122
|
+
},
|
|
123
|
+
zh: {
|
|
124
|
+
placeholder: '搜索文件名或路径… 支持 ext:pdf size:>10mb dm:thisweek path:src !tmp',
|
|
125
|
+
searchLabel: '文件搜索', dialog: '本地文件搜索', closeTitle: '关闭 (Esc)', closeLabel: '关闭',
|
|
126
|
+
filesOnly: '只看文件', dirsOnly: '只看目录', statusLoading: '索引状态读取中…',
|
|
127
|
+
status: '索引 {entries} 条 · {mode} · {roots} 个根目录', live: '实时监听', snapshot: '快照', usn: 'USN',
|
|
128
|
+
sortTitle: '点击切换排序', name: '名称', size: '大小', mtime: '修改时间', path: '路径',
|
|
129
|
+
dirBadge: '目录', fileBadge: '文件', loading: '搜索中…', errorPrefix: '搜索失败:', empty: '没有匹配的文件',
|
|
130
|
+
results: '{total} 条结果', showing: '显示前 {n} 条', indexing: '索引构建中,结果可能不完整',
|
|
131
|
+
copied: '已复制路径', revealed: '已在文件管理器中定位', opened: '已打开', inserted: '已插入 @file',
|
|
132
|
+
insertFailed: '插入失败,已复制 @file', footer: '↑↓ 选择 · Enter 复制 · Ctrl+O 打开 · Ctrl+Enter 插入 @file · 双击定位 · Esc 关闭',
|
|
133
|
+
launcher: '本地文件搜索 (Ctrl+Shift+F)',
|
|
134
|
+
justNow: '刚刚', minutesAgo: '{n} 分钟前', hoursAgo: '{n} 小时前',
|
|
135
|
+
},
|
|
136
|
+
es: {
|
|
137
|
+
placeholder: 'Busca nombres o rutas… p. ej. ext:pdf size:>10mb dm:thisweek path:src !tmp',
|
|
138
|
+
searchLabel: 'Buscar archivos', dialog: 'Búsqueda local de archivos', closeTitle: 'Cerrar (Esc)', closeLabel: 'Cerrar',
|
|
139
|
+
filesOnly: 'Solo archivos', dirsOnly: 'Solo carpetas', statusLoading: 'Leyendo el estado del índice…',
|
|
140
|
+
status: 'Índice: {entries} entradas · {mode} · {roots} raíces', live: 'en vivo', snapshot: 'instantánea', usn: 'USN',
|
|
141
|
+
sortTitle: 'Clic para cambiar el orden', name: 'Nombre', size: 'Tamaño', mtime: 'Modificado', path: 'Ruta',
|
|
142
|
+
dirBadge: 'DIR', fileBadge: 'ARCH', loading: 'Buscando…', errorPrefix: 'Error de búsqueda: ', empty: 'Sin coincidencias',
|
|
143
|
+
results: '{total} resultados', showing: 'mostrando {n}', indexing: 'indexando, resultados incompletos',
|
|
144
|
+
copied: 'Ruta copiada', revealed: 'Mostrado en el gestor de archivos', opened: 'Abierto', inserted: '@file insertado',
|
|
145
|
+
insertFailed: 'No se pudo insertar; @file copiado', footer: '↑↓ elegir · Enter copiar · Ctrl+O abrir · Ctrl+Enter insertar @file · doble clic revelar · Esc cerrar',
|
|
146
|
+
launcher: 'Búsqueda local (Ctrl+Shift+F)',
|
|
147
|
+
justNow: 'ahora', minutesAgo: 'hace {n} min', hoursAgo: 'hace {n} h',
|
|
148
|
+
},
|
|
149
|
+
pt: {
|
|
150
|
+
placeholder: 'Busque nomes ou caminhos… ex. ext:pdf size:>10mb dm:thisweek path:src !tmp',
|
|
151
|
+
searchLabel: 'Buscar arquivos', dialog: 'Busca local de arquivos', closeTitle: 'Fechar (Esc)', closeLabel: 'Fechar',
|
|
152
|
+
filesOnly: 'Somente arquivos', dirsOnly: 'Somente pastas', statusLoading: 'Lendo o estado do índice…',
|
|
153
|
+
status: 'Índice: {entries} entradas · {mode} · {roots} raízes', live: 'ao vivo', snapshot: 'instantâneo', usn: 'USN',
|
|
154
|
+
sortTitle: 'Clique para mudar a ordem', name: 'Nome', size: 'Tamanho', mtime: 'Modificado', path: 'Caminho',
|
|
155
|
+
dirBadge: 'DIR', fileBadge: 'ARQ', loading: 'Buscando…', errorPrefix: 'Falha na busca: ', empty: 'Nenhum resultado',
|
|
156
|
+
results: '{total} resultados', showing: 'mostrando {n}', indexing: 'indexando, resultados incompletos',
|
|
157
|
+
copied: 'Caminho copiado', revealed: 'Mostrado no gerenciador de arquivos', opened: 'Aberto', inserted: '@file inserido',
|
|
158
|
+
insertFailed: 'Falha ao inserir; @file copiado', footer: '↑↓ escolher · Enter copiar · Ctrl+O abrir · Ctrl+Enter inserir @file · clique duplo revelar · Esc fechar',
|
|
159
|
+
launcher: 'Busca local (Ctrl+Shift+F)',
|
|
160
|
+
justNow: 'agora', minutesAgo: 'há {n} min', hoursAgo: 'há {n} h',
|
|
161
|
+
},
|
|
162
|
+
hi: {
|
|
163
|
+
placeholder: 'फ़ाइल नाम या पथ खोजें… जैसे ext:pdf size:>10mb dm:thisweek path:src !tmp',
|
|
164
|
+
searchLabel: 'फ़ाइल खोज', dialog: 'स्थानीय फ़ाइल खोज', closeTitle: 'बंद करें (Esc)', closeLabel: 'बंद करें',
|
|
165
|
+
filesOnly: 'केवल फ़ाइलें', dirsOnly: 'केवल फ़ोल्डर', statusLoading: 'इंडेक्स स्थिति पढ़ी जा रही है…',
|
|
166
|
+
status: 'इंडेक्स {entries} प्रविष्टियाँ · {mode} · {roots} रूट', live: 'लाइव', snapshot: 'स्नैपशॉट', usn: 'USN',
|
|
167
|
+
sortTitle: 'क्रम बदलने के लिए क्लिक करें', name: 'नाम', size: 'आकार', mtime: 'संशोधित', path: 'पथ',
|
|
168
|
+
dirBadge: 'DIR', fileBadge: 'FILE', loading: 'खोज रहे हैं…', errorPrefix: 'खोज विफल: ', empty: 'कोई मेल नहीं',
|
|
169
|
+
results: '{total} परिणाम', showing: 'पहले {n} दिखाए', indexing: 'इंडेक्स बन रहा है, परिणाम अधूरे हो सकते हैं',
|
|
170
|
+
copied: 'पथ कॉपी हुआ', revealed: 'फ़ाइल मैनेजर में दिखाया', opened: 'खोला गया', inserted: '@file डाला गया',
|
|
171
|
+
insertFailed: 'डालना विफल; @file कॉपी हुआ', footer: '↑↓ चुनें · Enter कॉपी · Ctrl+O खोलें · Ctrl+Enter @file डालें · डबल-क्लिक दिखाएँ · Esc बंद',
|
|
172
|
+
launcher: 'स्थानीय फ़ाइल खोज (Ctrl+Shift+F)',
|
|
173
|
+
justNow: 'अभी', minutesAgo: '{n} मिनट पहले', hoursAgo: '{n} घंटे पहले',
|
|
174
|
+
},
|
|
175
|
+
}
|
|
176
|
+
const LANG = (() => {
|
|
177
|
+
const tag = String((typeof navigator !== 'undefined' && navigator.language) || 'en').toLowerCase()
|
|
178
|
+
if (tag.startsWith('zh')) return 'zh'
|
|
179
|
+
if (tag.startsWith('es')) return 'es'
|
|
180
|
+
if (tag.startsWith('pt')) return 'pt'
|
|
181
|
+
if (tag.startsWith('hi')) return 'hi'
|
|
182
|
+
return 'en'
|
|
183
|
+
})()
|
|
184
|
+
const TEXT = STRINGS[LANG]
|
|
185
|
+
function t(key, vars) {
|
|
186
|
+
let value = TEXT[key] || STRINGS.en[key] || key
|
|
187
|
+
if (vars) value = value.replace(/\{(\w+)\}/g, (_, name) => String(vars[name] ?? ''))
|
|
188
|
+
return value
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function formatRelative(ms) {
|
|
192
|
+
const diff = Date.now() - ms
|
|
193
|
+
if (diff >= 0 && diff < 60_000) return t('justNow')
|
|
194
|
+
if (diff >= 0 && diff < 3_600_000) return t('minutesAgo', { n: Math.floor(diff / 60_000) })
|
|
195
|
+
if (diff >= 0 && diff < 86_400_000) return t('hoursAgo', { n: Math.floor(diff / 3_600_000) })
|
|
196
|
+
return ''
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function copyText(text) {
|
|
200
|
+
if (navigator.clipboard && typeof navigator.clipboard.writeText === 'function') {
|
|
201
|
+
return navigator.clipboard.writeText(text)
|
|
202
|
+
}
|
|
203
|
+
return new Promise((resolve, reject) => {
|
|
204
|
+
const area = document.createElement('textarea')
|
|
205
|
+
area.value = text
|
|
206
|
+
document.body.appendChild(area)
|
|
207
|
+
area.select()
|
|
208
|
+
try {
|
|
209
|
+
if (document.execCommand('copy')) resolve()
|
|
210
|
+
else reject(new Error('copy failed'))
|
|
211
|
+
} finally {
|
|
212
|
+
area.remove()
|
|
213
|
+
}
|
|
214
|
+
})
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function insertIntoComposer(text) {
|
|
218
|
+
const element = document.querySelector('textarea, input[type="text"], [contenteditable="true"], [role="textbox"]')
|
|
219
|
+
if (!element) return false
|
|
220
|
+
element.focus()
|
|
221
|
+
if (element.tagName === 'TEXTAREA' || element.tagName === 'INPUT') {
|
|
222
|
+
const start = typeof element.selectionStart === 'number' ? element.selectionStart : element.value.length
|
|
223
|
+
const end = typeof element.selectionEnd === 'number' ? element.selectionEnd : start
|
|
224
|
+
if (typeof element.setRangeText === 'function') element.setRangeText(text, start, end, 'end')
|
|
225
|
+
else element.value = element.value.slice(0, start) + text + element.value.slice(end)
|
|
226
|
+
element.dispatchEvent(new Event('input', { bubbles: true }))
|
|
227
|
+
return true
|
|
228
|
+
}
|
|
229
|
+
return document.execCommand('insertText', false, text)
|
|
230
|
+
}
|
|
231
|
+
|
|
107
232
|
// ── helpers ─────────────────────────────────────────────────────────────
|
|
108
233
|
function formatSize(bytes) {
|
|
109
234
|
if (!bytes) return ''
|
|
@@ -122,11 +247,8 @@ window.__ModuleLoader__.load({
|
|
|
122
247
|
if (!ms) return ''
|
|
123
248
|
const date = new Date(ms)
|
|
124
249
|
if (Number.isNaN(date.getTime())) return ''
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
if (diff >= 0 && diff < 60_000) return '刚刚'
|
|
128
|
-
if (diff >= 0 && diff < 3_600_000) return Math.floor(diff / 60_000) + ' 分钟前'
|
|
129
|
-
if (diff >= 0 && diff < 86_400_000) return Math.floor(diff / 3_600_000) + ' 小时前'
|
|
250
|
+
const relative = formatRelative(ms)
|
|
251
|
+
if (relative !== '') return relative
|
|
130
252
|
const pad = value => String(value).padStart(2, '0')
|
|
131
253
|
return date.getFullYear() + '-' + pad(date.getMonth() + 1) + '-' + pad(date.getDate())
|
|
132
254
|
}
|
|
@@ -239,38 +361,38 @@ window.__ModuleLoader__.load({
|
|
|
239
361
|
}
|
|
240
362
|
}, [sort])
|
|
241
363
|
|
|
364
|
+
const notify = useCallback(message => {
|
|
365
|
+
setToast(message)
|
|
366
|
+
setTimeout(() => setToast(''), 1600)
|
|
367
|
+
}, [])
|
|
368
|
+
|
|
242
369
|
const copy = useCallback(hit => {
|
|
243
370
|
if (!hit) return
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
setToast('已复制路径')
|
|
247
|
-
setTimeout(() => setToast(''), 1500)
|
|
248
|
-
}
|
|
249
|
-
if (navigator.clipboard && typeof navigator.clipboard.writeText === 'function') {
|
|
250
|
-
navigator.clipboard.writeText(text).then(done).catch(() => {})
|
|
251
|
-
return
|
|
252
|
-
}
|
|
253
|
-
const area = document.createElement('textarea')
|
|
254
|
-
area.value = text
|
|
255
|
-
document.body.appendChild(area)
|
|
256
|
-
area.select()
|
|
257
|
-
try {
|
|
258
|
-
document.execCommand('copy')
|
|
259
|
-
done()
|
|
260
|
-
} finally {
|
|
261
|
-
area.remove()
|
|
262
|
-
}
|
|
263
|
-
}, [])
|
|
371
|
+
copyText(hit.path).then(() => notify(t('copied'))).catch(() => {})
|
|
372
|
+
}, [notify])
|
|
264
373
|
|
|
265
374
|
const reveal = useCallback(hit => {
|
|
266
375
|
if (!hit) return
|
|
267
|
-
post('/dsh-locator/reveal', { path: hit.path }).then(() =>
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
})
|
|
273
|
-
}, [copy])
|
|
376
|
+
post('/dsh-locator/reveal', { path: hit.path }).then(() => notify(t('revealed'))).catch(() => copy(hit))
|
|
377
|
+
}, [copy, notify])
|
|
378
|
+
|
|
379
|
+
const openFile = useCallback(hit => {
|
|
380
|
+
if (!hit || hit.dir) return
|
|
381
|
+
post('/dsh-locator/open', { path: hit.path }).then(() => notify(t('opened'))).catch(() => copy(hit))
|
|
382
|
+
}, [copy, notify])
|
|
383
|
+
|
|
384
|
+
const insert = useCallback(hit => {
|
|
385
|
+
if (!hit) return
|
|
386
|
+
const mention = '@"' + hit.path.replace(/"/g, '') + '" '
|
|
387
|
+
close()
|
|
388
|
+
setTimeout(() => {
|
|
389
|
+
if (insertIntoComposer(mention)) {
|
|
390
|
+
notify(t('inserted'))
|
|
391
|
+
} else {
|
|
392
|
+
copyText(mention).then(() => notify(t('insertFailed'))).catch(() => {})
|
|
393
|
+
}
|
|
394
|
+
}, 80)
|
|
395
|
+
}, [close, notify])
|
|
274
396
|
|
|
275
397
|
const onKeyDown = useCallback(event => {
|
|
276
398
|
if (event.key === 'Escape') {
|
|
@@ -288,11 +410,22 @@ window.__ModuleLoader__.load({
|
|
|
288
410
|
setSelected(value => Math.max(0, value - 1))
|
|
289
411
|
return
|
|
290
412
|
}
|
|
413
|
+
const modifier = event.ctrlKey || event.metaKey
|
|
414
|
+
if (modifier && String(event.key).toLowerCase() === 'o') {
|
|
415
|
+
event.preventDefault()
|
|
416
|
+
openFile(hits[selected])
|
|
417
|
+
return
|
|
418
|
+
}
|
|
419
|
+
if (modifier && event.key === 'Enter' && !event.isComposing) {
|
|
420
|
+
event.preventDefault()
|
|
421
|
+
insert(hits[selected])
|
|
422
|
+
return
|
|
423
|
+
}
|
|
291
424
|
if (event.key === 'Enter' && !event.isComposing) {
|
|
292
425
|
event.preventDefault()
|
|
293
426
|
copy(hits[selected])
|
|
294
427
|
}
|
|
295
|
-
}, [close, copy, hits, selected])
|
|
428
|
+
}, [close, copy, hits, insert, openFile, selected])
|
|
296
429
|
|
|
297
430
|
useEffect(() => {
|
|
298
431
|
const list = listRef.current
|
|
@@ -308,7 +441,7 @@ window.__ModuleLoader__.load({
|
|
|
308
441
|
className: sort === key ? 'sorted' : '',
|
|
309
442
|
style: { width },
|
|
310
443
|
onClick: () => toggleSort(key),
|
|
311
|
-
title: '
|
|
444
|
+
title: t('sortTitle'),
|
|
312
445
|
}, label + (sort === key ? (desc ? ' ↓' : ' ↑') : ''))
|
|
313
446
|
|
|
314
447
|
return h('div', {
|
|
@@ -318,7 +451,7 @@ window.__ModuleLoader__.load({
|
|
|
318
451
|
className: 'dsh-locator-panel',
|
|
319
452
|
role: 'dialog',
|
|
320
453
|
'aria-modal': 'true',
|
|
321
|
-
'aria-label': '
|
|
454
|
+
'aria-label': t('dialog'),
|
|
322
455
|
onKeyDown,
|
|
323
456
|
},
|
|
324
457
|
h('div', { className: 'dsh-locator-head' },
|
|
@@ -329,24 +462,28 @@ window.__ModuleLoader__.load({
|
|
|
329
462
|
value: query,
|
|
330
463
|
spellCheck: false,
|
|
331
464
|
autoComplete: 'off',
|
|
332
|
-
placeholder: '
|
|
465
|
+
placeholder: t('placeholder'),
|
|
333
466
|
onChange: event => setQuery(event.target.value),
|
|
334
|
-
'aria-label': '
|
|
467
|
+
'aria-label': t('searchLabel'),
|
|
335
468
|
}),
|
|
336
469
|
h('span', { className: 'dsh-locator-kbd' }, 'Ctrl+Shift+F'),
|
|
337
|
-
h('button', { className: 'dsh-locator-close', onClick: close, title: '
|
|
470
|
+
h('button', { className: 'dsh-locator-close', onClick: close, title: t('closeTitle'), 'aria-label': t('closeLabel') }, '✕'),
|
|
338
471
|
),
|
|
339
472
|
h('div', { className: 'dsh-locator-bar' },
|
|
340
473
|
h('label', { className: 'dsh-locator-check' },
|
|
341
474
|
h('input', { type: 'checkbox', checked: filesOnly, onChange: event => { setFilesOnly(event.target.checked); if (event.target.checked) setDirsOnly(false) } }),
|
|
342
|
-
'
|
|
475
|
+
t('filesOnly')),
|
|
343
476
|
h('label', { className: 'dsh-locator-check' },
|
|
344
477
|
h('input', { type: 'checkbox', checked: dirsOnly, onChange: event => { setDirsOnly(event.target.checked); if (event.target.checked) setFilesOnly(false) } }),
|
|
345
|
-
'
|
|
478
|
+
t('dirsOnly')),
|
|
346
479
|
h('span', { className: 'dsh-locator-status' },
|
|
347
480
|
status === null
|
|
348
|
-
? '
|
|
349
|
-
:
|
|
481
|
+
? t('statusLoading')
|
|
482
|
+
: t('status', {
|
|
483
|
+
entries: (status.entries || 0).toLocaleString(),
|
|
484
|
+
mode: status.watching ? t('live') : t('snapshot'),
|
|
485
|
+
roots: (status.roots || []).length,
|
|
486
|
+
}) + ((status.usnActive || status.usn) ? ' · ' + t('usn') : '')),
|
|
350
487
|
),
|
|
351
488
|
h('div', { className: 'dsh-locator-scroll', ref: listRef },
|
|
352
489
|
h('table', { className: 'dsh-locator-table' },
|
|
@@ -357,15 +494,15 @@ window.__ModuleLoader__.load({
|
|
|
357
494
|
h('col', { style: { width: '41%' } }),
|
|
358
495
|
),
|
|
359
496
|
h('thead', null, h('tr', null,
|
|
360
|
-
header('name', '
|
|
361
|
-
header('size', '
|
|
362
|
-
header('mtime', '
|
|
363
|
-
header('path', '
|
|
497
|
+
header('name', t('name')),
|
|
498
|
+
header('size', t('size')),
|
|
499
|
+
header('mtime', t('mtime')),
|
|
500
|
+
header('path', t('path')),
|
|
364
501
|
)),
|
|
365
502
|
h('tbody', null,
|
|
366
503
|
hits.length === 0
|
|
367
504
|
? h('tr', null, h('td', { colSpan: 4, className: 'dsh-locator-empty' },
|
|
368
|
-
loading ? '
|
|
505
|
+
loading ? t('loading') : error !== '' ? t('errorPrefix') + error : t('empty')))
|
|
369
506
|
: hits.map((hit, index) => h('tr', {
|
|
370
507
|
key: hit.path,
|
|
371
508
|
'data-index': index,
|
|
@@ -375,7 +512,7 @@ window.__ModuleLoader__.load({
|
|
|
375
512
|
onDoubleClick: () => reveal(hit),
|
|
376
513
|
},
|
|
377
514
|
h('td', null, h('div', { className: 'dsh-locator-name' },
|
|
378
|
-
h('span', { className: 'dsh-locator-badge' }, hit.dir ? '
|
|
515
|
+
h('span', { className: 'dsh-locator-badge' }, hit.dir ? t('dirBadge') : (hit.ext || t('fileBadge')).toUpperCase()),
|
|
379
516
|
h('span', null, highlight(hit.name, query)),
|
|
380
517
|
)),
|
|
381
518
|
h('td', { className: 'dsh-locator-size' }, hit.dir ? '' : formatSize(hit.size)),
|
|
@@ -388,12 +525,12 @@ window.__ModuleLoader__.load({
|
|
|
388
525
|
h('div', { className: 'dsh-locator-foot' },
|
|
389
526
|
h('span', null,
|
|
390
527
|
loading
|
|
391
|
-
? '
|
|
392
|
-
: total.toLocaleString()
|
|
393
|
-
+ (status && status.scanning ? ' ·
|
|
528
|
+
? t('loading')
|
|
529
|
+
: t('results', { total: total.toLocaleString() }) + (truncated ? ' (' + t('showing', { n: hits.length }) + ')' : '') + ' · ' + took.toFixed(1) + ' ms'
|
|
530
|
+
+ (status && status.scanning ? ' · ' + t('indexing') : '')),
|
|
394
531
|
h('span', { className: 'grow' }),
|
|
395
532
|
toast === '' ? null : h('span', { className: 'dsh-locator-toast' }, toast),
|
|
396
|
-
h('span', null, '
|
|
533
|
+
h('span', null, t('footer')),
|
|
397
534
|
),
|
|
398
535
|
))
|
|
399
536
|
}
|
|
@@ -401,8 +538,8 @@ window.__ModuleLoader__.load({
|
|
|
401
538
|
function Launcher() {
|
|
402
539
|
return h('button', {
|
|
403
540
|
className: 'dsh-locator-launch',
|
|
404
|
-
title: '
|
|
405
|
-
'aria-label': '
|
|
541
|
+
title: t('launcher'),
|
|
542
|
+
'aria-label': t('searchLabel'),
|
|
406
543
|
onClick: () => store.toggle(),
|
|
407
544
|
}, '🔎')
|
|
408
545
|
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 980 380" width="980" height="380" role="img" aria-label="dsh-locator architecture">
|
|
2
|
+
<style>
|
|
3
|
+
.box{fill:#fff;stroke:#c9d1d9;stroke-width:1.5;rx:10}
|
|
4
|
+
.accent{fill:#eef4ff;stroke:#4f7cff}
|
|
5
|
+
.title{font:600 15px -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;fill:#1f2328}
|
|
6
|
+
.body{font:12px -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;fill:#57606a}
|
|
7
|
+
.mono{font:11px ui-monospace,SFMono-Regular,Consolas,monospace;fill:#57606a}
|
|
8
|
+
.arrow{stroke:#8c959f;stroke-width:1.6;fill:none;marker-end:url(#a)}
|
|
9
|
+
.label{font:11px -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;fill:#8c959f}
|
|
10
|
+
.chip{fill:#f6f8fa;stroke:#d0d7de;stroke-width:1}
|
|
11
|
+
</style>
|
|
12
|
+
<defs>
|
|
13
|
+
<marker id="a" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
|
14
|
+
<path d="M0 0L10 5L0 10z" fill="#8c959f"/>
|
|
15
|
+
</marker>
|
|
16
|
+
</defs>
|
|
17
|
+
|
|
18
|
+
<text class="title" x="24" y="32">dsh-locator — self-built index, no Everything</text>
|
|
19
|
+
|
|
20
|
+
<!-- filesystem -->
|
|
21
|
+
<rect class="box" x="24" y="58" width="190" height="150"/>
|
|
22
|
+
<text class="title" x="42" y="86">Filesystems</text>
|
|
23
|
+
<rect class="chip" x="42" y="102" width="154" height="26" rx="6"/><text class="body" x="54" y="119">Linux · inotify</text>
|
|
24
|
+
<rect class="chip" x="42" y="136" width="154" height="26" rx="6"/><text class="body" x="54" y="153">macOS · FSEvents</text>
|
|
25
|
+
<rect class="chip" x="42" y="170" width="154" height="26" rx="6"/><text class="body" x="54" y="187">Windows · USN/MFT</text>
|
|
26
|
+
|
|
27
|
+
<!-- ingest -->
|
|
28
|
+
<rect class="accent" x="258" y="58" width="220" height="150"/>
|
|
29
|
+
<text class="title" x="276" y="86">Scan & watch</text>
|
|
30
|
+
<text class="body" x="276" y="112">parallel walker (16 workers)</text>
|
|
31
|
+
<text class="body" x="276" y="134">MFT enumeration + journal reader</text>
|
|
32
|
+
<text class="body" x="276" y="156">native change watchers</text>
|
|
33
|
+
<text class="mono" x="276" y="184">fallback: rebuild / refresh</text>
|
|
34
|
+
|
|
35
|
+
<!-- snapshot -->
|
|
36
|
+
<rect class="box" x="522" y="58" width="196" height="150"/>
|
|
37
|
+
<text class="title" x="540" y="86">Compact snapshot</text>
|
|
38
|
+
<text class="body" x="540" y="112">40 B records · shared name arena</text>
|
|
39
|
+
<text class="body" x="540" y="134">open-addressed path table</text>
|
|
40
|
+
<text class="body" x="540" y="156">atomic save · mmap-friendly load</text>
|
|
41
|
+
<text class="mono" x="540" y="184">usn-state.json → journal cursor</text>
|
|
42
|
+
|
|
43
|
+
<!-- query -->
|
|
44
|
+
<rect class="box" x="762" y="58" width="190" height="150"/>
|
|
45
|
+
<text class="title" x="780" y="86">Query engine</text>
|
|
46
|
+
<text class="body" x="780" y="112">parse Everything-style terms</text>
|
|
47
|
+
<text class="body" x="780" y="134">parallel match · bounded top-K</text>
|
|
48
|
+
<text class="body" x="780" y="156">25–35 ms over 1.2 M entries</text>
|
|
49
|
+
|
|
50
|
+
<path class="arrow" d="M214 133H250"/>
|
|
51
|
+
<path class="arrow" d="M478 133H514"/>
|
|
52
|
+
<path class="arrow" d="M718 133H754"/>
|
|
53
|
+
|
|
54
|
+
<!-- consumers -->
|
|
55
|
+
<rect class="box" x="258" y="254" width="300" height="88"/>
|
|
56
|
+
<text class="title" x="276" y="282">Agent tools (host side)</text>
|
|
57
|
+
<text class="mono" x="276" y="306">locator_search · locator_status</text>
|
|
58
|
+
<text class="mono" x="276" y="326">locator_rebuild · locator_export</text>
|
|
59
|
+
|
|
60
|
+
<rect class="box" x="590" y="254" width="362" height="88"/>
|
|
61
|
+
<text class="title" x="608" y="282">Web panel · Ctrl+Shift+F</text>
|
|
62
|
+
<text class="mono" x="608" y="306">POST /dsh-locator/search · status</text>
|
|
63
|
+
<text class="mono" x="608" y="326">reveal · open · sort · filters · @file</text>
|
|
64
|
+
|
|
65
|
+
<path class="arrow" d="M600 208V246"/>
|
|
66
|
+
<path class="arrow" d="M700 208V246"/>
|
|
67
|
+
<text class="label" x="610" y="232">same snapshot, no second server</text>
|
|
68
|
+
</svg>
|
|
Binary file
|
|
Binary file
|
package/lib/http.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAElD,OAAO,KAAK,EAAE,cAAc,EAAc,MAAM,cAAc,CAAA;AA+B9D,oEAAoE;AACpE,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,cAAc,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAElD,OAAO,KAAK,EAAE,cAAc,EAAc,MAAM,cAAc,CAAA;AA+B9D,oEAAoE;AACpE,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,cAAc,GAAG,IAAI,CA6BnE"}
|
package/lib/http.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* service, and the plugin still works there through its tools.
|
|
12
12
|
* @module dsh-locator/http
|
|
13
13
|
*/
|
|
14
|
-
import { revealInFileManager, withinRoots } from "./reveal.js";
|
|
14
|
+
import { openWithDefaultApp, revealInFileManager, withinRoots } from "./reveal.js";
|
|
15
15
|
import { statSync } from 'node:fs';
|
|
16
16
|
const BODY_LIMIT = 64 * 1024;
|
|
17
17
|
/** Mount the panel's routes when this profile runs a Web server. */
|
|
@@ -38,6 +38,11 @@ export function registerHttp(ctx, rt) {
|
|
|
38
38
|
path: '/dsh-locator/reveal',
|
|
39
39
|
handler: handler(scoped, async (body) => await reveal(rt, body)),
|
|
40
40
|
}));
|
|
41
|
+
scoped.effect(() => server.register({
|
|
42
|
+
kind: 'exact',
|
|
43
|
+
path: '/dsh-locator/open',
|
|
44
|
+
handler: handler(scoped, async (body) => await openPath(rt, body)),
|
|
45
|
+
}));
|
|
41
46
|
});
|
|
42
47
|
}
|
|
43
48
|
function handler(scoped, run) {
|
|
@@ -111,6 +116,27 @@ async function reveal(rt, raw) {
|
|
|
111
116
|
return { ok: false, error: messageOf(error) };
|
|
112
117
|
}
|
|
113
118
|
}
|
|
119
|
+
async function openPath(rt, raw) {
|
|
120
|
+
const path = typeof raw.path === 'string' ? raw.path : '';
|
|
121
|
+
if (path === '' || !withinRoots(path, rt.roots)) {
|
|
122
|
+
return { ok: false, error: 'path is outside the indexed roots' };
|
|
123
|
+
}
|
|
124
|
+
try {
|
|
125
|
+
const info = statSync(path);
|
|
126
|
+
if (!info.isFile())
|
|
127
|
+
return { ok: false, error: 'not a file' };
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
return { ok: false, error: 'path does not exist' };
|
|
131
|
+
}
|
|
132
|
+
try {
|
|
133
|
+
await openWithDefaultApp(path);
|
|
134
|
+
return { ok: true };
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
return { ok: false, error: messageOf(error) };
|
|
138
|
+
}
|
|
139
|
+
}
|
|
114
140
|
async function status(rt) {
|
|
115
141
|
rt.start();
|
|
116
142
|
const engine = await rt.engineStatus();
|
package/lib/http.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
|
package/lib/reveal.d.ts
CHANGED
|
@@ -5,9 +5,11 @@
|
|
|
5
5
|
/** Whether target is one of the roots or lives below one of them. */
|
|
6
6
|
export declare function withinRoots(target: string, roots: readonly string[]): boolean;
|
|
7
7
|
/**
|
|
8
|
-
* Ask the platform
|
|
9
|
-
* a shell, so a path can never be interpreted as a command. The
|
|
10
|
-
* detached: the opener outlives the plugin call.
|
|
8
|
+
* Ask the platform to reveal a path in its file manager. Uses an argument
|
|
9
|
+
* vector, not a shell, so a path can never be interpreted as a command. The
|
|
10
|
+
* child is detached: the opener outlives the plugin call.
|
|
11
11
|
*/
|
|
12
12
|
export declare function revealInFileManager(target: string): Promise<void>;
|
|
13
|
+
/** Open a path with its default application. */
|
|
14
|
+
export declare function openWithDefaultApp(target: string): Promise<void>;
|
|
13
15
|
//# sourceMappingURL=reveal.d.ts.map
|
package/lib/reveal.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reveal.d.ts","sourceRoot":"","sources":["../src/reveal.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,qEAAqE;AACrE,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAS7E;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"reveal.d.ts","sourceRoot":"","sources":["../src/reveal.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,qEAAqE;AACrE,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAS7E;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKvE;AAED,gDAAgD;AAChD,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKtE"}
|
package/lib/reveal.js
CHANGED
|
@@ -18,26 +18,28 @@ export function withinRoots(target, roots) {
|
|
|
18
18
|
return false;
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
|
-
* Ask the platform
|
|
22
|
-
* a shell, so a path can never be interpreted as a command. The
|
|
23
|
-
* detached: the opener outlives the plugin call.
|
|
21
|
+
* Ask the platform to reveal a path in its file manager. Uses an argument
|
|
22
|
+
* vector, not a shell, so a path can never be interpreted as a command. The
|
|
23
|
+
* child is detached: the opener outlives the plugin call.
|
|
24
24
|
*/
|
|
25
25
|
export async function revealInFileManager(target) {
|
|
26
26
|
const absolute = resolve(target);
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
if (process.platform === '
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
27
|
+
if (process.platform === 'win32')
|
|
28
|
+
return spawnDetached('explorer.exe', [`/select,${absolute}`]);
|
|
29
|
+
if (process.platform === 'darwin')
|
|
30
|
+
return spawnDetached('open', ['-R', absolute]);
|
|
31
|
+
return spawnDetached('xdg-open', [dirname(absolute)]);
|
|
32
|
+
}
|
|
33
|
+
/** Open a path with its default application. */
|
|
34
|
+
export async function openWithDefaultApp(target) {
|
|
35
|
+
const absolute = resolve(target);
|
|
36
|
+
if (process.platform === 'win32')
|
|
37
|
+
return spawnDetached('explorer.exe', [absolute]);
|
|
38
|
+
if (process.platform === 'darwin')
|
|
39
|
+
return spawnDetached('open', [absolute]);
|
|
40
|
+
return spawnDetached('xdg-open', [absolute]);
|
|
41
|
+
}
|
|
42
|
+
async function spawnDetached(command, args) {
|
|
41
43
|
await new Promise((resolvePromise, reject) => {
|
|
42
44
|
const child = spawn(command, args, { detached: true, stdio: 'ignore', windowsHide: true });
|
|
43
45
|
child.once('error', reject);
|
package/lib/reveal.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reveal.js","sourceRoot":"","sources":["../src/reveal.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAC1C,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAElE,qEAAqE;AACrE,MAAM,UAAU,WAAW,CAAC,MAAc,EAAE,KAAwB;IAClE,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAA;IACrC,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAChC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;QAC1B,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;QACpC,IAAI,GAAG,KAAK,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;YAAE,OAAO,IAAI,CAAA;IAC5E,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,MAAc;IACtD,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAChC,IAAI,
|
|
1
|
+
{"version":3,"file":"reveal.js","sourceRoot":"","sources":["../src/reveal.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAA;AAC1C,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAElE,qEAAqE;AACrE,MAAM,UAAU,WAAW,CAAC,MAAc,EAAE,KAAwB;IAClE,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAA;IACrC,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAChC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;QAC1B,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAA;QACpC,IAAI,GAAG,KAAK,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;YAAE,OAAO,IAAI,CAAA;IAC5E,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,MAAc;IACtD,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAChC,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO,aAAa,CAAC,cAAc,EAAE,CAAC,WAAW,QAAQ,EAAE,CAAC,CAAC,CAAA;IAC/F,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ;QAAE,OAAO,aAAa,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAA;IACjF,OAAO,aAAa,CAAC,UAAU,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;AACvD,CAAC;AAED,gDAAgD;AAChD,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,MAAc;IACrD,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAChC,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO,aAAa,CAAC,cAAc,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAA;IAClF,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ;QAAE,OAAO,aAAa,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAA;IAC3E,OAAO,aAAa,CAAC,UAAU,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAA;AAC9C,CAAC;AAED,KAAK,UAAU,aAAa,CAAC,OAAe,EAAE,IAAc;IAC1D,MAAM,IAAI,OAAO,CAAO,CAAC,cAAc,EAAE,MAAM,EAAE,EAAE;QACjD,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAA;QAC1F,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QAC3B,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE;YACvB,KAAK,CAAC,KAAK,EAAE,CAAA;YACb,cAAc,EAAE,CAAA;QAClB,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-locator",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"description": "Whole-disk, millisecond file search for DeepSeek Harness without Everything: a self-built cross-platform index, an Everything-style query language, agent tools and a Web search panel (Ctrl+Shift+F). Windows, macOS and Linux.",
|
|
5
5
|
"author": "PerryLink contributors",
|
|
6
6
|
"repository": {
|
|
@@ -33,9 +33,13 @@
|
|
|
33
33
|
"cordis.patch.yml",
|
|
34
34
|
"CHANGELOG.md",
|
|
35
35
|
"README.md",
|
|
36
|
-
"README-zh.md",
|
|
37
36
|
"LICENSE",
|
|
38
|
-
"SECURITY.md"
|
|
37
|
+
"SECURITY.md",
|
|
38
|
+
"README.en.md",
|
|
39
|
+
"README-es.md",
|
|
40
|
+
"README-pt.md",
|
|
41
|
+
"README-hi.md",
|
|
42
|
+
"docs/assets"
|
|
39
43
|
],
|
|
40
44
|
"sideEffects": false,
|
|
41
45
|
"dsh": {
|