feedparser-rs 0.1.8 → 0.2.1
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.
- package/README.md +61 -112
- package/package.json +1 -8
package/README.md
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
# feedparser-rs
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/feedparser-rs)
|
|
4
|
+
[](https://www.npmjs.com/package/feedparser-rs)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
|
|
7
|
+
High-performance RSS/Atom/JSON Feed parser for Node.js, written in Rust.
|
|
4
8
|
|
|
5
9
|
Drop-in replacement for Python's `feedparser` library, offering 10-100x performance improvement.
|
|
6
10
|
|
|
@@ -8,9 +12,10 @@ Drop-in replacement for Python's `feedparser` library, offering 10-100x performa
|
|
|
8
12
|
|
|
9
13
|
- **Fast**: Written in Rust, 10-100x faster than Python feedparser
|
|
10
14
|
- **Tolerant**: Handles malformed feeds with bozo flag (like feedparser)
|
|
11
|
-
- **Multi-format**:
|
|
12
|
-
- **
|
|
15
|
+
- **Multi-format**: RSS 0.9x/1.0/2.0, Atom 0.3/1.0, JSON Feed 1.0/1.1
|
|
16
|
+
- **HTTP fetching**: Built-in URL fetching with compression support
|
|
13
17
|
- **TypeScript**: Full TypeScript definitions included
|
|
18
|
+
- **Zero-copy**: Efficient parsing with minimal allocations
|
|
14
19
|
|
|
15
20
|
## Installation
|
|
16
21
|
|
|
@@ -22,12 +27,14 @@ yarn add feedparser-rs
|
|
|
22
27
|
pnpm add feedparser-rs
|
|
23
28
|
```
|
|
24
29
|
|
|
30
|
+
> [!IMPORTANT]
|
|
31
|
+
> Requires Node.js 18 or later.
|
|
32
|
+
|
|
25
33
|
## Quick Start
|
|
26
34
|
|
|
27
35
|
```javascript
|
|
28
36
|
import { parse } from 'feedparser-rs';
|
|
29
37
|
|
|
30
|
-
// Parse from string
|
|
31
38
|
const feed = parse(`
|
|
32
39
|
<?xml version="1.0"?>
|
|
33
40
|
<rss version="2.0">
|
|
@@ -44,8 +51,28 @@ const feed = parse(`
|
|
|
44
51
|
console.log(feed.feed.title); // "My Blog"
|
|
45
52
|
console.log(feed.entries[0].title); // "Hello World"
|
|
46
53
|
console.log(feed.version); // "rss20"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## HTTP Fetching
|
|
57
|
+
|
|
58
|
+
Fetch and parse feeds directly from URLs:
|
|
59
|
+
|
|
60
|
+
```javascript
|
|
61
|
+
import { fetchAndParse } from 'feedparser-rs';
|
|
62
|
+
|
|
63
|
+
const feed = await fetchAndParse('https://example.com/feed.xml');
|
|
64
|
+
console.log(feed.feed.title);
|
|
65
|
+
console.log(`Fetched ${feed.entries.length} entries`);
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
> [!TIP]
|
|
69
|
+
> `fetchAndParse` automatically handles compression (gzip, deflate, brotli) and follows redirects.
|
|
70
|
+
|
|
71
|
+
### Parsing from Buffer
|
|
72
|
+
|
|
73
|
+
```javascript
|
|
74
|
+
import { parse } from 'feedparser-rs';
|
|
47
75
|
|
|
48
|
-
// Parse from Buffer (e.g., HTTP response)
|
|
49
76
|
const response = await fetch('https://example.com/feed.xml');
|
|
50
77
|
const buffer = Buffer.from(await response.arrayBuffer());
|
|
51
78
|
const feed = parse(buffer);
|
|
@@ -66,24 +93,23 @@ Parse a feed from bytes or string.
|
|
|
66
93
|
**Throws:**
|
|
67
94
|
- `Error` if parsing fails catastrophically
|
|
68
95
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
96
|
+
### `fetchAndParse(url: string): Promise<ParsedFeed>`
|
|
97
|
+
|
|
98
|
+
Fetch and parse a feed from URL.
|
|
99
|
+
|
|
100
|
+
**Parameters:**
|
|
101
|
+
- `url` - Feed URL to fetch
|
|
102
|
+
|
|
103
|
+
**Returns:**
|
|
104
|
+
- Promise resolving to `ParsedFeed` object
|
|
75
105
|
|
|
76
106
|
### `detectFormat(source: Buffer | string | Uint8Array): string`
|
|
77
107
|
|
|
78
108
|
Detect feed format without full parsing.
|
|
79
109
|
|
|
80
|
-
**Parameters:**
|
|
81
|
-
- `source` - Feed content as Buffer, string, or Uint8Array
|
|
82
|
-
|
|
83
110
|
**Returns:**
|
|
84
111
|
- Format string: `"rss20"`, `"atom10"`, `"json11"`, etc.
|
|
85
112
|
|
|
86
|
-
**Example:**
|
|
87
113
|
```javascript
|
|
88
114
|
const format = detectFormat('<feed xmlns="http://www.w3.org/2005/Atom">...</feed>');
|
|
89
115
|
console.log(format); // "atom10"
|
|
@@ -114,22 +140,11 @@ interface FeedMeta {
|
|
|
114
140
|
link?: string;
|
|
115
141
|
links: Link[];
|
|
116
142
|
subtitle?: string;
|
|
117
|
-
subtitle_detail?: TextConstruct;
|
|
118
143
|
updated?: number; // Milliseconds since epoch
|
|
119
144
|
author?: string;
|
|
120
|
-
author_detail?: Person;
|
|
121
145
|
authors: Person[];
|
|
122
|
-
contributors: Person[];
|
|
123
|
-
publisher?: string;
|
|
124
|
-
publisher_detail?: Person;
|
|
125
146
|
language?: string;
|
|
126
|
-
rights?: string;
|
|
127
|
-
rights_detail?: TextConstruct;
|
|
128
|
-
generator?: string;
|
|
129
|
-
generator_detail?: Generator;
|
|
130
147
|
image?: Image;
|
|
131
|
-
icon?: string;
|
|
132
|
-
logo?: string;
|
|
133
148
|
tags: Tag[];
|
|
134
149
|
id?: string;
|
|
135
150
|
ttl?: number;
|
|
@@ -142,94 +157,21 @@ interface FeedMeta {
|
|
|
142
157
|
interface Entry {
|
|
143
158
|
id?: string;
|
|
144
159
|
title?: string;
|
|
145
|
-
title_detail?: TextConstruct;
|
|
146
160
|
link?: string;
|
|
147
161
|
links: Link[];
|
|
148
162
|
summary?: string;
|
|
149
|
-
summary_detail?: TextConstruct;
|
|
150
163
|
content: Content[];
|
|
151
164
|
published?: number; // Milliseconds since epoch
|
|
152
165
|
updated?: number;
|
|
153
|
-
created?: number;
|
|
154
|
-
expired?: number;
|
|
155
166
|
author?: string;
|
|
156
|
-
author_detail?: Person;
|
|
157
167
|
authors: Person[];
|
|
158
|
-
contributors: Person[];
|
|
159
|
-
publisher?: string;
|
|
160
|
-
publisher_detail?: Person;
|
|
161
168
|
tags: Tag[];
|
|
162
169
|
enclosures: Enclosure[];
|
|
163
|
-
comments?: string;
|
|
164
|
-
source?: Source;
|
|
165
170
|
}
|
|
166
171
|
```
|
|
167
172
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
```typescript
|
|
171
|
-
interface TextConstruct {
|
|
172
|
-
value: string;
|
|
173
|
-
type: "text" | "html" | "xhtml";
|
|
174
|
-
language?: string;
|
|
175
|
-
base?: string;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
interface Link {
|
|
179
|
-
href: string;
|
|
180
|
-
rel?: string;
|
|
181
|
-
type?: string;
|
|
182
|
-
title?: string;
|
|
183
|
-
length?: number;
|
|
184
|
-
hreflang?: string;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
interface Person {
|
|
188
|
-
name?: string;
|
|
189
|
-
email?: string;
|
|
190
|
-
uri?: string;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
interface Tag {
|
|
194
|
-
term: string;
|
|
195
|
-
scheme?: string;
|
|
196
|
-
label?: string;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
interface Image {
|
|
200
|
-
url: string;
|
|
201
|
-
title?: string;
|
|
202
|
-
link?: string;
|
|
203
|
-
width?: number;
|
|
204
|
-
height?: number;
|
|
205
|
-
description?: string;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
interface Enclosure {
|
|
209
|
-
url: string;
|
|
210
|
-
length?: number;
|
|
211
|
-
type?: string;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
interface Content {
|
|
215
|
-
value: string;
|
|
216
|
-
type?: string;
|
|
217
|
-
language?: string;
|
|
218
|
-
base?: string;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
interface Generator {
|
|
222
|
-
value: string;
|
|
223
|
-
uri?: string;
|
|
224
|
-
version?: string;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
interface Source {
|
|
228
|
-
title?: string;
|
|
229
|
-
link?: string;
|
|
230
|
-
id?: string;
|
|
231
|
-
}
|
|
232
|
-
```
|
|
173
|
+
> [!NOTE]
|
|
174
|
+
> See `index.d.ts` for complete type definitions including `Link`, `Person`, `Tag`, `Image`, `Enclosure`, and more.
|
|
233
175
|
|
|
234
176
|
## Error Handling
|
|
235
177
|
|
|
@@ -248,11 +190,9 @@ console.log(feed.feed.title); // "Broken"
|
|
|
248
190
|
|
|
249
191
|
## Dates
|
|
250
192
|
|
|
251
|
-
All date fields are returned as milliseconds since Unix epoch
|
|
193
|
+
All date fields are returned as milliseconds since Unix epoch. Convert to JavaScript Date:
|
|
252
194
|
|
|
253
195
|
```javascript
|
|
254
|
-
const feed = parse(xmlWithDates);
|
|
255
|
-
|
|
256
196
|
const entry = feed.entries[0];
|
|
257
197
|
if (entry.published) {
|
|
258
198
|
const date = new Date(entry.published);
|
|
@@ -269,16 +209,17 @@ Benchmarks vs Python feedparser (parsing 100KB RSS feed):
|
|
|
269
209
|
| feedparser-rs | 0.5ms | 100x |
|
|
270
210
|
| feedparser (Python) | 50ms | 1x |
|
|
271
211
|
|
|
272
|
-
See [benchmarks/](../../benchmarks/) for detailed results and methodology.
|
|
273
|
-
|
|
274
212
|
## Platform Support
|
|
275
213
|
|
|
276
214
|
Pre-built binaries available for:
|
|
277
|
-
- macOS (Intel & Apple Silicon)
|
|
278
|
-
- Linux (x64, ARM64)
|
|
279
|
-
- Windows (x64)
|
|
280
215
|
|
|
281
|
-
|
|
216
|
+
| Platform | Architecture |
|
|
217
|
+
|----------|--------------|
|
|
218
|
+
| macOS | Intel (x64), Apple Silicon (arm64) |
|
|
219
|
+
| Linux | x64, arm64 |
|
|
220
|
+
| Windows | x64 |
|
|
221
|
+
|
|
222
|
+
Supported Node.js versions: 18, 20, 22+
|
|
282
223
|
|
|
283
224
|
## Development
|
|
284
225
|
|
|
@@ -291,15 +232,23 @@ npm run build
|
|
|
291
232
|
|
|
292
233
|
# Run tests
|
|
293
234
|
npm test
|
|
235
|
+
|
|
236
|
+
# Run tests with coverage
|
|
237
|
+
npm run test:coverage
|
|
294
238
|
```
|
|
295
239
|
|
|
296
240
|
## License
|
|
297
241
|
|
|
298
|
-
|
|
242
|
+
Licensed under either of:
|
|
243
|
+
|
|
244
|
+
- [Apache License, Version 2.0](../../LICENSE-APACHE)
|
|
245
|
+
- [MIT License](../../LICENSE-MIT)
|
|
246
|
+
|
|
247
|
+
at your option.
|
|
299
248
|
|
|
300
249
|
## Links
|
|
301
250
|
|
|
302
251
|
- [GitHub](https://github.com/bug-ops/feedparser-rs)
|
|
303
252
|
- [npm](https://www.npmjs.com/package/feedparser-rs)
|
|
304
|
-
- [Documentation](https://docs.rs/feedparser-rs
|
|
253
|
+
- [Rust API Documentation](https://docs.rs/feedparser-rs)
|
|
305
254
|
- [Changelog](../../CHANGELOG.md)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "feedparser-rs",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "High-performance RSS/Atom/JSON Feed parser for Node.js",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -46,12 +46,5 @@
|
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@napi-rs/cli": "^3.5",
|
|
48
48
|
"c8": "^10.1.3"
|
|
49
|
-
},
|
|
50
|
-
"optionalDependencies": {
|
|
51
|
-
"feedparser-rs-darwin-x64": "0.1.8",
|
|
52
|
-
"feedparser-rs-darwin-arm64": "0.1.8",
|
|
53
|
-
"feedparser-rs-linux-x64-gnu": "0.1.8",
|
|
54
|
-
"feedparser-rs-linux-arm64-gnu": "0.1.8",
|
|
55
|
-
"feedparser-rs-win32-x64-msvc": "0.1.8"
|
|
56
49
|
}
|
|
57
50
|
}
|