mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-22 12:36:24 +08:00
refactor(component): cmdk ordering (#5722)
Replace internal CMDK command filtering/sorting logic. The new implementation includes the following for command scoring: - categories weights - highlighted fragments - original command score value The new logic should be much cleaner and remove some hacks in the original implementation. Not sure if this is optimal yet. Could be changed later. fix https://github.com/toeverything/AFFiNE/issues/5699
This commit is contained in:
@@ -1,33 +0,0 @@
|
||||
import { describe, expect, test } from 'vitest';
|
||||
|
||||
import { highlightTextFragments } from '../affine/use-highlight';
|
||||
|
||||
describe('highlightTextFragments', () => {
|
||||
test('should correctly highlight full matches', () => {
|
||||
const highlights = highlightTextFragments('This is a test', 'is');
|
||||
expect(highlights).toStrictEqual([
|
||||
{ text: 'Th', highlight: false },
|
||||
{ text: 'is', highlight: true },
|
||||
{ text: ' is a test', highlight: false },
|
||||
]);
|
||||
});
|
||||
|
||||
test('highlight with space', () => {
|
||||
const result = highlightTextFragments('Hello World', 'lo w');
|
||||
expect(result).toEqual([
|
||||
{ text: 'Hel', highlight: false },
|
||||
{ text: 'lo W', highlight: true },
|
||||
{ text: 'orld', highlight: false },
|
||||
]);
|
||||
});
|
||||
|
||||
test('should correctly perform partial matching', () => {
|
||||
const highlights = highlightTextFragments('Hello World', 'hw');
|
||||
expect(highlights).toStrictEqual([
|
||||
{ text: 'H', highlight: true },
|
||||
{ text: 'ello ', highlight: false },
|
||||
{ text: 'W', highlight: true },
|
||||
{ text: 'orld', highlight: false },
|
||||
]);
|
||||
});
|
||||
});
|
||||
@@ -1,50 +0,0 @@
|
||||
import { useMemo } from 'react';
|
||||
|
||||
function* highlightTextFragmentsGenerator(text: string, query: string) {
|
||||
const lowerCaseText = text.toLowerCase();
|
||||
let startIndex = lowerCaseText.indexOf(query);
|
||||
|
||||
if (startIndex !== -1) {
|
||||
if (startIndex > 0) {
|
||||
yield { text: text.substring(0, startIndex), highlight: false };
|
||||
}
|
||||
|
||||
yield {
|
||||
text: text.substring(startIndex, startIndex + query.length),
|
||||
highlight: true,
|
||||
};
|
||||
|
||||
if (startIndex + query.length < text.length) {
|
||||
yield {
|
||||
text: text.substring(startIndex + query.length),
|
||||
highlight: false,
|
||||
};
|
||||
}
|
||||
} else {
|
||||
startIndex = 0;
|
||||
for (const char of query) {
|
||||
const pos = text.toLowerCase().indexOf(char, startIndex);
|
||||
if (pos !== -1) {
|
||||
if (pos > startIndex) {
|
||||
yield {
|
||||
text: text.substring(startIndex, pos),
|
||||
highlight: false,
|
||||
};
|
||||
}
|
||||
yield { text: text.substring(pos, pos + 1), highlight: true };
|
||||
startIndex = pos + 1;
|
||||
}
|
||||
}
|
||||
if (startIndex < text.length) {
|
||||
yield { text: text.substring(startIndex), highlight: false };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function highlightTextFragments(text: string, query: string) {
|
||||
return Array.from(highlightTextFragmentsGenerator(text, query));
|
||||
}
|
||||
|
||||
export function useHighlight(text: string, query: string) {
|
||||
return useMemo(() => highlightTextFragments(text, query), [text, query]);
|
||||
}
|
||||
@@ -126,6 +126,7 @@ export function useRegisterBlocksuiteEditorCommands(
|
||||
})
|
||||
);
|
||||
|
||||
// todo: should not show duplicate for journal
|
||||
unsubs.push(
|
||||
registerAffineCommand({
|
||||
id: `editor:${mode}-duplicate`,
|
||||
|
||||
Reference in New Issue
Block a user