Initial commit of working RSS Aggregator build
This commit is contained in:
1 parent
ea3a2ca53e
commit
7ac2f6e384
4962 files changed
+1032666
No files matched your search
+24
@@ -0,0 +1,24 @@
|
||||
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
||||
|
||||
name: tests
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [14.x, 16.x, 18.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- run: npm ci
|
||||
- run: npm test
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
dist: trusty
|
||||
|
||||
language: node_js
|
||||
node_js:
|
||||
- "8"
|
||||
|
||||
before_script:
|
||||
- npm install -g mocha
|
||||
script: npm test
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libnss3
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2016 Bobby Brennan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+271
@@ -0,0 +1,271 @@
|
||||
# rss-parser
|
||||
|
||||
[![Version][npm-image]][npm-link]
|
||||
[![Build Status][build-image]][build-link]
|
||||
[![Downloads][downloads-image]][npm-link]
|
||||
|
||||
[downloads-image]: https://img.shields.io/npm/dm/rss-parser.svg
|
||||
[npm-image]: https://img.shields.io/npm/v/rss-parser.svg
|
||||
[npm-link]: https://npmjs.org/package/rss-parser
|
||||
[build-image]: https://github.com/rbren/rss-parser/workflows/tests/badge.svg
|
||||
[build-link]: https://github.com/rbren/rss-parser/actions
|
||||
|
||||
A small library for turning RSS XML feeds into JavaScript objects.
|
||||
|
||||
## Installation
|
||||
```bash
|
||||
npm install --save rss-parser
|
||||
```
|
||||
|
||||
## Usage
|
||||
You can parse RSS from a URL (`parser.parseURL`) or an XML string (`parser.parseString`).
|
||||
|
||||
Both callbacks and Promises are supported.
|
||||
|
||||
### NodeJS
|
||||
Here's an example in NodeJS using Promises with async/await:
|
||||
|
||||
```js
|
||||
let Parser = require('rss-parser');
|
||||
let parser = new Parser();
|
||||
|
||||
(async () => {
|
||||
|
||||
let feed = await parser.parseURL('https://www.reddit.com/.rss');
|
||||
console.log(feed.title);
|
||||
|
||||
feed.items.forEach(item => {
|
||||
console.log(item.title + ':' + item.link)
|
||||
});
|
||||
|
||||
})();
|
||||
```
|
||||
|
||||
### TypeScript
|
||||
When using TypeScript, you can set a type to control the custom fields:
|
||||
|
||||
```typescript
|
||||
import Parser from 'rss-parser';
|
||||
|
||||
type CustomFeed = {foo: string};
|
||||
type CustomItem = {bar: number};
|
||||
|
||||
const parser: Parser<CustomFeed, CustomItem> = new Parser({
|
||||
customFields: {
|
||||
feed: ['foo', 'baz'],
|
||||
// ^ will error because `baz` is not a key of CustomFeed
|
||||
item: ['bar']
|
||||
}
|
||||
});
|
||||
|
||||
(async () => {
|
||||
|
||||
const feed = await parser.parseURL('https://www.reddit.com/.rss');
|
||||
console.log(feed.title); // feed will have a `foo` property, type as a string
|
||||
|
||||
feed.items.forEach(item => {
|
||||
console.log(item.title + ':' + item.link) // item will have a `bar` property type as a number
|
||||
});
|
||||
})();
|
||||
```
|
||||
|
||||
### Web
|
||||
> We recommend using a bundler like [webpack](https://webpack.js.org/), but we also provide
|
||||
> pre-built browser distributions in the `dist/` folder. If you use the pre-built distribution,
|
||||
> you'll need a [polyfill](https://github.com/taylorhakes/promise-polyfill) for Promise support.
|
||||
|
||||
Here's an example in the browser using callbacks:
|
||||
|
||||
```html
|
||||
<script src="/node_modules/rss-parser/dist/rss-parser.min.js"></script>
|
||||
<script>
|
||||
|
||||
// Note: some RSS feeds can't be loaded in the browser due to CORS security.
|
||||
// To get around this, you can use a proxy.
|
||||
const CORS_PROXY = "https://cors-anywhere.herokuapp.com/"
|
||||
|
||||
let parser = new RSSParser();
|
||||
parser.parseURL(CORS_PROXY + 'https://www.reddit.com/.rss', function(err, feed) {
|
||||
if (err) throw err;
|
||||
console.log(feed.title);
|
||||
feed.items.forEach(function(entry) {
|
||||
console.log(entry.title + ':' + entry.link);
|
||||
})
|
||||
})
|
||||
|
||||
</script>
|
||||
```
|
||||
|
||||
### Upgrading from v2 to v3
|
||||
A few minor breaking changes were made in v3. Here's what you need to know:
|
||||
|
||||
* You need to construct a `new Parser()` before calling `parseString` or `parseURL`
|
||||
* `parseFile` is no longer available (for better browser support)
|
||||
* `options` are now passed to the Parser constructor
|
||||
* `parsed.feed` is now just `feed` (top-level object removed)
|
||||
* `feed.entries` is now `feed.items` (to better match RSS XML)
|
||||
|
||||
|
||||
## Output
|
||||
Check out the full output format in [test/output/reddit.json](test/output/reddit.json)
|
||||
|
||||
```yaml
|
||||
feedUrl: 'https://www.reddit.com/.rss'
|
||||
title: 'reddit: the front page of the internet'
|
||||
description: ""
|
||||
link: 'https://www.reddit.com/'
|
||||
items:
|
||||
- title: 'The water is too deep, so he improvises'
|
||||
link: 'https://www.reddit.com/r/funny/comments/3skxqc/the_water_is_too_deep_so_he_improvises/'
|
||||
pubDate: 'Thu, 12 Nov 2015 21:16:39 +0000'
|
||||
creator: "John Doe"
|
||||
content: '<a href="http://example.com">this is a link</a> & <b>this is bold text</b>'
|
||||
contentSnippet: 'this is a link & this is bold text'
|
||||
guid: 'https://www.reddit.com/r/funny/comments/3skxqc/the_water_is_too_deep_so_he_improvises/'
|
||||
categories:
|
||||
- funny
|
||||
isoDate: '2015-11-12T21:16:39.000Z'
|
||||
```
|
||||
|
||||
##### Notes:
|
||||
* The `contentSnippet` field strips out HTML tags and unescapes HTML entities
|
||||
* The `dc:` prefix will be removed from all fields
|
||||
* Both `dc:date` and `pubDate` will be available in ISO 8601 format as `isoDate`
|
||||
* If `author` is specified, but not `dc:creator`, `creator` will be set to `author` ([see article](http://www.lowter.com/blogs/2008/2/9/rss-dccreator-author))
|
||||
* Atom's `updated` becomes `lastBuildDate` for consistency
|
||||
|
||||
## XML Options
|
||||
|
||||
### Custom Fields
|
||||
If your RSS feed contains fields that aren't currently returned, you can access them using the `customFields` option.
|
||||
|
||||
```js
|
||||
let parser = new Parser({
|
||||
customFields: {
|
||||
feed: ['otherTitle', 'extendedDescription'],
|
||||
item: ['coAuthor','subtitle'],
|
||||
}
|
||||
});
|
||||
|
||||
parser.parseURL('https://www.reddit.com/.rss', function(err, feed) {
|
||||
console.log(feed.extendedDescription);
|
||||
|
||||
feed.items.forEach(function(entry) {
|
||||
console.log(entry.coAuthor + ':' + entry.subtitle);
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
To rename fields, you can pass in an array with two items, in the format `[fromField, toField]`:
|
||||
|
||||
```js
|
||||
let parser = new Parser({
|
||||
customFields: {
|
||||
item: [
|
||||
['dc:coAuthor', 'coAuthor'],
|
||||
]
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
To pass additional flags, provide an object as the third array item. Currently there is one such flag:
|
||||
|
||||
* `keepArray (false)` - set to `true` to return *all* values for fields that can have multiple entries.
|
||||
* `includeSnippet (false)` - set to `true` to add an additional field, `${toField}Snippet`, with HTML stripped out
|
||||
|
||||
```js
|
||||
let parser = new Parser({
|
||||
customFields: {
|
||||
item: [
|
||||
['media:content', 'media:content', {keepArray: true}],
|
||||
]
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### Default RSS version
|
||||
If your RSS Feed doesn't contain a `<rss>` tag with a `version` attribute,
|
||||
you can pass a `defaultRSS` option for the Parser to use:
|
||||
```js
|
||||
let parser = new Parser({
|
||||
defaultRSS: 2.0
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
### xml2js passthrough
|
||||
`rss-parser` uses [xml2js](https://github.com/Leonidas-from-XIV/node-xml2js)
|
||||
to parse XML. You can pass [these options](https://github.com/Leonidas-from-XIV/node-xml2js#options)
|
||||
to `new xml2js.Parser()` by specifying `options.xml2js`:
|
||||
|
||||
```js
|
||||
let parser = new Parser({
|
||||
xml2js: {
|
||||
emptyTag: '--EMPTY--',
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## HTTP Options
|
||||
|
||||
### Timeout
|
||||
You can set the amount of time (in milliseconds) to wait before the HTTP request times out (default 60 seconds):
|
||||
|
||||
```js
|
||||
let parser = new Parser({
|
||||
timeout: 1000,
|
||||
});
|
||||
```
|
||||
|
||||
### Headers
|
||||
You can pass headers to the HTTP request:
|
||||
```js
|
||||
let parser = new Parser({
|
||||
headers: {'User-Agent': 'something different'},
|
||||
});
|
||||
```
|
||||
|
||||
### Redirects
|
||||
By default, `parseURL` will follow up to five redirects. You can change this
|
||||
with `options.maxRedirects`.
|
||||
|
||||
```js
|
||||
let parser = new Parser({maxRedirects: 100});
|
||||
```
|
||||
|
||||
### Request passthrough
|
||||
`rss-parser` uses [http](https://nodejs.org/docs/latest/api/http.html#http_http_get_url_options_callback)/[https](https://nodejs.org/docs/latest/api/https.html#https_https_get_url_options_callback) module
|
||||
to do requests. You can pass [these options](https://nodejs.org/docs/latest/api/https.html#https_https_request_options_callback)
|
||||
to `http.get()`/`https.get()` by specifying `options.requestOptions`:
|
||||
|
||||
e.g. to allow unauthorized certificate
|
||||
```js
|
||||
let parser = new Parser({
|
||||
requestOptions: {
|
||||
rejectUnauthorized: false
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Contributing
|
||||
Contributions are welcome! If you are adding a feature or fixing a bug, please be sure to add a [test case](https://github.com/bobby-brennan/rss-parser/tree/master/test/input)
|
||||
|
||||
### Running Tests
|
||||
The tests run the RSS parser for several sample RSS feeds in `test/input` and outputs the resulting JSON into `test/output`. If there are any changes to the output files the tests will fail.
|
||||
|
||||
To check if your changes affect the output of any test cases, run
|
||||
|
||||
`npm test`
|
||||
|
||||
To update the output files with your changes, run
|
||||
|
||||
`WRITE_GOLDEN=true npm test`
|
||||
|
||||
### Publishing Releases
|
||||
```bash
|
||||
npm run build
|
||||
git commit -a -m "Build distribution"
|
||||
npm version minor # or major/patch
|
||||
npm publish
|
||||
git push --follow-tags
|
||||
```
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "rss-parser",
|
||||
"description": "",
|
||||
"version": "1.1.0",
|
||||
"main": "dist/rss-parser.js",
|
||||
"authors": [
|
||||
"Bobby Brennan"
|
||||
],
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/bobby-brennan/rss-parser",
|
||||
"moduleType": [
|
||||
"node"
|
||||
],
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"node_modules",
|
||||
"bower_components",
|
||||
"test",
|
||||
"tests"
|
||||
]
|
||||
}
|
||||
+11002
File diff suppressed because it is too large.
Load diff
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["webpack://RSSParser/webpack/universalModuleDefinition","webpack://RSSParser/webpack/bootstrap","webpack://RSSParser/./index.js","webpack://RSSParser/./lib/fields.js","webpack://RSSParser/./lib/parser.js","webpack://RSSParser/./lib/utils.js","webpack://RSSParser/./node_modules/base64-js/index.js","webpack://RSSParser/./node_modules/buffer/index.js","webpack://RSSParser/./node_modules/builtin-status-codes/browser.js","webpack://RSSParser/./node_modules/core-util-is/lib/util.js","webpack://RSSParser/./node_modules/entities/lib/decode.js","webpack://RSSParser/./node_modules/entities/lib/decode_codepoint.js","webpack://RSSParser/./node_modules/entities/lib/encode.js","webpack://RSSParser/./node_modules/entities/lib/index.js","webpack://RSSParser/./node_modules/events/events.js","webpack://RSSParser/./node_modules/https-browserify/index.js","webpack://RSSParser/./node_modules/ieee754/index.js","webpack://RSSParser/./node_modules/inherits/inherits_browser.js","webpack://RSSParser/./node_modules/isarray/index.js","webpack://RSSParser/./node_modules/node-libs-browser/node_modules/punycode/punycode.js","webpack://RSSParser/./node_modules/process-nextick-args/index.js","webpack://RSSParser/./node_modules/process/browser.js","webpack://RSSParser/./node_modules/querystring-es3/decode.js","webpack://RSSParser/./node_modules/querystring-es3/encode.js","webpack://RSSParser/./node_modules/querystring-es3/index.js","webpack://RSSParser/./node_modules/readable-stream/duplex-browser.js","webpack://RSSParser/./node_modules/readable-stream/lib/_stream_duplex.js","webpack://RSSParser/./node_modules/readable-stream/lib/_stream_passthrough.js","webpack://RSSParser/./node_modules/readable-stream/lib/_stream_readable.js","webpack://RSSParser/./node_modules/readable-stream/lib/_stream_transform.js","webpack://RSSParser/./node_modules/readable-stream/lib/_stream_writable.js","webpack://RSSParser/./node_modules/readable-stream/lib/internal/streams/BufferList.js","webpack://RSSParser/./node_modules/readable-stream/lib/internal/streams/destroy.js","webpack://RSSParser/./node_modules/readable-stream/lib/internal/streams/stream-browser.js","webpack://RSSParser/./node_modules/readable-stream/passthrough.js","webpack://RSSParser/./node_modules/readable-stream/readable-browser.js","webpack://RSSParser/./node_modules/readable-stream/transform.js","webpack://RSSParser/./node_modules/readable-stream/writable-browser.js","webpack://RSSParser/./node_modules/safe-buffer/index.js","webpack://RSSParser/./node_modules/sax/lib/sax.js","webpack://RSSParser/./node_modules/setimmediate/setImmediate.js","webpack://RSSParser/./node_modules/stream-browserify/index.js","webpack://RSSParser/./node_modules/stream-http/index.js","webpack://RSSParser/./node_modules/stream-http/lib/capability.js","webpack://RSSParser/./node_modules/stream-http/lib/request.js","webpack://RSSParser/./node_modules/stream-http/lib/response.js","webpack://RSSParser/./node_modules/string_decoder/lib/string_decoder.js","webpack://RSSParser/./node_modules/timers-browserify/main.js","webpack://RSSParser/./node_modules/to-arraybuffer/index.js","webpack://RSSParser/./node_modules/url/url.js","webpack://RSSParser/./node_modules/url/util.js","webpack://RSSParser/./node_modules/util-deprecate/browser.js","webpack://RSSParser/(webpack)/buildin/amd-options.js","webpack://RSSParser/(webpack)/buildin/global.js","webpack://RSSParser/(webpack)/buildin/module.js","webpack://RSSParser/./node_modules/xml2js/lib/bom.js","webpack://RSSParser/./node_modules/xml2js/lib/builder.js","webpack://RSSParser/./node_modules/xml2js/lib/defaults.js","webpack://RSSParser/./node_modules/xml2js/lib/parser.js","webpack://RSSParser/./node_modules/xml2js/lib/processors.js","webpack://RSSParser/./node_modules/xml2js/lib/xml2js.js","webpack://RSSParser/./node_modules/xtend/immutable.js","webpack://RSSParser/util (ignored)","webpack://RSSParser/util (ignored)?f534","webpack://RSSParser/external \"xmlbuilder\""],"names":["module","exports","require","fields","feed","item","includeSnippet","mapItunesField","f","podcastFeed","map","podcastItem","_typeof","obj","Symbol","iterator","constructor","prototype","_classCallCheck","instance","Constructor","TypeError","_defineProperties","target","props","i","length","descriptor","enumerable","configurable","writable","Object","defineProperty","_toPropertyKey","key","_createClass","protoProps","staticProps","arg","_toPrimitive","String","input","hint","prim","toPrimitive","undefined","res","call","Number","http","https","xml2js","url","utils","DEFAULT_HEADERS","DEFAULT_MAX_REDIRECTS","DEFAULT_TIMEOUT","Parser","options","arguments","headers","customFields","requestOptions","maxRedirects","timeout","xmlParser","value","parseString","xml","callback","_this","prom","Promise","resolve","reject","err","result","Error","buildAtomFeed","rss","$","version","match","buildRSS2","buildRSS1","buildRSS0_9","defaultRSS","maybePromisify","parseURL","feedUrl","_this2","redirectCLine truncated
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("xmlbuilder")):"function"==typeof define&&define.amd?define(["xmlbuilder"],e):"object"==typeof exports?exports.RSSParser=e(require("xmlbuilder")):t.RSSParser=e(t.xmlbuilder)}(this,(function(t){return function(t){var e={};function r(n){if(e[n])return e[n].exports;var i=e[n]={i:n,l:!1,exports:{}};return t[n].call(i.exports,i,i.exports,r),i.l=!0,i.exports}return r.m=t,r.c=e,r.d=function(t,e,n){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(t,e){if(1&e&&(t=r(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var i in t)r.d(n,i,function(e){return t[e]}.bind(null,i));return n},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="",r(r.s=30)}([function(t,e){function r(t){return(r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(t){"object"===("undefined"==typeof window?"undefined":r(window))&&(n=window)}t.exports=n},function(t,e){"function"==typeof Object.create?t.exports=function(t,e){t.super_=e,t.prototype=Object.create(e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}})}:t.exports=function(t,e){t.super_=e;var r=function(){};r.prototype=e.prototype,t.prototype=new r,t.prototype.constructor=t}},function(t,e,r){"use strict";var n=r(7),i=Object.keys||function(t){var e=[];for(var r in t)e.push(r);return e};t.exports=h;var o=r(6);o.inherits=r(1);var s=r(18),a=r(10);o.inherits(h,s);for(var u=i(a.prototype),c=0;c<u.length;c++){var l=u[c];h.prototype[l]||(h.prototype[l]=a.prototype[l])}function h(t){if(!(this instanceof h))return new h(t);s.call(this,t),a.call(this,t),t&&!1===t.readable&&(this.readable=!1),t&&!1===t.writable&&(this.writable=!1),this.allowHalfOpen=!0,t&&!1===t.allowHalfOpen&&(this.allowHalfOpen=!1),this.once("end",f)}function f(){this.allowHalfOpen||this._writableState.ended||n.nextTick(p,this)}function p(t){t.end()}Object.defineProperty(h.prototype,"writableHighWaterMark",{enumerable:!1,get:function(){return this._writableState.highWaterMark}}),Object.defineProperty(h.prototype,"destroyed",{get:function(){return void 0!==this._readableState&&void 0!==this._writableState&&(this._readableState.destroyed&&this._writableState.destroyed)},set:function(t){void 0!==this._readableState&&void 0!==this._writableState&&(this._readableState.destroyed=t,this._writableState.destroyed=t)}}),h.prototype._destroy=function(t,e){this.push(null),this.end(),n.nextTick(e,t)}},function(t,e,r){"use strict";(function(t){
|
||||
/*!
|
||||
* The buffer module from node.js, for the browser.
|
||||
*
|
||||
* @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
|
||||
* @license MIT
|
||||
*/
|
||||
var n=r(33),i=r(34),o=r(15);function s(){return u.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function a(t,e){if(s()<e)throw new RangeError("Invalid typed array length");return u.TYPED_ARRAY_SUPPORT?(t=new Uint8Array(e)).__proto__=u.prototype:(null===t&&(t=new u(e)),t.length=e),t}function u(t,e,r){if(!(u.TYPED_ARRAY_SUPPORT||this instanceof u))return new u(t,e,r);if("number"==typeof t){if("string"==typeof e)throw new Error("If encoding is specified then the first argument must be a string");return h(this,t)}return c(this,t,e,r)}function c(t,e,r,n){if("number"==typeof e)throw new TypeError('"value" argument must not be a number');return"undefined"!=typeof ArrayBuffer&&e instanceof ArrayBuffer?function(t,e,r,n){if(e.byteLength,r<0||e.byteLength<r)throw new RangeError("'offset' is out of bounds");if(e.byteLength<r+(n||0))throw new RangeError("'length' is out of bounds");e=void 0===r&&void 0===n?new Uint8Array(e):void 0===n?new Uint8Array(e,r):new Uint8Array(e,r,n);u.TYPED_ARRAY_SUPPORT?(t=e).__proto__=u.prototype:t=f(t,e);return t}(t,e,r,n):"string"==typeof e?function(t,e,r){"string"==typeof r&&""!==r||(r="utf8");if(!u.isEncoding(r))throw new TypeError('"encoding" must be a valid string encoding');var n=0|d(e,r),i=(t=a(t,n)).write(e,r);i!==n&&(t=t.slice(0,i));return t}(t,e,r):function(t,e){if(u.isBuffer(e)){var r=0|p(e.length);return 0===(t=a(t,r)).length||e.copy(t,0,0,r),t}if(e){if("undefined"!=typeof ArrayBuffer&&e.buffer instanceof ArrayBuffer||"length"in e)return"number"!=typeof e.length||(n=e.length)!=n?a(t,0):f(t,e);if("Buffer"===e.type&&o(e.data))return f(t,e.data)}var n;throw new TypeError("First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.")}(t,e)}function l(t){if("number"!=typeof t)throw new TypeError('"size" argument must be a number');if(t<0)throw new RangeError('"size" argument must not be negative')}function h(t,e){if(l(e),t=a(t,e<0?0:0|p(e)),!u.TYPED_ARRAY_SUPPORT)for(var r=0;r<e;++r)t[r]=0;return t}function f(t,e){var r=e.length<0?0:0|p(e.length);t=a(t,r);for(var n=0;n<r;n+=1)t[n]=255&e[n];return t}function p(t){if(t>=s())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+s().toString(16)+" bytes");return 0|t}function d(t,e){if(u.isBuffer(t))return t.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(t)||t instanceof ArrayBuffer))return t.byteLength;"string"!=typeof t&&(t=""+t);var r=t.length;if(0===r)return 0;for(var n=!1;;)switch(e){case"ascii":case"latin1":case"binary":return r;case"utf8":case"utf-8":case void 0:return j(t).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*r;case"hex":return r>>>1;case"base64":return F(t).length;default:if(n)return j(t).length;e=(""+e).toLowerCase(),n=!0}}function m(t,e,r){var n=!1;if((void 0===e||e<0)&&(e=0),e>this.length)return"";if((void 0===r||r>this.length)&&(r=this.length),r<=0)return"";if((r>>>=0)<=(e>>>=0))return"";for(t||(t="utf8");;)switch(t){case"hex":return O(this,e,r);case"utf8":case"utf-8":return x(this,e,r);case"ascii":return R(this,e,r);case"latin1":case"binary":return C(this,e,r);case"base64":return A(this,e,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return N(this,e,r);default:if(n)throw new TypeError("Unknown encoding: "+t);t=(t+"").toLowerCase(),n=!0}}function g(t,e,r){var n=t[e];t[e]=t[r],t[r]=n}function y(t,e,r,n,i){if(0===t.length)return-1;if("string"==typeof r?(n=r,r=0):r>2147483647?r=2147483647:r<-2147483648&&(r=-2147483648),r=+r,isNaN(r)&&(r=i?0:t.length-1),r<0&&(r=t.length+r),r>=t.length){if(i)return-1;r=t.length-1}else if(r<0){if(!i)return-1;r=0}if("string"==typeof e&&(e=u.from(e,n)),u.isBuffer(e))return 0===e.length?-1:b(t,e,r,n,i);if("number"==typeof e)return e&=255,u.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?i?Uint8Array.prototype.indexOf.call(t,e,r):Uint8Array.prototype.lastIndexOf.call(t,e,r):b(t,[e],r,n,i);throw new TypeError("val must be string, number or Buffer")}function b(t,e,r,n,i){var o,s=1,a=t.length,u=e.length;if(void 0!==n&&("ucs2"===(n=String(n).toLowerCase())||"ucs-2"===n||"utf16le"===n||"utf-16le"===n)){if(t.length<2||e.length<2)return-1;s=2,a/=2,u/=2,r/=2}function c(t,e){return 1===s?t[e]:t.readUInt16BE(e*s)}if(i){var l=-1;for(o=r;o<a;o++)if(c(t,o)===c(e,-1===l?0:o-l)){if(-1===l&&(l=o),o-l+1===u)return l*s}else-1!==l&&(o-=o-l),l=-1}else for(r+u>a&&(r=a-u),o=r;o>=0;o--){for(var h=!0,f=0;f<u;f++)if(c(t,o+f)!==c(e,f)){h=!1;break}if(h)return o}return-1}function v(t,e,r,n){r=Number(r)||0;var i=t.length-r;n?(n=Number(n))>i&&(n=i):n=i;var o=e.length;if(o%2!=0)throw new TypeError("Invalid hex string");n>o/2&&(n=o/2);for(var s=0;s<n;++s){var a=parseInt(e.substr(2*s,2),16);if(isNaN(a))return s;t[r+s]=a}return s}function w(t,e,r,n){return H(j(e,t.length-r),t,r,n)}function T(t,e,r,n){return H(function(t){for(var e=[],r=0;r<t.length;++r)e.push(255&t.charCodeAt(r));return e}(e),t,r,n)}function E(t,e,r,n){return T(t,e,r,n)}function _(t,e,r,n){return H(F(e),t,r,n)}Line truncated
|
||||
/*! https://mths.be/punycode v1.4.1 by @mathias */!function(s){var a="object"==o(e)&&e&&!e.nodeType&&e,u="object"==o(t)&&t&&!t.nodeType&&t,c="object"==(void 0===n?"undefined":o(n))&&n;c.global!==c&&c.window!==c&&c.self!==c||(s=c);var l,h,f=2147483647,p=/^xn--/,d=/[^\x20-\x7E]/,m=/[\x2E\u3002\uFF0E\uFF61]/g,g={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},y=Math.floor,b=String.fromCharCode;function v(t){throw new RangeError(g[t])}function w(t,e){for(var r=t.length,n=[];r--;)n[r]=e(t[r]);return n}function T(t,e){var r=t.split("@"),n="";return r.length>1&&(n=r[0]+"@",t=r[1]),n+w((t=t.replace(m,".")).split("."),e).join(".")}function E(t){for(var e,r,n=[],i=0,o=t.length;i<o;)(e=t.charCodeAt(i++))>=55296&&e<=56319&&i<o?56320==(64512&(r=t.charCodeAt(i++)))?n.push(((1023&e)<<10)+(1023&r)+65536):(n.push(e),i--):n.push(e);return n}function _(t){return w(t,(function(t){var e="";return t>65535&&(e+=b((t-=65536)>>>10&1023|55296),t=56320|1023&t),e+=b(t)})).join("")}function S(t,e){return t+22+75*(t<26)-((0!=e)<<5)}function A(t,e,r){var n=0;for(t=r?y(t/700):t>>1,t+=y(t/e);t>455;n+=36)t=y(t/35);return y(n+36*t/(t+38))}function x(t){var e,r,n,i,o,s,a,u,c,l,h,p=[],d=t.length,m=0,g=128,b=72;for((r=t.lastIndexOf("-"))<0&&(r=0),n=0;n<r;++n)t.charCodeAt(n)>=128&&v("not-basic"),p.push(t.charCodeAt(n));for(i=r>0?r+1:0;i<d;){for(o=m,s=1,a=36;i>=d&&v("invalid-input"),((u=(h=t.charCodeAt(i++))-48<10?h-22:h-65<26?h-65:h-97<26?h-97:36)>=36||u>y((f-m)/s))&&v("overflow"),m+=u*s,!(u<(c=a<=b?1:a>=b+26?26:a-b));a+=36)s>y(f/(l=36-c))&&v("overflow"),s*=l;b=A(m-o,e=p.length+1,0==o),y(m/e)>f-g&&v("overflow"),g+=y(m/e),m%=e,p.splice(m++,0,g)}return _(p)}function R(t){var e,r,n,i,o,s,a,u,c,l,h,p,d,m,g,w=[];for(p=(t=E(t)).length,e=128,r=0,o=72,s=0;s<p;++s)(h=t[s])<128&&w.push(b(h));for(n=i=w.length,i&&w.push("-");n<p;){for(a=f,s=0;s<p;++s)(h=t[s])>=e&&h<a&&(a=h);for(a-e>y((f-r)/(d=n+1))&&v("overflow"),r+=(a-e)*d,e=a,s=0;s<p;++s)if((h=t[s])<e&&++r>f&&v("overflow"),h==e){for(u=r,c=36;!(u<(l=c<=o?1:c>=o+26?26:c-o));c+=36)g=u-l,m=36-l,w.push(b(S(l+g%m,0))),u=y(g/m);w.push(b(S(u,0))),o=A(r,d,n==i),r=0,++n}++r,++e}return w.join("")}if(l={version:"1.4.1",ucs2:{decode:E,encode:_},decode:x,encode:R,toASCII:function(t){return T(t,(function(t){return d.test(t)?"xn--"+R(t):t}))},toUnicode:function(t){return T(t,(function(t){return p.test(t)?x(t.slice(4).toLowerCase()):t}))}},"object"==o(r(23))&&r(23))void 0===(i=function(){return l}.call(e,r,e,t))||(t.exports=i);else if(a&&u)if(t.exports==a)u.exports=l;else for(h in l)l.hasOwnProperty(h)&&(a[h]=l[h]);else s.punycode=l}(this)}).call(this,r(45)(t),r(0))},function(t,e){t.exports=function(t){return t.webpackPolyfill||(t.deprecate=function(){},t.paths=[],t.children||(t.children=[]),Object.defineProperty(t,"loaded",{enumerable:!0,get:function(){return t.l}}),Object.defineProperty(t,"id",{enumerable:!0,get:function(){return t.i}}),t.webpackPolyfill=1),t}},function(t,e,r){"use strict";function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}t.exports={isString:function(t){return"string"==typeof t},isObject:function(t){return"object"===n(t)&&null!==t},isNull:function(t){return null===t},isNullOrUndefined:function(t){return null==t}}},function(t,e,r){"use strict";e.decode=e.parse=r(48),e.encode=e.stringify=r(49)},function(t,e,r){"use strict";function n(t,e){return Object.prototype.hasOwnProperty.call(t,e)}t.exports=function(t,e,r,o){e=e||"&",r=r||"=";var s={};if("string"!=typeof t||0===t.length)return s;var a=/\+/g;t=t.split(e);var u=1e3;o&&"number"==typeof o.maxKeys&&(u=o.maxKeys);var c=t.length;u>0&&c>u&&(c=u);for(var l=0;l<c;++l){var h,f,p,d,m=t[l].replace(a,"%20"),g=m.indexOf(r);g>=0?(h=m.substr(0,g),f=m.substr(g+1)):(h=m,f=""),p=decodeURIComponent(h),d=decodeURIComponent(f),n(s,p)?i(s[p])?s[p].push(d):s[p]=[s[p],d]:s[p]=d}return s};var i=Array.isArray||function(t){return"[object Array]"===Object.prototype.toString.call(t)}},function(t,e,r){"use strict";function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var i=function(t){switch(n(t)){case"string":return t;case"boolean":return t?"true":"false";case"number":return isFinite(t)?t:"";default:return""}};t.exports=function(t,e,r,u){return e=e||"&",r=r||"=",null===t&&(t=void 0),"object"===n(t)?s(a(t),(function(n){var a=encodeURIComponent(i(n))+r;return o(t[n])?s(t[n],(function(t){return a+encodeURIComponent(i(t))})).join(e):a+encodeURIComponent(i(t[n]))})).join(e):u?encodeURIComponent(i(u))+r+encodeURIComponent(i(t)):""};var o=Array.isArray||function(t){return"[object Array]"===Object.prototype.toString.call(t)};function s(Line truncated
|
||||
/*! http://mths.be/fromcodepoint v0.1.0 by @mathias */,resume:function(){return this.error=null,this},close:function(){return this.write(null)},flush:function(){var t;R(t=this),""!==t.cdata&&(x(t,"oncdata",t.cdata),t.cdata=""),""!==t.script&&(x(t,"onscript",t.script),t.script="")}};try{i=r(55).Stream}catch(t){i=function(){}}var a=e.EVENTS.filter((function(t){return"error"!==t&&"end"!==t}));function u(t,e){if(!(this instanceof u))return new u(t,e);i.apply(this),this._parser=new s(t,e),this.writable=!0,this.readable=!0;var r=this;this._parser.onend=function(){r.emit("end")},this._parser.onerror=function(t){r.emit("error",t),r._parser.error=null},this._decoder=null,a.forEach((function(t){Object.defineProperty(r,"on"+t,{get:function(){return r._parser["on"+t]},set:function(e){if(!e)return r.removeAllListeners(t),r._parser["on"+t]=e,e;r.on(t,e)},enumerable:!0,configurable:!1})}))}u.prototype=Object.create(i.prototype,{constructor:{value:u}}),u.prototype.write=function(e){if("function"==typeof t&&"function"==typeof t.isBuffer&&t.isBuffer(e)){if(!this._decoder){var n=r(11).StringDecoder;this._decoder=new n("utf8")}e=this._decoder.write(e)}return this._parser.write(e.toString()),this.emit("data",e),!0},u.prototype.end=function(t){return t&&t.length&&this.write(t),this._parser.end(),!0},u.prototype.on=function(t,e){var r=this;return r._parser["on"+t]||-1===a.indexOf(t)||(r._parser["on"+t]=function(){var e=1===arguments.length?[arguments[0]]:Array.apply(null,arguments);e.splice(0,0,t),r.emit.apply(r,e)}),i.prototype.on.call(r,t,e)};var c="http://www.w3.org/XML/1998/namespace",l={xml:c,xmlns:"http://www.w3.org/2000/xmlns/"},h=/[:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/,f=/[:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u00B7\u0300-\u036F\u203F-\u2040.\d-]/,p=/[#:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/,d=/[#:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u00B7\u0300-\u036F\u203F-\u2040.\d-]/;function m(t){return" "===t||"\n"===t||"\r"===t||"\t"===t}function g(t){return'"'===t||"'"===t}function y(t){return">"===t||m(t)}function b(t,e){return t.test(e)}function v(t,e){return!b(t,e)}var w,T,E,_=0;for(var S in e.STATE={BEGIN:_++,BEGIN_WHITESPACE:_++,TEXT:_++,TEXT_ENTITY:_++,OPEN_WAKA:_++,SGML_DECL:_++,SGML_DECL_QUOTED:_++,DOCTYPE:_++,DOCTYPE_QUOTED:_++,DOCTYPE_DTD:_++,DOCTYPE_DTD_QUOTED:_++,COMMENT_STARTING:_++,COMMENT:_++,COMMENT_ENDING:_++,COMMENT_ENDED:_++,CDATA:_++,CDATA_ENDING:_++,CDATA_ENDING_2:_++,PROC_INST:_++,PROC_INST_BODY:_++,PROC_INST_ENDING:_++,OPEN_TAG:_++,OPEN_TAG_SLASH:_++,ATTRIB:_++,ATTRIB_NAME:_++,ATTRIB_NAME_SAW_WHITE:_++,ATTRIB_VALUE:_++,ATTRIB_VALUE_QUOTED:_++,ATTRIB_VALUE_CLOSED:_++,ATTRIB_VALUE_UNQUOTED:_++,ATTRIB_VALUE_ENTITY_Q:_++,ATTRIB_VALUE_ENTITY_U:_++,CLOSE_TAG:_++,CLOSE_TAG_SAW_WHITE:_++,SCRIPT:_++,SCRIPT_ENDING:_++},e.XML_ENTITIES={amp:"&",gt:">",lt:"<",quot:'"',apos:"'"},e.ENTITIES={amp:"&",gt:">",lt:"<",quot:'"',apos:"'",AElig:198,Aacute:193,Acirc:194,Agrave:192,Aring:197,Atilde:195,Auml:196,Ccedil:199,ETH:208,Eacute:201,Ecirc:202,Egrave:200,Euml:203,Iacute:205,Icirc:206,Igrave:204,Iuml:207,Ntilde:209,Oacute:211,Ocirc:212,Ograve:210,Oslash:216,Otilde:213,Ouml:214,THORN:222,Uacute:218,Ucirc:219,Ugrave:217,Uuml:220,Yacute:221,aacute:225,acirc:226,aelig:230,agrave:224,aring:229,atilde:227,auml:228,ccedil:231,eacute:233,ecirc:234,egrave:232,eth:240,euml:235,iacute:237,icirc:238,igrave:236,iuml:239,ntilde:241,oacute:243,ocirc:244,ograve:242,oslash:248,otilde:245,ouml:246,szlig:223,thorn:254,uacute:250,ucirc:251,ugrave:249,uuml:252,yacute:253,yuml:255,copy:169,reg:174,nbsp:160,iexcl:161,cent:162,pound:163,curren:164,yen:165,brvbar:166,sect:167,uml:168,ordf:170,laquo:171,not:172,shy:173,macr:175,deg:176,plusmn:177,sup1:185,sup2:178,sup3:179,acute:180,micro:181,para:182,middot:183,cedil:184,ordm:186,raquo:187,frac14:188,frac12:189,frac34:190,iquest:191,times:215,divide:247,OElig:338,oelig:339,Scaron:352,scaron:353,Yuml:376,fnof:402,circ:710,tilde:732,Alpha:913,Beta:914,Gamma:915,Delta:916,Epsilon:917,Zeta:918,Eta:919,Theta:920,Iota:921,Kappa:922,Lambda:923,Mu:924,Nu:925,Xi:926,Omicron:927,Pi:928,Rho:929,Sigma:931,Tau:932,Upsilon:933,Phi:934,Chi:935,Psi:936,Omega:937,alpha:945,beta:946,gamma:947,delta:948,epsilon:949,zeta:950,eta:951,theta:952,iota:953,kappa:954,lambda:955,mu:956,nu:957,xi:958,omicron:959,pi:960,rho:961,sigmaf:962,sigma:963,tau:964,upsilon:965,phi:966,chi:967,psi:968,omega:969,thetasym:977,upsih:978,piv:982,ensp:8194,emsp:8195,thinsp:8201,zwnj:8204,zwj:8205,lrm:8206,rlm:8207,ndash:8211,mdash:8212,lsquo:8216,rsquo:8217,sbquo:8218,ldquo:8220,rdquo:8221,bdquLine truncated
|
||||
//# sourceMappingURL=rss-parser.min.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["webpack://RSSParser/webpack/universalModuleDefinition","webpack://RSSParser/webpack/bootstrap","webpack://RSSParser/(webpack)/buildin/global.js","webpack://RSSParser/./node_modules/inherits/inherits_browser.js","webpack://RSSParser/./node_modules/readable-stream/lib/_stream_duplex.js","webpack://RSSParser/./node_modules/buffer/index.js","webpack://RSSParser/./node_modules/process/browser.js","webpack://RSSParser/./node_modules/readable-stream/readable-browser.js","webpack://RSSParser/./node_modules/core-util-is/lib/util.js","webpack://RSSParser/./node_modules/process-nextick-args/index.js","webpack://RSSParser/./node_modules/events/events.js","webpack://RSSParser/./node_modules/safe-buffer/index.js","webpack://RSSParser/./node_modules/readable-stream/lib/_stream_writable.js","webpack://RSSParser/./node_modules/string_decoder/lib/string_decoder.js","webpack://RSSParser/./node_modules/url/url.js","webpack://RSSParser/./node_modules/xml2js/lib/defaults.js","webpack://RSSParser/./node_modules/stream-http/index.js","webpack://RSSParser/./node_modules/isarray/index.js","webpack://RSSParser/./node_modules/stream-http/lib/capability.js","webpack://RSSParser/./node_modules/stream-http/lib/response.js","webpack://RSSParser/./node_modules/readable-stream/lib/_stream_readable.js","webpack://RSSParser/./node_modules/readable-stream/lib/internal/streams/stream-browser.js","webpack://RSSParser/./node_modules/readable-stream/lib/internal/streams/destroy.js","webpack://RSSParser/./node_modules/timers-browserify/main.js","webpack://RSSParser/./node_modules/readable-stream/lib/_stream_transform.js","webpack://RSSParser/(webpack)/buildin/amd-options.js","webpack://RSSParser/./node_modules/xml2js/lib/xml2js.js","webpack://RSSParser/./node_modules/xml2js/lib/processors.js","webpack://RSSParser/./node_modules/entities/lib/decode.js","webpack://RSSParser/./node_modules/entities/lib/encode.js","webpack://RSSParser/./index.js","webpack://RSSParser/./lib/parser.js","webpack://RSSParser/./node_modules/stream-http/lib/request.js","webpack://RSSParser/./node_modules/base64-js/index.js","webpack://RSSParser/./node_modules/ieee754/index.js","webpack://RSSParser/./node_modules/readable-stream/lib/internal/streams/BufferList.js","webpack://RSSParser/./node_modules/setimmediate/setImmediate.js","webpack://RSSParser/./node_modules/util-deprecate/browser.js","webpack://RSSParser/./node_modules/readable-stream/lib/_stream_passthrough.js","webpack://RSSParser/./node_modules/to-arraybuffer/index.js","webpack://RSSParser/./node_modules/xtend/immutable.js","webpack://RSSParser/./node_modules/builtin-status-codes/browser.js","webpack://RSSParser/./node_modules/node-libs-browser/node_modules/punycode/punycode.js","webpack://RSSParser/(webpack)/buildin/module.js","webpack://RSSParser/./node_modules/url/util.js","webpack://RSSParser/./node_modules/querystring-es3/index.js","webpack://RSSParser/./node_modules/querystring-es3/decode.js","webpack://RSSParser/./node_modules/querystring-es3/encode.js","webpack://RSSParser/./node_modules/https-browserify/index.js","webpack://RSSParser/./node_modules/xml2js/lib/builder.js","webpack://RSSParser/external \"xmlbuilder\"","webpack://RSSParser/./node_modules/xml2js/lib/parser.js","webpack://RSSParser/./node_modules/sax/lib/sax.js","webpack://RSSParser/./node_modules/stream-browserify/index.js","webpack://RSSParser/./node_modules/readable-stream/writable-browser.js","webpack://RSSParser/./node_modules/readable-stream/duplex-browser.js","webpack://RSSParser/./node_modules/readable-stream/transform.js","webpack://RSSParser/./node_modules/readable-stream/passthrough.js","webpack://RSSParser/./node_modules/xml2js/lib/bom.js","webpack://RSSParser/./lib/fields.js","webpack://RSSParser/./lib/utils.js","webpack://RSSParser/./node_modules/entities/lib/index.js","webpack://RSSParser/./node_modules/entities/lib/decode_codepoint.js"],"names":["root","factory","exports","module","require","define","amd","this","__WEBPACK_EXTERNAL_MODULE__52__","installedModules","__webpack_require__","moduleId","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","prototype","hasOwnProperty","p","s","g","Function","e","window","_typeof","ctor","superCtor","super_","constructor","writable","configurable","TempCtor","pna","objectKeys","keys","obj","push","Duplex","util","inherits","Readable","Writable","v","length","method","options","readable","allowHalfOpen","once","onend","_writableState","ended","nextTick","onEndNT","self","end","highWaterMark","undefined","_readableState","destroyed","set","_destroy","err","cb","base64","ieee754","isArray","kMaxLength","Buffer","TYPED_ARRAY_SUPPORT","createBuffer","that","RangeError","Uint8Array","__proto__","arg","encodingOrOffset","Error","allocUnsafe","from","TypeError","ArrayBuffer","array","byteOffset","byteLength","fromALine truncated
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
import { Options } from 'xml2js';
|
||||
import { RequestOptions } from 'https';
|
||||
|
||||
declare namespace Parser {
|
||||
type CustomFieldItem<U> = keyof U | (string | { keepArray: boolean })[]
|
||||
|
||||
export interface CustomFields<T, U> {
|
||||
readonly feed?: Array<keyof T>;
|
||||
readonly item?: CustomFieldItem<U>[] | CustomFieldItem<U>[][];
|
||||
}
|
||||
|
||||
export interface ParserOptions<T, U> {
|
||||
readonly xml2js?: Options;
|
||||
readonly requestOptions?: RequestOptions;
|
||||
readonly headers?: Record<string, string>;
|
||||
readonly defaultRSS?: number;
|
||||
readonly maxRedirects?: number;
|
||||
readonly customFields?: CustomFields<T, U>;
|
||||
readonly timeout?: number;
|
||||
}
|
||||
|
||||
export interface Enclosure {
|
||||
url: string;
|
||||
length?: number;
|
||||
type?: string;
|
||||
}
|
||||
|
||||
export interface Item {
|
||||
link?: string;
|
||||
guid?: string;
|
||||
title?: string;
|
||||
pubDate?: string;
|
||||
creator?: string;
|
||||
summary?: string;
|
||||
content?: string;
|
||||
isoDate?: string;
|
||||
categories?: string[];
|
||||
contentSnippet?: string;
|
||||
enclosure?: Enclosure;
|
||||
}
|
||||
|
||||
export interface PaginationLinks {
|
||||
self?: string;
|
||||
first?: string;
|
||||
next?: string;
|
||||
last?: string;
|
||||
prev?: string;
|
||||
}
|
||||
|
||||
export interface Output<U> {
|
||||
image?: {
|
||||
link?: string;
|
||||
url: string;
|
||||
title?: string;
|
||||
},
|
||||
paginationLinks?: PaginationLinks;
|
||||
link?: string;
|
||||
title?: string;
|
||||
items: (U & Item)[];
|
||||
feedUrl?: string;
|
||||
description?: string;
|
||||
itunes?: {
|
||||
[key: string]: any;
|
||||
image?: string;
|
||||
owner?: {
|
||||
name?: string;
|
||||
email?: string;
|
||||
};
|
||||
author?: string;
|
||||
summary?: string;
|
||||
explicit?: string;
|
||||
categories?: string[];
|
||||
keywords?: string[];
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class that handles all parsing or URL, or even XML, RSS feed to JSON.
|
||||
*/
|
||||
declare class Parser<T = {[key: string]: any}, U = {[key: string]: any}> {
|
||||
/**
|
||||
* @param options - Parser options.
|
||||
*/
|
||||
constructor(options?: Parser.ParserOptions<T, U>);
|
||||
/**
|
||||
* Parse XML content to JSON.
|
||||
*
|
||||
* @param xml - The xml to be parsed.
|
||||
* @param callback - Traditional callback.
|
||||
*
|
||||
* @returns Promise that has the same Output as the callback.
|
||||
*/
|
||||
parseString(
|
||||
xml: string,
|
||||
callback?: (err: Error, feed: Parser.Output<U>) => void
|
||||
): Promise<T & Parser.Output<U>>;
|
||||
|
||||
/**
|
||||
* Parse URL content to JSON.
|
||||
*
|
||||
* @param feedUrl - The url that needs to be parsed to JSON.
|
||||
* @param callback - Traditional callback.
|
||||
* @param redirectCount - Max of redirects, default is set to five.
|
||||
*
|
||||
* @example
|
||||
* await parseURL('https://www.reddit.com/.rss');
|
||||
* parseURL('https://www.reddit.com/.rss', (err, feed) => { ... });
|
||||
*
|
||||
* @returns Promise that has the same Output as the callback.
|
||||
*/
|
||||
parseURL(
|
||||
feedUrl: string,
|
||||
callback?: (err: Error, feed: Parser.Output<U>) => void,
|
||||
redirectCount?: number
|
||||
): Promise<T & Parser.Output<U>>;
|
||||
}
|
||||
|
||||
export = Parser;
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = require('./lib/parser');
|
||||
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
const fields = module.exports = {};
|
||||
|
||||
fields.feed = [
|
||||
['author', 'creator'],
|
||||
['dc:publisher', 'publisher'],
|
||||
['dc:creator', 'creator'],
|
||||
['dc:source', 'source'],
|
||||
['dc:title', 'title'],
|
||||
['dc:type', 'type'],
|
||||
'title',
|
||||
'description',
|
||||
'author',
|
||||
'pubDate',
|
||||
'webMaster',
|
||||
'managingEditor',
|
||||
'generator',
|
||||
'link',
|
||||
'language',
|
||||
'copyright',
|
||||
'lastBuildDate',
|
||||
'docs',
|
||||
'generator',
|
||||
'ttl',
|
||||
'rating',
|
||||
'skipHours',
|
||||
'skipDays',
|
||||
];
|
||||
|
||||
fields.item = [
|
||||
['author', 'creator'],
|
||||
['dc:creator', 'creator'],
|
||||
['dc:date', 'date'],
|
||||
['dc:language', 'language'],
|
||||
['dc:rights', 'rights'],
|
||||
['dc:source', 'source'],
|
||||
['dc:title', 'title'],
|
||||
'title',
|
||||
'link',
|
||||
'pubDate',
|
||||
'author',
|
||||
'summary',
|
||||
['content:encoded', 'content:encoded', {includeSnippet: true}],
|
||||
'enclosure',
|
||||
'dc:creator',
|
||||
'dc:date',
|
||||
'comments',
|
||||
];
|
||||
|
||||
var mapItunesField = function(f) {
|
||||
return ['itunes:' + f, f];
|
||||
}
|
||||
|
||||
fields.podcastFeed = ([
|
||||
'author',
|
||||
'subtitle',
|
||||
'summary',
|
||||
'explicit'
|
||||
]).map(mapItunesField);
|
||||
|
||||
fields.podcastItem = ([
|
||||
'author',
|
||||
'subtitle',
|
||||
'summary',
|
||||
'explicit',
|
||||
'duration',
|
||||
'image',
|
||||
'episode',
|
||||
'image',
|
||||
'season',
|
||||
'keywords',
|
||||
'episodeType'
|
||||
]).map(mapItunesField);
|
||||
|
||||
+349
@@ -0,0 +1,349 @@
|
||||
"use strict";
|
||||
const http = require('http');
|
||||
const https = require('https');
|
||||
const xml2js = require('xml2js');
|
||||
const url = require('url');
|
||||
|
||||
const fields = require('./fields');
|
||||
const utils = require('./utils');
|
||||
|
||||
const DEFAULT_HEADERS = {
|
||||
'User-Agent': 'rss-parser',
|
||||
'Accept': 'application/rss+xml',
|
||||
}
|
||||
const DEFAULT_MAX_REDIRECTS = 5;
|
||||
const DEFAULT_TIMEOUT = 60000;
|
||||
|
||||
class Parser {
|
||||
constructor(options={}) {
|
||||
options.headers = options.headers || {};
|
||||
options.xml2js = options.xml2js || {};
|
||||
options.customFields = options.customFields || {};
|
||||
options.customFields.item = options.customFields.item || [];
|
||||
options.customFields.feed = options.customFields.feed || [];
|
||||
options.requestOptions = options.requestOptions || {};
|
||||
if (!options.maxRedirects) options.maxRedirects = DEFAULT_MAX_REDIRECTS;
|
||||
if (!options.timeout) options.timeout = DEFAULT_TIMEOUT;
|
||||
this.options = options;
|
||||
this.xmlParser = new xml2js.Parser(this.options.xml2js);
|
||||
}
|
||||
|
||||
parseString(xml, callback) {
|
||||
let prom = new Promise((resolve, reject) => {
|
||||
this.xmlParser.parseString(xml, (err, result) => {
|
||||
if (err) return reject(err);
|
||||
if (!result) {
|
||||
return reject(new Error('Unable to parse XML.'));
|
||||
}
|
||||
let feed = null;
|
||||
if (result.feed) {
|
||||
feed = this.buildAtomFeed(result);
|
||||
} else if (result.rss && result.rss.$ && result.rss.$.version && result.rss.$.version.match(/^2/)) {
|
||||
feed = this.buildRSS2(result);
|
||||
} else if (result['rdf:RDF']) {
|
||||
feed = this.buildRSS1(result);
|
||||
} else if (result.rss && result.rss.$ && result.rss.$.version && result.rss.$.version.match(/0\.9/)) {
|
||||
feed = this.buildRSS0_9(result);
|
||||
} else if (result.rss && this.options.defaultRSS) {
|
||||
switch(this.options.defaultRSS) {
|
||||
case 0.9:
|
||||
feed = this.buildRSS0_9(result);
|
||||
break;
|
||||
case 1:
|
||||
feed = this.buildRSS1(result);
|
||||
break;
|
||||
case 2:
|
||||
feed = this.buildRSS2(result);
|
||||
break;
|
||||
default:
|
||||
return reject(new Error("default RSS version not recognized."))
|
||||
}
|
||||
} else {
|
||||
return reject(new Error("Feed not recognized as RSS 1 or 2."))
|
||||
}
|
||||
resolve(feed);
|
||||
});
|
||||
});
|
||||
prom = utils.maybePromisify(callback, prom);
|
||||
return prom;
|
||||
}
|
||||
|
||||
parseURL(feedUrl, callback, redirectCount=0) {
|
||||
let xml = '';
|
||||
let get = feedUrl.indexOf('https') === 0 ? https.get : http.get;
|
||||
let urlParts = url.parse(feedUrl);
|
||||
let headers = Object.assign({}, DEFAULT_HEADERS, this.options.headers);
|
||||
let timeout = null;
|
||||
let prom = new Promise((resolve, reject) => {
|
||||
const requestOpts = Object.assign({headers}, urlParts, this.options.requestOptions);
|
||||
let req = get(requestOpts, (res) => {
|
||||
if (this.options.maxRedirects && res.statusCode >= 300 && res.statusCode < 400 && res.headers['location']) {
|
||||
if (redirectCount === this.options.maxRedirects) {
|
||||
return reject(new Error("Too many redirects"));
|
||||
} else {
|
||||
const newLocation = url.resolve(feedUrl, res.headers['location']);
|
||||
return this.parseURL(newLocation, null, redirectCount + 1).then(resolve, reject);
|
||||
}
|
||||
} else if (res.statusCode >= 300) {
|
||||
return reject(new Error("Status code " + res.statusCode))
|
||||
}
|
||||
let encoding = utils.getEncodingFromContentType(res.headers['content-type']);
|
||||
res.setEncoding(encoding);
|
||||
res.on('data', (chunk) => {
|
||||
xml += chunk;
|
||||
});
|
||||
res.on('end', () => {
|
||||
return this.parseString(xml).then(resolve, reject);
|
||||
});
|
||||
})
|
||||
req.on('error', reject);
|
||||
timeout = setTimeout(() => {
|
||||
return reject(new Error("Request timed out after " + this.options.timeout + "ms"));
|
||||
}, this.options.timeout);
|
||||
}).then(data => {
|
||||
clearTimeout(timeout);
|
||||
return Promise.resolve(data);
|
||||
}, e => {
|
||||
clearTimeout(timeout);
|
||||
return Promise.reject(e);
|
||||
});
|
||||
prom = utils.maybePromisify(callback, prom);
|
||||
return prom;
|
||||
}
|
||||
|
||||
buildAtomFeed(xmlObj) {
|
||||
let feed = {items: []};
|
||||
utils.copyFromXML(xmlObj.feed, feed, this.options.customFields.feed);
|
||||
if (xmlObj.feed.link) {
|
||||
feed.link = utils.getLink(xmlObj.feed.link, 'alternate', 0);
|
||||
feed.feedUrl = utils.getLink(xmlObj.feed.link, 'self', 1);
|
||||
}
|
||||
if (xmlObj.feed.title) {
|
||||
let title = xmlObj.feed.title[0] || '';
|
||||
if (title._) title = title._
|
||||
if (title) feed.title = title;
|
||||
}
|
||||
if (xmlObj.feed.updated) {
|
||||
feed.lastBuildDate = xmlObj.feed.updated[0];
|
||||
}
|
||||
feed.items = (xmlObj.feed.entry || []).map(entry => this.parseItemAtom(entry));
|
||||
return feed;
|
||||
}
|
||||
|
||||
parseItemAtom(entry) {
|
||||
let item = {};
|
||||
utils.copyFromXML(entry, item, this.options.customFields.item);
|
||||
if (entry.title) {
|
||||
let title = entry.title[0] || '';
|
||||
if (title._) title = title._;
|
||||
if (title) item.title = title;
|
||||
}
|
||||
if (entry.link && entry.link.length) {
|
||||
item.link = utils.getLink(entry.link, 'alternate', 0);
|
||||
}
|
||||
if (entry.published && entry.published.length && entry.published[0].length) item.pubDate = new Date(entry.published[0]).toISOString();
|
||||
if (!item.pubDate && entry.updated && entry.updated.length && entry.updated[0].length) item.pubDate = new Date(entry.updated[0]).toISOString();
|
||||
if (entry.author && entry.author.length && entry.author[0].name && entry.author[0].name.length) item.author = entry.author[0].name[0];
|
||||
if (entry.content && entry.content.length) {
|
||||
item.content = utils.getContent(entry.content[0]);
|
||||
item.contentSnippet = utils.getSnippet(item.content)
|
||||
}
|
||||
if (entry.summary && entry.summary.length) {
|
||||
item.summary = utils.getContent(entry.summary[0]);
|
||||
}
|
||||
if (entry.id) {
|
||||
item.id = entry.id[0];
|
||||
}
|
||||
this.setISODate(item);
|
||||
return item;
|
||||
}
|
||||
|
||||
buildRSS0_9(xmlObj) {
|
||||
var channel = xmlObj.rss.channel[0];
|
||||
var items = channel.item;
|
||||
return this.buildRSS(channel, items);
|
||||
}
|
||||
|
||||
buildRSS1(xmlObj) {
|
||||
xmlObj = xmlObj['rdf:RDF'];
|
||||
let channel = xmlObj.channel[0];
|
||||
let items = xmlObj.item;
|
||||
return this.buildRSS(channel, items);
|
||||
}
|
||||
|
||||
buildRSS2(xmlObj) {
|
||||
let channel = xmlObj.rss.channel[0];
|
||||
let items = channel.item;
|
||||
let feed = this.buildRSS(channel, items);
|
||||
if (xmlObj.rss.$ && xmlObj.rss.$['xmlns:itunes']) {
|
||||
this.decorateItunes(feed, channel);
|
||||
}
|
||||
return feed;
|
||||
}
|
||||
|
||||
buildRSS(channel, items) {
|
||||
items = items || [];
|
||||
let feed = {items: []};
|
||||
let feedFields = fields.feed.concat(this.options.customFields.feed);
|
||||
let itemFields = fields.item.concat(this.options.customFields.item);
|
||||
if (channel['atom:link'] && channel['atom:link'][0] && channel['atom:link'][0].$) {
|
||||
feed.feedUrl = channel['atom:link'][0].$.href;
|
||||
}
|
||||
if (channel.image && channel.image[0] && channel.image[0].url) {
|
||||
feed.image = {};
|
||||
let image = channel.image[0];
|
||||
if (image.link) feed.image.link = image.link[0];
|
||||
if (image.url) feed.image.url = image.url[0];
|
||||
if (image.title) feed.image.title = image.title[0];
|
||||
if (image.width) feed.image.width = image.width[0];
|
||||
if (image.height) feed.image.height = image.height[0];
|
||||
}
|
||||
const paginationLinks = this.generatePaginationLinks(channel);
|
||||
if (Object.keys(paginationLinks).length) {
|
||||
feed.paginationLinks = paginationLinks;
|
||||
}
|
||||
utils.copyFromXML(channel, feed, feedFields);
|
||||
feed.items = items.map(xmlItem => this.parseItemRss(xmlItem, itemFields));
|
||||
return feed;
|
||||
}
|
||||
|
||||
parseItemRss(xmlItem, itemFields) {
|
||||
let item = {};
|
||||
utils.copyFromXML(xmlItem, item, itemFields);
|
||||
if (xmlItem.enclosure) {
|
||||
item.enclosure = xmlItem.enclosure[0].$;
|
||||
}
|
||||
if (xmlItem.description) {
|
||||
item.content = utils.getContent(xmlItem.description[0]);
|
||||
item.contentSnippet = utils.getSnippet(item.content);
|
||||
}
|
||||
if (xmlItem.guid) {
|
||||
item.guid = xmlItem.guid[0];
|
||||
if (item.guid._) item.guid = item.guid._;
|
||||
}
|
||||
if (xmlItem.$ && xmlItem.$['rdf:about']) {
|
||||
item['rdf:about'] = xmlItem.$['rdf:about']
|
||||
}
|
||||
if (xmlItem.category) item.categories = xmlItem.category;
|
||||
this.setISODate(item);
|
||||
return item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add iTunes specific fields from XML to extracted JSON
|
||||
*
|
||||
* @access public
|
||||
* @param {object} feed extracted
|
||||
* @param {object} channel parsed XML
|
||||
*/
|
||||
decorateItunes(feed, channel) {
|
||||
let items = channel.item || [];
|
||||
let categories = [];
|
||||
feed.itunes = {}
|
||||
|
||||
if (channel['itunes:owner']) {
|
||||
let owner = {};
|
||||
|
||||
if(channel['itunes:owner'][0]['itunes:name']) {
|
||||
owner.name = channel['itunes:owner'][0]['itunes:name'][0];
|
||||
}
|
||||
if(channel['itunes:owner'][0]['itunes:email']) {
|
||||
owner.email = channel['itunes:owner'][0]['itunes:email'][0];
|
||||
}
|
||||
feed.itunes.owner = owner;
|
||||
}
|
||||
|
||||
if (channel['itunes:image']) {
|
||||
let image;
|
||||
let hasImageHref = (channel['itunes:image'][0] &&
|
||||
channel['itunes:image'][0].$ &&
|
||||
channel['itunes:image'][0].$.href);
|
||||
image = hasImageHref ? channel['itunes:image'][0].$.href : null;
|
||||
if (image) {
|
||||
feed.itunes.image = image;
|
||||
}
|
||||
}
|
||||
|
||||
if (channel['itunes:category']) {
|
||||
const categoriesWithSubs = channel['itunes:category'].map((category) => {
|
||||
return {
|
||||
name: category && category.$ && category.$.text,
|
||||
subs: category['itunes:category'] ?
|
||||
category['itunes:category']
|
||||
.map((subcategory) => ({
|
||||
name: subcategory && subcategory.$ && subcategory.$.text
|
||||
})) : null,
|
||||
};
|
||||
});
|
||||
|
||||
feed.itunes.categories = categoriesWithSubs.map((category) => category.name);
|
||||
feed.itunes.categoriesWithSubs = categoriesWithSubs;
|
||||
}
|
||||
|
||||
if (channel['itunes:keywords']) {
|
||||
if (channel['itunes:keywords'].length > 1) {
|
||||
feed.itunes.keywords = channel['itunes:keywords'].map(
|
||||
keyword => keyword && keyword.$ && keyword.$.text
|
||||
);
|
||||
} else {
|
||||
let keywords = channel['itunes:keywords'][0];
|
||||
if (keywords && typeof keywords._ === 'string') {
|
||||
keywords = keywords._;
|
||||
}
|
||||
|
||||
if (keywords && keywords.$ && keywords.$.text) {
|
||||
feed.itunes.keywords = keywords.$.text.split(',')
|
||||
} else if (typeof keywords === "string") {
|
||||
feed.itunes.keywords = keywords.split(',');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
utils.copyFromXML(channel, feed.itunes, fields.podcastFeed);
|
||||
items.forEach((item, index) => {
|
||||
let entry = feed.items[index];
|
||||
entry.itunes = {};
|
||||
utils.copyFromXML(item, entry.itunes, fields.podcastItem);
|
||||
let image = item['itunes:image'];
|
||||
if (image && image[0] && image[0].$ && image[0].$.href) {
|
||||
entry.itunes.image = image[0].$.href;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setISODate(item) {
|
||||
let date = item.pubDate || item.date;
|
||||
if (date) {
|
||||
try {
|
||||
item.isoDate = new Date(date.trim()).toISOString();
|
||||
} catch (e) {
|
||||
// Ignore bad date format
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a pagination object where the rel attribute is the key and href attribute is the value
|
||||
* { self: 'self-url', first: 'first-url', ... }
|
||||
*
|
||||
* @access private
|
||||
* @param {Object} channel parsed XML
|
||||
* @returns {Object}
|
||||
*/
|
||||
generatePaginationLinks(channel) {
|
||||
if (!channel['atom:link']) {
|
||||
return {};
|
||||
}
|
||||
const paginationRelAttributes = ['self', 'first', 'next', 'prev', 'last'];
|
||||
|
||||
return channel['atom:link'].reduce((paginationLinks, link) => {
|
||||
if (!link.$ || !paginationRelAttributes.includes(link.$.rel)) {
|
||||
return paginationLinks;
|
||||
}
|
||||
paginationLinks[link.$.rel] = link.$.href;
|
||||
return paginationLinks;
|
||||
}, {});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Parser;
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
const utils = module.exports = {};
|
||||
const entities = require('entities');
|
||||
const xml2js = require('xml2js');
|
||||
|
||||
utils.stripHtml = function(str) {
|
||||
str = str.replace(/([^\n])<\/?(h|br|p|ul|ol|li|blockquote|section|table|tr|div)(?:.|\n)*?>([^\n])/gm, '$1\n$3')
|
||||
str = str.replace(/<(?:.|\n)*?>/gm, '');
|
||||
return str;
|
||||
}
|
||||
|
||||
utils.getSnippet = function(str) {
|
||||
return entities.decodeHTML(utils.stripHtml(str)).trim();
|
||||
}
|
||||
|
||||
utils.getLink = function(links, rel, fallbackIdx) {
|
||||
if (!links) return;
|
||||
for (let i = 0; i < links.length; ++i) {
|
||||
if (links[i].$.rel === rel) return links[i].$.href;
|
||||
}
|
||||
if (links[fallbackIdx]) return links[fallbackIdx].$.href;
|
||||
}
|
||||
|
||||
utils.getContent = function(content) {
|
||||
if (typeof content._ === 'string') {
|
||||
return content._;
|
||||
} else if (typeof content === 'object') {
|
||||
let builder = new xml2js.Builder({headless: true, explicitRoot: true, rootName: 'div', renderOpts: {pretty: false}});
|
||||
return builder.buildObject(content);
|
||||
} else {
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
||||
utils.copyFromXML = function(xml, dest, fields) {
|
||||
fields.forEach(function(f) {
|
||||
let from = f;
|
||||
let to = f;
|
||||
let options = {};
|
||||
if (Array.isArray(f)) {
|
||||
from = f[0];
|
||||
to = f[1];
|
||||
if (f.length > 2) {
|
||||
options = f[2];
|
||||
}
|
||||
}
|
||||
const { keepArray, includeSnippet } = options;
|
||||
if (xml[from] !== undefined){
|
||||
dest[to] = keepArray ? xml[from] : xml[from][0];
|
||||
}
|
||||
if (dest[to] && typeof dest[to]._ === 'string') {
|
||||
dest[to]=dest[to]._;
|
||||
}
|
||||
if (includeSnippet && dest[to] && typeof dest[to] === 'string') {
|
||||
dest[to + 'Snippet'] = utils.getSnippet(dest[to]);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
utils.maybePromisify = function(callback, promise) {
|
||||
if (!callback) return promise;
|
||||
return promise.then(
|
||||
data => setTimeout(() => callback(null, data)),
|
||||
err => setTimeout(() => callback(err))
|
||||
);
|
||||
}
|
||||
|
||||
const DEFAULT_ENCODING = 'utf8';
|
||||
const ENCODING_REGEX = /(encoding|charset)\s*=\s*(\S+)/;
|
||||
const SUPPORTED_ENCODINGS = ['ascii', 'utf8', 'utf16le', 'ucs2', 'base64', 'latin1', 'binary', 'hex'];
|
||||
const ENCODING_ALIASES = {
|
||||
'utf-8': 'utf8',
|
||||
'iso-8859-1': 'latin1',
|
||||
}
|
||||
|
||||
utils.getEncodingFromContentType = function(contentType) {
|
||||
contentType = contentType || '';
|
||||
let match = contentType.match(ENCODING_REGEX);
|
||||
let encoding = (match || [])[2] || '';
|
||||
encoding = encoding.toLowerCase();
|
||||
encoding = ENCODING_ALIASES[encoding] || encoding;
|
||||
if (!encoding || SUPPORTED_ENCODINGS.indexOf(encoding) === -1) {
|
||||
encoding = DEFAULT_ENCODING;
|
||||
}
|
||||
return encoding;
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"name": "rss-parser",
|
||||
"version": "3.13.0",
|
||||
"main": "index.js",
|
||||
"types": "index.d.ts",
|
||||
"scripts": {
|
||||
"test": "mocha --reporter-option maxDiffSize=0 --exit",
|
||||
"build": "./scripts/build.sh"
|
||||
},
|
||||
"author": "Bobby Brennan",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.21.4",
|
||||
"@babel/preset-env": "^7.21.4",
|
||||
"@types/xml2js": "^0.4.3",
|
||||
"babel-core": "^6.26.3",
|
||||
"babel-loader": "^8.0.4",
|
||||
"babel-preset-env": "^1.7.0",
|
||||
"chai": "^3.4.1",
|
||||
"express": "^4.16.3",
|
||||
"mocha": "^10.2.0",
|
||||
"puppeteer": "^5.2.1",
|
||||
"webpack": "^4.46.0",
|
||||
"webpack-cli": "^3.3.9"
|
||||
},
|
||||
"dependencies": {
|
||||
"entities": "^2.0.3",
|
||||
"xml2js": "^0.5.0"
|
||||
},
|
||||
"directories": {
|
||||
"test": "test"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/bobby-brennan/rss-parser.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/bobby-brennan/rss-parser/issues"
|
||||
},
|
||||
"homepage": "https://github.com/bobby-brennan/rss-parser#readme",
|
||||
"description": "A lightweight RSS parser, for Node and the browser",
|
||||
"keywords": [
|
||||
"RSS",
|
||||
"RSS to JSON",
|
||||
"RSS reader",
|
||||
"RSS parser",
|
||||
"RSS to JS",
|
||||
"Feed reader"
|
||||
]
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
set -e
|
||||
webpack-cli --mode=development --target=web
|
||||
webpack-cli --mode=production --target=web --output-filename=dist/[name].min.js --profile --json > dist/stats.json
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
var webpack = require("webpack");
|
||||
module.exports = {
|
||||
entry: {
|
||||
"rss-parser": "./index.js"
|
||||
},
|
||||
output: {
|
||||
path: __dirname,
|
||||
filename: "dist/[name].js",
|
||||
libraryTarget: 'umd',
|
||||
globalObject: 'this',
|
||||
library: 'RSSParser'
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.js']
|
||||
},
|
||||
devtool: 'source-map',
|
||||
module: {
|
||||
rules: [{
|
||||
test: /\.js$/,
|
||||
loader: 'babel-loader?presets[]=@babel/preset-env',
|
||||
}]
|
||||
},
|
||||
externals: {
|
||||
xmlbuilder:'xmlbuilder'
|
||||
},
|
||||
node: {
|
||||
fs: "empty"
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user