forked from snxraven/ravenscott-blog
Adding list and pagination]
This commit is contained in:
parent
249b793540
commit
eaa8eccb79
47
app.js
47
app.js
@ -62,23 +62,56 @@ function slugToTitle(slug) {
|
|||||||
return slug.replace(/-/g, ' ');
|
return slug.replace(/-/g, ' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to load all blog posts
|
// Function to load all blog posts with pagination support
|
||||||
function getAllBlogPosts() {
|
function getAllBlogPosts(page = 1, postsPerPage = 5) {
|
||||||
const blogFiles = fs.readdirSync(path.join(__dirname, 'markdown')).filter(file => file.endsWith('.md'));
|
const blogFiles = fs.readdirSync(path.join(__dirname, 'markdown')).filter(file => file.endsWith('.md'));
|
||||||
return blogFiles.map(file => {
|
|
||||||
|
// Paginate the results
|
||||||
|
const totalPosts = blogFiles.length;
|
||||||
|
const totalPages = Math.ceil(totalPosts / postsPerPage);
|
||||||
|
const start = (page - 1) * postsPerPage;
|
||||||
|
const end = start + postsPerPage;
|
||||||
|
|
||||||
|
const paginatedFiles = blogFiles.slice(start, end);
|
||||||
|
|
||||||
|
const blogPosts = paginatedFiles.map(file => {
|
||||||
const title = file.replace('.md', '').replace(/-/g, ' '); // Keep original casing for title
|
const title = file.replace('.md', '').replace(/-/g, ' '); // Keep original casing for title
|
||||||
const slug = titleToSlug(title); // Convert title to slug (lowercase)
|
const slug = titleToSlug(title); // Convert title to slug (lowercase)
|
||||||
|
|
||||||
|
// Get the last modified date of the markdown file
|
||||||
|
const stats = fs.statSync(path.join(__dirname, 'markdown', file));
|
||||||
|
const lastModifiedDate = new Date(stats.mtime); // Use mtime for last modification time
|
||||||
|
|
||||||
|
// Format the date
|
||||||
|
const formattedDate = lastModifiedDate.toLocaleDateString('en-US', {
|
||||||
|
year: 'numeric',
|
||||||
|
month: 'long',
|
||||||
|
day: 'numeric'
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title, // Original casing title
|
title, // Original casing title
|
||||||
slug
|
slug,
|
||||||
|
date: formattedDate // Include the formatted date
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return { blogPosts, totalPages };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Home Route (Blog Home)
|
// Home Route (Blog Home with Pagination)
|
||||||
app.get('/', (req, res) => {
|
app.get('/', (req, res) => {
|
||||||
const blogPosts = getAllBlogPosts();
|
const page = parseInt(req.query.page) || 1;
|
||||||
res.render('index', { title: 'Raven Scott Blog', blogPosts });
|
const postsPerPage = 5; // Set how many posts to display per page
|
||||||
|
|
||||||
|
const { blogPosts, totalPages } = getAllBlogPosts(page, postsPerPage);
|
||||||
|
|
||||||
|
res.render('index', {
|
||||||
|
title: 'Raven Scott Blog',
|
||||||
|
blogPosts,
|
||||||
|
currentPage: page,
|
||||||
|
totalPages
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// About Route
|
// About Route
|
||||||
|
@ -11,6 +11,11 @@ main {
|
|||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #000;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
.bg-primary {
|
.bg-primary {
|
||||||
--bs-bg-opacity: 1;
|
--bs-bg-opacity: 1;
|
||||||
background-color: rgb(0 0 0) !important;
|
background-color: rgb(0 0 0) !important;
|
||||||
@ -49,15 +54,45 @@ p.lead {
|
|||||||
font-size: 1.5rem;
|
font-size: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-primary {
|
/* Read Article Button Styling */
|
||||||
|
.btn-outline-primary {
|
||||||
font-size: 1.25rem;
|
font-size: 1.25rem;
|
||||||
padding: 10px 20px;
|
padding: 10px 20px;
|
||||||
|
color: #ffffff;
|
||||||
|
border: 2px solid #000000;
|
||||||
background-color: #000000;
|
background-color: #000000;
|
||||||
border: none;
|
transition: background-color 0.3s ease, color 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-primary:hover {
|
.btn-outline-primary:hover {
|
||||||
background-color: #000000;
|
background-color: #2c5364;
|
||||||
|
border-color: #2c5364;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pagination Styling */
|
||||||
|
.pagination {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination .page-item .page-link {
|
||||||
|
color: #ffffff;
|
||||||
|
background-color: #1e1e1e;
|
||||||
|
border: 1px solid #2c5364;
|
||||||
|
padding: 10px 15px;
|
||||||
|
transition: background-color 0.3s ease, color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination .page-item.active .page-link {
|
||||||
|
background-color: #2c5364;
|
||||||
|
border-color: #2c5364;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination .page-item .page-link:hover {
|
||||||
|
background-color: #2c5364;
|
||||||
|
border-color: #2c5364;
|
||||||
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
footer {
|
footer {
|
||||||
|
@ -31,7 +31,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
|
||||||
<header class="py-5">
|
<header class="py-5">
|
||||||
<div class="container text-center">
|
<div class="container text-center">
|
||||||
<h1>Welcome to my long form post blog</h1>
|
<h1>Welcome to my long form post blog</h1>
|
||||||
@ -42,18 +41,40 @@
|
|||||||
<section class="py-5">
|
<section class="py-5">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h2>Recent Posts</h2>
|
<h2>Recent Posts</h2>
|
||||||
<div class="row">
|
<ul class="list-group list-group-flush">
|
||||||
<% blogPosts.forEach(post => { %>
|
<% blogPosts.forEach(post => { %>
|
||||||
<div class="col-md-4">
|
<li class="list-group-item d-flex justify-content-between align-items-center py-4">
|
||||||
<div class="card mb-4">
|
<div>
|
||||||
<div class="card-body">
|
<h5 class="mb-1"><a href="/blog/<%= post.slug %>"> <%= post.title %> </a></h5>
|
||||||
<h5 class="card-title"><%= post.title %></h5>
|
<p class="mb-1 text-muted">Posted on <%= post.date %></p>
|
||||||
<a href="/blog/<%= post.slug %>" class="btn btn-primary">Read More</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<a href="/blog/<%= post.slug %>" class="btn btn-outline-primary">Read Article</a>
|
||||||
|
</li>
|
||||||
<% }) %>
|
<% }) %>
|
||||||
</div>
|
</ul>
|
||||||
|
|
||||||
|
<!-- Pagination controls -->
|
||||||
|
<nav aria-label="Page navigation">
|
||||||
|
<ul class="pagination justify-content-center mt-4">
|
||||||
|
<% if (currentPage > 1) { %>
|
||||||
|
<li class="page-item">
|
||||||
|
<a class="page-link" href="?page=<%= currentPage - 1 %>">Previous</a>
|
||||||
|
</li>
|
||||||
|
<% } %>
|
||||||
|
|
||||||
|
<% for (let i = 1; i <= totalPages; i++) { %>
|
||||||
|
<li class="page-item <%= currentPage === i ? 'active' : '' %>">
|
||||||
|
<a class="page-link" href="?page=<%= i %>"><%= i %></a>
|
||||||
|
</li>
|
||||||
|
<% } %>
|
||||||
|
|
||||||
|
<% if (currentPage < totalPages) { %>
|
||||||
|
<li class="page-item">
|
||||||
|
<a class="page-link" href="?page=<%= currentPage + 1 %>">Next</a>
|
||||||
|
</li>
|
||||||
|
<% } %>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user