Socket
Socket
Sign inDemoInstall

react-rss

Package Overview
Dependencies
8
Maintainers
1
Versions
4
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.0.1 to 1.0.0

15

components/RSS.d.ts
import React from 'react';
import { InjectionRSSProps, InjectionRSSUrlProps } from '../types';
export declare const rssEnhancer: <T, E extends string | null = null>(Component: ((props: T & InjectionRSSProps) => JSX.Element | null) | (new (props: T & InjectionRSSProps) => React.Component<T & InjectionRSSProps, {}, any>), url?: E) => (props: Pick<T, Exclude<keyof T, "rss">> & InjectionRSSUrlProps) => JSX.Element;
import { InjectionRSSProps, InjectionRSSUrlProps, Standard2RSSFormatItem, Standard2RSSFormatHeader } from '../types';
/**
* Higher-order component enhancer for rss feed
* @param Component Component to enhance
* @param url Static url from which to draw
* @param requestEnhancer You can use this to statically enhance requests by setting request headers, method etc.
* @param headerEnhancer Use this function to add properties to resulting rss object. You can use standard media queries on rssElement to do so.
* @param itemEnhacer Use this to enhance individual news from feed. You can use standard media queries on item to do so.
*/
export declare const rssEnhancer: <T, E extends string | null = null>(Component: ((props: T & InjectionRSSProps<{}, {}>) => JSX.Element | null) | (new (props: T & InjectionRSSProps<{}, {}>) => React.Component<T & InjectionRSSProps<{}, {}>, {}, any>), url?: E, requestEnhancer?: ((url: string) => ({
input: RequestInfo;
init?: RequestInit;
})) | undefined, headerEnhancer?: (<F extends Standard2RSSFormatHeader>(rssElement: Element, standard: Standard2RSSFormatHeader) => Standard2RSSFormatHeader | F) | undefined, itemEnhancer?: (<K extends Standard2RSSFormatItem>(item: Element, standard: Standard2RSSFormatItem) => Standard2RSSFormatItem | K) | undefined) => (props: Pick<T, Exclude<keyof T, "rss">> & InjectionRSSUrlProps) => JSX.Element;

114

components/RSS.js

@@ -85,2 +85,3 @@ "use strict";

