@tmlmobilidade/rss 20260331.1620.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2 @@
1
+ import { type CreateRssFeedOptions, type RssRawItem } from './types/index.js';
2
+ export declare function createRssFeed(rawItems: RssRawItem[], options: CreateRssFeedOptions): string;
package/dist/index.js ADDED
@@ -0,0 +1,29 @@
1
+ /* * */
2
+ import { rssFeedXml, rssItemXml } from './utils/index.js';
3
+ /* * */
4
+ export function createRssFeed(rawItems, options) {
5
+ //
6
+ //
7
+ // A. Create XML items
8
+ const itemsXml = rawItems.map(item => rssItemXml({
9
+ description: item.summary || item.description || '',
10
+ link: item.link || '',
11
+ publishDate: item.publishDate || item.publish_start_date || item.created_at ? new Date(item.publishDate || item.publish_start_date || item.created_at).toUTCString() : undefined,
12
+ title: item.title || '',
13
+ })).join('\n');
14
+ //
15
+ // B. Create and return XML feed
16
+ const now = new Date().toUTCString();
17
+ return rssFeedXml(itemsXml, {
18
+ channelCopyright: options.copyright,
19
+ channelDescription: options.description,
20
+ channelDocs: 'https://www.rssboard.org/rss-specification',
21
+ channelGenerator: '@tmlmobilidade/rss',
22
+ channelLanguage: 'pt-pt',
23
+ channelLastBuildDate: now,
24
+ channelLink: options.link,
25
+ channelPubDate: now,
26
+ channelTitle: options.title,
27
+ });
28
+ //
29
+ }
@@ -0,0 +1,19 @@
1
+ export interface RssRawItem {
2
+ _id?: string;
3
+ created_at?: number | string;
4
+ description?: null | string;
5
+ id?: string;
6
+ info_url?: null | string;
7
+ link?: null | string;
8
+ publish_start_date?: null | number;
9
+ publishDate?: null | string;
10
+ slug?: null | string;
11
+ summary?: null | string;
12
+ title?: null | string;
13
+ }
14
+ export interface CreateRssFeedOptions {
15
+ copyright: string;
16
+ description: string;
17
+ link: string;
18
+ title: string;
19
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export * from './feed.types.js';
@@ -0,0 +1 @@
1
+ export * from './feed.types.js';
@@ -0,0 +1 @@
1
+ export declare function escapeXml(value: null | string | undefined): string;
@@ -0,0 +1,12 @@
1
+ /* * */
2
+ export function escapeXml(value) {
3
+ if (!value)
4
+ return '';
5
+ return value
6
+ .replace(/&/g, '&')
7
+ .replace(/</g, '&lt;')
8
+ .replace(/>/g, '&gt;')
9
+ .replace(/"/g, '&quot;')
10
+ .replace(/'/g, '&apos;');
11
+ }
12
+ /* * */
@@ -0,0 +1,3 @@
1
+ export * from './escape-xml.js';
2
+ export * from './rss-feed-xml.js';
3
+ export * from './rss-item-xml.js';
@@ -0,0 +1,3 @@
1
+ export * from './escape-xml.js';
2
+ export * from './rss-feed-xml.js';
3
+ export * from './rss-item-xml.js';
@@ -0,0 +1,13 @@
1
+ interface RssChannelOptions {
2
+ channelCopyright: string;
3
+ channelDescription: string;
4
+ channelDocs: string;
5
+ channelGenerator: string;
6
+ channelLanguage: string;
7
+ channelLastBuildDate: string;
8
+ channelLink: string;
9
+ channelPubDate: string;
10
+ channelTitle: string;
11
+ }
12
+ export declare function rssFeedXml(itemsXml: string, channelOptions: RssChannelOptions): string;
13
+ export {};
@@ -0,0 +1,22 @@
1
+ /* * */
2
+ import { escapeXml } from './escape-xml.js';
3
+ export function rssFeedXml(itemsXml, channelOptions) {
4
+ return [
5
+ '<?xml version="1.0" encoding="UTF-8"?>',
6
+ '<rss version="2.0">',
7
+ '<channel>',
8
+ `<title>${escapeXml(channelOptions.channelTitle)}</title>`,
9
+ `<link>${escapeXml(channelOptions.channelLink)}</link>`,
10
+ `<description>${escapeXml(channelOptions.channelDescription)}</description>`,
11
+ `<language>${escapeXml(channelOptions.channelLanguage)}</language>`,
12
+ `<lastBuildDate>${escapeXml(channelOptions.channelLastBuildDate)}</lastBuildDate>`,
13
+ `<generator>${escapeXml(channelOptions.channelGenerator)}</generator>`,
14
+ `<docs>${escapeXml(channelOptions.channelDocs)}</docs>`,
15
+ `<pubDate>${escapeXml(channelOptions.channelPubDate)}</pubDate>`,
16
+ `<copyright>${escapeXml(channelOptions.channelCopyright)}</copyright>`,
17
+ itemsXml,
18
+ '</channel>',
19
+ '</rss>',
20
+ ].join('\n');
21
+ }
22
+ /* * */
@@ -0,0 +1,2 @@
1
+ import { type RssRawItem } from '../types/feed.types.js';
2
+ export declare function rssItemXml(item: RssRawItem): string;
@@ -0,0 +1,15 @@
1
+ /* * */
2
+ import { escapeXml } from './escape-xml.js';
3
+ /* * */
4
+ export function rssItemXml(item) {
5
+ return [
6
+ '<item>',
7
+ `<title>${escapeXml(item.title)}</title>`,
8
+ `<link>${escapeXml(item.link || '')}</link>`,
9
+ `<guid isPermaLink="true">${escapeXml(item.link || '')}</guid>`,
10
+ item.publishDate ? `<pubDate>${escapeXml(item.publishDate)}</pubDate>` : '',
11
+ `<description>${escapeXml(item.description)}</description>`,
12
+ '</item>',
13
+ ].filter(Boolean).join('\n');
14
+ }
15
+ /* * */
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@tmlmobilidade/rss",
3
+ "version": "20260331.1620.53",
4
+ "author": {
5
+ "email": "iso@tmlmobilidade.pt",
6
+ "name": "TML-ISO"
7
+ },
8
+ "license": "AGPL-3.0-or-later",
9
+ "homepage": "https://go.tmlmobilidade.pt",
10
+ "bugs": {
11
+ "url": "https://github.com/tmlmobilidade/go/issues"
12
+ },
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/tmlmobilidade/go.git"
16
+ },
17
+ "keywords": [
18
+ "public transit",
19
+ "tml",
20
+ "transportes metropolitanos de lisboa",
21
+ "go"
22
+ ],
23
+ "publishConfig": {
24
+ "access": "public"
25
+ },
26
+ "type": "module",
27
+ "files": [
28
+ "dist"
29
+ ],
30
+ "main": "./dist/index.js",
31
+ "types": "./dist/index.d.ts",
32
+ "scripts": {
33
+ "build": "tsc && resolve-tspaths",
34
+ "lint": "eslint ./src/ && tsc --noEmit",
35
+ "lint:fix": "eslint ./src/ --fix",
36
+ "watch": "tsc-watch --onSuccess 'resolve-tspaths'"
37
+ },
38
+ "dependencies": {
39
+ "@tmlmobilidade/dates": "*"
40
+ },
41
+ "devDependencies": {
42
+ "@tmlmobilidade/tsconfig": "*",
43
+ "@tmlmobilidade/types": "*",
44
+ "@types/node": "25.5.0",
45
+ "resolve-tspaths": "0.8.23",
46
+ "tsc-watch": "7.2.0",
47
+ "typescript": "5.9.3"
48
+ }
49
+ }