@objectivex666/dsh-settings-search 1.2.0 → 1.3.0
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/LICENSE +674 -674
- package/lib/client.js +69 -22
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -135,26 +135,50 @@ window.__ModuleLoader__.load({
|
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
/**
|
|
138
|
-
* Read visible titles for self-drawing occupants out of the live DOM
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
138
|
+
* Read visible titles for self-drawing occupants out of the live DOM.
|
|
139
|
+
* Two shell shapes exist for `[data-slot="<name>"]`:
|
|
140
|
+
* - per-occupant anchors: one element each, count === regs → pair ids;
|
|
141
|
+
* - a single WRAPPER around all rows (e.g. settings.general.item's
|
|
142
|
+
* stacked section): harvest each direct child as one row, keyed by
|
|
143
|
+
* render order ("#i") since id pairing is impossible.
|
|
142
144
|
*/
|
|
143
145
|
const runHarvest = () => {
|
|
144
146
|
let grew = false
|
|
145
147
|
if (typeof document === 'undefined') return false
|
|
148
|
+
let map
|
|
146
149
|
for (const cfg of DEEP_SLOTS) {
|
|
147
|
-
let
|
|
148
|
-
try {
|
|
150
|
+
let containers = []
|
|
151
|
+
try { containers = [...document.querySelectorAll(`[data-slot="${cfg.slot}"]`)] } catch { continue }
|
|
149
152
|
const regs = sortEntries(entriesOf(cfg.slot))
|
|
150
|
-
if (
|
|
151
|
-
let
|
|
153
|
+
if (regs.length === 0) continue
|
|
154
|
+
let nodes = []
|
|
155
|
+
if (containers.length === 1 && containers[0].childElementCount > 0) {
|
|
156
|
+
nodes = [...containers[0].children]
|
|
157
|
+
} else {
|
|
158
|
+
nodes = containers.filter((n) => n.childElementCount >= 0)
|
|
159
|
+
}
|
|
160
|
+
if (nodes.length === 0) continue
|
|
161
|
+
map = harvest.get(cfg.slot)
|
|
152
162
|
if (map === undefined) { map = new Map(); harvest.set(cfg.slot, map) }
|
|
163
|
+
if (nodes.length !== regs.length) {
|
|
164
|
+
// wrapper shape: index-keyed loose harvest of every rendered row
|
|
165
|
+
nodes.forEach((node, i) => {
|
|
166
|
+
const key = '#' + i
|
|
167
|
+
if (map.has(key)) return
|
|
168
|
+
const title = titleFromNode(node)
|
|
169
|
+
if (title === '') return
|
|
170
|
+
const text = (node.textContent ?? '').replace(/\s+/g, ' ').trim().slice(0, 160)
|
|
171
|
+
map.set(key, { title, idx: i, text }); grew = true
|
|
172
|
+
})
|
|
173
|
+
continue
|
|
174
|
+
}
|
|
153
175
|
regs.forEach((entry, i) => {
|
|
154
176
|
const id = String(entry.options?.id ?? i)
|
|
155
177
|
if (map.has(id)) return
|
|
156
178
|
const title = titleFromNode(nodes[i])
|
|
157
|
-
if (title
|
|
179
|
+
if (title === '') return
|
|
180
|
+
const text = (nodes[i].textContent ?? '').replace(/\s+/g, ' ').trim().slice(0, 160)
|
|
181
|
+
map.set(id, { title, idx: i, text }); grew = true
|
|
158
182
|
})
|
|
159
183
|
}
|
|
160
184
|
if (grew) harvestSeq += 1
|
|
@@ -194,24 +218,30 @@ window.__ModuleLoader__.load({
|
|
|
194
218
|
const out = []
|
|
195
219
|
for (const cfg of DEEP_SLOTS) {
|
|
196
220
|
const mapped = harvest.get(cfg.slot)
|
|
197
|
-
|
|
221
|
+
sortEntries(entriesOf(cfg.slot)).forEach((entry, i) => {
|
|
198
222
|
const id = String(entry.options?.id ?? '')
|
|
199
|
-
if (id === '')
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
223
|
+
if (id === '') return
|
|
224
|
+
// static label first, then id-paired harvest, then loose index-keyed harvest
|
|
225
|
+
const hitId = mapped?.get(id)
|
|
226
|
+
const hitIdx = mapped?.get('#' + i)
|
|
227
|
+
const hitObj = typeof hitId === 'object' ? hitId : (typeof hitIdx === 'object' ? hitIdx : undefined)
|
|
228
|
+
const label = staticLabel(entry, cfg) || hitObj?.title || ''
|
|
229
|
+
if (label === '') return // unmapped, unharvested — invisible until it renders once
|
|
230
|
+
const key = cfg.slot + '#' + id
|
|
231
|
+
if (out.some((e) => e.key === key)) return
|
|
204
232
|
out.push({
|
|
205
233
|
kind: 'option',
|
|
206
|
-
key
|
|
234
|
+
key,
|
|
207
235
|
slot: cfg.slot,
|
|
208
236
|
id,
|
|
209
237
|
order: entry.options?.order ?? 0,
|
|
210
238
|
label,
|
|
239
|
+
hay: label + ' ' + (hitObj?.text ?? ''),
|
|
240
|
+
rowIndex: hitObj?.idx ?? i,
|
|
211
241
|
parentId: cfg.parent,
|
|
212
242
|
parentLabel: parentLabel(cfg.parent),
|
|
213
243
|
})
|
|
214
|
-
}
|
|
244
|
+
})
|
|
215
245
|
}
|
|
216
246
|
return out.sort((a, b) => a.parentLabel !== b.parentLabel
|
|
217
247
|
? a.parentLabel.localeCompare(b.parentLabel)
|
|
@@ -232,8 +262,10 @@ window.__ModuleLoader__.load({
|
|
|
232
262
|
const want = String(wantText ?? '').trim()
|
|
233
263
|
if (want === '') return false
|
|
234
264
|
const buttons = panelButtons()
|
|
235
|
-
const
|
|
236
|
-
|
|
265
|
+
const textOf = (b) => (b.textContent ?? '').trim()
|
|
266
|
+
const hit = buttons.find((b) => textOf(b) === want)
|
|
267
|
+
?? buttons.find((b) => textOf(b).startsWith(want))
|
|
268
|
+
?? buttons.find((b) => want.length >= 2 && textOf(b) !== '' && (textOf(b).includes(want) || want.includes(textOf(b))))
|
|
237
269
|
if (!hit) return false
|
|
238
270
|
hit.click()
|
|
239
271
|
return true
|
|
@@ -261,8 +293,23 @@ window.__ModuleLoader__.load({
|
|
|
261
293
|
/** Highlight the rendered row card for one indexed option. */
|
|
262
294
|
const flashOptionRow = (item) => {
|
|
263
295
|
try {
|
|
264
|
-
|
|
265
|
-
|
|
296
|
+
let target = null
|
|
297
|
+
if (typeof item.rowIndex === 'number') {
|
|
298
|
+
// wrapper shape: pick the exact rendered row by index
|
|
299
|
+
const container = document.querySelector(`[data-slot="${item.slot}"]`)
|
|
300
|
+
target = container?.children?.[item.rowIndex] ?? null
|
|
301
|
+
if (target && !(target.textContent ?? '').includes(item.label)) {
|
|
302
|
+
// index drift — fall through to textual match below
|
|
303
|
+
target = null
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
if (!target) {
|
|
307
|
+
const nodes = [...document.querySelectorAll(`[data-slot="${item.slot}"]`)]
|
|
308
|
+
const rows = nodes.length === 1 && nodes[0].childElementCount > 0
|
|
309
|
+
? [...nodes[0].children]
|
|
310
|
+
: nodes
|
|
311
|
+
target = rows.find((n) => (n.textContent ?? '').includes(item.label)) ?? null
|
|
312
|
+
}
|
|
266
313
|
if (!target) return
|
|
267
314
|
target.scrollIntoView({ block: 'nearest' })
|
|
268
315
|
target.classList.remove('sss-flash')
|
|
@@ -342,7 +389,7 @@ window.__ModuleLoader__.load({
|
|
|
342
389
|
? sections.filter((s) => matches(`${s.label} ${s.id}`.toLowerCase()))
|
|
343
390
|
: []
|
|
344
391
|
const shownOptions = q !== ''
|
|
345
|
-
? deeps.filter((o) => matches(`${o.
|
|
392
|
+
? deeps.filter((o) => matches(`${o.hay} ${o.parentLabel} ${o.id} ${o.slot}`.toLowerCase()))
|
|
346
393
|
: []
|
|
347
394
|
const none = q !== '' && shownPages.length === 0 && shownOptions.length === 0
|
|
348
395
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@objectivex666/dsh-settings-search",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "DSH settings panel search plugin – instantly filter setting sections and general items with navigation guidance. Installable via `dsh plugin add`.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dsh",
|