Skip to content

Instantly share code, notes, and snippets.

@verfasor
Last active February 2, 2026 06:00
Show Gist options
  • Select an option

  • Save verfasor/cf7b4455eb158fd65386149fd7b07d6f to your computer and use it in GitHub Desktop.

Select an option

Save verfasor/cf7b4455eb158fd65386149fd7b07d6f to your computer and use it in GitHub Desktop.
script to sort posts by month on bear blog
/**
* 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();
}
})();
@verfasor
Copy link
Author

verfasor commented Feb 2, 2026

minified version -- sort posts by month without year

updated script with just the month name (no year):

<script>
(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;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;if(!lastUpdatedDate||date>lastUpdatedDate){lastUpdatedDate=date;lastUpdatedDateString=dateString}
const monthYear=date.toLocaleDateString('en-US',{month:'long',year:'numeric'});if(!groupedPosts[monthYear]){groupedPosts[monthYear]=[]}
groupedPosts[monthYear].push(li)});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});if(lastUpdatedDate&&lastUpdatedDateString){let header=postsList.parentNode.querySelector('h2.archive');if(!header){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('.'))}
postsList.innerHTML='';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()}}
if(document.readyState==='loading'){document.addEventListener('DOMContentLoaded',groupPostsByMonth)}else{groupPostsByMonth()}})()
</script>

the key change is on this line where i removed year:'numeric':

const monthYear=date.toLocaleDateString('en-US',{month:'long'});

Now the month headers will show just "January", "February", etc. instead of "January 2026", "February 2026".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment