3

We are bulding a website with hugo and added lunr.js for search. The content which is the .Content area is indexed but where there are sections in front matter (metadata) of the post, these contents are not indexed.

Example post with content in front matter:

---
    date: "2021-07-12"
    draft: false
    title: "Service1"
    description: "Contact us"
    icon: "fas fa-laptop-house"  
    layout: "layout-3"
    
    
    ######################### banner #####################
    banner:
      title: "Service1"
      image: "images/products/02.jpg"
      content : "something"
      background_class: "bg-light"
      button:
        enable : true
        label : "Try for Free"
        link : "get-demo/"
    
          
    ######################### product_info #####################
    product_info:
      enable : true
      title: "New experiments <br> Launch in minutes"
      content: "Some lorel ipsum"
      features:
      - image: "images/products/01.jpg"
        content : "##### For Football Teams
    
        Adipiscing elit Consequat tristique eget amet, tempus eu at consecttur. Leo facilisi nunc viverra tellus. Ac laoreet sit vel consquat. consectetur adipiscing elit. tempus eu at consecttur.
    
        <br><br>
    
        ##### For Basketball teams
    
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Consequat tristique eget amet, tempus eu at consecttur. Leo facilisi nunc viverra tellus. Ac laoreet sit vel consquat.
        "
    
      - image: "images/products/02.jpg"
        content : "##### For Design Teams
    
        Adipiscing elit Consequat tristique eget amet, tempus eu at consecttur. Leo facilisi nunc viverra tellus. Ac laoreet sit vel consquat. consectetur adipiscing elit. tempus eu at consecttur...
    
    ---
    
     Lorem ipsum content... 

The content at the bottom "Lorem ipsum content" is indexed as expected but the content in banner and product_info sections in front matter are not indexed.

layouts_default\index.json

{{ $.Scratch.Add "index" slice }}
{{ range site.RegularPages }}

{{ $date:= time.Format ":date_long" .PublishDate }}

{{ with .Params.image }}
{{ if (fileExists (add `assets/` .)) }}
{{ $image:= resources.Get . }}
{{ $image:= $image.Resize "650x" }}
{{ $.Scratch.Set "image" $image.Permalink }}
{{ end }}
{{ end }}
{{ $image:= $.Scratch.Get "image" }}

{{ $.Scratch.Add "index" (dict "title" .Title "date" $date "image" $image "categories" .Section "contents" .Plain "permalink" .RelPermalink) }}
{{ end }}
{{ $.Scratch.Get "index" | jsonify }}

Is there a way to index content of 'banner' and 'product_info' sections?

Configuration

In config.toml:

[outputs] home = ["HTML", "RSS", "JSON", "WebAppManifest"]

Code for indexing index.html:

<script>
    window.store = {
        {{ range .Site.Pages  }}
        "{{ .Permalink }}": {
            "title": "{{ .Title  }}",
            "tags": [{{ range .Params.Tags }}"{{ . }}",{{ end }}],
            "content": {{ .Content | plainify }}, 
            "url": "{{ .Permalink }}"
        },
        {{ end }}
    }
</script>
<script src="/js/lunr.min.js"></script>
<script src="/js/search.js"></script>

search.js

function displayResults (results, store) {
    const searchResults = document.getElementById('results')
    if (results.length) {
    let resultList = ''
    for (const n in results) {
        const item = store[results[n].ref]
        resultList += `
            <li>
                <h2>
                    <a href="${item.url}">${item.title}</a>
                </h2>'
                <p>${item.content.substring(0, 150)}...</p>
                <p>${item.tags}</p>
            </li>
        `;
    }
    searchResults.innerHTML = resultList
    } else {
    searchResults.innerHTML = 'No results found.'
}
}

const params = new URLSearchParams(window.location.search)
const query = params.get('query')

if (query) {
    document.getElementById('search-input').setAttribute('value', query)

    const idx = lunr(function () {
        this.ref('id')
        this.field('title', {
            // boost search to 15
            boost: 15
        })
        this.field('tags')
        this.field('content', {
            // boost search to 10
            boost: 10
        })

        for (const key in window.store) {
            this.add({
            id: key,
            title: window.store[key].title,
            tags: window.store[key].category,
            content: window.store[key].content
            })
        }
  })

  const results = idx.search(query)
  displayResults(results, window.store)

  document.getElementById('search-title').innerText = 'Search Results for ' + query
}
isin
  • 155
  • 1
  • 10

1 Answers1

1

I had to configure each type and loop (using range) in the contents in order to create a correct window.store in index.html displayed above. I some cases I had to concatenate strings different properties and add them in content property so that all text is searchable.

Some helpful snippets:

     //For simple pages 
{{ range where .Site.RegularPages "Type" "page" }}
"{{ .Permalink }}": {
        "title": "{{ .Title  }}",
        "tags": [{{ range .Params.Tags }}"{{ . }}",{{ end }}],
        "content": {{ .Content | plainify }}, // Strip out HTML tags
        "url": "{{ .Permalink }}"
    },
    {{ end }}

    // Products
    {{ range where .Site.RegularPages "Section" "products"}}
        {{ $data := "" }}
        {{ range $k, $_ := .Params.product_info.features }}
            {{ $m := (trim .content "#*") | plainify }}
            {{ $data = printf "%s" $data | printf "%s%s" $m }}
        {{ end }}

        "{{ .Permalink }}": {
            "title": "{{ .Title  }}",
            "tags": [{{ range .Params.Tags }}"{{ . }}",{{ end }}],
            "content": {{ printf "%s" (.Params.cta.content | plainify) | printf "%s%s" (.Params.intro_video.content | plainify)
                        | printf "%s%s" $data | printf "%s%s" (.Params.product_info.content | plainify)
                        | printf "%s%s" (.Params.banner.content | plainify) | printf "%s"
            }},
            "url": "{{ .Permalink }}"
        },
    {{ end }}
isin
  • 155
  • 1
  • 10