Chore: uFuzzy 1.0.2 (#62276)

Co-authored-by: joshhunt <josh@trtr.co>
This commit is contained in:
Leon Sorokin
2023-02-02 09:09:48 -06:00
committed by GitHub
parent 1aae808723
commit 4d564f8b0a
7 changed files with 63 additions and 66 deletions

View File

@@ -186,8 +186,8 @@ function useInternalMatches(filtered: ActionImpl[], search: string): Match[] {
return throttledFiltered.map((action) => ({ score: 0, action }));
}
const haystack = throttledFiltered.map((action) =>
[action.name, action.keywords, action.subtitle].join(' ').toLowerCase()
const haystack = throttledFiltered.map(({ name, keywords, subtitle }) =>
`${name} ${keywords ?? ''} ${subtitle ?? ''}`.toLowerCase()
);
const results: Match[] = [];
@@ -201,35 +201,27 @@ function useInternalMatches(filtered: ActionImpl[], search: string): Match[] {
const haystackItem = haystack[haystackIndex];
// Use the position of the match as a stand-in for score
const substringPosition = haystackItem.toLowerCase().indexOf(query);
const substringPosition = haystackItem.indexOf(query);
if (substringPosition > -1) {
const score = haystack.length - substringPosition;
const score = substringPosition * -1; // lower position of the match should be a higher priority score
const action = throttledFiltered[haystackIndex];
results.push({ score, action });
}
}
} else {
const allMatchedIndexes = new Set<number>();
const termCount = ufuzzy.split(throttledSearch).length;
const infoThresh = Infinity;
const oooSearch = termCount < 5;
const queryWords = ufuzzy.split(throttledSearch);
const queryPermutations =
queryWords.length < 5 ? uFuzzy.permute(queryWords).map((terms) => terms.join(' ')) : [throttledSearch];
for (const permutedSearchTerm of queryPermutations) {
const indexes = ufuzzy.filter(haystack, permutedSearchTerm);
const info = ufuzzy.info(indexes, haystack, permutedSearchTerm);
const order = ufuzzy.sort(info, haystack, permutedSearchTerm);
const [, info, order] = ufuzzy.search(haystack, throttledSearch, oooSearch, infoThresh);
if (info && order) {
for (let orderIndex = 0; orderIndex < order.length; orderIndex++) {
const actionIndex = order[orderIndex];
if (!allMatchedIndexes.has(actionIndex)) {
allMatchedIndexes.add(actionIndex);
const score = order.length - orderIndex;
const action = throttledFiltered[info.idx[actionIndex]];
results.push({ score, action });
}
const score = order.length - orderIndex;
const action = throttledFiltered[info.idx[actionIndex]];
results.push({ score, action });
}
}
}

View File

@@ -116,28 +116,27 @@ class FullResultCache {
// eslint-disable-next-line
const values = allFields.map((v) => [] as any[]); // empty value for each field
// out-of-order terms
const oooIdxs = new Set<number>();
const queryTerms = this.ufuzzy.split(query);
const oooNeedles = uFuzzy.permute(queryTerms).map((terms) => terms.join(' '));
let [idxs, info, order] = this.ufuzzy.search(haystack, query, true);
oooNeedles.forEach((needle) => {
let idxs = this.ufuzzy.filter(haystack, needle);
let info = this.ufuzzy.info(idxs, haystack, needle);
let order = this.ufuzzy.sort(info, haystack, needle);
for (let c = 0; c < allFields.length; c++) {
let src = allFields[c].values.toArray();
let dst = values[c];
for (let i = 0; i < order.length; i++) {
let haystackIdx = info.idx[order[i]];
if (!oooIdxs.has(haystackIdx)) {
oooIdxs.add(haystackIdx);
for (let c = 0; c < allFields.length; c++) {
values[c].push(allFields[c].values.get(haystackIdx));
}
// <= 1000 matches (ranked)
if (info && order) {
for (let i = 0; i < order.length; i++) {
let haystackIdx = info.idx[order[i]];
dst.push(src[haystackIdx]);
}
}
});
// > 1000 matches (unranked)
else {
for (let i = 0; i < idxs.length; i++) {
let haystackIdx = idxs[i];
dst.push(src[haystackIdx]);
}
}
}
// mutates the search object
this.empty.dataFrame.fields.forEach((f, idx) => {

View File

@@ -18,7 +18,7 @@
// THIS SOFTWARE.
import { css } from '@emotion/css';
import uFuzzy from '@leeoniya/ufuzzy';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useMeasure } from 'react-use';
import { CoreApp, createTheme, DataFrame, FieldType, getDisplayProcessor } from '@grafana/data';
@@ -90,6 +90,26 @@ const FlameGraph = ({
[levels, totalTicks, rangeMin]
);
const [ufuzzy] = useState(() => {
return new uFuzzy();
});
const uniqueLabels = useMemo(() => {
return [...new Set<string>(data.fields.find((f) => f.name === 'label')?.values.toArray())];
}, [data]);
const foundLabels = useMemo(() => {
const foundLabels = new Set<string>();
if (search) {
for (let idx of ufuzzy.filter(uniqueLabels, search)) {
foundLabels.add(uniqueLabels[idx]);
}
}
return foundLabels;
}, [ufuzzy, search, uniqueLabels]);
const render = useCallback(
(pixelsPerTick: number) => {
if (!levels.length) {
@@ -113,11 +133,6 @@ const FlameGraph = ({
theme: createTheme() /* theme does not matter for us here */,
});
const ufuzzy = new uFuzzy({
intraMode: 0,
intraIns: 0,
});
for (let levelIndex = 0; levelIndex < levels.length; levelIndex++) {
const level = levels[levelIndex];
// Get all the dimensions of the rectangles for the level. We do this by level instead of per rectangle, because
@@ -125,11 +140,11 @@ const FlameGraph = ({
const dimensions = getRectDimensionsForLevel(level, levelIndex, totalTicks, rangeMin, pixelsPerTick, processor);
for (const rect of dimensions) {
// Render each rectangle based on the computed dimensions
renderRect(ctx, rect, totalTicks, rangeMin, rangeMax, search, levelIndex, topLevelIndex, ufuzzy);
renderRect(ctx, rect, totalTicks, rangeMin, rangeMax, search, levelIndex, topLevelIndex, foundLabels);
}
}
},
[levels, wrapperWidth, valueField, totalTicks, rangeMin, rangeMax, search, topLevelIndex]
[levels, wrapperWidth, valueField, totalTicks, rangeMin, rangeMax, search, topLevelIndex, foundLabels]
);
useEffect(() => {

View File

@@ -86,7 +86,7 @@ export function renderRect(
query: string,
levelIndex: number,
topLevelIndex: number,
ufuzzy: uFuzzy
foundNames: Set<string>
) {
if (rect.width < HIDE_THRESHOLD) {
return;
@@ -101,19 +101,17 @@ export function renderRect(
const l = 65 + 7 * intensity;
const name = rect.label;
const idxs = ufuzzy.filter([name], query);
const queryResult = query && idxs.length > 0;
if (!rect.collapsed) {
ctx.stroke();
if (query) {
ctx.fillStyle = queryResult ? getBarColor(h, l) : colors[55];
ctx.fillStyle = foundNames.has(name) ? getBarColor(h, l) : colors[55];
} else {
ctx.fillStyle = levelIndex > topLevelIndex - 1 ? getBarColor(h, l) : getBarColor(h, l + 15);
}
} else {
ctx.fillStyle = queryResult ? getBarColor(h, l) : colors[55];
ctx.fillStyle = foundNames.has(name) ? getBarColor(h, l) : colors[55];
}
ctx.fill();