Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions astro/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions astro/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
},
"dependencies": {
"@astrojs/mdx": "^4.3.13",
"@astrojs/rss": "^4.0.17",
"@astrojs/sitemap": "^3.7.0",
"astro": "^5.18.0",
"astro-expressive-code": "^0.41.7",
Expand Down
2 changes: 1 addition & 1 deletion astro/src/content.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const blogCollection = defineCollection({
schema: z.object({
title: z.string(),
description: z.string().optional(),
tags: z.string().optional(),
tags: z.array(z.string()).optional(),
authors: z
.array(
z.object({
Expand Down
2 changes: 1 addition & 1 deletion astro/src/content/blog/en/2024-07-16-welcome-post.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Welcome to The Express Blog!
description: Introducing the new Express blog — a primary platform for announcements, updates, and communication from the Express technical committee.
tags: announcements
tags: ['announcements']
authors:
- name: Rand McKinney
github: crandmck
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: September 2024 Security Releases
description: Security releases for Express, body-parser, send, serve-static, and path-to-regexp have been published. We recommend that all users upgrade as soon as possible.
tags: security
tags: ['security']
authors:
- name: Ulises Gascón
github: UlisesGascon
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Express Never Ending Support Launched by HeroDevs and Express.js
description: The Express.js team is pleased to announce a partnership with HeroDevs to launch Express Never-Ending Support (NES), providing long-term support for applications built with legacy Express. This collaboration ensures that developers relying on older versions of the framework will continue to receive critical security and compatibility updates, allowing them to maintain and scale their applications securely, even after the framework's official end-of-life.
tags: announcements
tags: ['announcements']
authors:
- name: Express Technical Committee
github: expressjs
Expand Down
2 changes: 1 addition & 1 deletion astro/src/content/blog/en/2024-10-15-v5-release.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: 'Introducing Express v5: A New Era for the Node.js Framework'
tags: announcements
tags: ['announcements']
authors:
- name: Wes Todd
github: wesleytodd
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: 'Express.js Security Audit: A Milestone Achievement'
tags: security announcements
tags: ['security', 'announcements']
authors:
- name: Express Technical Committee
github: expressjs
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: 'A New Chapter for Express.js: Triumphs of 2024 and an ambitious 2025'
tags: announcements
tags: ['announcements']
authors:
- name: Express Technical Committee
github: expressjs
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: 'Express@5.1.0: Now the Default on npm with LTS Timeline'
tags: announcements
tags: ['announcements']
authors:
- name: Express Technical Committee
github: expressjs
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: 'Spring Cleaning in Express.js: Deprecations and the Path Ahead'
tags: announcements
tags: ['announcements']
authors:
- name: Express Technical Committee
github: expressjs
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: May 2025 Security Releases
description: Security release for Multer has been published. We recommend that all users upgrade as soon as possible.
tags: security
tags: ['security']
authors:
- name: Ulises Gascón
github: UlisesGascon
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: How Express.js Rebuilt Its Vulnerability Reporting Process
description: Express.js has overhauled its vulnerability reporting workflow with a unified process, consolidated documentation, and GitHub Security Advisories enabled across all repositories.
tags: security
tags: ['security']
authors:
- name: Ulises Gascón
github: UlisesGascon
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: June 2025 Security Releases
description: Security update for Multer released. All users are encouraged to upgrade.
tags: security
tags: ['security']
authors:
- name: Ulises Gascón
github: UlisesGascon
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: July 2025 Security Releases
description: Security releases for Multer and On-headers has been published. We recommend that all users upgrade as soon as possible.
tags: security
tags: ['security']
authors:
- name: Ulises Gascón
github: UlisesGascon
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: November 2025 Security Releases
description: Security release for body-parser has been published. We recommend that all users upgrade as soon as possible.
tags: security
tags: ['security']
authors:
- name: Ulises Gascón
github: UlisesGascon
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: February 2026 Security Releases
description: Security release for multer has been published. We recommend that all users upgrade as soon as possible.
tags: security
tags: ['security']
authors:
- name: Ulises Gascón
github: UlisesGascon
Expand Down
7 changes: 7 additions & 0 deletions astro/src/layouts/Layout.astro
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,13 @@ const lang = getLangFromUrl(Astro.url);
name="robots"
content={isNetlify ? 'noindex, nofollow' : 'max-image-preview:large, index, follow'}
/>
<link rel="alternate" type="application/rss+xml" href="/feed.xml" title="The Express.js blog" />
<link
rel="alternate"
type="application/rss+xml"
href="/vulnerabilities.xml"
title="Express.js Security Feed"
/>
</head>
<body>
<Header />
Expand Down
19 changes: 5 additions & 14 deletions astro/src/pages/[lang]/blog/[...page].astro
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,7 @@ export async function getStaticPaths({ paginate }: { paginate: PaginateFunction
return bFile.localeCompare(aFile);
});

const allTags = [
...new Set(
langPosts.flatMap((p) =>
(p.data.tags ?? '')
.split(' ')
.map((t: string) => t.trim())
.filter(Boolean)
)
),
];
const allTags = [...new Set(langPosts.flatMap((p) => p.data.tags ?? []))];

return paginate(langPosts, {
params: { lang },
Expand Down Expand Up @@ -57,8 +48,8 @@ function formatTagLabel(tag: string) {
return spaced.charAt(0).toUpperCase() + spaced.slice(1);
}

function getLabels(tags?: string) {
return (tags ?? '').split(' ').filter(Boolean).map(formatTagLabel);
function getLabels(tags?: string[]) {
return (tags ?? []).map(formatTagLabel);
}

function getPostProps(post: CollectionEntry<'blog'>) {
Expand Down Expand Up @@ -94,7 +85,7 @@ const filterTabs: TabItem[] = [
<Grid gap="4" align="stretch" data-posts-grid>
{
pagePosts.map((post) => (
<Col xs={12} md={6} lg={4} data-post-tags={post.data.tags ?? ''}>
<Col xs={12} md={6} lg={4} data-post-tags={(post.data.tags ?? []).join(' ')}>
<PostCard {...getPostProps(post)} />
</Col>
))
Expand All @@ -111,7 +102,7 @@ const filterTabs: TabItem[] = [
<template data-posts-pool>
{
langPosts.map((post) => (
<Col xs={12} md={6} lg={4} data-post-tags={post.data.tags ?? ''}>
<Col xs={12} md={6} lg={4} data-post-tags={(post.data.tags ?? []).join(' ')}>
<PostCard {...getPostProps(post)} />
</Col>
))
Expand Down
2 changes: 1 addition & 1 deletion astro/src/pages/[lang]/blog/[slug].astro
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const date = new Date(dateStr).toLocaleDateString('en-US', {
day: 'numeric',
year: 'numeric',
});
const label = tags?.split(' ')[0] ?? '';
const label = tags?.[0] ?? '';
---

<Layout title={title} description={description}>
Expand Down
31 changes: 31 additions & 0 deletions astro/src/pages/feed.xml.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import rss from '@astrojs/rss';
import { getCollection } from 'astro:content';
import type { APIRoute } from 'astro';
import {
getLinkedTitleContent,
getAuthorsCustomData,
getPubDateFromId,
shouldIncludeInFeed,
sortByIdDateDesc,
} from '@/utils/rss';

export const GET: APIRoute = async (context) => {
const site = context.site as URL;
const blog = await getCollection('blog');
const sortedBlog = sortByIdDateDesc(blog.filter((post) => shouldIncludeInFeed(post.id)));

return rss({
title: 'The Express.js Blog',
description: 'News and updates about express.js',
site: site.href,
items: sortedBlog.map((post) => ({
link: `/blog/${post.id}/`,
title: post.data.title,
pubDate: getPubDateFromId(post.id),
description: post.data.description,
content: getLinkedTitleContent(post.data.title, post.id, site),
categories: post.data.tags,
customData: getAuthorsCustomData(post.data.authors),
})),
});
};
35 changes: 35 additions & 0 deletions astro/src/pages/vulnerabilities.xml.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import rss from '@astrojs/rss';
import { getCollection } from 'astro:content';
import type { APIRoute } from 'astro';
import {
getLinkedTitleContent,
getAuthorsCustomData,
getPubDateFromId,
shouldIncludeInFeed,
sortByIdDateDesc,
} from '@/utils/rss';

export const GET: APIRoute = async (context) => {
const site = context.site as URL;
const blog = await getCollection('blog');
const securityPosts = sortByIdDateDesc(
blog.filter(
(post) => shouldIncludeInFeed(post.id) && (post.data.tags ?? []).includes('security')
)
);

return rss({
title: 'Express.js Security Feed',
description: 'Posts tagged as security from the Express.js blog.',
site: site.href,
items: securityPosts.map((post) => ({
link: `/blog/${post.id}/`,
title: post.data.title,
pubDate: getPubDateFromId(post.id),
description: post.data.description,
content: getLinkedTitleContent(post.data.title, post.id, site),
categories: post.data.tags,
customData: getAuthorsCustomData(post.data.authors),
})),
});
};
Loading