added optional js powered search
This commit is contained in:
parent
cfad046bb8
commit
f51db60b35
|
@ -44,6 +44,8 @@ summaryLength = 70 # number of words for article summaries
|
||||||
gridView = false # show post list as a grid. goes well with discreteCards
|
gridView = false # show post list as a grid. goes well with discreteCards
|
||||||
highlightBgColor = "#34363b"; # card and circle navigation background color for discrete card mode
|
highlightBgColor = "#34363b"; # card and circle navigation background color for discrete card mode
|
||||||
|
|
||||||
|
enableSearch = true # enable search page
|
||||||
|
|
||||||
# enable comments support with commento using the script from your server
|
# enable comments support with commento using the script from your server
|
||||||
commento = "https://example.com/js/commento.js"
|
commento = "https://example.com/js/commento.js"
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ a {
|
||||||
color: $fg_color;
|
color: $fg_color;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
border-bottom: 2px solid $fg_color;
|
border-bottom: 2px solid $fg_color;
|
||||||
&:hover {
|
&:hover, &:focus {
|
||||||
border-color: $accent_color !important;
|
border-color: $accent_color !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -335,3 +335,27 @@ ul.list {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.search {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
align-items: center;
|
||||||
|
.nerdlink {
|
||||||
|
display: inline-block;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
#searchbar {
|
||||||
|
@extend a;
|
||||||
|
width: 100%;
|
||||||
|
display: inline-block;
|
||||||
|
background-color: transparent;
|
||||||
|
border-top: none;
|
||||||
|
border-left: none;
|
||||||
|
border-right: none;
|
||||||
|
padding: 6px 0;
|
||||||
|
font-family: $main_font;
|
||||||
|
font-size: 1.3em;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
title: Search
|
||||||
|
layout: search
|
||||||
|
outputs:
|
||||||
|
- "html"
|
||||||
|
- "json"
|
||||||
|
---
|
|
@ -0,0 +1,51 @@
|
||||||
|
{{ define "main" }}
|
||||||
|
<noscript>
|
||||||
|
You need to enable JavaScript to be able to search.
|
||||||
|
</noscript>
|
||||||
|
<div class="search">
|
||||||
|
<input id="searchbar" type="text" placeholder="{{ .Title }}" />
|
||||||
|
<a class="nerdlink" onclick="newSearch();"></a>
|
||||||
|
</div>
|
||||||
|
<div class="postlist {{ if .Site.Params.gridView }}gridView{{ end }}" id="postlist">
|
||||||
|
</div>
|
||||||
|
{{- partial "js_paginator.html" . -}}
|
||||||
|
<script>
|
||||||
|
function matchTags(page, term) {
|
||||||
|
for (let tag of page.tags) {
|
||||||
|
if (tag.includes(term)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
function performSearch(term) {
|
||||||
|
document.getElementById('postlist').innerHTML = '';
|
||||||
|
term = term.toLowerCase();
|
||||||
|
fetch('/search/index.json').then(res => res.json())
|
||||||
|
.then(res => {
|
||||||
|
let articles = res.pages.filter(page => (
|
||||||
|
page.title.toLowerCase().includes(term) ||
|
||||||
|
matchTags(page, term) ||
|
||||||
|
page.text.includes(term)
|
||||||
|
));
|
||||||
|
if (articles.length > 0) renderArticles(articles);
|
||||||
|
else document.getElementById('postlist').innerHTML = `
|
||||||
|
<h3>No results found</h3>
|
||||||
|
`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
var url = location.href;
|
||||||
|
var baseUrl = url.split('?')[0];
|
||||||
|
var searchbar = document.getElementById('searchbar');
|
||||||
|
if (url.includes('?')) {
|
||||||
|
var urlParams = new URLSearchParams(url.split('?')[1]);
|
||||||
|
if (urlParams.has('q')) {
|
||||||
|
let searchTerm = urlParams.get('q');
|
||||||
|
searchbar.value = searchTerm;
|
||||||
|
performSearch(searchTerm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function newSearch() {
|
||||||
|
location.href = baseUrl+`?q=${searchbar.value}`;
|
||||||
|
}
|
||||||
|
searchbar.onkeyup = (ev) => {if (ev.keyCode == 13) newSearch()};
|
||||||
|
</script>
|
||||||
|
{{ end }}
|
|
@ -0,0 +1,26 @@
|
||||||
|
{{ define "main" }}
|
||||||
|
{
|
||||||
|
"pages": [
|
||||||
|
{{ range $i, $e := .Site.RegularPages }}
|
||||||
|
{{ if $i }},{{ end }}
|
||||||
|
{
|
||||||
|
"title": {{ .Title | jsonify }},
|
||||||
|
"date": {{ .Date.Format "2006-01-02" | jsonify }},
|
||||||
|
"tags": {{ if .Params.tags }}
|
||||||
|
{{ .Params.tags | jsonify }}
|
||||||
|
{{ else }}
|
||||||
|
[]
|
||||||
|
{{ end }},
|
||||||
|
"summary": {{ .Summary | jsonify }},
|
||||||
|
"text": {{ lower .Plain | jsonify }},
|
||||||
|
"link": "{{ .Permalink }}"
|
||||||
|
{{ if .Site.Params.imageInArticlePreview }}
|
||||||
|
, "image": {{ if .Params.Image }}
|
||||||
|
{{ .Params.Image | jsonify }}{{ else }}""
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
}
|
||||||
|
{{ end }}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
{{ end }}
|
|
@ -16,6 +16,9 @@
|
||||||
{{ if (.Site.Params.showTags | default true) }}
|
{{ if (.Site.Params.showTags | default true) }}
|
||||||
<li><a href="/tags">Tags</a></li>
|
<li><a href="/tags">Tags</a></li>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
{{ if (.Site.Params.enableSearch | default true) }}
|
||||||
|
<li><a href="/search">Search</a></li>
|
||||||
|
{{ end }}
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
<script>
|
||||||
|
function renderTags(tags) {
|
||||||
|
if (tags.length <= 0) return '';
|
||||||
|
let res = '| <span title="tags"> </span>';
|
||||||
|
for (let tag of tags) {
|
||||||
|
res += `<a href="/tags/${tag}">#${tag}</a>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
function renderImage(image) {
|
||||||
|
if (!image) return '';
|
||||||
|
return `<img src="${image}" />`
|
||||||
|
}
|
||||||
|
function renderSingleArticle(article) {
|
||||||
|
if (article.ignore) return '';
|
||||||
|
return `
|
||||||
|
<article class="card postlistitem {{ if .Site.Params.discreteCards }}discrete{{ end }}">
|
||||||
|
<div>
|
||||||
|
<h2>
|
||||||
|
<a href="${article.link}">${article.title}</a>
|
||||||
|
</h2>
|
||||||
|
<p class="date">
|
||||||
|
<span title="Date"> </span>
|
||||||
|
${article.date}
|
||||||
|
${renderTags(article.tags)}
|
||||||
|
</p>
|
||||||
|
{{ if .Site.Params.imageInArticlePreview }}
|
||||||
|
${renderImage(article.image)}
|
||||||
|
{{end}}
|
||||||
|
<div class="articlePreview">
|
||||||
|
<p>${article.summary}</p>
|
||||||
|
<p><a href="${article.link}">Continue reading </a></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
|
</article>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
function renderArticles(articles) {
|
||||||
|
let rendered = articles.map(a => renderSingleArticle(a)).join('\n');
|
||||||
|
document.getElementById('postlist').innerHTML += rendered;
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -1,48 +1,7 @@
|
||||||
{{ if .Site.Params.infiniteScrolling }}
|
{{ if .Site.Params.infiniteScrolling }}
|
||||||
|
{{- partial "js_paginator.html" . -}}
|
||||||
<script>
|
<script>
|
||||||
var nextPage = '/index.json';
|
var nextPage = '/index.json';
|
||||||
function renderTags(tags) {
|
|
||||||
if (tags.length <= 0) return '';
|
|
||||||
let res = '| <span title="tags"> </span>';
|
|
||||||
for (let tag of tags) {
|
|
||||||
res += `<a href="/tags/${tag}">#${tag}</a>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
function renderImage(image) {
|
|
||||||
if (!image) return '';
|
|
||||||
return `<img src="${image}" />`
|
|
||||||
}
|
|
||||||
function renderSingleArticle(article) {
|
|
||||||
if (article.ignore) return '';
|
|
||||||
return `
|
|
||||||
<article class="card postlistitem {{ if .Site.Params.discreteCards }}discrete{{ end }}">
|
|
||||||
<div>
|
|
||||||
<h2>
|
|
||||||
<a href="${article.link}">${article.title}</a>
|
|
||||||
</h2>
|
|
||||||
<p class="date">
|
|
||||||
<span title="Date"> </span>
|
|
||||||
${article.date}
|
|
||||||
${renderTags(article.tags)}
|
|
||||||
</p>
|
|
||||||
{{ if .Site.Params.imageInArticlePreview }}
|
|
||||||
${renderImage(article.image)}
|
|
||||||
{{end}}
|
|
||||||
<div class="articlePreview">
|
|
||||||
<p>${article.summary}</p>
|
|
||||||
<p><a href="${article.link}">Continue reading </a></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<hr />
|
|
||||||
</article>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
function renderArticles(articles) {
|
|
||||||
let rendered = articles.map(a => renderSingleArticle(a)).join('\n');
|
|
||||||
document.getElementById('postlist').innerHTML += rendered;
|
|
||||||
}
|
|
||||||
function getNext(first=false) {
|
function getNext(first=false) {
|
||||||
if (!nextPage) return;
|
if (!nextPage) return;
|
||||||
fetch(nextPage).then(res => res.json())
|
fetch(nextPage).then(res => res.json())
|
||||||
|
|
Loading…
Reference in New Issue