Skip to content

Commit e4b7cc2

Browse files
committed
src: MVP
0 parents  commit e4b7cc2

File tree

2 files changed

+176
-0
lines changed

2 files changed

+176
-0
lines changed

src/main.ts

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
export * from "./types.ts";
2+
import type { FeedInfo, Item } from "./types.ts";
3+
4+
/**
5+
* JSON feed
6+
*/
7+
export class Feed {
8+
/** The URL of the version of the feed format */
9+
#version = "https://jsonfeed.org/version/1.1";
10+
/** Information of the feed */
11+
#info: FeedInfo;
12+
/** Items of the feed */
13+
#items: Item[] = [];
14+
15+
/**
16+
* Creates new JSON Feed
17+
*
18+
* @param info Feed info
19+
*/
20+
// todo: validate arguments
21+
constructor(info: FeedInfo) {
22+
this.#info = info;
23+
}
24+
25+
/**
26+
* Add one or more items to the feed
27+
*
28+
* @param items items to add
29+
* @throws {Error} if item with same ID was already added
30+
*/
31+
// todo: validate arguments
32+
add(...items: Item[]): void {
33+
for (const item of items) {
34+
const itemId = item.id;
35+
36+
if (this.#items.some(({ id }) => id === itemId)) {
37+
throw new Error(`Item with ID '${itemId}' was already added`);
38+
}
39+
}
40+
41+
this.#items.push(...items);
42+
}
43+
44+
/**
45+
* Get feed as JSON
46+
*
47+
* @returns feed as JSON
48+
*/
49+
toJSON(): string {
50+
return JSON.stringify({
51+
version: this.#version,
52+
...this.#info,
53+
items: this.#items,
54+
});
55+
}
56+
}

src/types.ts

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
/**
2+
* Author of a feed or item
3+
*/
4+
export interface Author {
5+
/** The author's name */
6+
name?: string;
7+
/** The URL of a site owned by the author */
8+
url?: string;
9+
/** The URL for an image for the author */
10+
avatar?: string;
11+
}
12+
13+
/**
14+
* Hub for real-time notifications
15+
*/
16+
export interface Hub {
17+
/** The protocol used to talk with the hub */
18+
type: string;
19+
/** The URL of the hub */
20+
url: string;
21+
}
22+
23+
/**
24+
* Item with HTML and/or plain text content
25+
*/
26+
export type Item = HTMLItem | TextItem | (HTMLItem & TextItem);
27+
28+
/**
29+
* Item with HTML content
30+
*/
31+
export interface HTMLItem extends BaseItem {
32+
/** HTML content of the item */
33+
content_html: string;
34+
}
35+
36+
/**
37+
* Item with plain text content
38+
*/
39+
export interface TextItem extends BaseItem {
40+
/** Plain text content of the item */
41+
content_text: string;
42+
}
43+
44+
/**
45+
* Base item
46+
*/
47+
export interface BaseItem {
48+
/** Unique identifier for the item, e.g. `url` */
49+
id: string;
50+
/** URL of the resource described by the item */
51+
url?: string;
52+
/** URL of a page elsewhere */
53+
external_url?: string;
54+
/** Title of the item */
55+
title?: string;
56+
/** Summary of the item */
57+
summary?: string;
58+
/** URL of the main image for the item */
59+
image?: string;
60+
/** URL of an image to use as a banner */
61+
banner_image?: string;
62+
/** Date the item was published in RFC 3339 format, e.g. `2010-02-07T14:04:00-05:00` */
63+
date_published?: string;
64+
/** Date the item was modified in RFC 3339 format, e.g. `2010-02-07T14:04:00-05:00` */
65+
date_modified?: string;
66+
/** Authors of the item */
67+
authors?: Author[];
68+
/** Tags associated with the item */
69+
tags?: string[];
70+
/** Language of the item in RFC 5646 format, e.g. `en` or `en-US` */
71+
language?: string;
72+
/** Attachments associated with the item */
73+
attachments?: Attachment[];
74+
}
75+
76+
/**
77+
* Related resource of an item
78+
*/
79+
export interface Attachment {
80+
/** The URL of the attachment */
81+
url: string;
82+
/** The MIME type of the attachment */
83+
mime_type: string;
84+
/** A name for the attachment */
85+
title?: string;
86+
/** The size of the attachment in bytes */
87+
size_in_bytes?: number;
88+
/** The duration of the attachment in seconds */
89+
duration_in_seconds?: number;
90+
}
91+
92+
/**
93+
* Information of a JSON feed
94+
*/
95+
export interface FeedInfo {
96+
/** The name of the feed */
97+
title: string;
98+
/** The URL of the resource that the feed describes */
99+
home_page_url: string;
100+
/** The URL of the feed */
101+
feed_url: string;
102+
/** Description of the feed */
103+
description?: string;
104+
/** Description of the purpose of the feed, ignored by the feed reader */
105+
user_comment?: string;
106+
/** URL of the next page of the feed for pagination, different from `feed_url` to avoid infinite loops */
107+
next_url?: string;
108+
/** URL of an image for the feed */
109+
icon?: string;
110+
/** URL of a favicon for the feed */
111+
favicon?: string;
112+
/** Authors of the feed */
113+
authors?: Author[];
114+
/** Primary language for the feed in RFC 5646 format, e.g. `en` or `en-US` */
115+
language?: string;
116+
/** Whether the feed is finished and won't ever update */
117+
expired?: boolean;
118+
/** Endpoints for real-time notifications */
119+
hubs?: Hub[];
120+
}

0 commit comments

Comments
 (0)