Last active
November 10, 2025 06:04
-
-
Save verfasor/cf7b4455eb158fd65386149fd7b07d6f to your computer and use it in GitHub Desktop.
script to sort posts by month on bear blog
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Sort Posts by Month | |
| * Groups blog posts by month/year and displays them with a header showing total count and last updated date. | |
| * Use with {{posts}} embed on a Bear Blog page. | |
| * Explainer: https://mighil.com/script-to-sort-posts-by-month-on-bear-blog | |
| * | |
| * Usage: | |
| * <h2 class="archive">Loading posts...</h2> | |
| * {{posts}} | |
| * <script src="https://your-domain.com/path/to/archive-sort.js"></script> | |
| * | |
| * Tip: Target ".archive" class for custom styling | |
| */ | |
| (function() { | |
| 'use strict'; | |
| function groupPostsByMonth() { | |
| const postsList = document.querySelector('ul.embedded.blog-posts'); | |
| if (!postsList) return; | |
| const listItems = Array.from(postsList.querySelectorAll('li')); | |
| if (listItems.length === 0) return; | |
| const totalPosts = listItems.length; | |
| let lastUpdatedDate = null; | |
| let lastUpdatedDateString = null; | |
| // Group posts by month/year and find the most recent date | |
| const groupedPosts = {}; | |
| listItems.forEach(li => { | |
| const timeElement = li.querySelector('time[datetime]'); | |
| if (!timeElement) return; | |
| const dateString = timeElement.getAttribute('datetime'); | |
| if (!dateString) return; | |
| const date = new Date(dateString); | |
| if (isNaN(date.getTime())) return; | |
| // Track the most recent date | |
| if (!lastUpdatedDate || date > lastUpdatedDate) { | |
| lastUpdatedDate = date; | |
| lastUpdatedDateString = dateString; | |
| } | |
| // Format as "Month, Year" (e.g., "November, 2025") | |
| const monthYear = date.toLocaleDateString('en-US', { | |
| month: 'long', | |
| year: 'numeric' | |
| }); | |
| if (!groupedPosts[monthYear]) { | |
| groupedPosts[monthYear] = []; | |
| } | |
| groupedPosts[monthYear].push(li); | |
| }); | |
| // Sort months in descending order (newest first) | |
| const monthDates = {}; | |
| Object.keys(groupedPosts).forEach(monthYear => { | |
| const firstPost = groupedPosts[monthYear][0]; | |
| const timeElement = firstPost.querySelector('time[datetime]'); | |
| if (timeElement) { | |
| const dateString = timeElement.getAttribute('datetime'); | |
| const date = new Date(dateString); | |
| monthDates[monthYear] = date; | |
| } | |
| }); | |
| const sortedMonths = Object.keys(groupedPosts).sort((a, b) => { | |
| const dateA = monthDates[a] || new Date(0); | |
| const dateB = monthDates[b] || new Date(0); | |
| return dateB - dateA; // Descending order (newest first) | |
| }); | |
| // Create or update the header with total count and last updated date | |
| if (lastUpdatedDate && lastUpdatedDateString) { | |
| // Check if placeholder header already exists | |
| let header = postsList.parentNode.querySelector('h2.archive'); | |
| if (!header) { | |
| // Create new header if placeholder doesn't exist | |
| header = document.createElement('h2'); | |
| header.className = 'archive'; | |
| postsList.parentNode.insertBefore(header, postsList); | |
| } | |
| const formattedDate = lastUpdatedDate.toLocaleDateString('en-US', { | |
| month: 'long', | |
| day: 'numeric', | |
| year: 'numeric' | |
| }); | |
| const span = document.createElement('span'); | |
| span.id = 'last-updated'; | |
| span.setAttribute('data-date', lastUpdatedDateString); | |
| span.textContent = formattedDate; | |
| header.textContent = `${totalPosts} entries. Last updated on `; | |
| header.appendChild(span); | |
| header.appendChild(document.createTextNode('.')); | |
| } | |
| // Clear the original list | |
| postsList.innerHTML = ''; | |
| // Create grouped structure | |
| sortedMonths.forEach(monthYear => { | |
| const monthHeader = document.createElement('h3'); | |
| monthHeader.className = 'archive-h3'; | |
| monthHeader.textContent = monthYear; | |
| postsList.parentNode.insertBefore(monthHeader, postsList); | |
| const monthList = document.createElement('ul'); | |
| monthList.className = 'blog-posts'; | |
| groupedPosts[monthYear].forEach(li => { | |
| monthList.appendChild(li); | |
| }); | |
| postsList.parentNode.insertBefore(monthList, postsList); | |
| }); | |
| if (postsList.parentNode && postsList.children.length === 0) { | |
| postsList.remove(); | |
| } | |
| } | |
| // Auto-run on DOMContentLoaded | |
| if (document.readyState === 'loading') { | |
| document.addEventListener('DOMContentLoaded', groupPostsByMonth); | |
| } else { | |
| groupPostsByMonth(); | |
| } | |
| })(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment