mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-11 16:09:39 +00:00
* fix: allowlist resource_type and escape search highlights * fix: bound path length and keep marked-label offsets entity-aware * fix: match postgres word-char semantics and drop double-escaping * fix: sanitize db constraint and rls errors instead of relying on the regex
58 lines
1.6 KiB
Svelte
58 lines
1.6 KiB
Svelte
<script lang="ts">
|
|
import uFuzzy from '@leeoniya/ufuzzy'
|
|
import { untrack } from 'svelte'
|
|
import { escapeHtml } from '$lib/utils'
|
|
|
|
interface Props {
|
|
filter?: string
|
|
items: any[] | undefined
|
|
f: (item: any) => string
|
|
filteredItems: (any & { marked: string })[] | undefined
|
|
opts?: uFuzzy.Options
|
|
}
|
|
|
|
let { filter = '', items, f, filteredItems = $bindable(), opts = {} }: Props = $props()
|
|
|
|
let uf = new uFuzzy(untrack(() => opts))
|
|
|
|
// Consumers render `marked` with {@html}, and the searched text is workspace
|
|
// content (paths, descriptions, resource types, ...). uFuzzy's default mark
|
|
// concatenates the raw substrings, so escape every part and let only the
|
|
// <mark> wrapper through as markup.
|
|
const markEscaped = (part: string, matched: boolean) =>
|
|
matched ? `<mark>${escapeHtml(part)}</mark>` : escapeHtml(part)
|
|
|
|
function filterItems() {
|
|
let trimmed = filter.trim()
|
|
if (items == undefined || trimmed.length == 0) {
|
|
filteredItems = items
|
|
return
|
|
}
|
|
// pre-filter
|
|
let idxs = uf.filter(plaintextItems, trimmed) ?? []
|
|
|
|
let info = uf.info(idxs, plaintextItems, trimmed)
|
|
let order = uf.sort(info, plaintextItems, trimmed)
|
|
|
|
let result: any[] = []
|
|
|
|
for (let i = 0; i < order.length; i++) {
|
|
let infoIdx = order[i]
|
|
result.push({
|
|
...items[info.idx[infoIdx]],
|
|
marked: uFuzzy.highlight(
|
|
plaintextItems[info.idx[infoIdx]],
|
|
info.ranges[infoIdx],
|
|
markEscaped
|
|
)
|
|
})
|
|
}
|
|
filteredItems = result
|
|
}
|
|
let plaintextItems = $derived(items?.map((item) => f(item)) ?? [])
|
|
|
|
$effect.pre(() => {
|
|
plaintextItems && filter != undefined && setTimeout(() => untrack(() => filterItems()), 0)
|
|
})
|
|
</script>
|