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

fix(highlight): avoid to ignore highlightedTagName #3323

Merged
merged 6 commits into from
Dec 7, 2018

Conversation

samouss
Copy link
Contributor

@samouss samouss commented Dec 5, 2018

Summary

With the current implementation we update the source of the highlight two times:

  • the first time is inside the connector where we call escapeHits only when escapeHTML is provided. This operation replace the placeholder __ais-highlight__ with the tag mark recursively on all the hits.
  • the second time is either in user-land or inside the default template with the highlight or snippet function (though the inline template or a function template). This operation replace the tag em with the provided highlightedTagName. The issue is at this point we don't have a tag em anymore because we replace it the first time with mark we escape the value.

It means that the replace inside highlight & snippet is never executed. This PR aims to fix this issue. We now have two variables:

  • TAG_PLACEHOLDER: previously called tagConfig (renamed for consistency)
  • TAG_REPLACEMENT: avoid to rely on string and forget to update them

Before

screenshot 2018-12-05 at 10 55 25

After

screenshot 2018-12-05 at 10 55 09


Alternatives

The current implementation (with or without) the fix supports both syntax the inline Mustache template form with the three braces (because we do the replacement inside the connector):

{{{ _highlightResult.name.value }}}

And of course we also supports the one with the helper:

{{#helpers.highlight}}{ "attribute": "name" }{{/helpers.highlight}}

We recommend the usage of the helper but we perform useless work to support both implementation at the same time. We first transform the placeholder to mark and then we transform mark to the correct tag with the class. We might want to drop the support for the first form. One simple reason is that users don't have to care about Algolia internals.

It simplify the flow of the highlighting: we only have to replace the value inside the helper (we still have to escape the value) it's easier to follow and less error prone. One downside though is that we have to update the refinement list items data structure to allow highlight to work on it. WDYT?

@samouss samouss requested a review from a team December 5, 2018 09:59
@algobot
Copy link
Contributor

algobot commented Dec 5, 2018

Deploy preview for instantsearchjs ready!

Built with commit f93ba17

https://deploy-preview-3323--instantsearchjs.netlify.com

@Haroenv
Copy link
Contributor

Haroenv commented Dec 5, 2018

Does this mean that now the {{{ form will not work?

@samouss
Copy link
Contributor Author

samouss commented Dec 5, 2018

Does this mean that now the {{{ form will not work?

Right now it works because we still do the replace at the same time we escape. But in case we update the implementation to the proposal I made: no it won't work anymore. The value inside the record will still be the placeholder. Only the highlight function will have the knowledge to do the replacement (without mutating the original value).

Copy link
Contributor

@tkrugg tkrugg left a comment

Choose a reason for hiding this comment

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

Looks good to me.
I wonder if this has any implications on other flavours:
For example in vue-instantsearch sanitize function: https://github.com/algolia/vue-instantsearch/blob/fbb719616a03092489cb7422f108a1282ae081a2/src/sanitize-results.js

@samouss
Copy link
Contributor Author

samouss commented Dec 5, 2018

@tkrugg the implication for the other flavour are minimal because they only use the public API. Once the v3 is released we can drop those lines (the ones you linked are for the v1, but the lib doesn't use InstantSearch):

https://github.com/algolia/vue-instantsearch/blob/b4948323b5740df541265db814e7f7c3109c9a23/src/components/Highlight.vue#L32-L51

Copy link
Contributor

@Haroenv Haroenv left a comment

Choose a reason for hiding this comment

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

wording suggestion

docgen/src/guides/v3-migration.md Outdated Show resolved Hide resolved
@samouss samouss merged commit 9871829 into v3 Dec 7, 2018
@francoischalifour francoischalifour deleted the fix/highlighted-tag-name branch December 10, 2018 09:11
francoischalifour added a commit that referenced this pull request Dec 10, 2018
<a name=3.0.0-beta.0></a>
# [3.0.0-beta.0](v2.10.3...v3.0.0-beta.0) (2018-12-10)

### Bug Fixes

* **api:** remove transformData ([#3241](#3241)) ([5232936](5232936))
* **breadcrumb:** fix story with transformed label ([5a39312](5a39312))
* **breadcrumb:** rename item's name to label ([#3273](#3273)) ([0189cb4](0189cb4))
* **breadcrumb:** rename noRefinement to noRefinementRoot ([#3272](#3272)) ([21a5c61](21a5c61))
* **community:** fix search config ([#3142](#3142)) ([2b41982](2b41982))
* **connectRangeSlider:** remove deprecated connector ([#3189](#3189)) ([096ebeb](096ebeb))
* **current-refinements:** remove alphabetic sorting ([#3249](#3249)) ([9914f87](9914f87)), closes [/github.com/algolia/instantsearch.js/blob/011d47909894837f2c2da5088bc81803135d201b/src/lib/utils.js#L249](https://github.com//github.com/algolia/instantsearch.js/blob/011d47909894837f2c2da5088bc81803135d201b/src/lib/utils.js/issues/L249)
* **getRefinements:** provide attributeName for type: query ([6006fe1](6006fe1)), closes [#3205](#3205)
* **highlight:** avoid to ignore highlightedTagName ([#3323](#3323)) ([9871829](9871829))
* **highlight:** HighLight -> Highlight ([#3324](#3324)) ([5b4600d](5b4600d))
* **hits:** transform items after escaping ([#3251](#3251)) ([c46b82a](c46b82a)), closes [#3250](#3250)
* **infiniteHits:** move  option to templates ([#3300](#3300)) ([1828d66](1828d66))
* **InfiniteHits:** set the correct class for the last page ([#3232](#3232)) ([f604835](f604835))
* **lint:** remove unused import ([a9ec14c](a9ec14c))
* **pagination:** rename  to  ([#3275](#3275)) ([336945b](336945b))
* **range-input:** fix button classname ([#3234](#3234)) ([56695e1](56695e1)), closes [algolia/instantsearch-specs#92](algolia/instantsearch-specs#92)
* **range-input:** remove templates ([#3128](#3128)) ([94a1ce5](94a1ce5))
* **rangeInput:** convert labels to templates ([#3312](#3312)) ([cdf91e8](cdf91e8))
* **rangeSlider:** fix CSS classes ([#3316](#3316)) ([56a5255](56a5255))
* **refinement-list:** remove  in story ([0bf8db1](0bf8db1))
* **routing:** enforce RoutingManager is the last widget ([#3149](#3149)) ([1e86b2e](1e86b2e)), closes [#3148](#3148)
* **searchbox:** fix  and  templates ([#3313](#3313)) ([4e13122](4e13122))
* **tests:** add react-test-renderer ([176494b](176494b))
* **toggleRefinement:** provide  to templates ([#3303](#3303)) ([f515b62](f515b62))

### Features

* **3.0:** remove named exports on widgets ([#3129](#3129)) ([e718ea3](e718ea3))
* **breadcrumb:** implement InstantSearch.css ([#3115](#3115)) ([84d9f18](84d9f18))
* **clearRefinements:** implement InstantSearch.css ([#3308](#3308)) ([d98ecaf](d98ecaf)), closes [#3299](#3299)
* **clearRefinements:** implement is.css ([#3114](#3114)) ([11cdc14](11cdc14))
* **current-refinements:** implement InstantSearch.css ([#3190](#3190)) ([a70917d](a70917d))
* **GeoSearch:** implement InstantSearch.css ([#3138](#3138)) ([1867d30](1867d30))
* **hierarchical-menu:** implement InstantSearch.css ([#3182](#3182)) ([be0890d](be0890d))
* **hierarchical-menu:** implement show more feature ([#3151](#3151)) ([f54fccd](f54fccd))
* **hierarchicalMenu:** merge showMore templates ([#3318](#3318)) ([0059251](0059251))
* **highlight:** export highlight function ([#3137](#3137)) ([d4b6fb1](d4b6fb1))
* **highlight:** implement InstantSearch.css ([#3132](#3132)) ([260a0b8](260a0b8))
* **hits:** implement InstantSearch.css ([#3096](#3096)) ([b3cc413](b3cc413))
* **hits-per-page:** implement InstantSearch.css ([#3125](#3125)) ([49e7096](49e7096))
* **menu:** implement InstantSearch.css ([#3181](#3181)) ([a274ab7](a274ab7))
* **menuSelect:** implement is.css ([#3109](#3109)) ([43e654a](43e654a))
* **numeric-menu:** implement InstantSearch.css ([#3162](#3162)) ([f5358f4](f5358f4))
* **numericSelector:** remove widget ([#3183](#3183)) ([e9063c0](e9063c0))
* **pagination:** implement InstantSearch.css ([#3119](#3119)) ([f3c3343](f3c3343))
* **panel:** add Panel widget ([#3253](#3253)) ([82e19fc](82e19fc))
* **poweredBy:** implement InstantSearch.css ([#3164](#3164)) ([bcc18a0](bcc18a0))
* **poweredBy:** update logo ([#3256](#3256)) ([838abec](838abec))
* **price-ranges:** implement InstantSearch.css ([#3124](#3124)) ([335339b](335339b))
* **range-input:** implement InstantSearch.css ([#3098](#3098)) ([ee6bc7e](ee6bc7e))
* **range-slider:** implement InstantSearch.css ([#3126](#3126)) ([b9b8d31](b9b8d31))
* **rating-menu:** implement InstantSearch.css ([#3161](#3161)) ([d039e11](d039e11))
* **ratingMenu:** merge labels and templates ([#3317](#3317)) ([505a2e7](505a2e7))
* **refinement-list:** implement InstantSearch.css ([#3152](#3152)) ([11c5580](11c5580))
* **refinement-list:** implement InstantSearch.css (2) ([#3179](#3179)) ([0365641](0365641))
* **refinement-list:** implement InstantSearch.css to searchbox ([#3263](#3263)) ([ad905c7](ad905c7))
* **search-client:** use search client ([#3133](#3133)) ([8e70a3e](8e70a3e))
* **searchbox:** implement InstantSearch.css ([#3127](#3127)) ([c68c1fe](c68c1fe))
* **snippet:** implement InstantSearch.css ([#3134](#3134)) ([fa56657](fa56657))
* **sort-by:** implement InstantSearch.css ([#3120](#3120)) ([5f21723](5f21723))
* **sortBy:** rename item  to  ([#3230](#3230)) ([9e24a68](9e24a68))
* **stats:** implement InstantSearch.css ([#3097](#3097)) ([63a688e](63a688e))
* **stories:** add default CurrentRefinements story ([#3252](#3252)) ([45a8fd5](45a8fd5))
* **suit:** Default component names to empty object ([0b26356](0b26356))
* **suit-helper:** provide a helper to create suit css classnames ([f142496](f142496))
* **toggleRefinement:** implement InstantSearch.css ([#3135](#3135)) ([d67a437](d67a437))
* compress templates ([#3176](#3176)) ([54f2f77](54f2f77)), closes [#3095](#3095)
* **widgets:** use warn utils ([#3175](#3175)) ([3164b06](3164b06))
francoischalifour added a commit that referenced this pull request Dec 14, 2018
<a name=3.0.0-beta.1></a>
# [3.0.0-beta.1](v2.10.3...v3.0.0-beta.1) (2018-12-14)

### Bug Fixes

* **api:** remove transformData ([#3241](#3241)) ([5232936](5232936))
* **breadcrumb:** fix story with transformed label ([5a39312](5a39312))
* **breadcrumb:** rename item's name to label ([#3273](#3273)) ([0189cb4](0189cb4))
* **breadcrumb:** rename noRefinement to noRefinementRoot ([#3272](#3272)) ([21a5c61](21a5c61))
* **community:** fix search config ([#3142](#3142)) ([2b41982](2b41982))
* **configure:** make lifecycle functions optional ([#3339](#3339)) ([2b88cfa](2b88cfa))
* **connectRangeSlider:** remove deprecated connector ([#3189](#3189)) ([096ebeb](096ebeb))
* **current-refinements:** remove alphabetic sorting ([#3249](#3249)) ([9914f87](9914f87)), closes [/github.com/algolia/instantsearch.js/blob/011d47909894837f2c2da5088bc81803135d201b/src/lib/utils.js#L249](https://github.com//github.com/algolia/instantsearch.js/blob/011d47909894837f2c2da5088bc81803135d201b/src/lib/utils.js/issues/L249)
* **getRefinements:** provide attributeName for type: query ([6006fe1](6006fe1)), closes [#3205](#3205)
* **highlight:** avoid to ignore highlightedTagName ([#3323](#3323)) ([9871829](9871829))
* **highlight:** HighLight -> Highlight ([#3324](#3324)) ([5b4600d](5b4600d))
* **hits:** transform items after escaping ([#3251](#3251)) ([c46b82a](c46b82a)), closes [#3250](#3250)
* **infiniteHits:** move  option to templates ([#3300](#3300)) ([1828d66](1828d66))
* **InfiniteHits:** set the correct class for the last page ([#3232](#3232)) ([f604835](f604835))
* **lint:** remove unused import ([a9ec14c](a9ec14c))
* **pagination:** rename  to  ([#3275](#3275)) ([336945b](336945b))
* **poweredBy:** export connectPoweredBy connector ([#3331](#3331)) ([7d48c46](7d48c46))
* **poweredBy:** fix CSS classes ([#3332](#3332)) ([abc9b82](abc9b82))
* **range-input:** fix button classname ([#3234](#3234)) ([56695e1](56695e1)), closes [algolia/instantsearch-specs#92](algolia/instantsearch-specs#92)
* **range-input:** remove templates ([#3128](#3128)) ([94a1ce5](94a1ce5))
* **rangeInput:** convert labels to templates ([#3312](#3312)) ([cdf91e8](cdf91e8))
* **rangeSlider:** fix CSS classes ([#3316](#3316)) ([56a5255](56a5255))
* **refinement-list:** remove  in story ([0bf8db1](0bf8db1))
* **routing:** enforce RoutingManager is the last widget ([#3149](#3149)) ([1e86b2e](1e86b2e)), closes [#3148](#3148)
* **searchbox:** fix  and  templates ([#3313](#3313)) ([4e13122](4e13122))
* **tests:** add react-test-renderer ([176494b](176494b))
* **toggleRefinement:** provide  to templates ([#3303](#3303)) ([f515b62](f515b62))

### Features

* **3.0:** remove named exports on widgets ([#3129](#3129)) ([e718ea3](e718ea3))
* **breadcrumb:** implement InstantSearch.css ([#3115](#3115)) ([84d9f18](84d9f18))
* **bundle:** update bundle strategy ([#3260](#3260)) ([a7dab81](a7dab81))
* **clearRefinements:** implement InstantSearch.css ([#3308](#3308)) ([d98ecaf](d98ecaf)), closes [#3299](#3299)
* **clearRefinements:** implement is.css ([#3114](#3114)) ([11cdc14](11cdc14))
* **current-refinements:** implement InstantSearch.css ([#3190](#3190)) ([a70917d](a70917d))
* **GeoSearch:** implement InstantSearch.css ([#3138](#3138)) ([1867d30](1867d30))
* **hierarchical-menu:** implement InstantSearch.css ([#3182](#3182)) ([be0890d](be0890d))
* **hierarchical-menu:** implement show more feature ([#3151](#3151)) ([f54fccd](f54fccd))
* **hierarchicalMenu:** merge showMore templates ([#3318](#3318)) ([0059251](0059251))
* **highlight:** export highlight function ([#3137](#3137)) ([d4b6fb1](d4b6fb1))
* **highlight:** implement InstantSearch.css ([#3132](#3132)) ([260a0b8](260a0b8))
* **hits:** implement InstantSearch.css ([#3096](#3096)) ([b3cc413](b3cc413))
* **hits-per-page:** implement InstantSearch.css ([#3125](#3125)) ([49e7096](49e7096))
* **infiniteHits:** rename showMore template to showMoreText ([#3330](#3330)) ([babad39](babad39))
* **menu:** implement InstantSearch.css ([#3181](#3181)) ([a274ab7](a274ab7))
* **menu:** merge showMore templates ([#3328](#3328)) ([73a450b](73a450b))
* **menuSelect:** implement is.css ([#3109](#3109)) ([43e654a](43e654a))
* **numeric-menu:** implement InstantSearch.css ([#3162](#3162)) ([f5358f4](f5358f4))
* **numericSelector:** remove widget ([#3183](#3183)) ([e9063c0](e9063c0))
* **pagination:** implement InstantSearch.css ([#3119](#3119)) ([f3c3343](f3c3343))
* **pagination:** rename labels to templates ([#3333](#3333)) ([9f24098](9f24098))
* **panel:** add Panel widget ([#3253](#3253)) ([82e19fc](82e19fc))
* **poweredBy:** disable setting URL from widget ([#3334](#3334)) ([a5ff6af](a5ff6af))
* **poweredBy:** implement InstantSearch.css ([#3164](#3164)) ([bcc18a0](bcc18a0))
* **poweredBy:** update logo ([#3256](#3256)) ([838abec](838abec))
* **price-ranges:** implement InstantSearch.css ([#3124](#3124)) ([335339b](335339b))
* **range-input:** implement InstantSearch.css ([#3098](#3098)) ([ee6bc7e](ee6bc7e))
* **range-slider:** implement InstantSearch.css ([#3126](#3126)) ([b9b8d31](b9b8d31))
* **rating-menu:** implement InstantSearch.css ([#3161](#3161)) ([d039e11](d039e11))
* **ratingMenu:** merge labels and templates ([#3317](#3317)) ([505a2e7](505a2e7))
* **refinement-list:** implement InstantSearch.css ([#3152](#3152)) ([11c5580](11c5580))
* **refinement-list:** implement InstantSearch.css (2) ([#3179](#3179)) ([0365641](0365641))
* **refinement-list:** implement InstantSearch.css to searchbox ([#3263](#3263)) ([ad905c7](ad905c7))
* **refinementList:** merge showMore templates ([#3329](#3329)) ([9b6a9c4](9b6a9c4))
* **search-client:** use search client ([#3133](#3133)) ([8e70a3e](8e70a3e))
* **searchbox:** implement InstantSearch.css ([#3127](#3127)) ([c68c1fe](c68c1fe))
* **snippet:** implement InstantSearch.css ([#3134](#3134)) ([fa56657](fa56657))
* **sort-by:** implement InstantSearch.css ([#3120](#3120)) ([5f21723](5f21723))
* **sortBy:** rename item  to  ([#3230](#3230)) ([9e24a68](9e24a68))
* **stats:** implement InstantSearch.css ([#3097](#3097)) ([63a688e](63a688e))
* **stories:** add default CurrentRefinements story ([#3252](#3252)) ([45a8fd5](45a8fd5))
* **suit:** Default component names to empty object ([0b26356](0b26356))
* **suit-helper:** provide a helper to create suit css classnames ([f142496](f142496))
* **toggleRefinement:** implement InstantSearch.css ([#3135](#3135)) ([d67a437](d67a437))
* **widgets:** use warn utils ([#3175](#3175)) ([3164b06](3164b06))
* compress templates ([#3176](#3176)) ([54f2f77](54f2f77)), closes [#3095](#3095)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants