search almost done
This commit is contained in:
		
							
								
								
									
										3
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
{
 | 
			
		||||
    "cmake.configureOnOpen": false
 | 
			
		||||
}
 | 
			
		||||
@@ -22,5 +22,5 @@ theme = "fiscleconsult"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
[outputs]
 | 
			
		||||
home = [ "HTML", "RSS", "SearchIndex" ]
 | 
			
		||||
  home = ["HTML", "RSS", "JSON"]
 | 
			
		||||
  page = ["HTML"]
 | 
			
		||||
@@ -3,6 +3,7 @@ title: "Fiscale maatregelen van het Ministerie van Financiën in het kader van C
 | 
			
		||||
date: 2020-01-26T23:11:13Z
 | 
			
		||||
summary: "Veel gestelde vragen (FAQ) over de (versoepelde) fiscale maatregelen van het Ministerie van Financiën in het kader van COVID-19"
 | 
			
		||||
image : https://via.placeholder.com/150
 | 
			
		||||
tags: ["NL"]
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
**LOONBELASTING EN INKOMSTENBELASTING**
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								themes/fiscleconsult/layouts/index.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								themes/fiscleconsult/layouts/index.json
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
{{- $.Scratch.Add "pagesIndex" slice -}}
 | 
			
		||||
{{- range $index, $page := .Site.Pages -}}
 | 
			
		||||
 | 
			
		||||
  {{- if in (slice "category" ) $page.Type -}}
 | 
			
		||||
  {{- if gt (len $page.Content) 0 -}}
 | 
			
		||||
  {{- $pageData := (dict "title" $page.Title "href" $page.Permalink "categories" (delimit $page.Params.tags " ; ") "content" $page.Plain ) -}}  {{- $.Scratch.Add "pagesIndex" $pageData -}}
 | 
			
		||||
{{- end -}}
 | 
			
		||||
{{- end -}}
 | 
			
		||||
{{- end -}}
 | 
			
		||||
{{- $.Scratch.Get "pagesIndex" | jsonify -}}
 | 
			
		||||
@@ -11,7 +11,6 @@
 | 
			
		||||
    {{ $text }}
 | 
			
		||||
    </a>
 | 
			
		||||
    {{ end }}
 | 
			
		||||
    <a href="javascript:void(0);" class="icon" onclick="myFunction()">
 | 
			
		||||
        <i data-feather="menu" color="black"></i></a>
 | 
			
		||||
</nav>
 | 
			
		||||
<br>
 | 
			
		||||
<!-- {{ partial "search.html" . }} -->
 | 
			
		||||
 
 | 
			
		||||
@@ -18,3 +18,5 @@
 | 
			
		||||
 | 
			
		||||
<!-- search -->
 | 
			
		||||
<script src="https://unpkg.com/lunr/lunr.js"></script>
 | 
			
		||||
<!-- <script src="/js/search.js"></script> -->
 | 
			
		||||
<script src="/js/search2.js"></script>
 | 
			
		||||
							
								
								
									
										17
									
								
								themes/fiscleconsult/layouts/partials/search.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								themes/fiscleconsult/layouts/partials/search.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
 | 
			
		||||
<form id="search" class="search" >
 | 
			
		||||
    <label for="search-input">
 | 
			
		||||
       <i data-feather="search"></i>
 | 
			
		||||
    </label>
 | 
			
		||||
    <input type="search" id="search-input" class="search-input">
 | 
			
		||||
</form>
 | 
			
		||||
 | 
			
		||||
<template id="search-result" >
 | 
			
		||||
    <article class="content post">
 | 
			
		||||
        <h2 class="post-title"><a class="summary-title-link"></a></h2>
 | 
			
		||||
        <summary class="summary"></summary>
 | 
			
		||||
        <div class="read-more-container">
 | 
			
		||||
            <a class="read-more-link">{{ i18n "readMore" }} »</a>
 | 
			
		||||
        </div>
 | 
			
		||||
    </article>
 | 
			
		||||
</template>
 | 
			
		||||
							
								
								
									
										159
									
								
								themes/fiscleconsult/static/js/search.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								themes/fiscleconsult/static/js/search.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,159 @@
 | 
			
		||||
window.addEventListener("DOMContentLoaded", function(event)
 | 
			
		||||
{
 | 
			
		||||
  var index = null;
 | 
			
		||||
  var lookup = null;
 | 
			
		||||
  var queuedTerm = null;
 | 
			
		||||
 | 
			
		||||
  var form = document.getElementById("search");
 | 
			
		||||
  var input = document.getElementById("search-input");
 | 
			
		||||
 | 
			
		||||
  form.addEventListener("submit", function(event)
 | 
			
		||||
  {
 | 
			
		||||
    event.preventDefault();
 | 
			
		||||
 | 
			
		||||
    var term = input.value.trim();
 | 
			
		||||
    if (!term)
 | 
			
		||||
      return;
 | 
			
		||||
 | 
			
		||||
    startSearch(term);
 | 
			
		||||
  }, false);
 | 
			
		||||
 | 
			
		||||
  function startSearch(term)
 | 
			
		||||
  {
 | 
			
		||||
    // Start icon animation.
 | 
			
		||||
    form.setAttribute("data-running", "true");
 | 
			
		||||
 | 
			
		||||
    if (index)
 | 
			
		||||
    {
 | 
			
		||||
      // Index already present, search directly.
 | 
			
		||||
      search(term);
 | 
			
		||||
    }
 | 
			
		||||
    else if (queuedTerm)
 | 
			
		||||
    {
 | 
			
		||||
      // Index is being loaded, replace the term we want to search for.
 | 
			
		||||
      queuedTerm = term;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
      // Start loading index, perform the search when done.
 | 
			
		||||
      queuedTerm = term;
 | 
			
		||||
      initIndex();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function searchDone()
 | 
			
		||||
  {
 | 
			
		||||
    // Stop icon animation.
 | 
			
		||||
    form.removeAttribute("data-running");
 | 
			
		||||
 | 
			
		||||
    queuedTerm = null;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function initIndex()
 | 
			
		||||
  {
 | 
			
		||||
    var request = new XMLHttpRequest();
 | 
			
		||||
    request.open("GET", "/index.json");
 | 
			
		||||
    request.responseType = "json";
 | 
			
		||||
    request.addEventListener("load", function(event)
 | 
			
		||||
    {
 | 
			
		||||
      lookup = {};
 | 
			
		||||
      index = lunr(function()
 | 
			
		||||
      {
 | 
			
		||||
        // Uncomment the following line and replace de by the right language
 | 
			
		||||
        // code to use a lunr language pack.
 | 
			
		||||
 | 
			
		||||
        // this.use(lunr.nl);
 | 
			
		||||
 | 
			
		||||
        this.ref("uri");
 | 
			
		||||
 | 
			
		||||
        // If you added more searchable fields to the search index, list them here.
 | 
			
		||||
        this.field("title");
 | 
			
		||||
        this.field("content");
 | 
			
		||||
        this.field("description");
 | 
			
		||||
        this.field("categories");
 | 
			
		||||
 | 
			
		||||
        for (var doc of request.response)
 | 
			
		||||
        {
 | 
			
		||||
          this.add(doc);
 | 
			
		||||
          lookup[doc.uri] = doc;
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      // Search index is ready, perform the search now
 | 
			
		||||
      search(queuedTerm);
 | 
			
		||||
    }, false);
 | 
			
		||||
    request.addEventListener("error", searchDone, false);
 | 
			
		||||
    request.send(null);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function search(term)
 | 
			
		||||
  {
 | 
			
		||||
    var results = index.search(term);
 | 
			
		||||
    console.log(results);
 | 
			
		||||
 | 
			
		||||
    // The element where search results should be displayed, adjust as needed.
 | 
			
		||||
    var target = document.querySelector("#search-result");
 | 
			
		||||
 | 
			
		||||
    while (target.firstChild)
 | 
			
		||||
      target.removeChild(target.firstChild);
 | 
			
		||||
 | 
			
		||||
    var title = document.createElement("h1");
 | 
			
		||||
    title.id = "search-results";
 | 
			
		||||
    title.className = "list-title";
 | 
			
		||||
 | 
			
		||||
    if (results.length == 0)
 | 
			
		||||
      title.textContent = `No results found for “${term}”`;
 | 
			
		||||
    else if (results.length == 1)
 | 
			
		||||
      title.textContent = `Found one result for “${term}”`;
 | 
			
		||||
    else
 | 
			
		||||
      title.textContent = `Found ${results.length} results for “${term}”`;
 | 
			
		||||
    target.appendChild(title);
 | 
			
		||||
    document.title = title.textContent;
 | 
			
		||||
 | 
			
		||||
    var template = document.getElementById("search-result");
 | 
			
		||||
    for (var result of results)
 | 
			
		||||
    {
 | 
			
		||||
      var doc = lookup[result.ref];
 | 
			
		||||
 | 
			
		||||
      // Fill out search result template, adjust as needed.
 | 
			
		||||
      var element = template.content.cloneNode(true);
 | 
			
		||||
      element.querySelector(".summary-title-link").href =
 | 
			
		||||
          element.querySelector(".read-more-link").href = doc.uri;
 | 
			
		||||
      element.querySelector(".summary-title-link").textContent = doc.title;
 | 
			
		||||
      element.querySelector(".summary").textContent = truncate(doc.content, 70);
 | 
			
		||||
      target.appendChild(element);
 | 
			
		||||
    }
 | 
			
		||||
    title.scrollIntoView(true);
 | 
			
		||||
 | 
			
		||||
    searchDone();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // This matches Hugo's own summary logic:
 | 
			
		||||
  // https://github.com/gohugoio/hugo/blob/b5f39d23b8/helpers/content.go#L543
 | 
			
		||||
  function truncate(text, minWords)
 | 
			
		||||
  {
 | 
			
		||||
    var match;
 | 
			
		||||
    var result = "";
 | 
			
		||||
    var wordCount = 0;
 | 
			
		||||
    var regexp = /(\S+)(\s*)/g;
 | 
			
		||||
    while (match = regexp.exec(text))
 | 
			
		||||
    {
 | 
			
		||||
      wordCount++;
 | 
			
		||||
      if (wordCount <= minWords)
 | 
			
		||||
        result += match[0];
 | 
			
		||||
      else
 | 
			
		||||
      {
 | 
			
		||||
        var char1 = match[1][match[1].length - 1];
 | 
			
		||||
        var char2 = match[2][0];
 | 
			
		||||
        if (/[.?!"]/.test(char1) || char2 == "\n")
 | 
			
		||||
        {
 | 
			
		||||
          result += match[1];
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
          result += match[0];
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
}, false);
 | 
			
		||||
							
								
								
									
										101
									
								
								themes/fiscleconsult/static/js/search2.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								themes/fiscleconsult/static/js/search2.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,101 @@
 | 
			
		||||
let pagesIndex, searchIndex;
 | 
			
		||||
const MAX_SUMMARY_LENGTH = 100;
 | 
			
		||||
const SENTENCE_BOUNDARY_REGEX = /\b\.\s/gm;
 | 
			
		||||
const WORD_REGEX = /\b(\w*)[\W|\s|\b]?/gm;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
async function initSearchIndex() {
 | 
			
		||||
    try {
 | 
			
		||||
        const response = await fetch("/index.json");
 | 
			
		||||
        pagesIndex = await response.json();
 | 
			
		||||
        searchIndex = lunr(function () {
 | 
			
		||||
            this.field("title");
 | 
			
		||||
            this.field("categories");
 | 
			
		||||
            this.field("content");
 | 
			
		||||
            this.ref("href");
 | 
			
		||||
            pagesIndex.forEach(page => this.add(page));
 | 
			
		||||
        });
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
        console.log(e);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
initSearchIndex();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function getSearchResults(query) {
 | 
			
		||||
    return searchIndex.search(query).flatMap((hit) => {
 | 
			
		||||
        if (hit.ref == "undefined") return [];
 | 
			
		||||
        let pageMatch = pagesIndex.filter((page) => page.href === hit.ref)[0];
 | 
			
		||||
        pageMatch.score = hit.score;
 | 
			
		||||
        return [pageMatch];
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getLunrSearchQuery(query) {
 | 
			
		||||
    const searchTerms = query.split(" ");
 | 
			
		||||
    if (searchTerms.length === 1) {
 | 
			
		||||
        return query;
 | 
			
		||||
    }
 | 
			
		||||
    query = "";
 | 
			
		||||
    for (const term of searchTerms) {
 | 
			
		||||
        query += `+${term} `;
 | 
			
		||||
    }
 | 
			
		||||
    return query.trim();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function searchSite(query) {
 | 
			
		||||
    const originalQuery = query;
 | 
			
		||||
    query = getLunrSearchQuery(query);
 | 
			
		||||
    let results = getSearchResults(query);
 | 
			
		||||
    return results.length
 | 
			
		||||
        ? results
 | 
			
		||||
        : query !== originalQuery
 | 
			
		||||
            ? getSearchResults(originalQuery)
 | 
			
		||||
            : [];
 | 
			
		||||
}
 | 
			
		||||
const node = document.getElementById("search-input");
 | 
			
		||||
node.addEventListener('keydown', function (event) {
 | 
			
		||||
    if (event.code === 'Enter') {
 | 
			
		||||
        event.preventDefault();
 | 
			
		||||
        var q = node.value.trim().toLowerCase();
 | 
			
		||||
        var res = searchSite(q);
 | 
			
		||||
        console.log(res);
 | 
			
		||||
        renderSearchResults(res, q);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function renderSearchResults(results, term){
 | 
			
		||||
 | 
			
		||||
    var target = document.querySelector("#search-result");
 | 
			
		||||
    while (target.firstChild)
 | 
			
		||||
      target.removeChild(target.firstChild);
 | 
			
		||||
 | 
			
		||||
    var title = document.createElement("h1");
 | 
			
		||||
    title.id = "search-results";
 | 
			
		||||
    title.className = "list-title";
 | 
			
		||||
 | 
			
		||||
    if (results.length == 0)
 | 
			
		||||
      title.textContent = `No results found for “${term}”`;
 | 
			
		||||
    else if (results.length == 1)
 | 
			
		||||
      title.textContent = `Found one result for “${term}”`;
 | 
			
		||||
    else
 | 
			
		||||
      title.textContent = `Found ${results.length} results for “${term}”`;
 | 
			
		||||
    target.appendChild(title);
 | 
			
		||||
    document.title = title.textContent;
 | 
			
		||||
 | 
			
		||||
    var template = document.getElementById("search-result");
 | 
			
		||||
    for (var result of results)
 | 
			
		||||
    {
 | 
			
		||||
      var doc = lookup[result.ref];
 | 
			
		||||
 | 
			
		||||
      // Fill out search result template, adjust as needed.
 | 
			
		||||
      var element = template.content.cloneNode(true);
 | 
			
		||||
      element.querySelector(".summary-title-link").href =
 | 
			
		||||
          element.querySelector(".read-more-link").href = doc.uri;
 | 
			
		||||
      element.querySelector(".summary-title-link").textContent = doc.title;
 | 
			
		||||
      element.querySelector(".summary").textContent = truncate(doc.content, 70);
 | 
			
		||||
      target.appendChild(element);
 | 
			
		||||
    }
 | 
			
		||||
    title.scrollIntoView(true);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user