mirror of https://github.com/go-gitea/gitea
Improve emoji and mention matching (#24255)
Prioritize matches that start with the given text, then matches that contain the given text. I wanted to add a heart emoji on a pull request comment so I started writing `:`, `h`, `e`, `a`, `r` (at this point I still couldn't find the heart), `t`... The heart was not on the list, that's weird - it feels like I made a typo or a mistake. This fixes that. This also feels more like GitHub's emoji auto-complete. # Before ![image](https://user-images.githubusercontent.com/20454870/233630750-bd0a1b76-33d0-41d4-9218-a37b670c42b0.png) # After ![image](https://user-images.githubusercontent.com/20454870/233775128-05e67fc1-e092-4025-b6f7-1fd8e5f71e87.png) --------- Signed-off-by: Yarden Shoham <git@yardenshoham.com> Co-authored-by: silverwind <me@silverwind.io>pull/24262/head^2
parent
ce9c1ddc4c
commit
3cc87370c3
@ -0,0 +1,43 @@ |
||||
import emojis from '../../../assets/emoji.json'; |
||||
|
||||
const maxMatches = 6; |
||||
|
||||
function sortAndReduce(map) { |
||||
const sortedMap = new Map([...map.entries()].sort((a, b) => a[1] - b[1])); |
||||
return Array.from(sortedMap.keys()).slice(0, maxMatches); |
||||
} |
||||
|
||||
export function matchEmoji(queryText) { |
||||
const query = queryText.toLowerCase().replaceAll('_', ' '); |
||||
if (!query) return emojis.slice(0, maxMatches).map((e) => e.aliases[0]); |
||||
|
||||
// results is a map of weights, lower is better
|
||||
const results = new Map(); |
||||
for (const {aliases} of emojis) { |
||||
const mainAlias = aliases[0]; |
||||
for (const [aliasIndex, alias] of aliases.entries()) { |
||||
const index = alias.replaceAll('_', ' ').indexOf(query); |
||||
if (index === -1) continue; |
||||
const existing = results.get(mainAlias); |
||||
const rankedIndex = index + aliasIndex; |
||||
results.set(mainAlias, existing ? existing - rankedIndex : rankedIndex); |
||||
} |
||||
} |
||||
|
||||
return sortAndReduce(results); |
||||
} |
||||
|
||||
export function matchMention(queryText) { |
||||
const query = queryText.toLowerCase(); |
||||
|
||||
// results is a map of weights, lower is better
|
||||
const results = new Map(); |
||||
for (const obj of window.config.tributeValues) { |
||||
const index = obj.key.toLowerCase().indexOf(query); |
||||
if (index === -1) continue; |
||||
const existing = results.get(obj); |
||||
results.set(obj, existing ? existing - index : index); |
||||
} |
||||
|
||||
return sortAndReduce(results); |
||||
} |
@ -0,0 +1,47 @@ |
||||
import {test, expect} from 'vitest'; |
||||
import {matchEmoji, matchMention} from './match.js'; |
||||
|
||||
test('matchEmoji', () => { |
||||
expect(matchEmoji('')).toEqual([ |
||||
'+1', |
||||
'-1', |
||||
'100', |
||||
'1234', |
||||
'1st_place_medal', |
||||
'2nd_place_medal', |
||||
]); |
||||
|
||||
expect(matchEmoji('hea')).toEqual([ |
||||
'headphones', |
||||
'headstone', |
||||
'health_worker', |
||||
'hear_no_evil', |
||||
'heard_mcdonald_islands', |
||||
'heart', |
||||
]); |
||||
|
||||
expect(matchEmoji('hear')).toEqual([ |
||||
'hear_no_evil', |
||||
'heard_mcdonald_islands', |
||||
'heart', |
||||
'heart_decoration', |
||||
'heart_eyes', |
||||
'heart_eyes_cat', |
||||
]); |
||||
|
||||
expect(matchEmoji('poo')).toEqual([ |
||||
'poodle', |
||||
'hankey', |
||||
'spoon', |
||||
'bowl_with_spoon', |
||||
]); |
||||
|
||||
expect(matchEmoji('1st_')).toEqual([ |
||||
'1st_place_medal', |
||||
]); |
||||
}); |
||||
|
||||
test('matchMention', () => { |
||||
expect(matchMention('')).toEqual(window.config.tributeValues.slice(0, 6)); |
||||
expect(matchMention('user4')).toEqual([window.config.tributeValues[3]]); |
||||
}); |
Loading…
Reference in new issue