From 30be0c87a80b190410f8cea0c36f02e93bd16633 Mon Sep 17 00:00:00 2001 From: organic-CPU Date: Sat, 11 Jul 2026 23:43:04 +0200 Subject: [PATCH] test --- js/blog.js | 66 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 24 deletions(-) diff --git a/js/blog.js b/js/blog.js index 1f8a4be..4a7c31b 100644 --- a/js/blog.js +++ b/js/blog.js @@ -49,7 +49,7 @@ async function fetchPost(filename) { // generate preview: up to 3 sentences, but not exceeding ~300 chars function getPreview(text, maxLen = 300) { - if (text.length <= maxLen) return text; // not needed, but safe + if (text.length <= maxLen) return text; // try to split on sentence boundaries (. ! ?) followed by space or newline const sentences = text.match(/[^.!?]+[.!?]+/g) || []; @@ -116,40 +116,58 @@ function renderPost(filename, content) { bodyDiv.textContent = body; postDiv.appendChild(bodyDiv); } else { - // long post – use
with preview - const details = document.createElement('details'); - details.className = 'blog-collapse'; + // long post – show preview with toggle + const container = document.createElement('div'); + container.className = 'blog-collapsible'; - const summary = document.createElement('summary'); - // preview container + // preview const previewDiv = document.createElement('div'); previewDiv.className = 'blog-preview'; previewDiv.style.whiteSpace = 'pre-line'; - const previewText = getPreview(body); - previewDiv.textContent = previewText + (previewText.endsWith('…') ? '' : '…'); // add ellipsis if not already + let previewText = getPreview(body); + // ensure ellipsis if preview is truncated + if (previewText.length < body.length && !previewText.endsWith('…')) { + previewText += '…'; + } + previewDiv.textContent = previewText; + container.appendChild(previewDiv); - const readMoreSpan = document.createElement('span'); - readMoreSpan.className = 'read-more-text'; - readMoreSpan.textContent = 'Read more'; + // Read more button + const readMoreBtn = document.createElement('button'); + readMoreBtn.className = 'blog-toggle read-more'; + readMoreBtn.textContent = 'Read more'; + container.appendChild(readMoreBtn); - summary.appendChild(previewDiv); - summary.appendChild(readMoreSpan); - details.appendChild(summary); - - // full body (hidden until opened) + // Full content (hidden initially) const fullDiv = document.createElement('div'); - fullDiv.className = 'blog-body'; + fullDiv.className = 'blog-full'; fullDiv.style.whiteSpace = 'pre-line'; fullDiv.textContent = body; - details.appendChild(fullDiv); + fullDiv.style.display = 'none'; + container.appendChild(fullDiv); - // toggle text when details opens/closes - details.addEventListener('toggle', function() { - const span = this.querySelector('.read-more-text'); - span.textContent = this.open ? 'Show less' : 'Read more'; - }); + // Show less button (hidden initially) – appears at the bottom + const showLessBtn = document.createElement('button'); + showLessBtn.className = 'blog-toggle show-less'; + showLessBtn.textContent = '✕ Show less'; + showLessBtn.style.display = 'none'; + container.appendChild(showLessBtn); - postDiv.appendChild(details); + // Toggle logic + function expand() { + fullDiv.style.display = 'block'; + readMoreBtn.style.display = 'none'; + showLessBtn.style.display = 'inline-block'; + } + function collapse() { + fullDiv.style.display = 'none'; + readMoreBtn.style.display = 'inline-block'; + showLessBtn.style.display = 'none'; + } + readMoreBtn.addEventListener('click', expand); + showLessBtn.addEventListener('click', collapse); + + postDiv.appendChild(container); } return postDiv;