bloggg
This commit is contained in:
+26
-23
@@ -1,18 +1,16 @@
|
||||
// blog.js – Loads and renders blog posts with simple "Read more" toggle for long entries
|
||||
// blog.js – Loads blog posts and uses a gradient fade for long entries
|
||||
|
||||
const BLOG_DIR = 'blog/';
|
||||
const MANIFEST = BLOG_DIR + 'manifest.json';
|
||||
|
||||
// ---------- helpers ----------
|
||||
|
||||
// crude HTML parser for directory listings (when manifest is missing)
|
||||
function parseIndexHtmlList(html) {
|
||||
const hrefs = [];
|
||||
const re = /href="([^"]+)"/g;
|
||||
let m;
|
||||
while ((m = re.exec(html)) !== null) {
|
||||
const name = m[1];
|
||||
// accept typical text file extensions (and no extension)
|
||||
if (name.match(/\.(txt|md|text)$/i) || !name.includes('.')) {
|
||||
if (!name.endsWith('/')) hrefs.push(name);
|
||||
}
|
||||
@@ -20,7 +18,6 @@ function parseIndexHtmlList(html) {
|
||||
return hrefs;
|
||||
}
|
||||
|
||||
// fetch list of blog post filenames (manifest first, fallback to directory listing)
|
||||
async function loadPostList() {
|
||||
try {
|
||||
const r = await fetch(MANIFEST, { cache: 'no-cache' });
|
||||
@@ -39,7 +36,6 @@ async function loadPostList() {
|
||||
return [];
|
||||
}
|
||||
|
||||
// fetch a single post file
|
||||
async function fetchPost(filename) {
|
||||
const res = await fetch(BLOG_DIR + filename, { cache: 'no-cache' });
|
||||
if (!res.ok) throw new Error(`Failed to fetch ${filename}`);
|
||||
@@ -50,9 +46,7 @@ async function fetchPost(filename) {
|
||||
|
||||
function renderPost(filename, content) {
|
||||
const lines = content.split('\n');
|
||||
if (lines.length < 3) {
|
||||
return null; // malformed
|
||||
}
|
||||
if (lines.length < 3) return null;
|
||||
const dateTime = lines[0].trim();
|
||||
const title = lines[1].trim();
|
||||
const bodyLines = lines.slice(2);
|
||||
@@ -75,31 +69,41 @@ function renderPost(filename, content) {
|
||||
|
||||
const isLong = body.length > 300;
|
||||
|
||||
// Body container (always created, but hidden for long posts)
|
||||
// Container for the body (with optional fade)
|
||||
const wrapper = document.createElement('div');
|
||||
wrapper.className = 'blog-body-wrapper';
|
||||
|
||||
// The actual text
|
||||
const bodyDiv = document.createElement('div');
|
||||
bodyDiv.className = 'blog-body';
|
||||
bodyDiv.style.whiteSpace = 'pre-line';
|
||||
bodyDiv.textContent = body;
|
||||
wrapper.appendChild(bodyDiv);
|
||||
|
||||
if (!isLong) {
|
||||
// Short post – show body directly
|
||||
postDiv.appendChild(bodyDiv);
|
||||
} else {
|
||||
// Long post – hide body initially, add toggle button
|
||||
bodyDiv.style.display = 'none';
|
||||
postDiv.appendChild(bodyDiv);
|
||||
// If long, add collapsed class and a toggle button
|
||||
if (isLong) {
|
||||
wrapper.classList.add('collapsed');
|
||||
|
||||
// Toggle button
|
||||
const toggleBtn = document.createElement('button');
|
||||
toggleBtn.className = 'blog-toggle';
|
||||
toggleBtn.textContent = 'Read more';
|
||||
postDiv.appendChild(toggleBtn);
|
||||
|
||||
toggleBtn.addEventListener('click', function() {
|
||||
const isHidden = bodyDiv.style.display === 'none';
|
||||
bodyDiv.style.display = isHidden ? 'block' : 'none';
|
||||
this.textContent = isHidden ? 'Show less' : 'Read more';
|
||||
const isCollapsed = wrapper.classList.contains('collapsed');
|
||||
if (isCollapsed) {
|
||||
wrapper.classList.remove('collapsed');
|
||||
this.textContent = 'Show less';
|
||||
} else {
|
||||
wrapper.classList.add('collapsed');
|
||||
this.textContent = 'Read more';
|
||||
}
|
||||
});
|
||||
|
||||
postDiv.appendChild(wrapper);
|
||||
postDiv.appendChild(toggleBtn);
|
||||
} else {
|
||||
// Short post – no collapse, no button
|
||||
postDiv.appendChild(wrapper);
|
||||
}
|
||||
|
||||
return postDiv;
|
||||
@@ -120,8 +124,7 @@ async function initBlog() {
|
||||
return;
|
||||
}
|
||||
|
||||
files.sort(); // alphabetical -> chronological
|
||||
|
||||
files.sort();
|
||||
feed.innerHTML = '';
|
||||
|
||||
for (const file of files) {
|
||||
|
||||
Reference in New Issue
Block a user