Skip to content

Commit

Permalink
feat(reverseHighlight/reverseSnippet): implement sibling strategy fro…
Browse files Browse the repository at this point in the history
…m InstantSearch.js (#388)

* Implement sibling strategy from InstantSearch.js

* Increase bundle size

* Rename `getHighlightFromSiblings` to `isPartHighlighted`
  • Loading branch information
shortcuts committed Jan 12, 2021
1 parent d23f133 commit d86a33a
Show file tree
Hide file tree
Showing 6 changed files with 173 additions and 3 deletions.
4 changes: 2 additions & 2 deletions bundlesize.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
},
{
"path": "packages/autocomplete-js/dist/umd/index.production.js",
"maxSize": "10 kB"
"maxSize": "10.1 kB"
},
{
"path": "packages/autocomplete-preset-algolia/dist/umd/index.production.js",
Expand All @@ -22,7 +22,7 @@
},
{
"path": "packages/autocomplete-plugin-query-suggestions/dist/umd/index.production.js",
"maxSize": "2.25 kB"
"maxSize": "2.3 kB"
}
]
}
65 changes: 65 additions & 0 deletions packages/autocomplete-js/src/__tests__/reverseHighlightHit.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { reverseHighlightHit } from '../highlight';

describe('reverseHighlightHit', () => {
test('returns a reversed partially highlighted hit', () => {
expect(
reverseHighlightHit({
hit: {
objectID: 'amazon fire tablets',
query: 'amazon fire tablets',
_highlightResult: {
query: {
fullyHighlighted: false,
matchLevel: 'full',
matchedWords: ['fire', 'tablet'],
value:
'amazon __aa-highlight__fire__/aa-highlight__ __aa-highlight__tablet__/aa-highlight__s',
},
},
},
attribute: 'query',
})
).toMatchInlineSnapshot(`"<mark>amazon </mark>fire tablet<mark>s</mark>"`);
});

test('returns a reversed fully highlighted hit', () => {
expect(
reverseHighlightHit({
hit: {
objectID: 'amazon fire tablets',
query: 'amazon fire tablets',
_highlightResult: {
query: {
fullyHighlighted: true,
matchLevel: 'full',
matchedWords: ['amazon', 'fire', 'tablet'],
value:
'__aa-highlight__amazon__/aa-highlight__ __aa-highlight__fire__/aa-highlight__ __aa-highlight__tablets__/aa-highlight__',
},
},
},
attribute: 'query',
})
).toMatchInlineSnapshot(`"amazon fire tablets"`);
});

test('returns a reversed empty highlighted query hit', () => {
expect(
reverseHighlightHit({
hit: {
objectID: 'amazon fire tablets',
query: 'amazon fire tablets',
_highlightResult: {
query: {
fullyHighlighted: false,
matchLevel: 'none',
matchedWords: [],
value: 'amazon fire tablets',
},
},
},
attribute: 'query',
})
).toMatchInlineSnapshot(`"amazon fire tablets"`);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { isPartHighlighted } from '../isPartHighlighted';

describe('isPartHighlighted', () => {
test('returns the isHighlighted value with a missing sibling', () => {
expect(
isPartHighlighted(
[
{ isHighlighted: true, value: 'Amazon' },
{
isHighlighted: false,
value: ' - Fire HD8 - 8&quot; - Tablet - 16GB - Wi-Fi - Black',
},
],
0
)
).toEqual(true);
});

test('returns the isHighlighted value with both siblings', () => {
expect(
isPartHighlighted(
[
{ isHighlighted: true, value: 'Amazon' },
{ isHighlighted: false, value: ' - ' },
{ isHighlighted: true, value: 'Fire' },
{ isHighlighted: false, value: ' ' },
{ isHighlighted: true, value: 'TV' },
],
1
)
).toEqual(true);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { reverseHighlightedParts } from '../reverseHighlightedParts';

describe('reverseHighlightedParts', () => {
test('returns a reversed partially highlighted parts array', () => {
expect(
reverseHighlightedParts([
{ isHighlighted: true, value: 'amazon ((fire' },
{ isHighlighted: false, value: 'tv)) tablet??' },
])
).toEqual([
{ isHighlighted: false, value: 'amazon ((fire' },
{ isHighlighted: true, value: 'tv)) tablet??' },
]);
});

test('returns a reversed fully highlighted parts array', () => {
expect(
reverseHighlightedParts([
{ isHighlighted: true, value: 'amazon ((fire tv)) tablet??' },
])
).toEqual([{ isHighlighted: false, value: 'amazon ((fire tv)) tablet??' }]);
});

test('returns a reversed highlighted parts array based on sibling highlighting', () => {
expect(
reverseHighlightedParts([
{ isHighlighted: true, value: 'amazon ((fire tv)) tablet' },
{ isHighlighted: false, value: '??' },
])
).toEqual([
{ isHighlighted: false, value: 'amazon ((fire tv)) tablet' },
{ isHighlighted: false, value: '??' },
]);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { ParsedAttribute } from './ParsedAttribute';

const htmlEscapes = {
'&amp;': '&',
'&lt;': '<',
'&gt;': '>',
'&quot;': '"',
'&#39;': "'",
};
const hasAlphanumeric = new RegExp(/\w/i);
const regexEscapedHtml = /&(amp|quot|lt|gt|#39);/g;
const regexHasEscapedHtml = RegExp(regexEscapedHtml.source);

function unescape(value: string): string {
return value && regexHasEscapedHtml.test(value)
? value.replace(regexEscapedHtml, (character) => htmlEscapes[character])
: value;
}

export function isPartHighlighted(parts: ParsedAttribute[], i: number) {
const current = parts[i];
const isNextHighlighted = parts[i + 1]?.isHighlighted || true;
const isPreviousHighlighted = parts[i - 1]?.isHighlighted || true;

if (
!hasAlphanumeric.test(unescape(current.value)) &&
isPreviousHighlighted === isNextHighlighted
) {
return isPreviousHighlighted;
}

return current.isHighlighted;
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isPartHighlighted } from './isPartHighlighted';
import { ParsedAttribute } from './ParsedAttribute';

export function reverseHighlightedParts(parts: ParsedAttribute[]) {
Expand All @@ -6,5 +7,8 @@ export function reverseHighlightedParts(parts: ParsedAttribute[]) {
return parts.map((part) => ({ ...part, isHighlighted: false }));
}

return parts.map((part) => ({ ...part, isHighlighted: !part.isHighlighted }));
return parts.map((part, i) => ({
...part,
isHighlighted: !isPartHighlighted(parts, i),
}));
}

0 comments on commit d86a33a

Please sign in to comment.