Skip to content

Commit a3fc0f4

Browse files
Add a script to generate an atom feed.
1 parent 3b60293 commit a3fc0f4

File tree

7 files changed

+303
-14
lines changed

7 files changed

+303
-14
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
},
1010
"scripts": {
1111
"docusaurus": "docusaurus",
12-
"prestart": "node scripts/resize-images.js && node scripts/generate-rss-feed.js",
13-
"prebuild": "node scripts/resize-images.js && node scripts/generate-rss-feed.js",
12+
"prestart": "node scripts/resize-images.mjs && node scripts/generate-rss-feed.mjs && node scripts/generate-atom-feed.mjs",
13+
"prebuild": "node scripts/resize-images.mjs && node scripts/generate-rss-feed.mjs && node scripts/generate-atom-feed.mjs",
1414
"start": "docusaurus start",
1515
"build": "docusaurus build",
1616
"swizzle": "docusaurus swizzle",

scripts/generate-atom-feed.mjs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import fs from 'fs';
2+
import { Feed } from 'feed';
3+
import { blogpostsDetails } from '../src/components/blog/blogpostsDetails.js';
4+
import path from 'path';
5+
import { fileURLToPath } from 'url';
6+
const __filename = fileURLToPath(import.meta.url);
7+
const __dirname = path.dirname(__filename);
8+
9+
const outputDir = path.join(__dirname, '../static');
10+
if (!fs.existsSync(outputDir)) {
11+
fs.mkdirSync(outputDir, { recursive: true });
12+
}
13+
14+
const generateAtomFeedFromBlogDetails = (feed, blogpostsDetails, nbOfBlogPosts) => {
15+
let posts = [];
16+
for (let i = 0; i < nbOfBlogPosts; i++) {
17+
const post = blogpostsDetails[i];
18+
posts.push({
19+
title: post.title,
20+
link: post.url,
21+
description: post.summary,
22+
date: new Date(post.date),
23+
authors: post.authors.split(','),
24+
})
25+
};
26+
27+
posts.forEach((post) => {
28+
feed.addItem({
29+
title: post.title,
30+
id: post.url,
31+
link: post.url,
32+
description: post.summary,
33+
date: new Date(post.date),
34+
author: [{ name: post.authors }],
35+
});
36+
37+
})
38+
return feed;
39+
}
40+
const AtomFeedLast20 = new Feed({
41+
title: 'Recent blog posts featured by QuantStack team',
42+
description: 'Atom feed for QuantStack website blog page',
43+
id: 'https://quantstack.net/',
44+
link: 'https://quantstack.net/',
45+
language: 'en',
46+
updated: new Date(),
47+
feedLinks: {
48+
atom: 'https://quantstack.net/atom.xml',
49+
},
50+
author: {
51+
name: 'QuantStack Team',
52+
link: 'https://quantstack.net',
53+
},
54+
});
55+
56+
57+
const updatedFeedLast20 = generateAtomFeedFromBlogDetails(AtomFeedLast20, blogpostsDetails, 20);
58+
const xml = updatedFeedLast20.atom1(); // Atom format
59+
fs.writeFileSync(path.join(outputDir, 'atom.xml'), xml);
60+
61+
/*const AtomFeedAll = new Feed({
62+
title: 'All blog posts featured by QuantStack team',
63+
description: 'Atom feed for QuantStack website blog page',
64+
feed_url: 'https://quantstack.net/atom_all.xml',
65+
site_url: 'https://quantstack.net',
66+
language: 'en',
67+
});
68+
69+
const updatedFeedAll = generateAtomFeedFromBlogDetails(AtomFeedAll, blogpostsDetails, blogpostsDetails.length)
70+
fs.writeFileSync(path.join(outputDir, 'atom_all.xml'), updatedFeedAll.atom1({ indent: true }));*/

scripts/generate-rss-feed.js renamed to scripts/generate-rss-feed.mjs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
const fs = require('fs');
2-
const RSS = require('rss');
3-
const { blogpostsDetails } = require('../src/components/blog/blogpostsDetails.js');
4-
const path = require('path');
1+
import fs from 'fs';
2+
import RSS from 'rss';
3+
import { blogpostsDetails } from '../src/components/blog/blogpostsDetails.js';
4+
import path from 'path';
5+
import { fileURLToPath } from 'url';
6+
const __filename = fileURLToPath(import.meta.url);
7+
const __dirname = path.dirname(__filename);
58

69
const outputDir = path.join(__dirname, '../static');
710
if (!fs.existsSync(outputDir)) {

scripts/resize-images.js renamed to scripts/resize-images.mjs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
const sharp = require('sharp');
2-
const fs = require('fs');
3-
const path = require('path');
4-
const sizeOf = require('image-size');
5-
const fullSizeDir = path.join(__dirname, '../static', 'img', 'blogposts', 'full-size-images');
6-
const reducedSizeDir = path.join(__dirname, '../static', 'img', 'blogposts', 'resized-images');
1+
import sharp from 'sharp';
2+
import fs from 'fs';
3+
import path from 'path';
4+
import sizeOf from 'image-size';
5+
import { fileURLToPath } from 'url';
76
const containerHeight = 180;
87
const containerWidth = 273;
8+
const __filename = fileURLToPath(import.meta.url);
9+
const __dirname = path.dirname(__filename);
10+
const fullSizeDir = path.join(__dirname, '../static', 'img', 'blogposts', 'full-size-images');
11+
const reducedSizeDir = path.join(__dirname, '../static', 'img', 'blogposts', 'resized-images');
912

1013
if (!fs.existsSync(reducedSizeDir)) {
1114
fs.mkdirSync(reducedSizeDir, { recursive: true });

static/atom.xml

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<feed xmlns="http://www.w3.org/2005/Atom">
3+
<id>https://quantstack.net/</id>
4+
<title>Recent blog posts featured by QuantStack team</title>
5+
<updated>2025-07-29T13:01:23.478Z</updated>
6+
<generator>https://github.com/jpmonette/feed</generator>
7+
<author>
8+
<name>QuantStack Team</name>
9+
<uri>https://quantstack.net</uri>
10+
</author>
11+
<link rel="alternate" href="https://quantstack.net/"/>
12+
<link rel="self" href="https://quantstack.net/atom.xml"/>
13+
<subtitle>Atom feed for QuantStack website blog page</subtitle>
14+
<entry>
15+
<title type="html"><![CDATA[Create your own layers in JupyterGIS]]></title>
16+
<id/>
17+
<link/>
18+
<updated>2025-06-24T22:00:00.000Z</updated>
19+
<author>
20+
<name>David Brochart</name>
21+
</author>
22+
</entry>
23+
<entry>
24+
<title type="html"><![CDATA[C++ in Jupyter — Interpreting C++ in the Web]]></title>
25+
<id/>
26+
<link/>
27+
<updated>2025-06-18T22:00:00.000Z</updated>
28+
<author>
29+
<name>Anutosh Bhat</name>
30+
<name> Vassil Vassilev</name>
31+
</author>
32+
</entry>
33+
<entry>
34+
<title type="html"><![CDATA[JupyterLite 0.6.0 is released! 🎉]]></title>
35+
<id/>
36+
<link/>
37+
<updated>2025-06-11T22:00:00.000Z</updated>
38+
<author>
39+
<name>Jeremy Tuloup</name>
40+
</author>
41+
</entry>
42+
<entry>
43+
<title type="html"><![CDATA[JupyterLab 4.4 and Notebook 7.4 are available!]]></title>
44+
<id/>
45+
<link/>
46+
<updated>2025-05-20T22:00:00.000Z</updated>
47+
<author>
48+
<name>Jeremy Tuloup</name>
49+
</author>
50+
</entry>
51+
<entry>
52+
<title type="html"><![CDATA[Congratulations, Distinguished Contributors!]]></title>
53+
<id/>
54+
<link/>
55+
<updated>2025-05-14T22:00:00.000Z</updated>
56+
<author>
57+
<name>Johan Mabille</name>
58+
</author>
59+
</entry>
60+
<entry>
61+
<title type="html"><![CDATA[Making Qt collaborative using CRDTs]]></title>
62+
<id/>
63+
<link/>
64+
<updated>2025-03-30T22:00:00.000Z</updated>
65+
<author>
66+
<name>David Brochart</name>
67+
</author>
68+
</entry>
69+
<entry>
70+
<title type="html"><![CDATA[R in the Browser: Announcing Our WebAssembly Distribution]]></title>
71+
<id/>
72+
<link/>
73+
<updated>2025-02-27T23:00:00.000Z</updated>
74+
<author>
75+
<name>Isabel Paredes</name>
76+
</author>
77+
</entry>
78+
<entry>
79+
<title type="html"><![CDATA[Real-time collaboration and collaborative editing for GIS workflows with Jupyter and QGIS]]></title>
80+
<id/>
81+
<link/>
82+
<updated>2025-02-25T23:00:00.000Z</updated>
83+
<author>
84+
<name>Meriem Ben Ismail</name>
85+
<name> Nicolas Brichet</name>
86+
<name> David Brochart</name>
87+
<name> Matt Fisher</name>
88+
<name> Anne Fouilloux</name>
89+
<name> Greg Mooney</name>
90+
<name> Martin Renou</name>
91+
<name> Arjun Verma</name>
92+
</author>
93+
</entry>
94+
<entry>
95+
<title type="html"><![CDATA[PyData Paris 2025 Keynotes]]></title>
96+
<id/>
97+
<link/>
98+
<updated>2025-02-18T23:00:00.000Z</updated>
99+
<author>
100+
<name>Sandrine Pataut</name>
101+
</author>
102+
</entry>
103+
<entry>
104+
<title type="html"><![CDATA[Announcing JupyterCAD 3.0]]></title>
105+
<id/>
106+
<link/>
107+
<updated>2025-02-16T23:00:00.000Z</updated>
108+
<author>
109+
<name>Arjun Verma</name>
110+
<name> Trung Le</name>
111+
<name> Martin Renou</name>
112+
</author>
113+
</entry>
114+
<entry>
115+
<title type="html"><![CDATA[Sparrow]]></title>
116+
<id/>
117+
<link/>
118+
<updated>2025-01-30T23:00:00.000Z</updated>
119+
<author>
120+
<name>Johan Mabille</name>
121+
<name> Alexis Placet</name>
122+
<name> Thorsten Beier</name>
123+
<name> Joël Lamotte</name>
124+
</author>
125+
</entry>
126+
<entry>
127+
<title type="html"><![CDATA[JupyterLite Terminal]]></title>
128+
<id/>
129+
<link/>
130+
<updated>2024-11-12T23:00:00.000Z</updated>
131+
<author>
132+
<name>Ian Thomas</name>
133+
</author>
134+
</entry>
135+
<entry>
136+
<title type="html"><![CDATA[Automate your releases with the Jupyter Releaser 🚀]]></title>
137+
<id/>
138+
<link/>
139+
<updated>2024-10-27T23:00:00.000Z</updated>
140+
<author>
141+
<name>Jeremy Tuloup</name>
142+
</author>
143+
</entry>
144+
<entry>
145+
<title type="html"><![CDATA[QuantStack Steps Up to Support Apache Arrow with New Dedicated Team]]></title>
146+
<id/>
147+
<link/>
148+
<updated>2024-10-21T22:00:00.000Z</updated>
149+
<author>
150+
<name>Sylvain Corlay</name>
151+
</author>
152+
</entry>
153+
<entry>
154+
<title type="html"><![CDATA[Interactive Mapping with ipyopenlayers]]></title>
155+
<id/>
156+
<link/>
157+
<updated>2024-09-05T22:00:00.000Z</updated>
158+
<author>
159+
<name>Nour Cheour</name>
160+
</author>
161+
</entry>
162+
<entry>
163+
<title type="html"><![CDATA[Announcing the 2023 cohort of Jupyter distinguished contributors]]></title>
164+
<id/>
165+
<link/>
166+
<updated>2024-09-03T22:00:00.000Z</updated>
167+
<author>
168+
<name>Johan Mabille</name>
169+
<name> on behalf of the Jupyter Distinguished Contributors</name>
170+
</author>
171+
</entry>
172+
<entry>
173+
<title type="html"><![CDATA[Ipydatagrid is now part of Project Jupyter]]></title>
174+
<id/>
175+
<link/>
176+
<updated>2024-08-21T22:00:00.000Z</updated>
177+
<author>
178+
<name>Sylvain Corlay</name>
179+
<name> on behalf of the Jupyter Widgets Council</name>
180+
</author>
181+
</entry>
182+
<entry>
183+
<title type="html"><![CDATA[Introducing Mamba 2.0]]></title>
184+
<id/>
185+
<link/>
186+
<updated>2024-07-15T22:00:00.000Z</updated>
187+
<author>
188+
<name>Antoine Prouvost</name>
189+
<name> Joël Lamotte</name>
190+
<name> Johan Mabille</name>
191+
<name> Hind Montassif</name>
192+
</author>
193+
</entry>
194+
<entry>
195+
<title type="html"><![CDATA[QuantStack open-source internship program]]></title>
196+
<id/>
197+
<link/>
198+
<updated>2024-07-08T22:00:00.000Z</updated>
199+
<author>
200+
<name>Sylvain Corlay</name>
201+
</author>
202+
</entry>
203+
<entry>
204+
<title type="html"><![CDATA[JupyterCAD 2.0]]></title>
205+
<id/>
206+
<link/>
207+
<updated>2024-07-04T22:00:00.000Z</updated>
208+
<author>
209+
<name>Trung Le</name>
210+
<name> Martin Renou</name>
211+
</author>
212+
</entry>
213+
</feed>

static/rss.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

static/rss_all.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)