event-drops
Advanced tools
Comparing version 0.1.1 to 0.2.0
@@ -1,248 +0,65 @@ | ||
"use strict"; | ||
/* global require, module */ | ||
import d3 from 'd3'; | ||
var configurable = require('./util/configurable'); | ||
var eventLine = require('./eventLine'); | ||
var delimiter = require('./delimiter'); | ||
import configurable from 'configurable.js'; | ||
import defaultConfig from './config'; | ||
import drawer from './drawer'; | ||
import zoom from './zoom'; | ||
module.exports = function (d3) { | ||
function eventDrops(config = {}) { | ||
const finalConfiguration = {...defaultConfig, ...config}; | ||
var defaultConfig = { | ||
start: new Date(0), | ||
end: new Date(), | ||
minScale: 0, | ||
maxScale: Infinity, | ||
width: 1000, | ||
margin: { | ||
top: 60, | ||
left: 200, | ||
bottom: 40, | ||
right: 50 | ||
}, | ||
locale: null, | ||
axisFormat: null, | ||
tickFormat: [ | ||
[".%L", function(d) { return d.getMilliseconds(); }], | ||
[":%S", function(d) { return d.getSeconds(); }], | ||
["%I:%M", function(d) { return d.getMinutes(); }], | ||
["%I %p", function(d) { return d.getHours(); }], | ||
["%a %d", function(d) { return d.getDay() && d.getDate() != 1; }], | ||
["%b %d", function(d) { return d.getDate() != 1; }], | ||
["%B", function(d) { return d.getMonth(); }], | ||
["%Y", function() { return true; }] | ||
], | ||
eventHover: null, | ||
eventZoom: null, | ||
hasDelimiter: true, | ||
hasTopAxis: true, | ||
hasBottomAxis: function (data) { | ||
return data.length >= 10; | ||
}, | ||
eventLineColor: 'black', | ||
eventColor: null | ||
}; | ||
const yScale = (data) => { | ||
const scale = d3.scale.ordinal(); | ||
return function eventDrops(config) { | ||
var xScale = d3.time.scale(); | ||
var yScale = d3.scale.ordinal(); | ||
config = config || {}; | ||
for (var key in defaultConfig) { | ||
config[key] = config[key] || defaultConfig[key]; | ||
} | ||
return scale | ||
.domain(data.map((d) => d.name)) | ||
.range(data.map((d, i) => i * 40)); | ||
}; | ||
const xScale = (width, timeBounds) => { | ||
return d3.time.scale() | ||
.range([0, width]) | ||
.domain(timeBounds); | ||
}; | ||
function eventDropGraph(selection) { | ||
selection.each(function (data) { | ||
var zoom = d3.behavior.zoom().center(null).scaleExtent([config.minScale, config.maxScale]).on("zoom", updateZoom); | ||
selection.each(function selector(data) { | ||
d3.select(this).select('.event-drops-chart').remove(); | ||
zoom.on("zoomend", zoomEnd); | ||
const height = data.length * 40; | ||
const dimensions = { | ||
width: finalConfiguration.width - finalConfiguration.margin.right - finalConfiguration.margin.left, | ||
height, | ||
outer_height: height + finalConfiguration.margin.top + finalConfiguration.margin.bottom, | ||
}; | ||
var graphWidth = config.width - config.margin.right - config.margin.left; | ||
var graphHeight = data.length * 40; | ||
var height = graphHeight + config.margin.top + config.margin.bottom; | ||
const scales = { | ||
x: xScale(dimensions.width, [finalConfiguration.start, finalConfiguration.end]), | ||
y: yScale(data), | ||
}; | ||
d3.select(this).select('svg').remove(); | ||
const svg = d3.select(this).append('svg') | ||
.classed('event-drops-chart', true) | ||
.attr({ | ||
width: dimensions.width, | ||
height: dimensions.outer_height, | ||
}); | ||
var svg = d3.select(this) | ||
.append('svg') | ||
.attr('width', config.width) | ||
.attr('height', height) | ||
; | ||
const draw = drawer(svg, dimensions, scales, finalConfiguration).bind(selection); | ||
draw(data); | ||
var graph = svg.append('g') | ||
.attr('transform', 'translate(0, 25)'); | ||
var yDomain = []; | ||
var yRange = []; | ||
data.forEach(function (event, index) { | ||
yDomain.push(event.name); | ||
yRange.push(index * 40); | ||
if (finalConfiguration.zoomable) { | ||
zoom(d3.select(this), dimensions, scales, finalConfiguration, data, draw); | ||
} | ||
}); | ||
} | ||
yScale.domain(yDomain).range(yRange); | ||
configurable(eventDropGraph, finalConfiguration); | ||
var yAxisEl = graph.append('g') | ||
.classed('y-axis', true) | ||
.attr('transform', 'translate(0, 60)'); | ||
return eventDropGraph; | ||
} | ||
var yTick = yAxisEl.append('g').selectAll('g').data(yDomain); | ||
d3.chart = d3.chart || {}; | ||
d3.chart.eventDrops = eventDrops; | ||
yTick.enter() | ||
.append('g') | ||
.attr('transform', function(d) { | ||
return 'translate(0, ' + yScale(d) + ')'; | ||
}) | ||
.append('line') | ||
.classed('y-tick', true) | ||
.attr('x1', config.margin.left) | ||
.attr('x2', config.margin.left + graphWidth); | ||
yTick.exit().remove(); | ||
var curx, cury; | ||
var zoomRect = svg | ||
.append('rect') | ||
.call(zoom) | ||
.classed('zoom', true) | ||
.attr('width', graphWidth) | ||
.attr('height', height ) | ||
.attr('transform', 'translate(' + config.margin.left + ', 35)') | ||
; | ||
if (typeof config.eventHover === 'function') { | ||
zoomRect.on('mousemove', function(d, e) { | ||
var event = d3.event; | ||
if (curx == event.clientX && cury == event.clientY) return; | ||
curx = event.clientX; | ||
cury = event.clientY; | ||
zoomRect.attr('display', 'none'); | ||
var el = document.elementFromPoint(d3.event.clientX, d3.event.clientY); | ||
zoomRect.attr('display', 'block'); | ||
if (el.tagName !== 'circle') return; | ||
config.eventHover(el); | ||
}); | ||
} | ||
xScale.range([0, graphWidth]).domain([config.start, config.end]); | ||
zoom.x(xScale); | ||
function updateZoom() { | ||
if (d3.event.sourceEvent.toString() === '[object MouseEvent]') { | ||
zoom.translate([d3.event.translate[0], 0]); | ||
} | ||
if (d3.event.sourceEvent.toString() === '[object WheelEvent]') { | ||
zoom.scale(d3.event.scale); | ||
} | ||
redraw(); | ||
} | ||
function redrawDelimiter() { | ||
svg.select('.delimiter').remove(); | ||
var delimiterEl = svg | ||
.append('g') | ||
.classed('delimiter', true) | ||
.attr('width', graphWidth) | ||
.attr('height', 10) | ||
.attr('transform', 'translate(' + config.margin.left + ', ' + (config.margin.top - 45) + ')') | ||
.call(delimiter({ | ||
xScale: xScale, | ||
dateFormat: config.locale ? config.locale.timeFormat("%d %B %Y") : d3.time.format("%d %B %Y") | ||
})) | ||
; | ||
} | ||
function zoomEnd() { | ||
if (config.eventZoom) { | ||
config.eventZoom(xScale); | ||
} | ||
if (config.hasDelimiter) { | ||
redrawDelimiter(); | ||
} | ||
} | ||
function drawXAxis(where) { | ||
// copy config.tickFormat because d3 format.multi edit its given tickFormat data | ||
var tickFormatData = []; | ||
config.tickFormat.forEach(function (item) { | ||
var tick = item.slice(0); | ||
tickFormatData.push(tick); | ||
}); | ||
var tickFormat = config.locale ? config.locale.timeFormat.multi(tickFormatData) : d3.time.format.multi(tickFormatData); | ||
var xAxis = d3.svg.axis() | ||
.scale(xScale) | ||
.orient(where) | ||
.tickFormat(tickFormat) | ||
; | ||
if (typeof config.axisFormat === 'function') { | ||
config.axisFormat(xAxis); | ||
} | ||
var y = (where == 'bottom' ? parseInt(graphHeight) : 0) + config.margin.top - 40; | ||
graph.select('.x-axis.' + where).remove(); | ||
var xAxisEl = graph | ||
.append('g') | ||
.classed('x-axis', true) | ||
.classed(where, true) | ||
.attr('transform', 'translate(' + config.margin.left + ', ' + y + ')') | ||
.call(xAxis) | ||
; | ||
} | ||
function redraw() { | ||
var hasTopAxis = typeof config.hasTopAxis === 'function' ? config.hasTopAxis(data) : config.hasTopAxis; | ||
if (hasTopAxis) { | ||
drawXAxis('top'); | ||
} | ||
var hasBottomAxis = typeof config.hasBottomAxis === 'function' ? config.hasBottomAxis(data) : config.hasBottomAxis; | ||
if (hasBottomAxis) { | ||
drawXAxis('bottom'); | ||
} | ||
zoom.size([config.width, height]); | ||
graph.select('.graph-body').remove(); | ||
var graphBody = graph | ||
.append('g') | ||
.classed('graph-body', true) | ||
.attr('transform', 'translate(' + config.margin.left + ', ' + (config.margin.top - 15) + ')'); | ||
var lines = graphBody.selectAll('g').data(data); | ||
lines.enter() | ||
.append('g') | ||
.classed('line', true) | ||
.attr('transform', function(d) { | ||
return 'translate(0,' + yScale(d.name) + ')'; | ||
}) | ||
.style('fill', config.eventLineColor) | ||
.call(eventLine({ xScale: xScale, eventColor: config.eventColor })) | ||
; | ||
lines.exit().remove(); | ||
} | ||
redraw(); | ||
if (config.hasDelimiter) { | ||
redrawDelimiter(); | ||
} | ||
if (config.eventZoom) { | ||
config.eventZoom(xScale); | ||
} | ||
}); | ||
} | ||
configurable(eventDropGraph, config); | ||
return eventDropGraph; | ||
}; | ||
}; | ||
module.exports = eventDrops; |
@@ -1,19 +0,4 @@ | ||
"use strict"; | ||
/* global module */ | ||
module.exports = function filterDate(data, scale) { | ||
data = data || []; | ||
var filteredData = []; | ||
var boundary = scale.range(); | ||
var min = boundary[0]; | ||
var max = boundary[1]; | ||
data.forEach(function (datum) { | ||
var value = scale(datum); | ||
if (value < min || value > max) { | ||
return; | ||
} | ||
filteredData.push(datum); | ||
}); | ||
return filteredData; | ||
}; | ||
export default function filterData(data = [], scale) { | ||
const [min, max] = scale.domain(); | ||
return data.filter(d => d >= min && d <= max); | ||
} |
{ | ||
"name": "event-drops", | ||
"version": "0.1.1", | ||
"version": "0.2.0", | ||
"description": "A time based / event series interactive visualization using d3.js. Use drag and zoom to navigate in time.", | ||
"main": "src/EventDrop.js", | ||
"main": "dist/eventDrops.js", | ||
"repository": { | ||
@@ -10,17 +10,30 @@ "type": "git", | ||
}, | ||
"dependencies": {}, | ||
"dependencies": { | ||
"d3": "3.5.3" | ||
}, | ||
"devDependencies": { | ||
"browserify": "5.11.2", | ||
"d3": "3.4.11", | ||
"gulp": "3.8.10", | ||
"gulp-mocha": "0.5.2", | ||
"gulp-streamify": "0.0.5", | ||
"gulp-uglify": "^1.0.1", | ||
"babel-core": "6.4.5", | ||
"babel-eslint": "^4.1.8", | ||
"babel-loader": "6.2.1", | ||
"babel-preset-es2015": "6.3.13", | ||
"babel-preset-stage-0": "^6.3.13", | ||
"configurable.js": "0.1.0", | ||
"css-loader": "0.19.0", | ||
"eslint": "1.6.0", | ||
"eslint-config-airbnb": "0.1.0", | ||
"extract-text-webpack-plugin": "1.0.1", | ||
"html-loader": "0.3.0", | ||
"html-webpack-plugin": "1.6.1", | ||
"jasmine-core": "2.4.1", | ||
"jsdom": "1.0.0-pre.6", | ||
"karma": "0.12.23", | ||
"karma-chrome-launcher": "0.1.4", | ||
"karma-jasmine": "0.1.5", | ||
"karma": "^0.13.19", | ||
"karma-jasmine": "^0.3.6", | ||
"karma-firefox-launcher": "0.1.7", | ||
"karma-webpack": "^1.7.0", | ||
"mocha": "1.21.4", | ||
"vinyl-source-stream": "0.1.1", | ||
"watchify": "1.0.1" | ||
"mocha-traceur": "2.1.0", | ||
"scss-loader": "0.0.1", | ||
"style-loader": "0.12.4", | ||
"webpack": "1.12.2", | ||
"webpack-dev-server": "1.11.0" | ||
}, | ||
@@ -38,4 +51,16 @@ "bugs": { | ||
}, | ||
"author": "thiery <thiery@marmelab.com>", | ||
"license": "ISC" | ||
"author": "Thiery Michel <thiery@marmelab.com>", | ||
"contributors": [ | ||
{ "name": "Chad Ramos" }, | ||
{ "name": "Chulki Lee" }, | ||
{ "name": "Emmanuel Quentin" }, | ||
{ "name": "Francois Zaninotto" }, | ||
{ "name": "Joan Yin" }, | ||
{ "name": "Joel Schlosser" }, | ||
{ "name": "Jonathan Petitcolas", "email": "petitcolas.jonathan@gmail.com" }, | ||
{ "name": "Mélodie Benmouffek" }, | ||
{ "name": "messense" }, | ||
{ "name": "Robin Bressan" } | ||
], | ||
"license": "MIT" | ||
} |
EventDrops | ||
========== | ||
A time based / event series interactive visualization using d3.js. Use drag and zoom to navigate in time. | ||
A time based / event series interactive visualization using d3.js. Use drag and zoom to navigate in time. [See the demo](http://marmelab.com/EventDrops/) | ||
![EventDrops example](http://static.marmelab.com/EventDrops.gif) | ||
## Installation | ||
You can use `npm` to install event-drops | ||
``` | ||
npm install event-drops --save | ||
``` | ||
For Bower users, even if Bower is not officially supported, you can still use GitHub URL such as: | ||
``` | ||
{ | ||
"dependencies": { | ||
"eventDrops": "marmelab/EventDrops#0.1.2" | ||
} | ||
} | ||
``` | ||
## Usage | ||
@@ -55,6 +73,7 @@ | ||
- `locale`: locale used for the X axis labels. See [d3.locale](https://github.com/mbostock/d3/wiki/Localization#locale) for the expected format. Defaults to null (i.e. d3 default locale). | ||
- `axisFormat`: function receiving the d3 axis object, to customize tick number and size. | ||
- `axisFormat`: function receiving the d3 axis object, to customize tick number and size. | ||
- `tickFormat`: tickFormat for the X axis. See [d3.timeFormat.multi()](https://github.com/mbostock/d3/wiki/Time-Formatting#format_multi) for expected format. | ||
- `eventHover`: function to be called when hovering an event in the chart. Receives the DOM element hovered (uses event delegation). | ||
- `eventZoom`: function to be called when done zooming on the chart. Receives the d3 scale at the end of the zoom. | ||
- `eventClick`: function to be called on click event of data-point (circle). Receives the DOM element hovered (uses event delegation). | ||
- `hasDelimiter`: whether to draw time boundaries on top of the chart. Defaults to true. | ||
@@ -67,2 +86,3 @@ - `hasTopAxis`: whether the chart has a top X axis. Accepts both a boolean or a function receiving the data of the graph that returns a boolean. | ||
- `maxScale`: The maximum scaling (zoom in), default to Infinity. | ||
- `zoomable`: *true* by default. Enable zoom-in/zoom-out and dragging handlers. | ||
@@ -78,27 +98,31 @@ ## Styling | ||
```sh | ||
$ npm install | ||
make install | ||
``` | ||
Source files are located under the `lib/` folder, and use [browserify](http://browserify.org/) for dependency management. | ||
Once your changes are finished, regenerate the combined and minified source under `src/` by calling the following command: | ||
For development purpose, you can use the following command: | ||
```sh | ||
$ gulp browserify | ||
``` sh | ||
make run | ||
``` | ||
To update your change dynamically and have sourcemap that allow the console to map to the original file type: | ||
It serves the demo at http://localhost:8080. It also watches source files and live | ||
reloads your browser as soon as a change is detected. | ||
When your changes are done, ensure that all tests pass with: | ||
``` sh | ||
make test | ||
``` | ||
$ gulp watch | ||
``` | ||
To run the test : | ||
Finally, if everything is fine, you can rebuild the library using: | ||
``` sh | ||
make build | ||
``` | ||
$ gulp test // all test | ||
$ gulp karma-test | ||
$ gulp mocha-test | ||
``` | ||
You can test the result by launching a server at the project root, and navigating to the `examples/` directory. | ||
However, for better Pull Request reviewing, please do not commit the build files | ||
in the same PR. You can then rebuild it once merged. | ||
## License | ||
EventDrops is released under the MIT License, courtesy of [marmelab](http://marmelab.com) and [Canal Plus](https://github.com/canalplus). |
@@ -1,100 +0,83 @@ | ||
"use strict"; | ||
require('../../lib/eventDrops'); | ||
describe('d3.chart.eventDrops', function () { | ||
var eventDrops, elements; | ||
describe('d3.chart.eventDrops', () => { | ||
it('should append a SVG element to given selection', () => { | ||
const div = document.createElement('div'); | ||
const data = [{ name: 'foo', dates: [] }]; | ||
beforeEach(function () { | ||
var body = d3.select(document.createElement('body')); | ||
elements = body | ||
.selectAll('div') | ||
.data([[{name: "field1", dates: []}, {name: "field2", dates: []}], [{name: "field1", dates: []}, {name: "field2", dates: []}]]) | ||
; | ||
elements | ||
.enter() | ||
.append('div') | ||
; | ||
const chart = d3.chart.eventDrops(); | ||
d3.select(div).datum(data).call(chart); | ||
elements.exit().remove(); | ||
expect(div.querySelectorAll('svg.event-drops-chart').length).toBe(1); | ||
}); | ||
eventDrops = d3.chart.eventDrops(); | ||
it('should remove all previously created charts in current selection to prevent duplicates', () => { | ||
const div = document.createElement('div'); | ||
const data = [{ name: 'foo', dates: [] }]; | ||
eventDrops(elements); | ||
}); | ||
const chart = d3.chart.eventDrops(); | ||
d3.select(div).datum(data).call(chart); | ||
d3.select(div).datum(data).call(chart); | ||
it('should add a eventDrops function to d3 that return a function', function () { | ||
expect(typeof d3.chart.eventDrops).toBe('function'); | ||
expect(div.querySelectorAll('svg.event-drops-chart').length).toBe(1); | ||
}); | ||
expect(typeof d3.chart.eventDrops()).toBe('function'); | ||
}); | ||
describe('start period', () => { | ||
it('should be configurable', () => { | ||
const div = document.createElement('div'); | ||
const data = [{ name: 'foo', dates: [] }]; | ||
it ('should append one svg element to the given elements or replace it when called', function () { | ||
elements.each(function (data) { | ||
var svgs = d3.select(this).selectAll('svg')[0]; | ||
expect(svgs.length).toBe(1); | ||
}); | ||
const chart = d3.chart.eventDrops().start(new Date('2010-01-25')); | ||
d3.select(div).datum(data).call(chart); | ||
eventDrops(elements); | ||
elements.each(function (data) { | ||
var svgs = d3.select(this).selectAll('svg')[0]; | ||
expect(svgs.length).toBe(1); | ||
expect(div.querySelector('.extremum .minimum').textContent).toBe('25 January 2010'); | ||
}); | ||
}); | ||
}); | ||
it ('should have a configurable start', function () { | ||
expect(typeof eventDrops.start).toBe('function'); | ||
expect(eventDrops.start().getTime()).toBe((new Date(0)).getTime()); | ||
it('should have as many lines as events', () => { | ||
const div = document.createElement('div'); | ||
const data = [ | ||
{ name: 'foo', dates: [] }, | ||
{ name: 'bar', dates: [] }, | ||
{ name: 'quz', dates: [] }, | ||
]; | ||
eventDrops.start(new Date()); | ||
expect(eventDrops.start().getTime()).toBe((new Date()).getTime()); | ||
}); | ||
const chart = d3.chart.eventDrops().start(new Date('2010-01-25')); | ||
d3.select(div).datum(data).call(chart); | ||
it ('should have as many line as event', function () { | ||
elements.each(function (data) { | ||
var svg = d3.select(this).select('svg'); | ||
var lines = svg.selectAll('.line')[0]; | ||
expect(lines.length).toBe(2); | ||
expect(div.querySelectorAll('.drop-line').length).toBe(3); | ||
}); | ||
elements = elements.data([[{name: "field1", dates: []}]]); | ||
it('should have as many drops as given dates', () => { | ||
const div = document.createElement('div'); | ||
const data = [ | ||
{ name: 'foo', dates: [new Date('2010-01-01')] }, | ||
{ name: 'bar', dates: [] }, | ||
{ name: 'quz', dates: [new Date('2011-01-04'), new Date('2012-08-09')] }, | ||
]; | ||
eventDrops(elements); | ||
const chart = d3.chart.eventDrops().start(new Date('2010-01-25')); | ||
d3.select(div).datum(data).call(chart); | ||
elements.each(function (data) { | ||
var svg = d3.select(this).select('svg'); | ||
var lines = svg.selectAll('.line')[0]; | ||
expect(lines.length).toBe(1); | ||
expect(div.querySelectorAll('.drop').length).toBe(3); | ||
}); | ||
}); | ||
it('should enable zoom only if `zoomable` configuration property is true', () => { | ||
const zoom = require('../../lib/zoom'); | ||
const data = [ { name: 'foo', dates: [new Date()] }]; | ||
it ('should have as many circle by name as timestamps', function () { | ||
elements.each(function (data) { | ||
var lines = d3.select(this).select('svg').selectAll('.line'); | ||
const test = (zoomable, expectedZoomableBehavior) => { | ||
zoom.default = jasmine.createSpy(); | ||
lines.each(function (data) { | ||
var circles = d3.select(this).selectAll('circle')[0]; | ||
expect(circles.length).toBe(data.dates.length); | ||
}); | ||
}); | ||
const div = document.createElement('div'); | ||
elements = elements.data([[{name: "field1", dates: [new Date(1402318080000), new Date(1402323060000), new Date(1402332120000)]}]]); | ||
const chart = d3.chart.eventDrops().zoomable(zoomable); | ||
d3.select(div).datum(data).call(chart); | ||
eventDrops(elements); | ||
expect(zoom.default.calls.any()).toBe(expectedZoomableBehavior); | ||
}; | ||
elements.each(function (data) { | ||
var lines = d3.select(this).select('svg').selectAll('.line'); | ||
expect(data.length).toBe(1); | ||
lines.each(function (data) { | ||
expect(data.dates.length).toBe(3); | ||
var circles = d3.select(this).selectAll('circle')[0]; | ||
expect(circles.length).toBe(data.dates.length); | ||
}); | ||
test(false, false); | ||
test(true, true); | ||
}); | ||
}); | ||
}); |
@@ -1,13 +0,29 @@ | ||
// karma.conf.js | ||
module.exports = function(config) { | ||
config.set({ | ||
basePath: '../..', | ||
frameworks: ['jasmine'], | ||
browsers: ['Chrome'], | ||
files: [ | ||
'node_modules/d3/d3.js', | ||
'src/eventDrops.js', | ||
'test/karma/*' | ||
] | ||
}); | ||
module.exports = function (config) { | ||
// Retrieve a Webpack config specialized in tests | ||
var webpackConfig = require('../../webpack.config.js'); | ||
webpackConfig.context = __dirname + '/../..'; | ||
delete webpackConfig.entry; | ||
delete webpackConfig.output; | ||
config.set({ | ||
basePath: '../..', | ||
browserNoActivityTimeout: 30000, | ||
frameworks: ['jasmine'], | ||
browsers: ['Firefox'], | ||
files: [ | ||
'./node_modules/d3/d3.js', | ||
'./test/karma/*', | ||
'./test/karma/**/*.js' | ||
], | ||
plugins: ['karma-webpack', 'karma-jasmine', 'karma-firefox-launcher'], | ||
preprocessors: { | ||
'lib/**/*.js': 'webpack', | ||
'test/karma/**/*.js': 'webpack' | ||
}, | ||
webpackMiddleware: { | ||
noInfo: true, | ||
devtool: 'inline-source-map' | ||
}, | ||
webpack: webpackConfig | ||
}); | ||
}; |
Sorry, the diff of this file is not supported yet
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
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
Mixed license
License(Experimental) Package contains multiple licenses.
Found 1 instance in 1 package
110347
40
0
2
126
0
1
24
615
2
+ Addedd3@3.5.3
+ Addedajv@6.12.6(transitive)
+ Addedasn1@0.2.6(transitive)
+ Addedassert-plus@1.0.0(transitive)
+ Addedasynckit@0.4.0(transitive)
+ Addedaws-sign2@0.7.0(transitive)
+ Addedaws4@1.13.2(transitive)
+ Addedbcrypt-pbkdf@1.0.2(transitive)
+ Addedbindings@1.5.0(transitive)
+ Addedcaseless@0.12.0(transitive)
+ Addedcombined-stream@1.0.8(transitive)
+ Addedcontextify@0.1.15(transitive)
+ Addedcore-util-is@1.0.2(transitive)
+ Addedcssom@0.3.8(transitive)
+ Addedcssstyle@0.2.37(transitive)
+ Addedd3@3.5.3(transitive)
+ Addeddashdash@1.14.1(transitive)
+ Addeddelayed-stream@1.0.0(transitive)
+ Addeddom-serializer@0.2.2(transitive)
+ Addeddomelementtype@1.3.12.3.0(transitive)
+ Addeddomhandler@2.4.2(transitive)
+ Addeddomutils@1.7.0(transitive)
+ Addedecc-jsbn@0.1.2(transitive)
+ Addedentities@1.1.22.2.0(transitive)
+ Addedextend@3.0.2(transitive)
+ Addedextsprintf@1.3.0(transitive)
+ Addedfast-deep-equal@3.1.3(transitive)
+ Addedfast-json-stable-stringify@2.1.0(transitive)
+ Addedfile-uri-to-path@1.0.0(transitive)
+ Addedforever-agent@0.6.1(transitive)
+ Addedform-data@2.3.3(transitive)
+ Addedgetpass@0.1.7(transitive)
+ Addedhar-schema@2.0.0(transitive)
+ Addedhar-validator@5.1.5(transitive)
+ Addedhtmlparser2@3.10.1(transitive)
+ Addedhttp-signature@1.2.0(transitive)
+ Addedinherits@2.0.4(transitive)
+ Addedis-typedarray@1.0.0(transitive)
+ Addedisstream@0.1.2(transitive)
+ Addedjsbn@0.1.1(transitive)
+ Addedjsdom@1.0.0(transitive)
+ Addedjson-schema@0.4.0(transitive)
+ Addedjson-schema-traverse@0.4.1(transitive)
+ Addedjson-stringify-safe@5.0.1(transitive)
+ Addedjsprim@1.4.2(transitive)
+ Addedmime-db@1.52.0(transitive)
+ Addedmime-types@2.1.35(transitive)
+ Addednan@2.22.0(transitive)
+ Addednwmatcher@1.4.4(transitive)
+ Addedoauth-sign@0.9.0(transitive)
+ Addedparse5@1.5.1(transitive)
+ Addedperformance-now@2.1.0(transitive)
+ Addedpsl@1.15.0(transitive)
+ Addedpunycode@2.3.1(transitive)
+ Addedqs@6.5.3(transitive)
+ Addedreadable-stream@3.6.2(transitive)
+ Addedrequest@2.88.2(transitive)
+ Addedsafe-buffer@5.2.1(transitive)
+ Addedsafer-buffer@2.1.2(transitive)
+ Addedsshpk@1.18.0(transitive)
+ Addedstring_decoder@1.3.0(transitive)
+ Addedtough-cookie@2.5.0(transitive)
+ Addedtunnel-agent@0.6.0(transitive)
+ Addedtweetnacl@0.14.5(transitive)
+ Addeduri-js@4.4.1(transitive)
+ Addedutil-deprecate@1.0.2(transitive)
+ Addeduuid@3.4.0(transitive)
+ Addedverror@1.10.0(transitive)
+ Addedxmlhttprequest@1.8.0(transitive)