var getRss_1 = require("../utils/getRss");
var enhanceUrl = function (url, requestEnhancer) { return requestEnhancer ? requestEnhancer(url) : { input: url }; };
var RSS = /** @class */ (function (_super) {

@@ -95,8 +96,9 @@ __extends(RSS, _super);

};
return _this;
}
RSS.prototype.componentDidMount = function () {
return __awaiter(this, void 0, void 0, function () {
var props, contents, subscription, e_1;
var _this = this;
_this.clearInterval = function () {
if (_this.interval !== null) {
clearInterval(_this.interval);
}
};
_this.getRss = function () { return __awaiter(_this, void 0, void 0, function () {
var props, enhanced, contents;
return __generator(this, function (_a) {

@@ -106,2 +108,16 @@ switch (_a.label) {

props = this.props;
enhanced = enhanceUrl(props.url, props.requestEnhancer);
return [4 /*yield*/, getRss_1.getRss(enhanced, window.fetch, props.headerEnhancer, props.itemEnhancer)];
case 1:
contents = _a.sent();
return [2 /*return*/, contents];
}
});
}); };
_this.sendRequest = function () { return __awaiter(_this, void 0, void 0, function () {
var props, contents, e_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
props = this.props;
this.setState({ loading: true });

@@ -114,3 +130,3 @@ _a.label = 1;

}
return [4 /*yield*/, getRss_1.getRss(props.url, window.fetch)];
return [4 /*yield*/, this.getRss()];
case 2:

@@ -120,26 +136,3 @@ contents = _a.sent();

if (props.subscribe) {
subscription = parseInt(contents.header.ttl, 10);
this.interval = window.setInterval(function () { return __awaiter(_this, void 0, void 0, function () {
var contents_1, e_2;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
if (!props.url) {
throw Error('Cannot set up rss feed of nonexistent url!');
}
this.setState({ loading: true });
return [4 /*yield*/, getRss_1.getRss(props.url, window.fetch)];
case 1:
contents_1 = _a.sent();
this.setState({ contents: contents_1, loading: false, error: null });
return [3 /*break*/, 3];
case 2:
e_2 = _a.sent();
this.setState({ error: e_2, loading: false });
return [3 /*break*/, 3];
case 3: return [2 /*return*/];
}
});
}); }, (isNaN(subscription) ? 10 : subscription) * 60 * 1000);
this.setupSubscription(contents);
}

@@ -154,9 +147,50 @@ return [3 /*break*/, 4];

});
}); };
_this.setupSubscription = function (contents) {
var props = _this.props;
var subscription = parseInt(contents.header.ttl, 10);
_this.interval = window.setInterval(function () { return __awaiter(_this, void 0, void 0, function () {
var contents_1, e_2;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
_a.trys.push([0, 2, , 3]);
if (!props.url) {
throw Error('Cannot set up rss feed of nonexistent url!');
}
this.setState({ loading: true });
return [4 /*yield*/, this.getRss()];
case 1:
contents_1 = _a.sent();
this.setState({ contents: contents_1, loading: false, error: null });
return [3 /*break*/, 3];
case 2:
e_2 = _a.sent();
this.setState({ error: e_2, loading: false });
return [3 /*break*/, 3];
case 3: return [2 /*return*/];
}
});
}); }, (isNaN(subscription) ? 10 : subscription) * 60 * 1000);
};
return _this;
}
RSS.prototype.componentDidMount = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
this.sendRequest();
return [2 /*return*/];
});
});
};
RSS.prototype.componentWillUnmount = function () {
if (this.interval !== null) {
clearInterval(this.interval);
RSS.prototype.componentDidUpdate = function (prevProps) {
var props = this.props;
if (prevProps.subscribe !== props.subscribe || prevProps.url !== props.url) {
this.clearInterval();
this.sendRequest();
}
};
RSS.prototype.componentWillUnmount = function () {
this.clearInterval();
};
RSS.prototype.render = function () {

@@ -183,7 +217,15 @@ var _a = this, state = _a.state, props = _a.props;

}(react_1.Component));
exports.rssEnhancer = function (Component, url) {
/**
* Higher-order component enhancer for rss feed
* @param Component Component to enhance
* @param url Static url from which to draw
* @param requestEnhancer You can use this to statically enhance requests by setting request headers, method etc.
* @param headerEnhancer Use this function to add properties to resulting rss object. You can use standard media queries on rssElement to do so.
* @param itemEnhacer Use this to enhance individual news from feed. You can use standard media queries on item to do so.
*/
exports.rssEnhancer = function (Component, url, requestEnhancer, headerEnhancer, itemEnhancer) {
if (url === void 0) { url = null; }
return function (props) {
return (react_1.default.createElement(RSS, { url: (props.url || url), loadingComponent: props.loadingComponent, errorComponent: props.errorComponent }, function (rss) { return (react_1.default.createElement(Component, __assign({}, props, { rss: rss }))); }));
return (react_1.default.createElement(RSS, { url: (props.url || url), loadingComponent: props.loadingComponent, errorComponent: props.errorComponent, requestEnhancer: requestEnhancer, headerEnhancer: headerEnhancer, itemEnhancer: itemEnhancer }, function (rss) { return (react_1.default.createElement(Component, __assign({}, props, { rss: rss }))); }));
};
};
{
"name": "react-rss",
"version": "0.0.1",
"version": "1.0.0",
"description": "React component capable of reading and rendering any RSS feed",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -6,3 +6,3 @@ # react-rss

So far this feed only supports standart RSS params defined in: https://validator.w3.org/feed/docs/rss2.html.
So far this feed only supports standard RSS params defined in: https://validator.w3.org/feed/docs/rss2.html.

@@ -126,2 +126,57 @@ ## Example of usage

### Changes since 1.0.0
Fixed typos in typings of this package. Added enhancers, which allow you to pick custom xml elements (using query selectors) out of RSS and add them to the component props.
Also, fixed default parsing of RSS XML document and added component update mechanism when passed url changes.
#### Example of use
```JSX
/**
* Props injected have a two-type template: first is header enhancement, second one is with what is each item enhanced.
*/
class SourcedRSSComponent extends Component<{ label: string } & InjectionRSSProps<{ hasImage: boolean }, { mediaUrl?: string }>> {
public render() {
const { props } = this;
return (
<div>
<h2>{props.label}</h2>
<a href={props.rss.header.link}>
{props.rss.header.title}
{props.rss.header.hasImage && ' Has image!'}
</a>
<ul>
{props.rss.items.map(item => (
<li>
{item.description}
{item.mediaUrl && <span>Url: {item.mediaUrl}</span>}
</li>
))}
</ul>
</div>
);
}
};
export default rssEnhancer(
SourcedRSSComponent,
null, // Default url is null, which means resulting component will need an url passed in its props.
url => ({ input: url, init: { method: 'POST' } }), // Enhances the used url request by any optional parameter, such as headers, method, etc.
(rss, header) => { // Enhances header portion of result
return { ...header, hasImage: Boolean(rss.querySelector('image')) };
},
(rssItem, item) => { // Enhances each item by certain query
const mediaUrl = rssItem.querySelector('content')?.getAttribute('url');
if (mediaUrl) {
return { ...item, mediaUrl };
}
return item;
}
);
```
## Addendum

@@ -128,0 +183,0 @@

/// <reference types="react" />
export interface Standart2RSSFormat {
header: Standart2RSSFormatHeader;
items: Standart2RSSFormatItem[];
export interface Standard2RSSFormat {
header: Standard2RSSFormatHeader;
items: Standard2RSSFormatItem[];
}
export interface InjectionRSSProps {
export interface InjectionRSSProps<T = {}, K = {}> {
/**
* Formatted RSS2 standard feed
*/
rss: Standart2RSSFormat;
rss: {
header: T & Standard2RSSFormatHeader;
} & {
items: (K & Standard2RSSFormatItem)[];
};
}

@@ -28,11 +32,21 @@ export interface InjectionRSSUrlProps {

*/
errorComponent?: (props: {
errorComponent?: <T extends Standard2RSSFormat = Standard2RSSFormat>(props: {
error: any;
contents: Standart2RSSFormat | null;
contents: T | null;
}) => JSX.Element;
}
export interface RSSProps extends InjectionRSSUrlProps {
children: (rss: Standart2RSSFormat) => JSX.Element | null;
export interface RSSProps<T = {}, K = {}> extends InjectionRSSUrlProps {
requestEnhancer?: (url: string) => ({
input: RequestInfo;
init?: RequestInit;
});
headerEnhancer?: (rssElement: Element, standard: Standard2RSSFormatHeader) => T & Standard2RSSFormatHeader;
itemEnhancer?: (item: Element, standard: Standard2RSSFormatItem) => K & Standard2RSSFormatItem;
children: (rss: Standard2RSSFormat & {
header: T;
} & {
items: K[];
}) => JSX.Element | null;
}
export interface Standart2RSSFormatHeader {
export interface Standard2RSSFormatHeader {
title: string;

@@ -49,7 +63,2 @@ image?: {

language: string;
blogChannel: {
blogRoll: string;
mySubscriptions: string;
blink: string;
};
copyright: string;

@@ -67,3 +76,3 @@ lastBuildDate: string;

}
export interface Standart2RSSFormatItem {
export interface Standard2RSSFormatItem {
description: string;

@@ -70,0 +79,0 @@ pubDate: string;

@@ -1,1 +0,9 @@

export declare const getRss: (url: string, fetch: (input: RequestInfo, init?: RequestInit | undefined) => Promise<Response>) => Promise<import("../types").Standart2RSSFormat>;
import { Standard2RSSFormat, Standard2RSSFormatItem, Standard2RSSFormatHeader } from "../types";
export declare const getRss: <T, E>(enhanced: {
input: RequestInfo;
init?: RequestInit;
}, fetch: (input: RequestInfo, init?: RequestInit | undefined) => Promise<Response>, headerEnhancer?: ((rssElement: Element, standard: Standard2RSSFormatHeader) => T & Standard2RSSFormatHeader) | undefined, itemEnhancer?: ((item: Element, standard: Standard2RSSFormatItem) => E & Standard2RSSFormatItem) | undefined) => Promise<Standard2RSSFormat & {
header: T;
} & {
items: E[];
}>;

@@ -41,3 +41,3 @@ "use strict";

var parseXml_1 = require("./parseXml");
exports.getRss = function (url, fetch) { return __awaiter(void 0, void 0, void 0, function () {
exports.getRss = function (enhanced, fetch, headerEnhancer, itemEnhancer) { return __awaiter(void 0, void 0, void 0, function () {
var result, xml;

@@ -50,3 +50,3 @@ return __generator(this, function (_a) {

}
return [4 /*yield*/, fetch(url)];
return [4 /*yield*/, fetch(enhanced.input, enhanced.init)];
case 1:

@@ -57,5 +57,5 @@ result = _a.sent();

xml = _a.sent();
return [2 /*return*/, parseXml_1.parseXml(xml)];
return [2 /*return*/, parseXml_1.parseXml(xml, headerEnhancer, itemEnhancer)];
}
});
}); };

@@ -1,2 +0,6 @@

import { Standart2RSSFormat } from "../types";
export declare const parseXml: (xml: string) => Standart2RSSFormat;
import { Standard2RSSFormat, Standard2RSSFormatItem, Standard2RSSFormatHeader } from "../types";
export declare const parseXml: <T, E>(xml: string, enhancer?: ((rssElement: Element, standard: Standard2RSSFormatHeader) => T & Standard2RSSFormatHeader) | undefined, itemEnhancer?: ((item: Element, standard: Standard2RSSFormatItem) => E & Standard2RSSFormatItem) | undefined) => Standard2RSSFormat & {
header: T;
} & {
items: E[];
};

@@ -12,15 +12,11 @@ "use strict";

};
exports.parseXml = function (xml) {
exports.parseXml = function (xml, enhancer, itemEnhancer) {
var _a;
var doc = new DOMParser().parseFromString(xml, 'text/xml');
try {
var channel = doc.querySelector('rss').querySelector('channel');
var rssElement = doc.querySelector('rss');
var channel = rssElement.querySelector('channel');
var image = channel.querySelector('image');
var rss = {
header: {
blogChannel: {
blink: getFromChannel(channel, 'blogChannel\\:blink'),
blogRoll: getFromChannel(channel, 'blogChannel\\:blogRoll'),
mySubscriptions: getFromChannel(channel, 'blogChannel\\:mySubscriptions'),
},
category: {

@@ -52,3 +48,3 @@ category: getFromChannel(channel, 'category'),

var source = item.querySelector('source');
return {
var result = {
author: getFromChannel(item, 'author'),

@@ -72,4 +68,11 @@ category: getFromChannel(item, 'category'),

};
if (itemEnhancer) {
return itemEnhancer(item, result);
}
return result;
}),
};
if (enhancer) {
return { header: enhancer(rssElement, rss.header), items: rss.items };
}
return rss;

@@ -76,0 +79,0 @@ }

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc