Sort menu posts by publication date with YYYY-MM-DD shortened-title prefix
This commit is contained in:
@@ -42,6 +42,11 @@ CSS file (Gruvbox, light + dark, theme toggle without reload).
|
|||||||
between that section's pages (server-side `.blog-pagination`), not globally.
|
between that section's pages (server-side `.blog-pagination`), not globally.
|
||||||
- **Article prev/next** (`scripts/prev_next.js`) is scoped to the article's category
|
- **Article prev/next** (`scripts/prev_next.js`) is scoped to the article's category
|
||||||
(`blog_data.articles[].category`); falls back to the global list when uncategorized.
|
(`blog_data.articles[].category`); falls back to the global list when uncategorized.
|
||||||
|
- **Menu sorting** (`scripts/menu_date_sort.js`, `shareHtmlLocation=body:end`): reads
|
||||||
|
`blog_data.articles[].date` (generator exposes the `date` label, fallback `dateCreated`,
|
||||||
|
`YYYY-MM-DD`), re-sorts each category's menu entries by date descending and prefixes the
|
||||||
|
label with `YYYY-MM-DD <shortened title>` (icons preserved). Non-article entries are left
|
||||||
|
in place.
|
||||||
- **Thumbnails** (`thumbSrc()`): prefer a child note of the article titled `*_thumb.*`
|
- **Thumbnails** (`thumbSrc()`): prefer a child note of the article titled `*_thumb.*`
|
||||||
(e.g. `ngc281_thumb.jpg`) → `api/notes/<id>/download`; otherwise use the first `<img>`
|
(e.g. `ngc281_thumb.jpg`) → `api/notes/<id>/download`; otherwise use the first `<img>`
|
||||||
from the note content. Layout: image left, summary right (`.blog-post-inner`),
|
from the note content. Layout: image left, summary right (`.blog-post-inner`),
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ no external dependencies (except `highlight.js`, vendored in `lib/`).
|
|||||||
|
|
||||||
- Gruvbox light/dark theme for the share, with a theme toggle in the header.
|
- Gruvbox light/dark theme for the share, with a theme toggle in the header.
|
||||||
- Blog index, category pages, sub-categories, tags and tag overview.
|
- Blog index, category pages, sub-categories, tags and tag overview.
|
||||||
|
- **Menu sorting**: articles in the left menu are sorted by publication date (newest first)
|
||||||
|
and labelled `YYYY-MM-DD <shortened title>` automatically.
|
||||||
- **Article thumbnails**: each post card shows the first image of the article on the left
|
- **Article thumbnails**: each post card shows the first image of the article on the left
|
||||||
(bounded by the teaser height), summary on the right, lazy-loaded. If an article has a child
|
(bounded by the teaser height), summary on the right, lazy-loaded. If an article has a child
|
||||||
note named `*_thumb.*` (e.g. `ngc281_thumb.jpg`), that image is used instead – ideal for
|
note named `*_thumb.*` (e.g. `ngc281_thumb.jpg`), that image is used instead – ideal for
|
||||||
|
|||||||
+2
-1
@@ -387,7 +387,8 @@ function run() {
|
|||||||
url: SHARE_BASE + "/" + encodeURIComponent(a.getLabelValue("shareAlias") || a.noteId),
|
url: SHARE_BASE + "/" + encodeURIComponent(a.getLabelValue("shareAlias") || a.noteId),
|
||||||
summary: a.getLabelValue("summary") || "",
|
summary: a.getLabelValue("summary") || "",
|
||||||
tags: tagList(a),
|
tags: tagList(a),
|
||||||
category: a.getLabelValue("category") || ""
|
category: a.getLabelValue("category") || "",
|
||||||
|
date: (a.getLabelValue("date") || a.dateCreated).slice(0, 10)
|
||||||
}));
|
}));
|
||||||
const html = `<script>window.blogData = ${JSON.stringify({ articles: list })};</script>`;
|
const html = `<script>window.blogData = ${JSON.stringify({ articles: list })};</script>`;
|
||||||
if (dataNote.getContent() !== html) {
|
if (dataNote.getContent() !== html) {
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
<script>
|
||||||
|
(function () {
|
||||||
|
var data = window.blogData;
|
||||||
|
if (!data || !data.articles || !data.articles.length) return;
|
||||||
|
var menu = document.getElementById("menu");
|
||||||
|
if (!menu) return;
|
||||||
|
|
||||||
|
var byAlias = {};
|
||||||
|
data.articles.forEach(function (a) {
|
||||||
|
var alias = String(a.url || "").split("/").pop();
|
||||||
|
if (alias) byAlias[alias] = a;
|
||||||
|
});
|
||||||
|
|
||||||
|
function shorten(t) {
|
||||||
|
t = String(t || "").replace(/\s+/g, " ").trim();
|
||||||
|
if (t.length <= 26) return t;
|
||||||
|
var cut = t.slice(0, 26).replace(/\s+\S*$/, "");
|
||||||
|
return (cut.length ? cut : t.slice(0, 26)) + "…";
|
||||||
|
}
|
||||||
|
|
||||||
|
menu.querySelectorAll("li").forEach(function (li) {
|
||||||
|
var a = li.querySelector(":scope > a");
|
||||||
|
if (!a) return;
|
||||||
|
var m = String(a.getAttribute("href") || "").match(/\.\/([^/?#]+)$/);
|
||||||
|
if (!m) return;
|
||||||
|
var art = byAlias[m[1]];
|
||||||
|
if (!art) return;
|
||||||
|
var date = String(art.date || "").slice(0, 10);
|
||||||
|
li.setAttribute("data-pubdate", date);
|
||||||
|
var span = a.querySelector("span");
|
||||||
|
if (span) {
|
||||||
|
var label = (date ? date + " " : "") + shorten(a.textContent.replace(/\s+/g, " ").trim());
|
||||||
|
var icon = span.querySelector("i");
|
||||||
|
span.textContent = "";
|
||||||
|
if (icon) span.appendChild(icon);
|
||||||
|
span.appendChild(document.createTextNode(" " + label));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
menu.querySelectorAll("ul").forEach(function (ul) {
|
||||||
|
var items = Array.from(ul.children);
|
||||||
|
var dated = items.filter(function (li) { return li.hasAttribute("data-pubdate"); });
|
||||||
|
if (dated.length < 2) return;
|
||||||
|
dated.sort(function (x, y) {
|
||||||
|
var dx = x.getAttribute("data-pubdate");
|
||||||
|
var dy = y.getAttribute("data-pubdate");
|
||||||
|
if (dx === dy) return 0;
|
||||||
|
return dx > dy ? -1 : 1;
|
||||||
|
});
|
||||||
|
items.forEach(function (li) { if (!li.hasAttribute("data-pubdate")) ul.appendChild(li); });
|
||||||
|
dated.forEach(function (li) { ul.appendChild(li); });
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user