@@ -12,18 +12,39 @@ import { SearchContext } from '../../types'
1212 */
1313function replaceHighlightTags (
1414 value : any ,
15- highlightPreTag ?: string ,
16- highlightPostTag ?: string
15+ preTag ?: string ,
16+ postTag ?: string
1717) : string {
18- highlightPreTag = highlightPreTag || '__ais-highlight__'
19- highlightPostTag = highlightPostTag || '__/ais-highlight__'
18+ preTag = preTag || '__ais-highlight__'
19+ postTag = postTag || '__/ais-highlight__'
2020 // Highlight is applied by MeiliSearch (<em> tags)
2121 // We replace the <em> by the expected tag for InstantSearch
2222 const stringifiedValue = isString ( value ) ? value : JSON . stringify ( value )
2323
24- return stringifiedValue
25- . replace ( / < e m > / g, highlightPreTag )
26- . replace ( / < \/ e m > / g, highlightPostTag )
24+ return stringifiedValue . replace ( / < e m > / g, preTag ) . replace ( / < \/ e m > / g, postTag )
25+ }
26+
27+ function addHighlightTags ( value : string , preTag ?: string , postTag ?: string ) {
28+ return {
29+ value : replaceHighlightTags ( value , preTag , postTag ) ,
30+ }
31+ }
32+
33+ function resolveHighlightValue (
34+ value : string ,
35+ preTag ?: string ,
36+ postTag ?: string
37+ ) {
38+ if ( typeof value === 'string' ) {
39+ // String
40+ return addHighlightTags ( value , preTag , postTag )
41+ } else if ( value === undefined ) {
42+ // undefined
43+ return { value : JSON . stringify ( null ) }
44+ } else {
45+ // Other
46+ return { value : JSON . stringify ( value ) }
47+ }
2748}
2849
2950/**
@@ -33,98 +54,93 @@ function replaceHighlightTags(
3354 * @returns {Record }
3455 */
3556function adaptHighlight (
36- formattedHit : Record < string , any > ,
37- highlightPreTag ?: string ,
38- highlightPostTag ?: string
57+ hit : Record < string , any > ,
58+ preTag ?: string ,
59+ postTag ?: string
3960) : Record < string , any > {
40- // formattedHit is the `_formatted` object returned by MeiliSearch.
61+ // hit is the `_formatted` object returned by MeiliSearch.
4162 // It contains all the highlighted and croped attributes
42- const toHighlightMatch = ( value : any ) => ( {
43- value : replaceHighlightTags ( value , highlightPreTag , highlightPostTag ) ,
44- } )
45- return Object . keys ( formattedHit ) . reduce ( ( result , key ) => {
46- const value = formattedHit [ key ]
63+
64+ return Object . keys ( hit ) . reduce ( ( result , key ) => {
65+ const value = hit [ key ]
66+
4767 if ( Array . isArray ( value ) ) {
48- result [ key ] = value . map ( ( val ) => ( {
49- value : typeof val === 'object' ? JSON . stringify ( val ) : val ,
50- } ) )
51- } else if ( typeof value === 'object' && value !== null ) {
52- result [ key ] = { value : JSON . stringify ( value ) }
68+ // Array
69+ result [ key ] = value . map ( ( elem ) =>
70+ resolveHighlightValue ( elem , preTag , postTag )
71+ )
5372 } else {
54- result [ key ] = toHighlightMatch ( value )
73+ result [ key ] = resolveHighlightValue ( value , preTag , postTag )
5574 }
5675 return result
5776 } , { } as any )
5877}
5978
6079/**
6180 * @param {string } value
62- * @param {string } snippetEllipsisText ?
63- * @param {string } highlightPreTag ?
64- * @param {string } highlightPostTag ?
81+ * @param {string } preTag ?
82+ * @param {string } postTag ?
83+ * @param {string } ellipsis ?
6584 * @returns {string }
6685 */
67- function snippetValue (
86+ function resolveSnippetValue (
6887 value : string ,
69- snippetEllipsisText ?: string ,
70- highlightPreTag ?: string ,
71- highlightPostTag ?: string
72- ) : string {
88+ preTag ?: string ,
89+ postTag ?: string ,
90+ ellipsis ?: string
91+ ) : { value : string } {
7392 let newValue = value
74- // manage a kind of `...` for the crop until this feature is implemented https://roadmap.meilisearch.com/c/69-policy-for-cropped-values?utm_medium=social&utm_source=portal_share
75- // `...` is put if we are at the middle of a sentence (instead at the middle of the document field)
76- if ( snippetEllipsisText !== undefined && isString ( newValue ) && newValue ) {
93+
94+ // Manage ellpsis on cropped values until this feature is implemented https://roadmap.meilisearch.com/c/69-policy-for-cropped-values?utm_medium=social&utm_source=portal_share in MeiliSearch
95+ if ( newValue && ellipsis !== undefined && isString ( newValue ) ) {
7796 if (
7897 newValue [ 0 ] === newValue [ 0 ] . toLowerCase ( ) && // beginning of a sentence
79- newValue . startsWith ( '<em>' ) === false // beginning of the document field, otherwise MeiliSearch would crop around the highligh
98+ newValue . startsWith ( '<em>' ) === false // beginning of the document field, otherwise MeiliSearch would crop around the highlight
8099 ) {
81- newValue = `${ snippetEllipsisText } ${ newValue } `
100+ newValue = `${ ellipsis } ${ newValue } `
82101 }
83102 if ( ! ! newValue . match ( / [ . ! ? ] $ / ) === false ) {
84103 // end of the sentence
85- newValue = `${ newValue } ${ snippetEllipsisText } `
104+ newValue = `${ newValue } ${ ellipsis } `
86105 }
87106 }
88- return replaceHighlightTags ( newValue , highlightPreTag , highlightPostTag )
107+ return resolveHighlightValue ( newValue , preTag , postTag )
89108}
90109
91110/**
92- * @param {Record<string } formattedHit
93- * @param {readonlystring[]|undefined } attributesToSnippet
94- * @param {string|undefined } snippetEllipsisText
95- * @param {string|undefined } highlightPreTag
96- * @param {string|undefined } highlightPostTag
111+ * @param {Record<string } hit
112+ * @param {readonlystring[]|undefined } attributes
113+ * @param {string|undefined } ellipsis
114+ * @param {string|undefined } preTag
115+ * @param {string|undefined } postTage
97116 */
98117function adaptSnippet (
99- formattedHit : Record < string , any > ,
100- attributesToSnippet : readonly string [ ] | undefined ,
101- snippetEllipsisText : string | undefined ,
102- highlightPreTag : string | undefined ,
103- highlightPostTag : string | undefined
118+ hit : Record < string , any > ,
119+ attributes : readonly string [ ] | undefined ,
120+ ellipsis : string | undefined ,
121+ pretag : string | undefined ,
122+ postTag : string | undefined
104123) {
105- if ( attributesToSnippet === undefined ) {
124+ if ( attributes === undefined ) {
106125 return null
107126 }
108- attributesToSnippet = attributesToSnippet . map (
109- ( attribute ) => attribute . split ( ':' ) [ 0 ]
110- ) as any [ ]
111- const snippetAll = attributesToSnippet . includes ( '*' )
112- // formattedHit is the `_formatted` object returned by MeiliSearch.
127+ attributes = attributes . map ( ( attribute ) => attribute . split ( ':' ) [ 0 ] ) as any [ ]
128+ const snippetAll = attributes . includes ( '*' )
129+
130+ // hit is the `_formatted` object returned by MeiliSearch.
113131 // It contains all the highlighted and croped attributes
114- const toSnippetMatch = ( value : any ) => ( {
115- value : snippetValue (
116- value ,
117- snippetEllipsisText ,
118- highlightPreTag ,
119- highlightPostTag
120- ) ,
121- } )
122- return ( Object . keys ( formattedHit ) as any [ ] ) . reduce ( ( result , key ) => {
123- if ( snippetAll || attributesToSnippet ?. includes ( key ) ) {
124- const value = formattedHit [ key ]
125- result [ key ] = Array . isArray ( value )
126- ? value . map ( toSnippetMatch )
127- : toSnippetMatch ( value )
132+
133+ return ( Object . keys ( hit ) as any [ ] ) . reduce ( ( result , key ) => {
134+ if ( snippetAll || attributes ?. includes ( key ) ) {
135+ const value = hit [ key ]
136+ if ( Array . isArray ( value ) ) {
137+ // Array
138+ result [ key ] = value . map ( ( elem ) =>
139+ resolveSnippetValue ( elem , pretag , postTag , ellipsis )
140+ )
141+ } else {
142+ result [ key ] = resolveSnippetValue ( value , pretag , postTag , ellipsis )
143+ }
128144 }
129145 return result
130146 } , { } as any )
@@ -138,27 +154,24 @@ function adaptSnippet(
138154 * @returns {Record }
139155 */
140156export function adaptFormating (
141- formattedHit : Record < string , any > ,
157+ hit : Record < string , any > ,
142158 searchContext : SearchContext
143159) : Record < string , any > {
144160 const attributesToSnippet = searchContext ?. attributesToSnippet
145- const snippetEllipsisText = searchContext ?. snippetEllipsisText
146- const highlightPreTag = searchContext ?. highlightPreTag
147- const highlightPostTag = searchContext ?. highlightPostTag
161+ const ellipsis = searchContext ?. snippetEllipsisText
162+ const preTag = searchContext ?. highlightPreTag
163+ const postTag = searchContext ?. highlightPostTag
148164
149- if ( ! formattedHit || formattedHit . length ) return { }
150- return {
151- _highlightResult : adaptHighlight (
152- formattedHit ,
153- highlightPreTag ,
154- highlightPostTag
155- ) ,
165+ if ( ! hit || hit . length ) return { }
166+ const highlightedHit = {
167+ _highlightResult : adaptHighlight ( hit , preTag , postTag ) ,
156168 _snippetResult : adaptSnippet (
157- formattedHit ,
169+ hit ,
158170 attributesToSnippet ,
159- snippetEllipsisText ,
160- highlightPreTag ,
161- highlightPostTag
171+ ellipsis ,
172+ preTag ,
173+ postTag
162174 ) ,
163175 }
176+ return highlightedHit
164177}
0 commit comments