Comparing version 1.1.1 to 2.0.0
534
lib/feed.js
@@ -1,507 +0,33 @@ | ||
'use strict'; | ||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
var _xml = require('xml'); | ||
var _xml2 = _interopRequireDefault(_xml); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
var GENERATOR = 'Feed for Node.js'; | ||
var DOCTYPE = '<?xml version="1.0" encoding="utf-8"?>\n'; | ||
var Feed = function () { | ||
function Feed(options) { | ||
_classCallCheck(this, Feed); | ||
this.options = options; | ||
this.items = []; | ||
this.categories = []; | ||
this.contributors = []; | ||
this.extensions = []; | ||
} | ||
_createClass(Feed, [{ | ||
key: 'addItem', | ||
value: function addItem(item) { | ||
this.items.push(item); | ||
} | ||
}, { | ||
key: 'addCategory', | ||
value: function addCategory(category) { | ||
this.categories.push(category); | ||
} | ||
}, { | ||
key: 'addContributor', | ||
value: function addContributor(contributor) { | ||
this.contributors.push(contributor); | ||
} | ||
}, { | ||
key: 'addExtension', | ||
value: function addExtension(extension) { | ||
this.extensions.push(extension); | ||
} | ||
}, { | ||
key: 'render', | ||
value: function render(format) { | ||
console.warn('DEPRECATED: use atom1() or rss2() instead of render()'); | ||
if (format === 'atom-1.0') { | ||
return this.atom1(); | ||
} else { | ||
return this.rss2(); | ||
} | ||
} | ||
}, { | ||
key: 'atom1', | ||
value: function atom1() { | ||
var _this = this; | ||
var options = this.options; | ||
var feed = [{ _attr: { xmlns: 'http://www.w3.org/2005/Atom' } }, { id: options.id }, { title: options.title }, { updated: options.updated ? this.ISODateString(options.updated) : this.ISODateString(new Date()) }, { generator: options.generator || GENERATOR }]; | ||
var root = [{ feed: feed }]; | ||
if (options.author) { | ||
var _options$author = options.author, | ||
name = _options$author.name, | ||
email = _options$author.email, | ||
link = _options$author.link; | ||
var author = []; | ||
if (name) { | ||
author.push({ name: name }); | ||
} | ||
if (email) { | ||
author.push({ email: email }); | ||
} | ||
if (link) { | ||
author.push({ uri: link }); | ||
} | ||
feed.push({ author: author }); | ||
} | ||
// link (rel="alternate") | ||
if (options.link) { | ||
feed.push({ link: { _attr: { rel: 'alternate', href: options.link } } }); | ||
} | ||
// link (rel="self") | ||
var atomLink = options.feed || options.feedLinks && options.feedLinks.atom; | ||
if (atomLink) { | ||
feed.push({ "link": { _attr: { rel: 'self', href: atomLink } } }); | ||
} | ||
// link (rel="hub") | ||
if (options.hub) { | ||
feed.push({ link: { _attr: { rel: 'hub', href: options.hub } } }); | ||
} | ||
/************************************************************************** | ||
* "feed" node: optional elements | ||
*************************************************************************/ | ||
if (options.description) { | ||
feed.push({ subtitle: options.description }); | ||
} | ||
if (options.image) { | ||
feed.push({ logo: options.image }); | ||
} | ||
if (options.favicon) { | ||
feed.push({ icon: options.favicon }); | ||
} | ||
if (options.copyright) { | ||
feed.push({ rights: options.copyright }); | ||
} | ||
this.categories.forEach(function (category) { | ||
feed.push({ category: [{ _attr: { term: category } }] }); | ||
}); | ||
this.contributors.forEach(function (item) { | ||
var name = item.name, | ||
email = item.email, | ||
link = item.link; | ||
var contributor = []; | ||
if (name) { | ||
contributor.push({ name: name }); | ||
} | ||
if (email) { | ||
contributor.push({ email: email }); | ||
} | ||
if (link) { | ||
contributor.push({ uri: link }); | ||
} | ||
feed.push({ contributor: contributor }); | ||
}); | ||
// icon | ||
/************************************************************************** | ||
* "entry" nodes | ||
*************************************************************************/ | ||
this.items.forEach(function (item) { | ||
// | ||
// entry: required elements | ||
// | ||
var entry = [{ title: { _attr: { type: 'html' }, _cdata: item.title } }, { id: item.id || item.link }, { link: [{ _attr: { href: item.link } }] }, { updated: _this.ISODateString(item.date) }]; | ||
// | ||
// entry: recommended elements | ||
// | ||
if (item.description) { | ||
entry.push({ summary: { _attr: { type: 'html' }, _cdata: item.description } }); | ||
} | ||
if (item.content) { | ||
entry.push({ content: { _attr: { type: 'html' }, _cdata: item.content } }); | ||
} | ||
// entry author(s) | ||
if (Array.isArray(item.author)) { | ||
item.author.forEach(function (oneAuthor) { | ||
var name = oneAuthor.name, | ||
email = oneAuthor.email, | ||
link = oneAuthor.link; | ||
var author = []; | ||
if (name) { | ||
author.push({ name: name }); | ||
} | ||
if (email) { | ||
author.push({ email: email }); | ||
} | ||
if (link) { | ||
author.push({ uri: link }); | ||
} | ||
entry.push({ author: author }); | ||
}); | ||
} | ||
// content | ||
// link - relative link to article | ||
// | ||
// entry: optional elements | ||
// | ||
// category | ||
// contributor | ||
if (Array.isArray(item.contributor)) { | ||
item.contributor.forEach(function (item) { | ||
var name = item.name, | ||
email = item.email, | ||
link = item.link; | ||
var contributor = []; | ||
if (name) { | ||
contributor.push({ name: name }); | ||
} | ||
if (email) { | ||
contributor.push({ email: email }); | ||
} | ||
if (link) { | ||
contributor.push({ uri: link }); | ||
} | ||
entry.push({ contributor: contributor }); | ||
}); | ||
} | ||
// published | ||
if (item.published) { | ||
entry.push({ published: _this.ISODateString(item.published) }); | ||
} | ||
// source | ||
// rights | ||
if (item.copyright) { | ||
entry.push({ rights: item.copyright }); | ||
} | ||
feed.push({ entry: entry }); | ||
}); | ||
return DOCTYPE + (0, _xml2.default)(root, true); | ||
} | ||
}, { | ||
key: 'rss2', | ||
value: function rss2() { | ||
var options = this.options; | ||
var isAtom = false; | ||
var isContent = false; | ||
var channel = [{ title: options.title }, { link: options.link }, { description: options.description }, { lastBuildDate: options.updated ? options.updated.toUTCString() : new Date().toUTCString() }, { docs: 'http://blogs.law.harvard.edu/tech/rss' }, { generator: options.generator || GENERATOR }]; | ||
var rss = [{ _attr: { version: '2.0' } }, { channel: channel }]; | ||
var root = [{ rss: rss }]; | ||
/** | ||
* Channel Image | ||
* http://cyber.law.harvard.edu/rss/rss.html#ltimagegtSubelementOfLtchannelgt | ||
*/ | ||
if (options.image) { | ||
channel.push({ | ||
image: [{ title: options.title }, { url: options.image }, { link: options.link }] | ||
}); | ||
} | ||
/** | ||
* Channel Copyright | ||
* http://cyber.law.harvard.edu/rss/rss.html#optionalChannelElements | ||
*/ | ||
if (options.copyright) { | ||
channel.push({ copyright: options.copyright }); | ||
} | ||
/** | ||
* Channel Categories | ||
* http://cyber.law.harvard.edu/rss/rss.html#comments | ||
*/ | ||
this.categories.forEach(function (category) { | ||
channel.push({ category: category }); | ||
}); | ||
/** | ||
* Feed URL | ||
* http://validator.w3.org/feed/docs/warning/MissingAtomSelfLink.html | ||
*/ | ||
var atomLink = options.feed || options.feedLinks && options.feedLinks.atom; | ||
if (atomLink) { | ||
isAtom = true; | ||
channel.push({ | ||
"atom:link": { | ||
_attr: { | ||
href: atomLink, | ||
rel: 'self', | ||
type: 'application/rss+xml' | ||
} | ||
} | ||
}); | ||
} | ||
/** | ||
* Hub for PubSubHubbub | ||
* https://code.google.com/p/pubsubhubbub/ | ||
*/ | ||
if (options.hub) { | ||
isAtom = true; | ||
channel.push({ | ||
"atom:link": { | ||
_attr: { | ||
href: options.hub, | ||
rel: 'hub' | ||
} | ||
} | ||
}); | ||
} | ||
/** | ||
* Channel Categories | ||
* http://cyber.law.harvard.edu/rss/rss.html#hrelementsOfLtitemgt | ||
*/ | ||
this.items.forEach(function (entry) { | ||
var item = []; | ||
if (entry.title) { | ||
item.push({ title: { _cdata: entry.title } }); | ||
} | ||
if (entry.link) { | ||
item.push({ link: entry.link }); | ||
} | ||
if (entry.guid) { | ||
item.push({ guid: entry.guid }); | ||
} else if (entry.link) { | ||
item.push({ guid: entry.link }); | ||
} | ||
if (entry.date) { | ||
item.push({ pubDate: entry.date.toUTCString() }); | ||
} | ||
if (entry.description) { | ||
item.push({ description: { _cdata: entry.description } }); | ||
} | ||
if (entry.content) { | ||
isContent = true; | ||
item.push({ 'content:encoded': { _cdata: entry.content } }); | ||
} | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var atom1_1 = require("./atom1"); | ||
var json_1 = require("./json"); | ||
var rss2_1 = require("./rss2"); | ||
var Feed = /** @class */ (function () { | ||
function Feed(options) { | ||
var _this = this; | ||
this.items = []; | ||
this.categories = []; | ||
this.contributors = []; | ||
this.extensions = []; | ||
this.addItem = function (item) { return _this.items.push(item); }; | ||
this.addCategory = function (category) { return _this.categories.push(category); }; | ||
this.addContributor = function (contributor) { return _this.contributors.push(contributor); }; | ||
this.addExtension = function (extension) { return _this.extensions.push(extension); }; | ||
/** | ||
* Item Author | ||
* http://cyber.law.harvard.edu/rss/rss.html#ltauthorgtSubelementOfLtitemgt | ||
* Returns a Atom 1.0 feed | ||
*/ | ||
if (Array.isArray(entry.author)) { | ||
entry.author.some(function (author) { | ||
if (author.email && author.name) { | ||
item.push({ author: author.email + ' (' + author.name + ')' }); | ||
return true; | ||
} else { | ||
return false; | ||
} | ||
}); | ||
} | ||
if (entry.image) { | ||
item.push({ enclosure: [{ _attr: { url: entry.image } }] }); | ||
} | ||
channel.push({ item: item }); | ||
}); | ||
if (isContent) { | ||
rss[0]._attr['xmlns:content'] = 'http://purl.org/rss/1.0/modules/content/'; | ||
} | ||
if (isAtom) { | ||
rss[0]._attr['xmlns:atom'] = 'http://www.w3.org/2005/Atom'; | ||
} | ||
return DOCTYPE + (0, _xml2.default)(root, true); | ||
this.atom1 = function () { return atom1_1.default(_this); }; | ||
/** | ||
* Returns a RSS 2.0 feed | ||
*/ | ||
this.rss2 = function () { return rss2_1.default(_this); }; | ||
/** | ||
* Returns a JSON1 feed | ||
*/ | ||
this.json1 = function () { return json_1.default(_this); }; | ||
this.options = options; | ||
} | ||
}, { | ||
key: 'json1', | ||
value: function json1() { | ||
var _this2 = this; | ||
var options = this.options, | ||
items = this.items, | ||
extensions = this.extensions; | ||
var feed = { | ||
version: 'https://jsonfeed.org/version/1', | ||
title: options.title | ||
}; | ||
if (options.link) { | ||
feed.home_page_url = options.link; | ||
} | ||
if (options.feedLinks && options.feedLinks.json) { | ||
feed.feed_url = options.feedLinks.json; | ||
} | ||
if (options.description) { | ||
feed.description = options.description; | ||
} | ||
if (options.image) { | ||
feed.icon = options.image; | ||
} | ||
if (options.author) { | ||
feed.author = {}; | ||
if (options.author.name) { | ||
feed.author.name = options.author.name; | ||
} | ||
if (options.author.link) { | ||
feed.author.url = options.author.link; | ||
} | ||
} | ||
extensions.forEach(function (e) { | ||
feed[e.name] = e.objects; | ||
}); | ||
feed.items = items.map(function (item) { | ||
var feedItem = { | ||
id: item.id, | ||
// json_feed distinguishes between html and text content | ||
// but since we only take a single type, we'll assume HTML | ||
html_content: item.content | ||
}; | ||
if (item.link) { | ||
feedItem.url = item.link; | ||
} | ||
if (item.title) { | ||
feedItem.title = item.title; | ||
} | ||
if (item.description) { | ||
feedItem.summary = item.description; | ||
} | ||
if (item.image) { | ||
feedItem.image = item.image; | ||
} | ||
if (item.date) { | ||
feedItem.date_modified = _this2.ISODateString(item.date); | ||
} | ||
if (item.published) { | ||
feedItem.date_published = _this2.ISODateString(item.published); | ||
} | ||
if (item.author) { | ||
var author = item.author; | ||
if (author instanceof Array) { | ||
// json feed only supports 1 author per post | ||
author = author[0]; | ||
} | ||
feedItem.author = {}; | ||
if (author.name) { | ||
feedItem.author.name = author.name; | ||
} | ||
if (author.link) { | ||
feedItem.author.url = author.link; | ||
} | ||
} | ||
if (item.extensions) { | ||
item.extensions.forEach(function (e) { | ||
feedItem[e.name] = e.objects; | ||
}); | ||
} | ||
return feedItem; | ||
}); | ||
return JSON.stringify(feed, null, 4); | ||
} | ||
}, { | ||
key: 'ISODateString', | ||
value: function ISODateString(d) { | ||
function pad(n) { | ||
return n < 10 ? '0' + n : n; | ||
} | ||
return d.getUTCFullYear() + '-' + pad(d.getUTCMonth() + 1) + '-' + pad(d.getUTCDate()) + 'T' + pad(d.getUTCHours()) + ':' + pad(d.getUTCMinutes()) + ':' + pad(d.getUTCSeconds()) + 'Z'; | ||
} | ||
}]); | ||
return Feed; | ||
}(); | ||
module.exports = Feed; | ||
//# sourceMappingURL=feed.js.map | ||
return Feed; | ||
}()); | ||
exports.Feed = Feed; |
{ | ||
"name": "feed", | ||
"version": "1.1.1", | ||
"description": "Feed is a RSS and Atom feed generator for Node.js, making content syndication simple and intuitive!", | ||
"homepage": "http://projets.jpmonette.net/en/feed", | ||
"version": "2.0.0", | ||
"description": "Feed is a RSS, Atom and JSON feed generator for Node.js, making content syndication simple and intuitive!", | ||
"homepage": "https://github.com/jpmonette", | ||
"author": "Jean-Philippe Monette <contact@jpmonette.net>", | ||
"contributors": [ | ||
{ | ||
"name": "Ben McCormick", | ||
"email": "ben.mccormick@windsorcircle.com" | ||
}, | ||
{ | ||
"name": "Pierre Galvez", | ||
"email": "contact@pierre-galvez.fr" | ||
} | ||
], | ||
"license": "MIT", | ||
"main": "lib/feed.js", | ||
"types": "dist/feed.d.ts", | ||
"scripts": { | ||
"build": "rm -rf lib/ && mkdir lib && babel -d lib/ src/ --ignore **/*.spec.js -s", | ||
"build": "rm -rf lib/ && mkdir lib && tsc", | ||
"prepublish": "npm run build", | ||
"test": "export NODE_ENV=test && jest", | ||
"test": "export NODE_ENV=test && jest --silent", | ||
"test-travis": "export NODE_ENV=test && jest --coverage" | ||
}, | ||
"jest": { | ||
"verbose": true, | ||
"collectCoverage": true, | ||
"collectCoverageFrom": [ | ||
"**/src/*.{js}" | ||
], | ||
"testMatch": [ | ||
"**/*.spec.js" | ||
] | ||
}, | ||
"keywords": [ | ||
@@ -45,10 +26,17 @@ "rss", | ||
"dependencies": { | ||
"luxon": "^1.3.3", | ||
"xml": "^1.0.1" | ||
}, | ||
"devDependencies": { | ||
"babel-cli": "^6.24.1", | ||
"babel-preset-env": "^1.5.1", | ||
"@types/jest": "^23.3.1", | ||
"@types/xml": "^1.0.2", | ||
"awesome-typescript-loader": "^5.2.0", | ||
"codeclimate-test-reporter": "^0.5.0", | ||
"coveralls": "^2.13.1", | ||
"jest": "^20.0.4" | ||
"jest": "^23.4.2", | ||
"prettier": "^1.14.0", | ||
"source-map-loader": "^0.2.3", | ||
"ts-jest": "^23.1.2", | ||
"tslint": "^5.11.0", | ||
"typescript": "^3.0.1" | ||
}, | ||
@@ -55,0 +43,0 @@ "engines": { |
166
README.md
@@ -1,56 +0,51 @@ | ||
# Feed for Node.js | ||
<p align="center"> | ||
<img src="./assets/title.png" alt="Feed for Node.js" width="326"> | ||
<br> | ||
<a href="https://travis-ci.org/jpmonette/feed"><img src="https://travis-ci.org/jpmonette/feed.svg?branch=master" alt="Build Status"></a> <a href='https://coveralls.io/github/jpmonette/feed?branch=master'><img src='https://coveralls.io/repos/github/jpmonette/feed/badge.svg?branch=master' alt='Coverage Status' /></a> <a href="https://badge.fury.io/js/feed"><img src="https://badge.fury.io/js/feed.svg" alt="npm version" height="18"></a> <a href="https://github.com/facebook/jest"><img src="https://img.shields.io/badge/tested_with-jest-99424f.svg" alt="Tested with Jest"></a> <a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT"></a> | ||
</p> | ||
<p align="center"><code>jpmonette/feed</code> - <strong>RSS 2.0, JSON Feed 1.0, and Atom 1.0</strong> generator for <strong>Node.js</strong><br> | ||
Making content syndication simple and intuitive!</p> | ||
> [Feed](http://projets.jpmonette.net/en/feed) is a *RSS 2.0*, *JSON Feed 1.0*, and *Atom 1.0* generator for **Node.js**, making content syndication simple and intuitive! | ||
--- | ||
[![Build Status](https://travis-ci.org/jpmonette/feed.svg?branch=master)](https://travis-ci.org/jpmonette/feed) | ||
[![Coverage Status](https://coveralls.io/repos/github/jpmonette/feed/badge.svg?branch=master)](https://coveralls.io/github/jpmonette/feed?branch=master) | ||
**👩🏻💻 Developer Ready**: Quickly generate syndication feeds for your Website. | ||
**💪🏼 Strongly Typed**: Developed using TypeScript / type-safe. | ||
**🔒 Tested**: Tests & snapshot for each syndication format to avoid regressions. | ||
# Getting Started | ||
## Installation | ||
```bash | ||
$ npm install feed | ||
$ yarn add feed | ||
``` | ||
## Features | ||
## Example | ||
* Pure JavaScript | ||
* Support for Atom 1.0 and RSS 2.0 | ||
* Lightweight - Only 1 dependency! | ||
## Quick Start | ||
First, add the module: | ||
```js | ||
const Feed = require('feed') | ||
``` | ||
import { Feed } from "feed"; | ||
Insert feed-specific information: | ||
```js | ||
let feed = new Feed({ | ||
title: 'Feed Title', | ||
description: 'This is my personal feed!', | ||
id: 'http://example.com/', | ||
link: 'http://example.com/', | ||
image: 'http://example.com/image.png', | ||
favicon: 'http://example.com/favicon.ico', | ||
copyright: 'All rights reserved 2013, John Doe', | ||
updated: new Date(2013, 06, 14), // optional, default = today | ||
generator: 'awesome', // optional, default = 'Feed for Node.js' | ||
const feed = new Feed({ | ||
title: "Feed Title", | ||
description: "This is my personal feed!", | ||
id: "http://example.com/", | ||
link: "http://example.com/", | ||
image: "http://example.com/image.png", | ||
favicon: "http://example.com/favicon.ico", | ||
copyright: "All rights reserved 2013, John Doe", | ||
updated: new Date(2013, 6, 14), // optional, default = today | ||
generator: "awesome", // optional, default = 'Feed for Node.js' | ||
feedLinks: { | ||
json: 'https://example.com/json', | ||
atom: 'https://example.com/atom', | ||
json: "https://example.com/json", | ||
atom: "https://example.com/atom" | ||
}, | ||
author: { | ||
name: 'John Doe', | ||
email: 'johndoe@example.com', | ||
link: 'https://example.com/johndoe' | ||
name: "John Doe", | ||
email: "johndoe@example.com", | ||
link: "https://example.com/johndoe" | ||
} | ||
}) | ||
``` | ||
}); | ||
Insert items using the item function: | ||
```js | ||
posts.forEach(post => { | ||
@@ -63,68 +58,53 @@ feed.addItem({ | ||
content: post.content, | ||
author: [{ | ||
name: 'Jane Doe', | ||
email: 'janedoe@example.com', | ||
link: 'https://example.com/janedoe' | ||
}, { | ||
name: 'Joe Smith', | ||
email: 'joesmith@example.com', | ||
link: 'https://example.com/joesmith' | ||
}], | ||
contributor: [{ | ||
name: 'Shawn Kemp', | ||
email: 'shawnkemp@example.com', | ||
link: 'https://example.com/shawnkemp' | ||
}, { | ||
name: 'Reggie Miller', | ||
email: 'reggiemiller@example.com', | ||
link: 'https://example.com/reggiemiller' | ||
}], | ||
author: [ | ||
{ | ||
name: "Jane Doe", | ||
email: "janedoe@example.com", | ||
link: "https://example.com/janedoe" | ||
}, | ||
{ | ||
name: "Joe Smith", | ||
email: "joesmith@example.com", | ||
link: "https://example.com/joesmith" | ||
} | ||
], | ||
contributor: [ | ||
{ | ||
name: "Shawn Kemp", | ||
email: "shawnkemp@example.com", | ||
link: "https://example.com/shawnkemp" | ||
}, | ||
{ | ||
name: "Reggie Miller", | ||
email: "reggiemiller@example.com", | ||
link: "https://example.com/reggiemiller" | ||
} | ||
], | ||
date: post.date, | ||
image: post.image | ||
}) | ||
}) | ||
``` | ||
}); | ||
}); | ||
Insert categories using: | ||
feed.addCategory("Technologie"); | ||
```js | ||
feed.addCategory('Technologie') | ||
``` | ||
Insert contributors using: | ||
```js | ||
feed.addContributor({ | ||
name: 'Johan Cruyff', | ||
email: 'johancruyff@example.com', | ||
link: 'https://example.com/johancruyff' | ||
}) | ||
``` | ||
name: "Johan Cruyff", | ||
email: "johancruyff@example.com", | ||
link: "https://example.com/johancruyff" | ||
}); | ||
Output a RSS 2.0 feed: | ||
console.log(feed.rss2()); | ||
// Output: RSS 2.0 | ||
```js | ||
feed.rss2() | ||
``` | ||
console.log(feed.atom1()); | ||
// Output: Atom 1.0 | ||
Output an Atom 1.0 feed: | ||
```js | ||
feed.atom1() | ||
console.log(feed.json1()); | ||
// Output: JSON Feed 1.0 | ||
``` | ||
Output a JSON Feed 1.0 feed: | ||
```js | ||
feed.json1() | ||
``` | ||
Yes, it's that simple :)! | ||
## More Information | ||
* [Feed for Node.js](http://projets.jpmonette.net/en/feed) (English) | ||
* [Feed pour Node.js](http://projets.jpmonette.net/feed) (French) | ||
* Follow [@jpmonette](https://twitter.com/jpmonette) on Twitter for updates | ||
* Read my personal blog [Blogue de Jean-Philippe Monette](http://blogue.jpmonette.net/) to learn more about what I do! | ||
- Follow [@jpmonette](https://twitter.com/jpmonette) on Twitter for updates | ||
- Read my personal blog [Blogue de Jean-Philippe Monette](http://blogue.jpmonette.net/) to learn more about what I do! | ||
@@ -131,0 +111,0 @@ ## License |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
228963
36
0
2
11
925
119
1
+ Addedluxon@^1.3.3
+ Addedluxon@1.28.1(transitive)