wip page links and display

This commit is contained in:
kbe
2025-08-19 11:34:40 +02:00
parent dd3a0240f9
commit 140552a35f
4 changed files with 142 additions and 46 deletions

View File

@@ -34,7 +34,7 @@
</main> </main>
<!-- Footer --> <!-- Footer -->
{{ partial "footer.html" }} {{ partial "footer.html" . }}
<!-- Scroll to top button --> <!-- Scroll to top button -->
<div class="scrolltotop icon-lg"> <div class="scrolltotop icon-lg">

View File

@@ -5,24 +5,37 @@
<div class="col-6 col-sm-6 col-lg-3"> <div class="col-6 col-sm-6 col-lg-3">
<h3 class="uppercase letter-spacing-1">{{ .Site.Title }}</h3> <h3 class="uppercase letter-spacing-1">{{ .Site.Title }}</h3>
</div> </div>
<div class="col-6 col-sm-6 col-lg-3"> <div class="col-6 col-sm-6 col-lg-3">
<h6 class="font-small fw-medium uppercase">Useful Links</h6> <h6 class="font-small fw-medium uppercase">Catégories</h6>
<ul class="list-dash animate-links"> <ul class="list-unstyled">
<li><a href="/about/">About us</a></li> <li><a href="/">Accueil</a></li>
<li><a href="/team/">Team</a></li> {{ if .Site.Data.wordpress }}
<li><a href="/pricing/">Prices</a></li> {{ $count := 0 }}
<li><a href="/contact/">Contact</a></li> {{ range $index, $element := .Site.Data.wordpress.navigation }}
<li class="nav-item">
<a class="nav-link" href="/{{ $element.slug }}">{{ $element.title }}</a>
</li>
{{ end }}
{{ end }}
</ul> </ul>
</div> </div>
<div class="col-6 col-sm-6 col-lg-3"> <div class="col-6 col-sm-6 col-lg-3">
<h6 class="font-small fw-medium uppercase">Additional Links</h6> <h6 class="font-small fw-medium uppercase">Toutes les catégories</h6>
<ul class="list-dash animate-links"> <ul class="list-unstyled">
<li><a href="/services/">Services</a></li> {{ if .Site.Data.wordpress }}
<li><a href="/process/">Process</a></li> {{ $count := 0 }}
<li><a href="/faq/">FAQ</a></li> {{ range $index, $element := .Site.Data.wordpress.categories }}
<li><a href="/careers/">Careers</a></li> <li class="nav-item">
<a class="nav-link" href="/categories/{{ $element.slug }}">{{ $element.name }}</a>
</li>
{{ end }}
{{ end }}
</ul> </ul>
</div> </div>
<div class="col-6 col-sm-6 col-lg-3"> <div class="col-6 col-sm-6 col-lg-3">
<h6 class="font-small fw-medium uppercase">Contact Info</h6> <h6 class="font-small fw-medium uppercase">Contact Info</h6>
<ul class="list-unstyled"> <ul class="list-unstyled">

View File

@@ -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 WORDPRESS_API = 'https://www.mistergeek.net/wp-json/wp/v2';
const OUTPUT_DIR = path.join(__dirname, '..', 'data', 'wordpress'); const OUTPUT_DIR = path.join(__dirname, '..', 'data', 'wordpress');
const HUGO_DATA_DIR = path.join(__dirname, '..', 'data');
async function fetchPosts(page = 1, perPage = 100) { async function fetchAll(endpoint, perPage = 100) {
const response = await fetch(`${WORDPRESS_API}/posts?page=${page}&per_page=${perPage}&_embed`); let page = 1;
const posts = await response.json(); let items = [];
if (response.headers.get('x-wp-totalpages') > page) { while (true) {
const nextPosts = await fetchPosts(page + 1, perPage); const url = `${WORDPRESS_API}/${endpoint}?page=${page}&per_page=${perPage}&_embed`;
return [...posts, ...nextPosts]; 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() { return items;
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();
} }
async function generateData() { async function generateData() {
@@ -39,21 +39,45 @@ async function generateData() {
} }
console.log('Fetching WordPress data...'); console.log('Fetching WordPress data...');
const [posts, categories, tags, authors] = await Promise.all([ // Fetch all relevant endpoints concurrently (pages + posts + taxonomies + users)
fetchPosts(), const [
fetchCategories(), posts,
fetchTags(), pages,
fetchAuthors() 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 // Save data as JSON files
fs.writeFileSync(path.join(OUTPUT_DIR, 'posts.json'), JSON.stringify(posts, null, 2)); 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, '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, '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, '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); generateData().catch(console.error);

View File

@@ -4,15 +4,22 @@ const he = require('he');
const DATA_DIR = path.join(__dirname, '..', 'data', 'wordpress'); const DATA_DIR = path.join(__dirname, '..', 'data', 'wordpress');
const CONTENT_DIR = path.join(__dirname, '..', 'content'); const CONTENT_DIR = path.join(__dirname, '..', 'content');
const PAGES_DIR = path.join(CONTENT_DIR, 'pages');
function generateContent() { function generateContent() {
const posts = JSON.parse(fs.readFileSync(path.join(DATA_DIR, 'posts.json'), 'utf8')); const posts = JSON.parse(fs.readFileSync(path.join(DATA_DIR, 'posts.json'), 'utf8'));
const pages = JSON.parse(fs.readFileSync(path.join(DATA_DIR, 'pages.json'), 'utf8'));
// Ensure content directory exists
// Ensure content directories exist
if (!fs.existsSync(CONTENT_DIR)) { if (!fs.existsSync(CONTENT_DIR)) {
fs.mkdirSync(CONTENT_DIR, { recursive: true }); fs.mkdirSync(CONTENT_DIR, { recursive: true });
} }
if (!fs.existsSync(PAGES_DIR)) {
fs.mkdirSync(PAGES_DIR, { recursive: true });
}
// Process posts
posts.forEach(post => { posts.forEach(post => {
const slug = post.slug; const slug = post.slug;
const date = new Date(post.date); const date = new Date(post.date);
@@ -61,7 +68,58 @@ function generateContent() {
contentHtml = contentHtml contentHtml = contentHtml
.replace(/<p>\s*<\/p>/g, '') // Remove empty paragraphs .replace(/<p>\s*<\/p>/g, '') // Remove empty paragraphs
.replace(/<\/p>\s*<p>/g, '\n\n') // Replace paragraph breaks with newlines .replace(/<\/p>\s*<p>/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(/<a\s+[^>]*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(/<p>\s*<\/p>/g, '') // Remove empty paragraphs
.replace(/<\/p>\s*<p>/g, '\n\n'); // Replace paragraph breaks with newlines
const content = `--- const content = `---
${Object.entries(frontmatter) ${Object.entries(frontmatter)
@@ -74,6 +132,7 @@ ${contentHtml.trim()}`;
}); });
console.log(`✅ Generated ${posts.length} content files`); console.log(`✅ Generated ${posts.length} content files`);
console.log(`✅ Generated ${pages.length} page files`);
} }
generateContent(); generateContent();