diff --git a/package-lock.json b/package-lock.json
index 7967736..56e9b3a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8670,8 +8670,7 @@
"sax": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
- "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
- "dev": true
+ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
},
"semver": {
"version": "5.7.0",
@@ -9670,10 +9669,13 @@
"async-limiter": "~1.0.0"
}
},
- "xml": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz",
- "integrity": "sha1-eLpyAgApxbyHuKgaPPzXS0ovweU="
+ "xml-js": {
+ "version": "1.6.11",
+ "resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz",
+ "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==",
+ "requires": {
+ "sax": "^1.2.4"
+ }
},
"xml-name-validator": {
"version": "3.0.0",
diff --git a/package.json b/package.json
index 7ca4d39..5136935 100644
--- a/package.json
+++ b/package.json
@@ -9,7 +9,7 @@
"express": "^4.17.1",
"ncp": "^2.0.0",
"showdown": "^1.9.0",
- "xml": "^1.0.1"
+ "xml-js": "^1.6.11"
},
"devDependencies": {
"babel-cli": "^6.26.0",
diff --git a/src/config.default.json b/src/config.default.json
index 25acebc..88c5156 100644
--- a/src/config.default.json
+++ b/src/config.default.json
@@ -2,6 +2,7 @@
"node_port": 3000,
"data_dir": "data",
"view_engine": "ejs",
+ "loopback_url": "http://localhost:3000",
"modules": {
"plantuml": false,
"rss": true,
@@ -22,6 +23,8 @@
"default_thumbnail": null
},
"rss": {
+ "title": "mygitblog RSS feed",
+ "description": "a generated RSS feed from my articles",
"endpoint": "/rss",
"length": 10
},
diff --git a/src/rss.js b/src/rss.js
new file mode 100644
index 0000000..efd36aa
--- /dev/null
+++ b/src/rss.js
@@ -0,0 +1,40 @@
+const convert = require('xml-js');
+
+const mapArticle = (url, article) => {
+ return {
+ 'title': {'_text': article.title},
+ 'link': {'_text': (url + article.url).replace(/([^:])\/\//g, '$1/')},
+ 'pubDate': {'_text': article.date.toString()},
+ };
+};
+
+module.exports = (config) => {
+ return {
+ get: (dict) => {
+ const items = Object.values(dict)
+ .sort((a, b) => ('' + b.path).localeCompare(a.path))
+ .slice(0, config['rss']['length']);
+ const data = {
+ '_declaration': {
+ '_attributes': {
+ 'version': '1.0',
+ 'encoding': 'UTF-8'
+ }
+ },
+ 'rss': {
+ '_attributes': {
+ 'version': '2.0'
+ },
+ 'title': {'_text': config['rss']['title']},
+ 'description': {'_text': config['rss']['description']},
+ 'link': {'_text': config['loopback_url']},
+ 'lastBuildDate': {'_text': new Date().toString()},
+ 'lastPubDate': {'_text': new Date().toString()},
+ 'ttl': {'_text': '60'},
+ 'item': items.map((a) => mapArticle(config['loopback_url'], a))
+ }
+ };
+ return convert.js2xml(data, {compact: true});
+ }
+ };
+};
\ No newline at end of file
diff --git a/test/rss.test.js b/test/rss.test.js
new file mode 100644
index 0000000..087a2eb
--- /dev/null
+++ b/test/rss.test.js
@@ -0,0 +1,100 @@
+/* jshint -W117 */
+const config = {
+ 'loopback_url': 'http://test.test/',
+ 'rss': {
+ 'title': 'test rss',
+ 'description': 'description',
+ 'endpoint': '/rss',
+ 'length': 2
+ },
+};
+
+const rss = require('../src/rss')(config);
+
+test('empty rss', () => {
+ const xml = rss.get({});
+ expect(xml).toBe('' +
+ '' +
+ 'test rss' +
+ 'description' +
+ 'http://test.test/' +
+ '' + new Date().toString() + '' +
+ '' + new Date().toString() + '' +
+ '60' +
+ '');
+});
+
+test('1 item', () => {
+ const data = {
+ 'a': {
+ path: 'a',
+ realPath: 'b',
+ year: 2019,
+ month: 5,
+ day: 5,
+ date: new Date(2019, 5, 5),
+ title: 'Title with : info !',
+ thumbnail: '/2019/05/05/thumbnail.jpg/',
+ escapedTitle: 'title_with___info',
+ url: '/2019/05/05/title_with___info/',
+ }
+ };
+ const xml = rss.get(data);
+ expect(xml).toEqual('' +
+ '' +
+ 'test rss' +
+ 'description' +
+ 'http://test.test/' +
+ '' + new Date().toString() + '' +
+ '' + new Date().toString() + '' +
+ '60' +
+ '- ' +
+ 'Title with : info !' +
+ 'http://test.test/2019/05/05/title_with___info/' +
+ '' + new Date(2019, 5, 5).toString() + '' +
+ '
' +
+ '');
+});
+
+test('3 items only 2 shown sorted', () => {
+ const data = {
+ 'a': {
+ path: '2019/05/05',
+ date: new Date(2019, 5, 5),
+ title: 'a',
+ url: 'a',
+ },
+ 'b': {
+ path: '2018/05/05',
+ date: new Date(2018, 5, 5),
+ title: 'b',
+ url: 'b',
+ },
+ 'c': {
+ path: '2020/05/05',
+ date: new Date(2020, 5, 5),
+ title: 'c',
+ url: 'c',
+ }
+ };
+ const xml = rss.get(data);
+ expect(xml).toEqual('' +
+ '' +
+ 'test rss' +
+ 'description' +
+ 'http://test.test/' +
+ '' + new Date().toString() + '' +
+ '' + new Date().toString() + '' +
+ '60' +
+ '- ' +
+ 'c' +
+ 'http://test.test/c' +
+ '' + new Date(2020, 5, 5).toString() + '' +
+ '
' +
+ '- ' +
+ 'a' +
+ 'http://test.test/a' +
+ '' + new Date(2019, 5, 5).toString() + '' +
+ '
' +
+ '');
+});
\ No newline at end of file