From a518c15cbf92ad50b8a50c27aa74a5311fa2f07c Mon Sep 17 00:00:00 2001 From: Haroen Viaene Date: Thu, 24 Oct 2024 11:44:06 +0200 Subject: [PATCH] doc(templates): explain how to use htm in a connector (#6410) * doc(templates): explain how to use htm in a connector This avoids the usage of the deprecated `highlight` and `snippet` functions * !fixup --- examples/js/media/package.json | 1 + examples/js/media/src/widgets/Articles.ts | 314 +++++++++++++--------- 2 files changed, 184 insertions(+), 131 deletions(-) diff --git a/examples/js/media/package.json b/examples/js/media/package.json index 467ef1f8cd..59f1df12d1 100644 --- a/examples/js/media/package.json +++ b/examples/js/media/package.json @@ -10,6 +10,7 @@ "dependencies": { "algoliasearch": "5.1.1", "date-fns": "2.25.0", + "htm": "^3.0.0", "instantsearch.css": "8.5.1", "instantsearch.js": "4.75.2" }, diff --git a/examples/js/media/src/widgets/Articles.ts b/examples/js/media/src/widgets/Articles.ts index 8b22c0adbe..ce2f4c90dd 100644 --- a/examples/js/media/src/widgets/Articles.ts +++ b/examples/js/media/src/widgets/Articles.ts @@ -1,8 +1,10 @@ import { formatDistanceToNow } from 'date-fns'; +import { html, render } from 'htm/preact'; +import { Hit } from 'instantsearch.js'; import { connectInfiniteHits } from 'instantsearch.js/es/connectors'; -import { highlight, snippet } from 'instantsearch.js/es/helpers'; +import { Snippet, Highlight } from 'instantsearch.js/es/helpers/components'; -type Hit = { +type Result = Hit<{ slug: string; primary_category: { slug: string; @@ -16,13 +18,13 @@ type Hit = { created_at_timestamp: number; cloudinary_url: string; title: string; -}; +}>; -const getBlogPostUrl = (hit: Hit) => +const getBlogPostUrl = (hit: Result) => `https://algolia.com/blog/${hit.primary_category.slug}/${hit.slug}`; function createHit( - hit: Hit, + hit: Result, { isHighlighted, refinedCategory, @@ -32,11 +34,12 @@ function createHit( const date = formatDistanceToNow(hit.created_at_timestamp * 1000, { addSuffix: true, }).replace('about ', ''); - return ` + + return html`
  • @@ -46,57 +49,54 @@ function createHit(
    - ${ - hit.primary_category - ? `${ - refinedCategory || hit.primary_category.title - } • ` - : '' - } + ${hit.primary_category + ? html` + ${refinedCategory || hit.primary_category.title} + + • ` + : ''} ${date}

    - ${highlight({ - attribute: 'title', - hit, - })} + <${Highlight} attribute="title" hit=${hit} />

    - ${snippet({ - attribute: 'content', - hit, - })} + <${Snippet} attribute="content" hit=${hit} />

    - ${ - author - ? `
    ${author.nickname}${author.nickname}${author.job_title}
    ` - : '' - } + ${author + ? html`
    + ${author.nickname}${author.nickname}${author.job_title} +
    ` + : ''}

    - ${highlight({ - attribute: 'title', - hit, - })} + <${Highlight} attribute="title" hit=${hit} />

    @@ -107,20 +107,18 @@ function createHit( } function createPlaceholderHit({ isHighlighted }: { isHighlighted: boolean }) { - return ` -
  • -
    -
    -
    - -
    - -
    -
    -
  • -`; + return html` +
  • +
    +
    +
    +
    +
  • + `; } let globalIsLastPage = false; @@ -129,7 +127,7 @@ const infiniteHits = connectInfiniteHits<{ container: string }>( ( { results, - hits, + items, showPrevious, showMore, isFirstPage, @@ -165,13 +163,16 @@ const infiniteHits = connectInfiniteHits<{ container: string }>( observer.observe(loadMoreTrigger); - containerNode.querySelector('div')!.innerHTML = ` -
      - ${[...Array(7)] - .map((_, index) => createPlaceholderHit({ isHighlighted: index === 0 })) - .join('')} -
    -`; + render( + html` +
      + ${[...Array(7)].map((_, index) => + createPlaceholderHit({ isHighlighted: index === 0 }) + )} +
    + `, + containerNode.querySelector('div')! + ); return; } @@ -180,57 +181,109 @@ const infiniteHits = connectInfiniteHits<{ container: string }>( results = results!; if (results.nbHits === 0) { - containerNode.querySelector('div')!.innerHTML = ` -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

    - Sorry, we can't find any matches${ - results.query ? ` for "${results.query}"` : '' - }. -

    -
    -`; + render( + html` +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    + Sorry, we can't find any + matches${results.query ? ` for "${results.query}"` : ''}. +

    +
    + `, + containerNode.querySelector('div')! + ); return; } - const hitsOffset = hits.findIndex( + const hitsOffset = items.findIndex( ({ objectID }) => results.hits[0].objectID === objectID ); const hitsWindow = { start: results.hitsPerPage * results.page - hitsOffset + 1, - end: results.hitsPerPage * results.page + hits.length - hitsOffset, + end: results.hitsPerPage * results.page + items.length - hitsOffset, }; const refinedCategory = ((facet) => { @@ -238,36 +291,35 @@ const infiniteHits = connectInfiniteHits<{ container: string }>( return category ? category.name : undefined; })(results.hierarchicalFacets.find(({ name }) => name === 'categories')); - containerNode.querySelector('div')!.innerHTML = ` -
    -

    - Showing ${hitsWindow.start} - ${hitsWindow.end} out of - ${results.nbHits} articles -

    - -
    -
      - ${hits - .map((hit, index: number) => - createHit(hit as unknown as Hit, { + render( + html` +
      +

      + Showing ${hitsWindow.start} - ${hitsWindow.end} out of + ${results.nbHits} articles +

      + +
      +
        + ${items.map((hit, index) => + createHit(hit as unknown as Result, { isHighlighted: results.nbHits !== 3 && (index === 0 || results.nbHits === 2), refinedCategory, }) - ) - .join('')} -
      - - ${ - results.nbHits > 0 && isLastPage - ? ` -
      -

      ${results.nbHits} articles shown

      -
      -` - : '' - } - `; + )} +
    + + ${results.nbHits > 0 && isLastPage + ? html` +
    +

    ${results.nbHits} articles shown

    +
    + ` + : ''} + `, + containerNode.querySelector('div')! + ); containerNode .querySelector('.previous-hits')!