Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(algolia): fix highlighting hit type #452

Merged
merged 1 commit into from
Feb 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 2 additions & 3 deletions examples/js/categoriesPlugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
getAlgoliaFacetHits,
highlightHit,
} from '@algolia/autocomplete-js';
import { Hit } from '@algolia/client-search';
import { SearchClient } from 'algoliasearch/lite';
import { h, Fragment } from 'preact';

Expand Down Expand Up @@ -70,8 +69,8 @@ export function createCategoriesPlugin({
</div>
<div className="aa-ItemContent">
<div className="aa-ItemContentTitle">
{highlightHit<Hit<CategoryItem>>({
hit: item as any,
{highlightHit<CategoryItem>({
hit: item,
attribute: 'label',
})}
</div>
Expand Down
33 changes: 17 additions & 16 deletions packages/autocomplete-js/src/highlight.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,30 @@ import {
parseAlgoliaHitReverseHighlight,
parseAlgoliaHitReverseSnippet,
parseAlgoliaHitSnippet,
HighlightedHit,
SnippetedHit,
} from '@algolia/autocomplete-preset-algolia';
import { Hit } from '@algolia/client-search';
import { createElement as preactCreateElement } from 'preact';

import { AutocompleteRenderer } from './types';

type HighlightItemParams<TItem> = {
hit: TItem;
attribute: keyof TItem | string[];
type HighlightItemParams<THit> = {
hit: THit;
attribute: keyof THit | string[];
tagName?: string;
createElement?: AutocompleteRenderer['createElement'];
};

/**
* Highlights and escapes the matching parts of an Algolia hit.
*/
export function highlightHit<TItem extends Hit<{}>>({
export function highlightHit<THit extends HighlightedHit<unknown>>({
hit,
attribute,
tagName = 'mark',
createElement = preactCreateElement,
}: HighlightItemParams<TItem>) {
return parseAlgoliaHitHighlight<TItem>({ hit, attribute }).map((x, index) =>
}: HighlightItemParams<THit>) {
return parseAlgoliaHitHighlight<THit>({ hit, attribute }).map((x, index) =>
x.isHighlighted ? createElement(tagName, { key: index }, x.value) : x.value
);
}
Expand All @@ -35,13 +36,13 @@ export function highlightHit<TItem extends Hit<{}>>({
*
* This is a common pattern for Query Suggestions.
*/
export function reverseHighlightHit<TItem extends Hit<{}>>({
export function reverseHighlightHit<THit extends HighlightedHit<unknown>>({
hit,
attribute,
tagName = 'mark',
createElement = preactCreateElement,
}: HighlightItemParams<TItem>) {
return parseAlgoliaHitReverseHighlight<TItem>({
}: HighlightItemParams<THit>) {
return parseAlgoliaHitReverseHighlight<THit>({
hit,
attribute,
}).map((x, index) =>
Expand All @@ -52,13 +53,13 @@ export function reverseHighlightHit<TItem extends Hit<{}>>({
/**
* Highlights and escapes the matching parts of an Algolia hit snippet.
*/
export function snippetHit<TItem extends Hit<{}>>({
export function snippetHit<THit extends SnippetedHit<unknown>>({
hit,
attribute,
tagName = 'mark',
createElement = preactCreateElement,
}: HighlightItemParams<TItem>) {
return parseAlgoliaHitSnippet<TItem>({ hit, attribute }).map((x, index) =>
}: HighlightItemParams<THit>) {
return parseAlgoliaHitSnippet<THit>({ hit, attribute }).map((x, index) =>
x.isHighlighted ? createElement(tagName, { key: index }, x.value) : x.value
);
}
Expand All @@ -68,13 +69,13 @@ export function snippetHit<TItem extends Hit<{}>>({
*
* This is a common pattern for Query Suggestions.
*/
export function reverseSnippetHit<TItem extends Hit<{}>>({
export function reverseSnippetHit<THit extends SnippetedHit<unknown>>({
hit,
attribute,
tagName = 'mark',
createElement = preactCreateElement,
}: HighlightItemParams<TItem>) {
return parseAlgoliaHitReverseSnippet<TItem>({
}: HighlightItemParams<THit>) {
return parseAlgoliaHitReverseSnippet<THit>({
hit,
attribute,
}).map((x, index) =>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/** @jsx createElement */
import { reverseHighlightHit, SourceTemplates } from '@algolia/autocomplete-js';
import { HighlightedHit } from '@algolia/autocomplete-preset-algolia';

import { RecentSearchesItem } from './types';

Expand All @@ -23,7 +24,7 @@ export function getTemplates<TItem extends RecentSearchesItem>({
</div>
<div className="aa-ItemContent">
<div className="aa-ItemContentTitle">
{reverseHighlightHit<RecentSearchesItem>({
{reverseHighlightHit<HighlightedHit<RecentSearchesItem>>({
hit: item,
attribute: 'query',
createElement,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { HighlightResult } from '@algolia/client-search';

export type HighlightedHit<THit> = THit & {
_highlightResult?: HighlightResult<THit>;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { SnippetResult } from '@algolia/client-search';

export type SnippetedHit<THit> = THit & {
_snippetResult?: SnippetResult<THit>;
};
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { warn } from '@algolia/autocomplete-shared';
import { Hit } from '@algolia/client-search';

import { getAttributeValueByPath } from './getAttributeValueByPath';
import { HighlightedHit } from './HighlightedHit';
import { ParseAlgoliaHitParams } from './ParseAlgoliaHitParams';
import { parseAttribute } from './parseAttribute';
import { ParsedAttribute } from './ParsedAttribute';

export function parseAlgoliaHitHighlight<THit extends Hit<{}>>({
export function parseAlgoliaHitHighlight<THit extends HighlightedHit<unknown>>({
hit,
attribute,
}: ParseAlgoliaHitParams<THit>): ParsedAttribute[] {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { Hit } from '@algolia/client-search';

import { HighlightedHit } from './HighlightedHit';
import { parseAlgoliaHitHighlight } from './parseAlgoliaHitHighlight';
import { ParseAlgoliaHitParams } from './ParseAlgoliaHitParams';
import { ParsedAttribute } from './ParsedAttribute';
import { reverseHighlightedParts } from './reverseHighlightedParts';

export function parseAlgoliaHitReverseHighlight<THit extends Hit<{}>>(
props: ParseAlgoliaHitParams<THit>
): ParsedAttribute[] {
export function parseAlgoliaHitReverseHighlight<
THit extends HighlightedHit<unknown>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You suggested Record<string, unknown> in message, any reason why you changed it to unknown again?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given:

import { HighlightResult } from '@algolia/client-search';

export type HighlightedHit<THit> = THit & {
  _highlightResult?: HighlightResult<THit>;
};

I tried HighlightResult<Record<string, unknown>> with a DocSearch hit and it doesn't work because properties can be null (e.g., content).

We need to improve the client's HighlightResult type to allow this.

>(props: ParseAlgoliaHitParams<THit>): ParsedAttribute[] {
return reverseHighlightedParts(parseAlgoliaHitHighlight<THit>(props));
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { Hit } from '@algolia/client-search';

import { ParseAlgoliaHitParams } from './ParseAlgoliaHitParams';
import { parseAlgoliaHitSnippet } from './parseAlgoliaHitSnippet';
import { ParsedAttribute } from './ParsedAttribute';
import { reverseHighlightedParts } from './reverseHighlightedParts';
import { SnippetedHit } from './SnippetedHit';

export function parseAlgoliaHitReverseSnippet<THit extends Hit<{}>>(
props: ParseAlgoliaHitParams<THit>
): ParsedAttribute[] {
export function parseAlgoliaHitReverseSnippet<
THit extends SnippetedHit<unknown>
>(props: ParseAlgoliaHitParams<THit>): ParsedAttribute[] {
return reverseHighlightedParts(parseAlgoliaHitSnippet<THit>(props));
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { warn } from '@algolia/autocomplete-shared';
import { Hit } from '@algolia/client-search';

import { getAttributeValueByPath } from './getAttributeValueByPath';
import { ParseAlgoliaHitParams } from './ParseAlgoliaHitParams';
import { parseAttribute } from './parseAttribute';
import { ParsedAttribute } from './ParsedAttribute';
import { SnippetedHit } from './SnippetedHit';

export function parseAlgoliaHitSnippet<THit extends Hit<{}>>({
export function parseAlgoliaHitSnippet<THit extends SnippetedHit<unknown>>({
hit,
attribute,
}: ParseAlgoliaHitParams<THit>): ParsedAttribute[] {
Expand Down
2 changes: 2 additions & 0 deletions packages/autocomplete-preset-algolia/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
export * from './highlight/HighlightedHit';
export * from './highlight/parseAlgoliaHitHighlight';
export * from './highlight/parseAlgoliaHitReverseHighlight';
export * from './highlight/parseAlgoliaHitReverseSnippet';
export * from './highlight/parseAlgoliaHitSnippet';
export * from './highlight/SnippetedHit';
export * from './search/getAlgoliaFacetHits';
export * from './search/getAlgoliaHits';
export * from './search/getAlgoliaResults';
Expand Down