From 140552a35f86097c2de399f9b769b5806f947089 Mon Sep 17 00:00:00 2001 From: kbe Date: Tue, 19 Aug 2025 11:34:40 +0200 Subject: [PATCH] wip page links and display --- layouts/_default/baseof.html | 2 +- layouts/partials/footer.html | 37 ++++++++++------ scripts/fetch-wordpress.js | 84 +++++++++++++++++++++++------------- scripts/generate-content.js | 65 ++++++++++++++++++++++++++-- 4 files changed, 142 insertions(+), 46 deletions(-) diff --git a/layouts/_default/baseof.html b/layouts/_default/baseof.html index c4e00be..62edca7 100644 --- a/layouts/_default/baseof.html +++ b/layouts/_default/baseof.html @@ -34,7 +34,7 @@ - {{ partial "footer.html" }} + {{ partial "footer.html" . }}
diff --git a/layouts/partials/footer.html b/layouts/partials/footer.html index f313f75..f62dcc0 100644 --- a/layouts/partials/footer.html +++ b/layouts/partials/footer.html @@ -5,24 +5,37 @@

{{ .Site.Title }}

+
-
Useful Links
-
+ +
-
Additional Links
-
+
Contact Info
    diff --git a/scripts/fetch-wordpress.js b/scripts/fetch-wordpress.js index 290e176..13dfd93 100644 --- a/scripts/fetch-wordpress.js +++ b/scripts/fetch-wordpress.js @@ -4,32 +4,32 @@ const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch const WORDPRESS_API = 'https://www.mistergeek.net/wp-json/wp/v2'; const OUTPUT_DIR = path.join(__dirname, '..', 'data', 'wordpress'); +const HUGO_DATA_DIR = path.join(__dirname, '..', 'data'); -async function fetchPosts(page = 1, perPage = 100) { - const response = await fetch(`${WORDPRESS_API}/posts?page=${page}&per_page=${perPage}&_embed`); - const posts = await response.json(); - - if (response.headers.get('x-wp-totalpages') > page) { - const nextPosts = await fetchPosts(page + 1, perPage); - return [...posts, ...nextPosts]; +async function fetchAll(endpoint, perPage = 100) { + let page = 1; + let items = []; + + while (true) { + const url = `${WORDPRESS_API}/${endpoint}?page=${page}&per_page=${perPage}&_embed`; + const response = await fetch(url); + + // If endpoint does not support paging or returns empty, break + if (!response.ok) { + // 400 often means "page out of range" for WP; stop paging + if (response.status === 400) break; + throw new Error(`Failed to fetch ${endpoint} (page ${page}): ${response.status} ${response.statusText}`); + } + + const batch = await response.json(); + items = items.concat(batch); + + const totalPages = parseInt(response.headers.get('x-wp-totalpages') || '1', 10); + if (page >= totalPages) break; + page++; } - - return posts; -} -async function fetchCategories() { - const response = await fetch(`${WORDPRESS_API}/categories?per_page=100`); - return response.json(); -} - -async function fetchTags() { - const response = await fetch(`${WORDPRESS_API}/tags?per_page=100`); - return response.json(); -} - -async function fetchAuthors() { - const response = await fetch(`${WORDPRESS_API}/users?per_page=100`); - return response.json(); + return items; } async function generateData() { @@ -39,21 +39,45 @@ async function generateData() { } console.log('Fetching WordPress data...'); - - const [posts, categories, tags, authors] = await Promise.all([ - fetchPosts(), - fetchCategories(), - fetchTags(), - fetchAuthors() + + // Fetch all relevant endpoints concurrently (pages + posts + taxonomies + users) + const [ + posts, + pages, + categories, + tags, + authors + ] = await Promise.all([ + fetchAll('posts'), + fetchAll('pages'), + fetchAll('categories'), + fetchAll('tags'), + fetchAll('users') ]); + // Filter pages to only include published pages + const publishedPages = pages.filter(page => page.status === 'publish'); + + // Create navigation data from published pages + const navigationData = publishedPages.map(page => ({ + id: page.id, + title: page.title?.rendered || page.slug, + slug: page.slug, + link: page.link, + date: page.date, + modified: page.modified + })); + // Save data as JSON files fs.writeFileSync(path.join(OUTPUT_DIR, 'posts.json'), JSON.stringify(posts, null, 2)); + fs.writeFileSync(path.join(OUTPUT_DIR, 'pages.json'), JSON.stringify(publishedPages, null, 2)); fs.writeFileSync(path.join(OUTPUT_DIR, 'categories.json'), JSON.stringify(categories, null, 2)); fs.writeFileSync(path.join(OUTPUT_DIR, 'tags.json'), JSON.stringify(tags, null, 2)); fs.writeFileSync(path.join(OUTPUT_DIR, 'authors.json'), JSON.stringify(authors, null, 2)); + fs.writeFileSync(path.join(OUTPUT_DIR, 'navigation.json'), JSON.stringify(navigationData, null, 2)); - console.log(`✅ Fetched ${posts.length} posts, ${categories.length} categories, ${tags.length} tags, ${authors.length} authors`); + console.log(`✅ Fetched ${posts.length} posts, ${publishedPages.length} pages, ${categories.length} categories, ${tags.length} tags, ${authors.length} authors`); + console.log(`✅ Generated navigation data with ${navigationData.length} items`); } generateData().catch(console.error); \ No newline at end of file diff --git a/scripts/generate-content.js b/scripts/generate-content.js index f07af8c..aa48178 100644 --- a/scripts/generate-content.js +++ b/scripts/generate-content.js @@ -4,15 +4,22 @@ const he = require('he'); const DATA_DIR = path.join(__dirname, '..', 'data', 'wordpress'); const CONTENT_DIR = path.join(__dirname, '..', 'content'); +const PAGES_DIR = path.join(CONTENT_DIR, 'pages'); function generateContent() { const posts = JSON.parse(fs.readFileSync(path.join(DATA_DIR, 'posts.json'), 'utf8')); - - // Ensure content directory exists + const pages = JSON.parse(fs.readFileSync(path.join(DATA_DIR, 'pages.json'), 'utf8')); + + // Ensure content directories exist if (!fs.existsSync(CONTENT_DIR)) { fs.mkdirSync(CONTENT_DIR, { recursive: true }); } + + if (!fs.existsSync(PAGES_DIR)) { + fs.mkdirSync(PAGES_DIR, { recursive: true }); + } + // Process posts posts.forEach(post => { const slug = post.slug; const date = new Date(post.date); @@ -61,7 +68,58 @@ function generateContent() { contentHtml = contentHtml .replace(/

    \s*<\/p>/g, '') // Remove empty paragraphs - .replace(/<\/p>\s*

    /g, '\n\n') // Replace paragraph breaks with newlines + .replace(/<\/p>\s*

    /g, '\n\n'); // Replace paragraph breaks with newlines + + const content = `--- +${Object.entries(frontmatter) + .map(([key, value]) => `${key}: ${JSON.stringify(value)}`) + .join('\n')} +--- +${contentHtml.trim()}`; + + fs.writeFileSync(path.join(contentDir, 'index.md'), content); + }); + + // Process pages + pages.forEach(page => { + const slug = page.slug; + + const contentDir = path.join(PAGES_DIR, slug); + + if (!fs.existsSync(contentDir)) { + fs.mkdirSync(contentDir, { recursive: true }); + } + + const frontmatter = { + title: he.decode(page.title.rendered), + slug: slug, + type: "pages", + layout: "single", + wordpress_id: page.id, + date: page.date, + modified: page.modified, + draft: page.status !== 'publish', + aliases: [`/${slug}/`] + }; + + // Decode HTML entities in the content and clean up HTML tags + let contentHtml = he.decode(page.content.rendered); + + // Convert absolute URLs in a href to relative URLs + contentHtml = contentHtml.replace(/]*href="([^"]+)"[^>]*>/g, (match, href) => { + // Check if the href is an absolute URL (starts with http:// or https://) + if (href.startsWith('http://') || href.startsWith('https://')) { + // Extract the path part of the URL + const url = new URL(href); + // Return the modified a tag with relative URL + return match.replace(href, url.pathname); + } + return match; + }); + + contentHtml = contentHtml + .replace(/

    \s*<\/p>/g, '') // Remove empty paragraphs + .replace(/<\/p>\s*

    /g, '\n\n'); // Replace paragraph breaks with newlines const content = `--- ${Object.entries(frontmatter) @@ -74,6 +132,7 @@ ${contentHtml.trim()}`; }); console.log(`✅ Generated ${posts.length} content files`); + console.log(`✅ Generated ${pages.length} page files`); } generateContent(); \ No newline at end of file