From babb352b6abface18189f1b3b83cff4e2ccdc129 Mon Sep 17 00:00:00 2001 From: Sylvain Utard Date: Sun, 17 Jul 2016 16:34:07 +0200 Subject: [PATCH] feat(highlight): get the best matching values instead of the first one (#285) Fix #172 --- src/formatHit.js | 35 +++++++++++++++++++++++++++++++---- src/formatHit.test.js | 19 ++++++++++++++++++- 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/src/formatHit.js b/src/formatHit.js index 01e43b240..35e795b24 100644 --- a/src/formatHit.js +++ b/src/formatHit.js @@ -1,6 +1,33 @@ import findCountryCode from './findCountryCode.js'; import findType from './findType.js'; +function getBestHighlightedForm(highlightedValues) { + const defaultValue = highlightedValues[0].value; + // collect all other matches + const bestAttributes = []; + for (let i = 1; i < highlightedValues.length; ++i) { + if (highlightedValues[i].matchLevel !== 'none') { + bestAttributes.push({index: i, matchedWords: highlightedValues[i].words}); + } + } + // no matches in this attribute, retrieve first value + if (bestAttributes.length === 0) { + return defaultValue; + } + // sort the matches by `desc(words), asc(index)` + bestAttributes.sort((a, b) => { + if (a.words > b.words) { + return -1; + } else if (a.words < b.words) { + return 1; + } + return a.index - b.index; + }); + // and append the best match to the first value + return bestAttributes[0].index === 0 ? `${defaultValue} (${highlightedValues[bestAttributes[1].index].value})` + : `${highlightedValues[bestAttributes[0].index].value} (${defaultValue})`; +} + export default function formatHit({ formatInputValue, hit, @@ -16,10 +43,10 @@ export default function formatHit({ const city = hit.city && hit.city[0] !== name ? hit.city[0] : undefined; const highlight = { - name: hit._highlightResult.locale_names[0].value, - city: city ? hit._highlightResult.city[0].value : undefined, - administrative: administrative ? hit._highlightResult.administrative[0].value : undefined, - country: country ? hit._highlightResult.country.value : undefined + name: getBestHighlightedForm(hit._highlightResult.locale_names), + city: city ? getBestHighlightedForm(hit._highlightResult.city) : undefined, + administrative: administrative ? getBestHighlightedForm(hit._highlightResult.administrative) : undefined, + country: hit._highlightResult.country.value }; const suggestion = { diff --git a/src/formatHit.test.js b/src/formatHit.test.js index d80ace15f..923a1feb8 100644 --- a/src/formatHit.test.js +++ b/src/formatHit.test.js @@ -35,6 +35,23 @@ describe('formatHit', () => { highlight: {administrative: undefined, name: 'Île-de-France'} } }), + getTestCase({ + name: 'locale_names[1] is matching', + hit: { + locale_names: ['Paris', 'Lutèce'], + city: ['Paris'], + administrative: ['Île-de-France'], + _highlightResult: { + locale_names: [{value: 'Paris', matchedWords: []}, {value: 'Lutèce', matchedWords: ['Lutèce']}] + } + }, + expected: { + name: 'Paris', + administrative: 'Île-de-France', + city: undefined, + highlight: {name: 'Lutèce (Paris)', city: undefined} + } + }), getTestCase({ name: 'no city', hit: {city: undefined}, @@ -67,7 +84,7 @@ describe('formatHit', () => { // check properties Object.keys(testCase.expected).forEach(key => - expect(output[key]).toEqual(testCase.expected[key]) + expect(output[key]).toEqual(testCase.expected[key], `unexcepted value of "${key}"`) ); // hit is passed through