Rework Notes page: balanced two columns, filter, bibliography section, drop prev/next links

This commit is contained in:
tdehaeze committed 2026-10-17 21:49:47 +02:00
1 parent 0699938cd5
commit 2490e8bbb1
10 files changed
+364 -30

No files matched your search

+4
View File
@@ -0,0 +1,4 @@
+++
title = "Bibliography"
build = { render = "never", list = "never" }
+++
+5 -2
View File
@@ -1,8 +1,11 @@
+++ +++
title = "Zettels" title = "Notes"
author = ["Thomas Dehaeze"] author = ["Thomas Dehaeze"]
type = "zettels" type = "zettels"
url = "/notes/"
draft = false draft = false
+++ +++
Here is the list of subjects I took note about. Technical notes on control, mechatronics, instrumentation and related topics.
This is a living personal wiki, so some notes are still incomplete.
Further down, there is a list of notes on books, theses and articles I have read and found interesting.
+34
View File
@@ -0,0 +1,34 @@
{{ define "content" -}}
<article class="post">
<!-- post-header -->
<header class="post-header">
<h1 class="post-title">{{ .Title | title }}</h1>
</header>
<!-- TOC -->
{{- partial "post/toc.html" . -}}
<!-- Content -->
<div class="post-content">
{{ .Content }}
</div>
<!-- Backlinks -->
{{ partial "backlinks" . }}
<footer class="post-footer">
{{ with .Params.tags -}}
<div class="post-tags">
{{ range . -}}
<a href="{{ "tags" | relLangURL }}/{{ . | urlize }}/">{{ . }}</a>
{{ end -}}
</div>
{{- end -}}
<!-- Post Pagination -->
</footer>
</article>
<div id="comments">
{{ partial "comments.html" $ }}
</div>
{{- end }}
+34
View File
@@ -0,0 +1,34 @@
{{ define "content" -}}
<article class="post">
<!-- post-header -->
<header class="post-header">
<h1 class="post-title">{{ .Title | title }}</h1>
</header>
<!-- TOC -->
{{- partial "post/toc.html" . -}}
<!-- Content -->
<div class="post-content">
{{ .Content }}
</div>
<!-- Backlinks -->
{{ partial "backlinks" . }}
<footer class="post-footer">
{{ with .Params.tags -}}
<div class="post-tags">
{{ range . -}}
<a href="{{ "tags" | relLangURL }}/{{ . | urlize }}/">{{ . }}</a>
{{ end -}}
</div>
{{- end -}}
<!-- Post Pagination -->
</footer>
</article>
<div id="comments">
{{ partial "comments.html" $ }}
</div>
{{- end }}
+34
View File
@@ -0,0 +1,34 @@
{{ define "content" -}}
<article class="post">
<!-- post-header -->
<header class="post-header">
<h1 class="post-title">{{ .Title | title }}</h1>
</header>
<!-- TOC -->
{{- partial "post/toc.html" . -}}
<!-- Content -->
<div class="post-content">
{{ .Content }}
</div>
<!-- Backlinks -->
{{ partial "backlinks" . }}
<footer class="post-footer">
{{ with .Params.tags -}}
<div class="post-tags">
{{ range . -}}
<a href="{{ "tags" | relLangURL }}/{{ . | urlize }}/">{{ . }}</a>
{{ end -}}
</div>
{{- end -}}
<!-- Post Pagination -->
</footer>
</article>
<div id="comments">
{{ partial "comments.html" $ }}
</div>
{{- end }}
+13
View File
@@ -0,0 +1,13 @@
{{- $p := . -}}
{{- $raw := $p.RawContent -}}
{{- $author := $p.Params.ref_author | default "" -}}
{{- if not $author }}{{ with findRE `(?m)^Author\(s\)\r?\n: (.+)$` $raw 1 }}{{ $author = replaceRE `^Author\(s\)\r?\n: ` "" (index . 0) }}{{ end }}{{ end -}}
{{- $author = $author | replaceRE `&amp;` "&" | strings.TrimSpace -}}
{{- $year := $p.Params.ref_year | default "" -}}
{{- if not $year }}{{ with findRE `(?m)^Year\r?\n: (\d{4})` $raw 1 }}{{ $year = replaceRE `^Year\r?\n: ` "" (index . 0) }}{{ end }}{{ end -}}
{{- $notes := slice -}}
{{- range findRE `relref "[^"]+\.md"` $raw -}}
{{- $base := . | replaceRE `^relref "(?:.*/)?([^"/]+)\.md"$` "$1" -}}
{{- with site.GetPage (printf "/zettels/%s" $base) }}{{ $notes = $notes | append . }}{{ end -}}
{{- end -}}
{{- return (dict "author" $author "year" (string $year) "notes" $notes) -}}
+68
View File
@@ -0,0 +1,68 @@
<style>
.notes-intro { max-width: 42em; }
.notes-bar { position: sticky; top: 0; z-index: 5; background: #fff; border-bottom: 1px solid #e5e5e5; padding: .6em 0; margin: 1.2em 0; }
.notes-filter { display: none; align-items: center; gap: .8em; margin-bottom: .5em; }
.notes-filter.is-on { display: flex; }
.notes-filter input { flex: 1; max-width: 22em; padding: .4em .6em; border: 1px solid #ccc; border-radius: 4px; font: inherit; }
.notes-filter input:focus { outline: 2px solid hsl(232, 61%, 64%); outline-offset: 1px; }
.notes-count { color: #777; font-size: .85em; }
.notes-block { margin-top: 2em; }
.notes-block > h2 { font-size: 1.4em; margin: 0 0 .6em; padding-bottom: .3em; border-bottom: 1px solid #e5e5e5; }
.notes-block > h2 span { font-size: .6em; font-weight: normal; color: #888; }
.notes-block-bib { margin-top: 3.5em; scroll-margin-top: 4em; }
.notes-cols { display: flex; gap: 1.2em; align-items: flex-start; }
.notes-col { flex: 1 1 0; min-width: 0; }
@media (max-width: 699px) { .notes-cols { flex-direction: column; align-items: stretch; } }
.notes-single { max-width: 50em; }
.note-references { margin-top: 2em; }
.notes-card { break-inside: avoid; display: inline-block; width: 100%; box-sizing: border-box; margin: 0 0 1.2em; border: 1px solid #e5e5e5; border-radius: 6px; padding: .9em 1.1em 1em; min-width: 0; }
.notes-card h3 { margin: 0 0 .5em; font-size: 1.1em; display: flex; justify-content: space-between; align-items: baseline; gap: .5em; }
.notes-card h3 span { font-size: .75em; font-weight: normal; color: #888; }
.notes-card ul { list-style: none; margin: 0; padding: 0; }
.notes-card li { margin: .3em 0; line-height: 1.35; }
.notes-card .keywords { color: #888; font-size: .8em; margin-left: .3em; }
.notes-card .description { color: #666; font-size: .85em; }
.notes-sub { margin-top: .9em; }
.notes-sub h4 { margin: 0 0 .2em; font-size: .95em; }
.notes-sub h4 span { font-weight: normal; color: #888; font-size: .85em; }
.notes-sub ul { padding-left: 1em; border-left: 2px solid #eee; }
.notes-card li > a { color: #2a6ebb; }
.notes-block-bib .notes-card .description a { color: #c05b4d; }
.notes-card [hidden], .notes-sub[hidden], .notes-block[hidden], .notes-empty[hidden] { display: none; }
.notes-card-flow { break-inside: auto; display: block; }
.notes-card-flow h3 { break-after: avoid; }
</style>
<script>
document.addEventListener('DOMContentLoaded', function () {
var input = document.getElementById('notes-filter');
if (!input) return;
input.parentNode.classList.add('is-on');
var items = [].slice.call(document.querySelectorAll('.notes-card li[data-text]'));
var cards = [].slice.call(document.querySelectorAll('.notes-card'));
var count = document.getElementById('notes-count');
var empty = document.getElementById('notes-empty');
var total = items.length;
function run() {
var q = input.value.trim().toLowerCase(), shown = 0;
items.forEach(function (li) {
var ok = !q || li.getAttribute('data-text').indexOf(q) !== -1;
li.hidden = !ok;
if (ok) shown++;
});
[].forEach.call(document.querySelectorAll('.notes-sub'), function (d) {
d.hidden = !d.querySelector('li:not([hidden])');
});
cards.forEach(function (c) {
var hide = !c.querySelector('li:not([hidden])');
c.hidden = hide;
});
[].forEach.call(document.querySelectorAll('.notes-block'), function (b) {
b.hidden = !b.querySelector('li:not([hidden])');
});
count.textContent = q ? shown + ' of ' + total + ' entries' : total + ' entries';
empty.hidden = shown !== 0;
}
input.addEventListener('input', run);
run();
});
</script>
+34
View File
@@ -0,0 +1,34 @@
{{ define "content" -}}
<article class="post">
<!-- post-header -->
<header class="post-header">
<h1 class="post-title">{{ .Title | title }}</h1>
</header>
<!-- TOC -->
{{- partial "post/toc.html" . -}}
<!-- Content -->
<div class="post-content">
{{ .Content }}
</div>
<!-- Backlinks -->
{{ partial "backlinks" . }}
<footer class="post-footer">
{{ with .Params.tags -}}
<div class="post-tags">
{{ range . -}}
<a href="{{ "tags" | relLangURL }}/{{ . | urlize }}/">{{ . }}</a>
{{ end -}}
</div>
{{- end -}}
<!-- Post Pagination -->
</footer>
</article>
<div id="comments">
{{ partial "comments.html" $ }}
</div>
{{- end }}
+93 -28
View File
@@ -1,44 +1,109 @@
{{- define "title" }}{{ T "archive" }} - {{ .Site.Title }}{{ end -}} {{- define "title" }}{{ .Title }} - {{ .Site.Title }}{{ end -}}
{{- define "item" -}} {{- define "item" -}}
<li> <li data-text="{{ printf "%s %s %s" .Title (delimit (.Params.keywords | default slice) " ") (.Description | default "") | lower }}">
<a href="{{ .Permalink }}">{{ .Title | title }}</a> <a href="{{ .Permalink }}">{{ .Title | title }}</a>
{{ with .Keywords }}<span class="keywords">{{ . }}</span>{{ end }} {{ with .Keywords }}<span class="keywords">{{ delimit . ", " }}</span>{{ end }}
{{ with .Description }}<div class="description">{{ . }}</div>{{ end }} {{ with .Description }}<div class="description">{{ . }}</div>{{ end }}
</li> </li>
{{- end }} {{- end }}
{{- define "content" }} {{- define "card" -}}
{{- range .Pages.GroupByParam "category" }} {{- $id := .Key | urlize }}
<section class="list-zettels"> <section class="notes-card" id="{{ $id }}" aria-labelledby="{{ $id }}-h">
<span class="list-title">{{ .Key | title }}:</span> <h3 id="{{ $id }}-h">{{ .Key | title }} <span>{{ len .Pages }}</span></h3>
{{- $plain := where .Pages "Params.subcategory" "eq" nil }}
{{- if $plain }}
<ul> <ul>
{{- range (where .Pages "Params.subcategory" "eq" nil).ByTitle }} {{- range $plain.ByTitle }}{{ template "item" . }}{{ end }}
{{ template "item" . }} </ul>
{{- end }} {{- end }}
{{- range .Pages.GroupByParam "subcategory" }} {{- range (where .Pages "Params.subcategory" "ne" nil).GroupByParam "subcategory" }}
<li class="subcategory"> <div class="notes-sub">
<span class="list-subtitle">{{ .Key | title }}:</span> <h4>{{ .Key | title }} <span>({{ len .Pages }})</span></h4>
<ul> <ul>
{{- range .Pages.ByTitle }} {{- range .Pages.ByTitle }}{{ template "item" . }}{{ end }}
{{ template "item" . }} </ul>
{{- end }} </div>
</ul> {{- end }}
</section>
{{- end }}
{{- define "bibcard" -}}
{{- $label := .label }}
<section class="notes-card notes-card-flow" id="bib-{{ $label | urlize }}" aria-labelledby="bib-{{ $label | urlize }}-h">
<h3 id="bib-{{ $label | urlize }}-h">{{ $label }} <span>{{ len .pages }}</span></h3>
{{- $rows := slice }}
{{- range .pages }}{{ $m := partial "notes/bibmeta.html" . }}{{ $rows = $rows | append (dict "page" . "m" $m "year" (or $m.year "0")) }}{{ end }}
<ul>
{{- range sort $rows "year" "desc" }}
{{- $m := .m }}{{ with .page }}
<li data-text="{{ printf "%s %s %s %s %s" .Title $m.author $m.year (delimit (.Params.keywords | default slice) " ") (.Description | default "") | lower }}">
<a href="{{ .Permalink }}">{{ .Title }}</a>
{{ with .Keywords }}<span class="keywords">{{ delimit . ", " }}</span>{{ end }}
{{- if or $m.author $m.year }}
<div class="description">{{ $m.author }}{{ if and $m.author $m.year }}, {{ end }}{{ $m.year }}</div>
{{- end }}
{{- with $m.notes }}
<div class="description">Notes: {{ range $i, $n := . }}{{ if $i }}, {{ end }}<a href="{{ $n.Permalink }}">{{ $n.Title | title }}</a>{{ end }}</div>
{{- end }}
</li> </li>
{{- end }} {{- end }}{{ end }}
</ul> </ul>
</section> </section>
{{- end }} {{- end }}
{{- define "content" }}
{{- partial "notes/styles.html" . }}
{{- $cats := .Pages.GroupByParam "category" }}
{{- $uncat := where .Pages "Params.category" "eq" nil }} {{- $uncat := where .Pages "Params.category" "eq" nil }}
{{- if $uncat }} {{- $bibTypes := slice
<section class="list-zettels"> (dict "label" "Books" "pages" (where site.RegularPages "Section" "book"))
<span class="list-title">Other:</span> (dict "label" "PhD theses" "pages" (where site.RegularPages "Section" "phdthesis"))
<ul> (dict "label" "Journal articles" "pages" (where site.RegularPages "Section" "article"))
{{- range $uncat.ByTitle }} (dict "label" "Conference papers" "pages" (where site.RegularPages "Section" "inproceedings"))
{{ template "item" . }} (dict "label" "Book chapters" "pages" (where site.RegularPages "Section" "inbook"))
(dict "label" "Reports" "pages" (where site.RegularPages "Section" "techreport"))
(dict "label" "Websites" "pages" (where site.RegularPages "Section" "websites")) }}
{{- $bibCount := 0 }}
{{- range $bibTypes }}{{ $bibCount = add $bibCount (len .pages) }}{{ end }}
<article class="post">
<div class="post-content notes-intro">{{ .Content }}</div>
<div class="notes-bar">
<div class="notes-filter">
<label for="notes-filter">Filter</label>
<input type="search" id="notes-filter" placeholder="Title, keyword, author, year…" autocomplete="off">
<span class="notes-count" id="notes-count" aria-live="polite">{{ add (len .Pages) $bibCount }} entries</span>
</div>
</div>
<section class="notes-block" aria-labelledby="notes-h">
<h2 id="notes-h">Notes <span>{{ len .Pages }}</span></h2>
{{- $groups := slice }}
{{- range $cats }}
{{- $subs := len ((where .Pages "Params.subcategory" "ne" nil).GroupByParam "subcategory") }}
{{- $groups = $groups | append (dict "Key" .Key "Pages" .Pages "w" (add (len .Pages) (mul 2 $subs) 3)) }}
{{- end }} {{- end }}
</ul> {{- if $uncat }}{{ $groups = $groups | append (dict "Key" "Other" "Pages" $uncat "w" (add (len $uncat) 3)) }}{{ end }}
</section> {{- $colA := slice }}{{ $colB := slice }}{{ $wA := 0 }}{{ $wB := 0 }}
{{- end }} {{- range sort $groups "w" "desc" }}
{{- if le $wA $wB }}{{ $colA = $colA | append . }}{{ $wA = add $wA .w }}
{{- else }}{{ $colB = $colB | append . }}{{ $wB = add $wB .w }}{{ end }}
{{- end }}
<div class="notes-cols">
<div class="notes-col">{{ range sort $colA "Key" }}{{ template "card" . }}{{ end }}</div>
<div class="notes-col">{{ range sort $colB "Key" }}{{ template "card" . }}{{ end }}</div>
</div>
</section>
<section class="notes-block notes-block-bib" id="bibliography" aria-labelledby="bibliography-h">
<h2 id="bibliography-h">Bibliography <span>{{ $bibCount }}</span></h2>
<div class="notes-single">
{{- range $bibTypes }}{{ if .pages }}{{ template "bibcard" (dict "label" .label "pages" .pages.ByTitle) }}{{ end }}{{ end }}
</div>
</section>
<p class="notes-empty" id="notes-empty" hidden>Nothing matches this filter.</p>
</article>
{{- end }} {{- end }}
+45
View File
@@ -0,0 +1,45 @@
{{ define "content" -}}
<article class="post">
<header class="post-header">
<h1 class="post-title">{{ .Title }}</h1>
</header>
{{- partial "post/toc.html" . -}}
<div class="post-content">
{{ .Content }}
</div>
{{- $base := .File.BaseFileName }}
{{- $needle := printf `/%s.md"` $base }}
{{- $needle2 := printf `"%s.md"` $base }}
{{- $refs := slice }}
{{- range where site.RegularPages "Section" "in" (slice "book" "article" "phdthesis" "inproceedings" "inbook" "techreport") }}
{{- if or (strings.Contains .RawContent (printf `relref "%s.md"` $base)) (strings.Contains .RawContent (printf `/%s.md"` $base)) }}{{ $refs = $refs | append . }}{{ end }}
{{- end }}
{{- with $refs }}
<section class="note-references">
<h2>References</h2>
<ul>
{{- range sort . "Title" }}<li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li>{{ end }}
</ul>
</section>
{{- end }}
{{ partial "backlinks" . }}
<footer class="post-footer">
{{ with .Params.tags -}}
<div class="post-tags">
{{ range . -}}
<a href="{{ "tags" | relLangURL }}/{{ . | urlize }}/">{{ . }}</a>
{{ end -}}
</div>
{{- end -}}
</footer>
</article>
<div id="comments">
{{ partial "comments.html" $ }}
</div>
{{- end }}