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
|
||||
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
|
||||
commento = "https://example.com/js/commento.js"
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ a {
|
|||
color: $fg_color;
|
||||
text-decoration: none;
|
||||
border-bottom: 2px solid $fg_color;
|
||||
&:hover {
|
||||
&:hover, &:focus {
|
||||
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) }}
|
||||
<li><a href="/tags">Tags</a></li>
|
||||
{{ end }}
|
||||
{{ if (.Site.Params.enableSearch | default true) }}
|
||||
<li><a href="/search">Search</a></li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
</nav>
|
||||
</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 }}
|
||||
{{- partial "js_paginator.html" . -}}
|
||||
<script>
|
||||
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) {
|
||||
if (!nextPage) return;
|
||||
fetch(nextPage).then(res => res.json())
|
||||
|
|
Loading…
Reference in New Issue