This commit is contained in:
2026-07-11 23:06:59 +02:00
parent 82903a3dd2
commit cd382e2ff2
+39 -59
View File
@@ -3,8 +3,6 @@ const ATTACHMENT_DIR = BLOG_DIR + 'files/';
const MANIFEST = BLOG_DIR + 'manifest.json'; const MANIFEST = BLOG_DIR + 'manifest.json';
const TXT_EXT = /\.(txt|text)$/i; const TXT_EXT = /\.(txt|text)$/i;
const ATTACHMENT_RE = /\[\[(?:file|attachment):\s*([^\]]+)\]\]/gi; const ATTACHMENT_RE = /\[\[(?:file|attachment):\s*([^\]]+)\]\]/gi;
const BLOG_COLLAPSE_THRESHOLD = 300; // characters before collapsing
const BLOG_PREVIEW_LINES = 3; // number of lines shown in preview
function escapeHtml(value) { function escapeHtml(value) {
return value return value
@@ -143,16 +141,11 @@ function renderBlogEntries(entries) {
const meta = document.createElement('div'); const meta = document.createElement('div');
meta.className = 'blog-meta'; meta.className = 'blog-meta';
meta.textContent = entry.date meta.textContent = entry.date ? formatDate(entry.date) : entry.dateLabel || 'Date not provided';
? formatDate(entry.date)
: entry.dateLabel || 'Date not provided';
const body = document.createElement('div'); const body = document.createElement('div');
body.className = 'blog-body'; body.className = 'blog-body';
const paragraphs = createParagraphs(entry.body); const paragraphs = createParagraphs(entry.body);
if (!paragraphs.length) { if (!paragraphs.length) {
const empty = document.createElement('p'); const empty = document.createElement('p');
empty.textContent = 'No content yet.'; empty.textContent = 'No content yet.';
@@ -161,78 +154,65 @@ function renderBlogEntries(entries) {
paragraphs.forEach((p) => body.appendChild(p)); paragraphs.forEach((p) => body.appendChild(p));
} }
let content = body;
// Collapse long posts
if (entry.body.length > BLOG_COLLAPSE_THRESHOLD) {
const wrapper = document.createElement('div');
wrapper.className = 'blog-collapse';
const preview = document.createElement('p');
preview.className = 'blog-preview';
preview.textContent = entry.body
.split('\n')
.filter(line => line.trim())
.slice(0, BLOG_PREVIEW_LINES)
.join('\n');
const button = document.createElement('button');
button.className = 'blog-expand-button';
button.textContent = 'Read more';
body.style.display = 'none';
button.addEventListener('click', () => {
const expanded = body.style.display !== 'none';
body.style.display = expanded ? 'none' : 'block';
preview.style.display = expanded ? 'block' : 'none';
button.textContent = expanded ? 'Read more' : 'Show less';
});
wrapper.appendChild(preview);
wrapper.appendChild(button);
wrapper.appendChild(body);
content = wrapper;
}
if (entry.attachments && entry.attachments.length) { if (entry.attachments && entry.attachments.length) {
const attachTitle = document.createElement('div'); const attachTitle = document.createElement('div');
attachTitle.className = 'blog-meta'; attachTitle.className = 'blog-meta';
attachTitle.textContent = 'Attachments:'; attachTitle.textContent = 'Attachments:';
const list = document.createElement('ul'); const list = document.createElement('ul');
list.className = 'blog-attachment-list'; list.className = 'blog-attachment-list';
entry.attachments.forEach((attachment) => { entry.attachments.forEach((attachment) => {
const item = document.createElement('li'); const item = document.createElement('li');
const link = document.createElement('a'); const link = document.createElement('a');
link.href = ATTACHMENT_DIR + encodeURI(attachment); link.href = ATTACHMENT_DIR + encodeURI(attachment);
link.target = '_blank'; link.target = '_blank';
link.rel = 'noopener noreferrer'; link.rel = 'noopener noreferrer';
link.textContent = attachment; link.textContent = attachment;
item.appendChild(link); item.appendChild(link);
list.appendChild(item); list.appendChild(item);
}); });
article.appendChild(attachTitle); article.appendChild(attachTitle);
article.appendChild(list); article.appendChild(list);
} }
article.appendChild(title); article.appendChild(title);
article.appendChild(meta); article.appendChild(meta);
article.appendChild(content); article.appendChild(body);
container.appendChild(article); container.appendChild(article);
}); });
} }
function sortEntries(entries) {
return entries.slice().sort((a, b) => {
if (a.date && b.date) return b.date - a.date;
if (a.date) return -1;
if (b.date) return 1;
return a.filename.localeCompare(b.filename);
});
}
async function initBlog() {
const fileNames = await loadBlogFiles();
if (!fileNames.length) {
renderBlogEntries([]);
return;
}
const promises = fileNames
.filter((name) => TXT_EXT.test(name))
.map(async (name) => {
try {
const response = await fetch(BLOG_DIR + name, { cache: 'no-cache' });
if (!response.ok) throw new Error('Failed to load ' + name);
const text = await response.text();
return parseBlogText(text, name);
} catch (error) {
console.warn(error);
return null;
}
});
const entries = (await Promise.all(promises)).filter(Boolean);
renderBlogEntries(sortEntries(entries));
}
document.addEventListener('DOMContentLoaded', initBlog);