From 0ae0c5c7afd9b7a8aa20d17578e070513bfe696a Mon Sep 17 00:00:00 2001 From: Alden Quimby Date: Mon, 8 Jul 2024 13:01:43 -0400 Subject: [PATCH] fix(core): allow number index for hit attribute #1261 (#1262) --- .gitignore | 1 + examples/react-17/src/Highlight.tsx | 2 +- .../src/Autocomplete.tsx | 2 +- .../src/highlight/ParseAlgoliaHitParams.ts | 2 +- .../parseAlgoliaHitHighlight.test.ts | 29 +++++++++++++++++ .../parseAlgoliaHitReverseHighlight.test.ts | 31 ++++++++++++++++++- .../parseAlgoliaHitReverseSnippet.test.ts | 28 ++++++++++++++++- .../__tests__/parseAlgoliaHitSnippet.test.ts | 26 ++++++++++++++++ .../src/getAttributeValueByPath.ts | 2 +- .../src/js/HighlightHitParams.ts | 2 +- 10 files changed, 118 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index f7b3f260f..3534aed6b 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ dist/ # IDE .vscode/ +.idea/ # Environment files .env diff --git a/examples/react-17/src/Highlight.tsx b/examples/react-17/src/Highlight.tsx index bff3bc19c..9e85b730f 100644 --- a/examples/react-17/src/Highlight.tsx +++ b/examples/react-17/src/Highlight.tsx @@ -11,7 +11,7 @@ type HighlightHitParams = { * * You can use the array syntax to reference nested attributes. */ - attribute: keyof THit | string[]; + attribute: keyof THit | (string | number)[]; /** * The tag name to use for highlighted parts. * diff --git a/examples/twitter-compose-with-typeahead/src/Autocomplete.tsx b/examples/twitter-compose-with-typeahead/src/Autocomplete.tsx index e3b4f9f1b..748d65fec 100644 --- a/examples/twitter-compose-with-typeahead/src/Autocomplete.tsx +++ b/examples/twitter-compose-with-typeahead/src/Autocomplete.tsx @@ -235,7 +235,7 @@ function AccountItem({ hit }: AccountItemProps) { type HighlightParams = { hit: THit; - attribute: keyof THit | string[]; + attribute: keyof THit | (string | number)[]; }; function Highlight({ hit, attribute }: HighlightParams) { diff --git a/packages/autocomplete-preset-algolia/src/highlight/ParseAlgoliaHitParams.ts b/packages/autocomplete-preset-algolia/src/highlight/ParseAlgoliaHitParams.ts index abf9b2a58..faf708875 100644 --- a/packages/autocomplete-preset-algolia/src/highlight/ParseAlgoliaHitParams.ts +++ b/packages/autocomplete-preset-algolia/src/highlight/ParseAlgoliaHitParams.ts @@ -1,4 +1,4 @@ export type ParseAlgoliaHitParams = { hit: TItem; - attribute: keyof TItem | string[]; + attribute: keyof TItem | (string | number)[]; }; diff --git a/packages/autocomplete-preset-algolia/src/highlight/__tests__/parseAlgoliaHitHighlight.test.ts b/packages/autocomplete-preset-algolia/src/highlight/__tests__/parseAlgoliaHitHighlight.test.ts index 7fed3e3e7..25872466e 100644 --- a/packages/autocomplete-preset-algolia/src/highlight/__tests__/parseAlgoliaHitHighlight.test.ts +++ b/packages/autocomplete-preset-algolia/src/highlight/__tests__/parseAlgoliaHitHighlight.test.ts @@ -167,6 +167,35 @@ describe('parseAlgoliaHitHighlight', () => { ]); }); + test('returns the highlighted parts of the hit with an array result', () => { + expect( + parseAlgoliaHitHighlight({ + attribute: ['titles', 1], + hit: { + objectID: '1', + titles: ['Hello', 'world'], + _highlightResult: { + titles: [{ + value: 'Hello', + matchLevel: 'none', + matchedWords: [], + }, { + value: '__aa-highlight__world__/aa-highlight__', + matchLevel: 'full', + matchedWords: ['world'], + fullyHighlighted: true, + }] + }, + }, + }) + ).toEqual([ + { + isHighlighted: true, + value: 'world', + }, + ]); + }); + test('returns the attribute value if the attribute cannot be highlighted', () => { expect( parseAlgoliaHitHighlight({ diff --git a/packages/autocomplete-preset-algolia/src/highlight/__tests__/parseAlgoliaHitReverseHighlight.test.ts b/packages/autocomplete-preset-algolia/src/highlight/__tests__/parseAlgoliaHitReverseHighlight.test.ts index a433371fb..5c37ea836 100644 --- a/packages/autocomplete-preset-algolia/src/highlight/__tests__/parseAlgoliaHitReverseHighlight.test.ts +++ b/packages/autocomplete-preset-algolia/src/highlight/__tests__/parseAlgoliaHitReverseHighlight.test.ts @@ -122,7 +122,7 @@ describe('parseAlgoliaHitReverseHighlight', () => { ]); }); - test('returns the highlighted parts of the hit with a nested array attribute containing a dot', () => { + test('returns the reverse-highlighted parts of the hit with a nested array attribute containing a dot', () => { expect( parseAlgoliaHitReverseHighlight({ attribute: ['hierarchy', 'lvl0.inside'], @@ -164,6 +164,35 @@ describe('parseAlgoliaHitReverseHighlight', () => { ]); }); + test('returns the reverse-highlighted parts of the hit with an array result', () => { + expect( + parseAlgoliaHitReverseHighlight({ + attribute: ['titles', 1], + hit: { + objectID: '1', + titles: ['Hello', 'world'], + _highlightResult: { + titles: [{ + value: 'Hello', + matchLevel: 'none', + matchedWords: [], + }, { + value: '__aa-highlight__world__/aa-highlight__', + matchLevel: 'full', + matchedWords: ['world'], + fullyHighlighted: true, + }] + }, + }, + }) + ).toEqual([ + { + isHighlighted: false, + value: 'world', + }, + ]); + }); + test('returns the non-highlighted parts when every part matches', () => { expect( parseAlgoliaHitReverseHighlight({ diff --git a/packages/autocomplete-preset-algolia/src/highlight/__tests__/parseAlgoliaHitReverseSnippet.test.ts b/packages/autocomplete-preset-algolia/src/highlight/__tests__/parseAlgoliaHitReverseSnippet.test.ts index 4c19aa32c..df86b1aa4 100644 --- a/packages/autocomplete-preset-algolia/src/highlight/__tests__/parseAlgoliaHitReverseSnippet.test.ts +++ b/packages/autocomplete-preset-algolia/src/highlight/__tests__/parseAlgoliaHitReverseSnippet.test.ts @@ -116,7 +116,7 @@ describe('parseAlgoliaHitReverseSnippet', () => { ]); }); - test('returns the highlighted snippet parts of the hit with a nested array attribute containing a dot', () => { + test('returns the reverse-highlighted snippet parts of the hit with a nested array attribute containing a dot', () => { expect( parseAlgoliaHitReverseSnippet({ attribute: ['hierarchy', 'lvl0.inside'], @@ -155,6 +155,32 @@ describe('parseAlgoliaHitReverseSnippet', () => { ]); }); + test('returns the reverse-highlighted snippet parts of the hit with an array result', () => { + expect( + parseAlgoliaHitReverseSnippet({ + attribute: ['titles', 1], + hit: { + objectID: '1', + titles: ['Hello', 'world'], + _snippetResult: { + titles: [{ + value: 'Hello', + matchLevel: 'none', + }, { + value: '__aa-highlight__world__/aa-highlight__', + matchLevel: 'full', + }] + }, + }, + }) + ).toEqual([ + { + isHighlighted: false, + value: 'world', + }, + ]); + }); + test('returns the non-highlighted parts when every part matches', () => { expect( parseAlgoliaHitReverseSnippet({ diff --git a/packages/autocomplete-preset-algolia/src/highlight/__tests__/parseAlgoliaHitSnippet.test.ts b/packages/autocomplete-preset-algolia/src/highlight/__tests__/parseAlgoliaHitSnippet.test.ts index a7e094788..bef5ac1cf 100644 --- a/packages/autocomplete-preset-algolia/src/highlight/__tests__/parseAlgoliaHitSnippet.test.ts +++ b/packages/autocomplete-preset-algolia/src/highlight/__tests__/parseAlgoliaHitSnippet.test.ts @@ -155,6 +155,32 @@ describe('parseAlgoliaHitSnippet', () => { ]); }); + test('returns the highlighted snippet parts of the hit with an array result', () => { + expect( + parseAlgoliaHitSnippet({ + attribute: ['titles', 1], + hit: { + objectID: '1', + titles: ['Hello', 'world'], + _snippetResult: { + titles: [{ + value: 'Hello', + matchLevel: 'none', + }, { + value: '__aa-highlight__world__/aa-highlight__', + matchLevel: 'full', + }] + }, + }, + }) + ).toEqual([ + { + isHighlighted: true, + value: 'world', + }, + ]); + }); + test('returns the attribute value if the attribute cannot be snippeted', () => { expect( parseAlgoliaHitSnippet({ diff --git a/packages/autocomplete-shared/src/getAttributeValueByPath.ts b/packages/autocomplete-shared/src/getAttributeValueByPath.ts index 28e19491c..8f78cd9a0 100644 --- a/packages/autocomplete-shared/src/getAttributeValueByPath.ts +++ b/packages/autocomplete-shared/src/getAttributeValueByPath.ts @@ -1,6 +1,6 @@ export function getAttributeValueByPath( record: TRecord, - path: string[] + path: (string | number)[] ): any { return path.reduce((current, key) => current && current[key], record); } diff --git a/packages/autocomplete-shared/src/js/HighlightHitParams.ts b/packages/autocomplete-shared/src/js/HighlightHitParams.ts index 5b01d2b3a..99ddf1a5c 100644 --- a/packages/autocomplete-shared/src/js/HighlightHitParams.ts +++ b/packages/autocomplete-shared/src/js/HighlightHitParams.ts @@ -8,7 +8,7 @@ export type HighlightHitParams = { * * You can use the array syntax to reference nested attributes. */ - attribute: keyof THit | string[]; + attribute: keyof THit | (string | number)[]; /** * The tag name to use for highlighted parts. *