New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

sigma

Package Overview
Dependencies
Maintainers
2
Versions
117
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

sigma - npm Package Compare versions

Comparing version 2.0.0-alpha1 to 2.0.0-alpha10-rc1

heuristics/labels.js

188

camera.js

@@ -39,2 +39,4 @@ 'use strict';

var DEFAULT_ZOOMING_RATIO = 1.5;
// TODO: animate options = number polymorphism?

@@ -63,4 +65,4 @@ // TODO: pan, zoom, unzoom, reset, rotate, zoomTo

_this.x = 0;
_this.y = 0;
_this.x = 0.5;
_this.y = 0.5;
_this.angle = 0;

@@ -73,2 +75,3 @@ _this.ratio = 1;

_this.nextFrame = null;
_this.previousState = _this.getState();
_this.enabled = true;

@@ -123,2 +126,21 @@ return _this;

/**
* Method used to retrieve the camera's previous state.
*
* @return {object}
*/
}, {
key: 'getPreviousState',
value: function getPreviousState() {
var state = this.previousState;
return {
x: state.x,
y: state.y,
angle: state.angle,
ratio: state.ratio
};
}
/**
* Method used to retrieve the camera's dimensions.

@@ -151,19 +173,27 @@ *

/**
* Method returning the coordinates of a point from the display frame to the
* graph one but ignores the offset and dimensions of the container.
* Method returning the coordinates of a point from the graph frame to the
* viewport.
*
* @param {number} x The X coordinate.
* @param {number} y The Y coordinate.
* @return {object} The point coordinates in the frame of the graph.
* @param {object} dimensions - Dimensions of the viewport.
* @param {number} x - The X coordinate.
* @param {number} y - The Y coordinate.
* @return {object} - The point coordinates in the viewport.
*/
// TODO: assign to gain one object
// TODO: angles
}, {
key: 'abstractDisplayToGraph',
value: function abstractDisplayToGraph(x, y) {
var cos = Math.cos(this.angle),
sin = Math.sin(this.angle);
key: 'graphToViewport',
value: function graphToViewport(dimensions, x, y) {
var smallestDimension = Math.min(dimensions.width, dimensions.height);
var dx = smallestDimension / dimensions.width,
dy = smallestDimension / dimensions.height;
// TODO: we keep on the upper left corner!
// TODO: how to normalize sizes?
return {
x: (x * cos - y * sin) * this.ratio,
y: (y * cos + x * sin) * this.ratio
x: (x - this.x + this.ratio / 2 / dx) * (smallestDimension / this.ratio),
y: (this.y - y + this.ratio / 2 / dy) * (smallestDimension / this.ratio)
};

@@ -173,25 +203,24 @@ }

/**
* Method returning the coordinates of a point from the display frame to the
* graph one.
* Method returning the coordinates of a point from the viewport frame to the
* graph frame.
*
* @param {number} x The X coordinate.
* @param {number} y The Y coordinate.
* @return {object} The point coordinates in the frame of the graph.
* @param {object} dimensions - Dimensions of the viewport.
* @param {number} x - The X coordinate.
* @param {number} y - The Y coordinate.
* @return {object} - The point coordinates in the graph frame.
*/
// TODO: angles
}, {
key: 'displayToGraph',
value: function displayToGraph(x, y) {
var cos = Math.cos(this.angle),
sin = Math.sin(this.angle);
key: 'viewportToGraph',
value: function viewportToGraph(dimensions, x, y) {
var smallestDimension = Math.min(dimensions.width, dimensions.height);
var xOffset = this.width / 2 - (this.x * cos + this.y * sin) / this.ratio,
yOffset = this.height / 2 - (this.y * cos - this.x * sin) / this.ratio;
var dx = smallestDimension / dimensions.width,
dy = smallestDimension / dimensions.height;
var X = x - xOffset,
Y = y - yOffset;
return {
x: (X * cos - Y * sin) * this.ratio,
y: (Y * cos + X * sin) * this.ratio
x: this.ratio / smallestDimension * x + this.x - this.ratio / 2 / dx,
y: -(this.ratio / smallestDimension * y - this.y - this.ratio / 2 / dy)
};

@@ -201,21 +230,28 @@ }

/**
* Method returning the coordinates of a point from the graph frame to the
* display one.
* Method returning the abstract rectangle containing the graph according
* to the camera's state.
*
* @param {number} x The X coordinate.
* @param {number} y The Y coordinate.
* @return {object} The point coordinates in the frame of the display.
* @return {object} - The view's rectangle.
*/
// TODO: angle
}, {
key: 'graphToDisplay',
value: function graphToDisplay(x, y) {
var relCos = Math.cos(this.angle) / this.ratio,
relSin = Math.sin(this.angle) / this.ratio,
xOffset = this.width / 2 - this.x * relCos - this.y * relSin,
yOffset = this.height / 2 - this.y * relCos + this.x * relSin;
key: 'viewRectangle',
value: function viewRectangle(dimensions) {
// TODO: reduce relative margin?
var marginX = 0 * this.width / 8,
marginY = 0 * this.height / 8;
var p1 = this.viewportToGraph(dimensions, 0 - marginX, 0 - marginY),
p2 = this.viewportToGraph(dimensions, this.width + marginX, 0 - marginY),
h = this.viewportToGraph(dimensions, 0, this.height + marginY);
return {
x: x * relCos + y * relSin + xOffset,
y: y * relCos - x * relSin + yOffset
x1: p1.x,
y1: p1.y,
x2: p2.x,
y2: p2.y,
height: p2.y - h.y
};

@@ -240,2 +276,5 @@ }

// Keeping track of last state
this.previousState = this.getState();
if ('x' in state) this.x = state.x;

@@ -290,3 +329,3 @@

key: 'animate',
value: function animate(state, options /*, callback */) {
value: function animate(state, options, callback) {
var _this2 = this;

@@ -318,2 +357,4 @@

if (typeof callback === 'function') callback();
return;

@@ -336,4 +377,63 @@ }

this.nextFrame = requestAnimationFrame(fn);
if (this.nextFrame) {
cancelAnimationFrame(this.nextFrame);
this.nextFrame = requestAnimationFrame(fn);
} else {
fn();
}
}
/**
* Method used to zoom the camera.
*
* @param {number|object} factorOrOptions - Factor or options.
* @return {function}
*/
}, {
key: 'animatedZoom',
value: function animatedZoom(factorOrOptions) {
if (!factorOrOptions) {
return this.animate({ ratio: this.ratio / DEFAULT_ZOOMING_RATIO });
} else {
if (typeof factorOrOptions === 'number') return this.animate({ ratio: this.ratio / factorOrOptions });else return this.animate({ ratio: this.ratio / (factorOrOptions.factor || DEFAULT_ZOOMING_RATIO) }, factorOrOptions);
}
}
/**
* Method used to unzoom the camera.
*
* @param {number|object} factorOrOptions - Factor or options.
* @return {function}
*/
}, {
key: 'animatedUnzoom',
value: function animatedUnzoom(factorOrOptions) {
if (!factorOrOptions) {
return this.animate({ ratio: this.ratio * DEFAULT_ZOOMING_RATIO });
} else {
if (typeof factorOrOptions === 'number') return this.animate({ ratio: this.ratio * factorOrOptions });else return this.animate({ ratio: this.ratio * (factorOrOptions.factor || DEFAULT_ZOOMING_RATIO) }, factorOrOptions);
}
}
/**
* Method used to reset the camera.
*
* @param {object} options - Options.
* @return {function}
*/
}, {
key: 'animatedReset',
value: function animatedReset(options) {
return this.animate({
x: 0,
y: 0,
ratio: 1,
angle: 0
}, options);
}
}]);

@@ -340,0 +440,0 @@

@@ -9,2 +9,6 @@ 'use strict';

var _camera = require('../camera');
var _camera2 = _interopRequireDefault(_camera);
var _captor = require('../captor');

@@ -64,6 +68,6 @@

_this.downStartTime = null;
_this.startMouseX = null;
_this.startMouseY = null;
_this.lastMouseX = null;
_this.lastMouseY = null;
_this.isMouseDown = false;
_this.isMoving = true;
_this.isMoving = false;
_this.movingTimeout = null;

@@ -74,2 +78,3 @@ _this.startCameraState = null;

_this.doubleClickTimeout = null;
_this.wheelLock = false;

@@ -126,4 +131,2 @@ // Binding methods

var ratio = 1 / DOUBLE_CLICK_ZOOMING_RATIO;
var center = (0, _utils.getCenter)(e);

@@ -133,8 +136,33 @@

var position = this.camera.abstractDisplayToGraph((0, _utils.getX)(e) - center.x, (0, _utils.getY)(e) - center.y);
var newRatio = cameraState.ratio / DOUBLE_CLICK_ZOOMING_RATIO;
// TODO: factorize
var dimensions = {
width: this.container.offsetWidth,
height: this.container.offsetHeight
};
var clickX = (0, _utils.getX)(e),
clickY = (0, _utils.getY)(e);
// TODO: baaaad we mustn't mutate the camera, create a Camera.from or #.copy
// TODO: factorize pan & zoomTo
var cameraWithNewRatio = new _camera2.default();
cameraWithNewRatio.ratio = newRatio;
cameraWithNewRatio.x = cameraState.x;
cameraWithNewRatio.y = cameraState.y;
var clickGraph = this.camera.viewportToGraph(dimensions, clickX, clickY),
centerGraph = this.camera.viewportToGraph(dimensions, center.x, center.y);
var clickGraphNew = cameraWithNewRatio.viewportToGraph(dimensions, clickX, clickY),
centerGraphNew = cameraWithNewRatio.viewportToGraph(dimensions, center.x, center.y);
var deltaX = clickGraphNew.x - centerGraphNew.x - clickGraph.x + centerGraph.x,
deltaY = clickGraphNew.y - centerGraphNew.y - clickGraph.y + centerGraph.y;
this.camera.animate({
x: position.x * (1 - ratio) + cameraState.x,
y: position.y * (1 - ratio) + cameraState.y,
ratio: ratio * cameraState.ratio
x: cameraState.x - deltaX,
y: cameraState.y - deltaY,
ratio: newRatio
}, {

@@ -159,4 +187,4 @@ easing: 'quadraticInOut',

this.startMouseX = (0, _utils.getX)(e);
this.startMouseY = (0, _utils.getY)(e);
this.lastMouseX = (0, _utils.getX)(e);
this.lastMouseY = (0, _utils.getY)(e);

@@ -191,8 +219,9 @@ this.hasDragged = false;

var cameraState = this.camera.getState();
var cameraState = this.camera.getState(),
previousCameraState = this.camera.getPreviousState();
if (this.isMoving) {
this.camera.animate({
x: cameraState.x + MOUSE_INERTIA_RATIO * (cameraState.x - this.lastCameraState.x),
y: cameraState.y + MOUSE_INERTIA_RATIO * (cameraState.y - this.lastCameraState.y)
x: cameraState.x + MOUSE_INERTIA_RATIO * (cameraState.x - previousCameraState.x),
y: cameraState.y + MOUSE_INERTIA_RATIO * (cameraState.y - previousCameraState.y)
}, {

@@ -202,3 +231,3 @@ duration: MOUSE_INERTIA_DURATION,

});
} else if (this.startMouseX !== x || this.startMouseY !== y) {
} else if (this.lastMouseX !== x || this.lastMouseY !== y) {
this.camera.setState({

@@ -210,4 +239,5 @@ x: cameraState.x,

this.isMoving = false;
this.hasDragged = false;
this.emit('mouseup', (0, _utils.getMouseCoords)(e));
this.isMoving = false;
}

@@ -236,18 +266,26 @@ }, {

var position = this.camera.abstractDisplayToGraph((0, _utils.getX)(e) - this.startMouseX, (0, _utils.getY)(e) - this.startMouseY);
var dimensions = {
width: this.container.offsetWidth,
height: this.container.offsetHeight
};
var x = this.startCameraState.x - position.x,
y = this.startCameraState.y - position.y;
var eX = (0, _utils.getX)(e),
eY = (0, _utils.getY)(e);
var lastMouse = this.camera.viewportToGraph(dimensions, this.lastMouseX, this.lastMouseY);
var mouse = this.camera.viewportToGraph(dimensions, eX, eY);
var offsetX = lastMouse.x - mouse.x,
offsetY = lastMouse.y - mouse.y;
var cameraState = this.camera.getState();
if (cameraState.x !== x || cameraState.y !== y) {
var x = cameraState.x + offsetX,
y = cameraState.y + offsetY;
this.lastCameraState = cameraState;
this.camera.setState({ x: x, y: y });
this.camera.setState({
x: x,
y: y
});
}
this.lastMouseX = eX;
this.lastMouseY = eY;
}

@@ -264,29 +302,62 @@

value: function handleWheel(e) {
if (!this.enabled) return;
var _this4 = this;
if (e.preventDefault) e.preventDefault();else e.returnValue = false;
e.stopPropagation();
if (!this.enabled) return false;
var delta = (0, _utils.getWheelDelta)(e);
if (!delta) return;
if (!delta) return false;
if (this.wheelLock) return false;
this.wheelLock = true;
// TODO: handle max zoom
var ratio = delta > 0 ? 1 / ZOOMING_RATIO : ZOOMING_RATIO;
var cameraState = this.camera.getState();
var newRatio = ratio * cameraState.ratio;
var center = (0, _utils.getCenter)(e);
var cameraState = this.camera.getState();
var dimensions = {
width: this.container.offsetWidth,
height: this.container.offsetHeight
};
var position = this.camera.abstractDisplayToGraph((0, _utils.getX)(e) - center.x, (0, _utils.getY)(e) - center.y);
var clickX = (0, _utils.getX)(e),
clickY = (0, _utils.getY)(e);
// TODO: baaaad we mustn't mutate the camera, create a Camera.from or #.copy
// TODO: factorize pan & zoomTo
var cameraWithNewRatio = new _camera2.default();
cameraWithNewRatio.ratio = newRatio;
cameraWithNewRatio.x = cameraState.x;
cameraWithNewRatio.y = cameraState.y;
var clickGraph = this.camera.viewportToGraph(dimensions, clickX, clickY),
centerGraph = this.camera.viewportToGraph(dimensions, center.x, center.y);
var clickGraphNew = cameraWithNewRatio.viewportToGraph(dimensions, clickX, clickY),
centerGraphNew = cameraWithNewRatio.viewportToGraph(dimensions, center.x, center.y);
var deltaX = clickGraphNew.x - centerGraphNew.x - clickGraph.x + centerGraph.x,
deltaY = clickGraphNew.y - centerGraphNew.y - clickGraph.y + centerGraph.y;
this.camera.animate({
x: position.x * (1 - ratio) + cameraState.x,
y: position.y * (1 - ratio) + cameraState.y,
ratio: ratio * cameraState.ratio
x: cameraState.x - deltaX,
y: cameraState.y - deltaY,
ratio: newRatio
}, {
easing: 'quadraticOut',
easing: 'linear',
duration: MOUSE_ZOOM_DURATION
}, function () {
return _this4.wheelLock = false;
});
if (e.preventDefault) e.preventDefault();else e.returnValue = false;
e.stopPropagation();
return false;

@@ -293,0 +364,0 @@ }

@@ -6,11 +6,2 @@ 'use strict';

});
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; /**
* Sigma.js Captor Utils
* ======================
*
* Miscellenous helper functions related to the captors.
*/
exports.getX = getX;

@@ -48,2 +39,8 @@ exports.getY = getY;

*/
/**
* Sigma.js Captor Utils
* ======================
*
* Miscellenous helper functions related to the captors.
*/
function getY(e) {

@@ -115,14 +112,6 @@ if (typeof e.offsetY !== 'undefined') return e.offsetY;

*/
function getMouseCoords(e, x, y) {
if (arguments.length < 2) {
x = getX(e);
y = getY(e);
}
var center = getCenter(e);
// TODO: is this really needed to have this strange {x,y} with now?
function getMouseCoords(e) {
return {
x: x - center.x,
y: y - center.y,
x: getX(e),
y: getY(e),
clientX: e.clientX,

@@ -144,7 +133,7 @@ clientY: e.clientY,

function getWheelDelta(e) {
if (_typeof(e.wheelDelta) !== undefined) return e.wheelDelta;
if (typeof e.wheelDelta !== 'undefined') return e.wheelDelta / 360;
if (_typeof(e.detail) !== undefined) return -e.detail;
if (typeof e.detail !== 'undefined') return e.detail / -9;
throw new Error('sigma/captors/utils.getDelta: could not extract delta from event.');
}
{
"name": "sigma",
"version": "2.0.0-alpha1",
"version": "2.0.0-alpha10-rc1",
"description": "A JavaScript library dedicated to graph drawing.",

@@ -12,10 +12,10 @@ "homepage": "http://sigmajs.org",

"dist": "npm run clean && babel src --out-dir . && webpack --config ./webpack.programs.config.js",
"examples": "webpack-dev-server --config ./examples/webpack.config.js --port 8000 --progress",
"examples": "webpack-dev-server --config ./examples/webpack.config.js --progress",
"lint": "eslint examples src test",
"postpublish": "npm run clean",
"prepublish": "npm run test && npm run dist && npm run build",
"test": "mocha --compilers js:babel-core/register ./test/endpoint.js"
"test": "mocha --require babel-core/register ./test/endpoint.js"
},
"sigma": {
"clean": "camera.js captor.js easings.js endpoint.js quadtree.js renderer.js sigma.js utils.js captors renderers"
"clean": "camera.js captor.js easings.js endpoint.js quadtree.js renderer.js sigma.js utils.js captors heuristics renderers"
},

@@ -41,19 +41,20 @@ "repository": {

"babel-core": "^6.14.0",
"babel-loader": "^7.0.0",
"babel-loader": "^7.1.4",
"babel-preset-es2015": "^6.14.0",
"chroma-js": "^1.3.3",
"eslint": "^4.0.0",
"chroma-js": "^1.3.6",
"eslint": "^4.19.1",
"faker": "^4.1.0",
"graphology": "^0.10.2",
"graphology-generators": "^0.6.1",
"glob": "^7.1.2",
"graphology": "^0.11.3",
"graphology-generators": "^0.9.0",
"graphology-gexf": "^0.3.1",
"graphology-layout": "0.0.1",
"graphology-layout-forceatlas2": "0.0.1",
"graphology-layout-forceatlas2": "^0.1.1",
"html-webpack-plugin": "^2.22.0",
"mocha": "^3.0.2",
"mocha": "^5.0.5",
"raw-loader": "^0.5.1",
"rimraf": "^2.6.1",
"webpack": "^2.5.1",
"webpack-dev-server": "^2.4.5",
"worker-loader": "^0.8.0"
"webpack": "^3.10.0",
"webpack-dev-server": "^2.11.2",
"worker-loader": "^1.1.1"
},

@@ -77,6 +78,6 @@ "keywords": [

"dependencies": {
"events": "^1.1.1",
"gl-matrix": "^2.3.2",
"graphology-utils": "^1.1.1"
"events": "^2.0.0",
"graphology-metrics": "1.5.0",
"graphology-utils": "^1.3.0"
}
}

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

"use strict";
'use strict';

@@ -12,2 +12,3 @@ Object.defineProperty(exports, "__esModule", {

/* eslint no-nested-ternary: 0 */
/* eslint no-constant-condition: 0 */
/**

@@ -25,10 +26,14 @@ * Sigma.js Quad Tree Class

// TODO: a square can be represented as topleft + width
// TODO: a square can be represented as topleft + width, saying for the quad blocks (reduce mem)
// TODO: jsdoc
// TODO: be sure we can handle cases overcoming boundaries (because of size) or use a max
// TODO: be sure we can handle cases overcoming boundaries (because of size) or use a maxed size
// TODO: decide whether to store at leaf level or at medium levels (frustum vs. hover)
// TODO: filtering unwanted labels beforehand through the filter function
// NOTE: this is basically a MX-CIF Quadtree at this point
// NOTE: need to explore R-Trees for edges
// NOTE: need to explore 2d segment tree for edges
/**

@@ -74,6 +79,10 @@ * Constants.

function rectangleCollidesWithQuad(x1, y1, w, qx, qy, qw, qh) {
function squareCollidesWithQuad(x1, y1, w, qx, qy, qw, qh) {
return x1 < qx + qw && x1 + w > qx && y1 < qy + qh && y1 + w > qy;
}
function rectangleCollidesWithQuad(x1, y1, w, h, qx, qy, qw, qh) {
return x1 < qx + qw && x1 + w > qx && y1 < qy + qh && y1 + h > qy;
}
function pointIsInQuad(x, y, qx, qy, qw, qh) {

@@ -147,12 +156,9 @@ var xmp = qx + qw / 2,

// [block, level]
// TODO: does not require a stack if sticking with mid-level containers
var stack = [0, 0];
var level = 0,
block = 0;
while (stack.length) {
var level = stack.pop(),
block = stack.pop();
while (true) {
// If we reached max level
if (level === maxLevel) {
if (level >= maxLevel) {
containers[block] = containers[block] || [];

@@ -168,9 +174,9 @@ containers[block].push(key);

var collidingWithTopLeft = rectangleCollidesWithQuad(x1, y1, w, data[topLeftBlock + X_OFFSET], data[topLeftBlock + Y_OFFSET], data[topLeftBlock + WIDTH_OFFSET], data[topLeftBlock + HEIGHT_OFFSET]);
var collidingWithTopLeft = squareCollidesWithQuad(x1, y1, w, data[topLeftBlock + X_OFFSET], data[topLeftBlock + Y_OFFSET], data[topLeftBlock + WIDTH_OFFSET], data[topLeftBlock + HEIGHT_OFFSET]);
var collidingWithTopRight = rectangleCollidesWithQuad(x1, y1, w, data[topRightBlock + X_OFFSET], data[topRightBlock + Y_OFFSET], data[topRightBlock + WIDTH_OFFSET], data[topRightBlock + HEIGHT_OFFSET]);
var collidingWithTopRight = squareCollidesWithQuad(x1, y1, w, data[topRightBlock + X_OFFSET], data[topRightBlock + Y_OFFSET], data[topRightBlock + WIDTH_OFFSET], data[topRightBlock + HEIGHT_OFFSET]);
var collidingWithBottomLeft = rectangleCollidesWithQuad(x1, y1, w, data[bottomLeftBlock + X_OFFSET], data[bottomLeftBlock + Y_OFFSET], data[bottomLeftBlock + WIDTH_OFFSET], data[bottomLeftBlock + HEIGHT_OFFSET]);
var collidingWithBottomLeft = squareCollidesWithQuad(x1, y1, w, data[bottomLeftBlock + X_OFFSET], data[bottomLeftBlock + Y_OFFSET], data[bottomLeftBlock + WIDTH_OFFSET], data[bottomLeftBlock + HEIGHT_OFFSET]);
var collidingWithBottomRight = rectangleCollidesWithQuad(x1, y1, w, data[bottomRightBlock + X_OFFSET], data[bottomRightBlock + Y_OFFSET], data[bottomRightBlock + WIDTH_OFFSET], data[bottomRightBlock + HEIGHT_OFFSET]);
var collidingWithBottomRight = squareCollidesWithQuad(x1, y1, w, data[bottomRightBlock + X_OFFSET], data[bottomRightBlock + Y_OFFSET], data[bottomRightBlock + WIDTH_OFFSET], data[bottomRightBlock + HEIGHT_OFFSET]);

@@ -180,13 +186,93 @@ var collisions = collidingWithTopLeft + collidingWithTopRight + collidingWithBottomLeft + collidingWithBottomRight;

// If we don't have at least a collision, there is an issue
if (collisions === 0) throw new Error("sigma/quadtree.insertNode: no collision (level: " + level + ", key: " + key + ", x: " + x + ", y: " + y + ", size: " + size + ").");
if (collisions === 0) throw new Error('sigma/quadtree.insertNode: no collision (level: ' + level + ', key: ' + key + ', x: ' + x + ', y: ' + y + ', size: ' + size + ').');
// If we have 3 collisions, we have a geometry problem obviously
if (collisions === 3) throw new Error('sigma/quadtree.insertNode: 3 impossible collisions (level: ' + level + ', key: ' + key + ', x: ' + x + ', y: ' + y + ', size: ' + size + ').');
// If we have more that one collision, we stop here and store the node
// in the relevant container
// in the relevant containers
if (collisions > 1) {
// NOTE: this is a nice way to optimize for hover, but not for frustum
// since it requires to uniq the collected nodes
// if (collisions < 4) {
// // If we intersect two quads, we place the node in those two
// if (collidingWithTopLeft) {
// containers[topLeftBlock] = containers[topLeftBlock] || [];
// containers[topLeftBlock].push(key);
// }
// if (collidingWithTopRight) {
// containers[topRightBlock] = containers[topRightBlock] || [];
// containers[topRightBlock].push(key);
// }
// if (collidingWithBottomLeft) {
// containers[bottomLeftBlock] = containers[bottomLeftBlock] || [];
// containers[bottomLeftBlock].push(key);
// }
// if (collidingWithBottomRight) {
// containers[bottomRightBlock] = containers[bottomRightBlock] || [];
// containers[bottomRightBlock].push(key);
// }
// }
// else {
// // Else we keep the node where it is to avoid more pointless computations
// containers[block] = containers[block] || [];
// containers[block].push(key);
// }
containers[block] = containers[block] || [];
containers[block].push(key);
return;
} else {
level++;
}
// Else we recurse into the correct quad
// Else we recurse into the correct quads
if (collidingWithTopLeft) block = topLeftBlock;
if (collidingWithTopRight) block = topRightBlock;
if (collidingWithBottomLeft) block = bottomLeftBlock;
if (collidingWithBottomRight) block = bottomRightBlock;
}
}
function getNodesInAxisAlignedRectangleArea(maxLevel, data, containers, x1, y1, w, h) {
// [block, level]
var stack = [0, 0];
var collectedNodes = [];
var container = void 0;
while (stack.length) {
var level = stack.pop(),
block = stack.pop();
// Collecting nodes
container = containers[block];
if (container) collectedNodes.push.apply(collectedNodes, container);
// If we reached max level
if (level >= maxLevel) continue;
var topLeftBlock = 4 * block + BLOCKS,
topRightBlock = 4 * block + 2 * BLOCKS,
bottomLeftBlock = 4 * block + 3 * BLOCKS,
bottomRightBlock = 4 * block + 4 * BLOCKS;
var collidingWithTopLeft = rectangleCollidesWithQuad(x1, y1, w, h, data[topLeftBlock + X_OFFSET], data[topLeftBlock + Y_OFFSET], data[topLeftBlock + WIDTH_OFFSET], data[topLeftBlock + HEIGHT_OFFSET]);
var collidingWithTopRight = rectangleCollidesWithQuad(x1, y1, w, h, data[topRightBlock + X_OFFSET], data[topRightBlock + Y_OFFSET], data[topRightBlock + WIDTH_OFFSET], data[topRightBlock + HEIGHT_OFFSET]);
var collidingWithBottomLeft = rectangleCollidesWithQuad(x1, y1, w, h, data[bottomLeftBlock + X_OFFSET], data[bottomLeftBlock + Y_OFFSET], data[bottomLeftBlock + WIDTH_OFFSET], data[bottomLeftBlock + HEIGHT_OFFSET]);
var collidingWithBottomRight = rectangleCollidesWithQuad(x1, y1, w, h, data[bottomRightBlock + X_OFFSET], data[bottomRightBlock + Y_OFFSET], data[bottomRightBlock + WIDTH_OFFSET], data[bottomRightBlock + HEIGHT_OFFSET]);
if (collidingWithTopLeft) stack.push(topLeftBlock, level + 1);

@@ -200,2 +286,4 @@

}
return collectedNodes;
}

@@ -207,9 +295,11 @@

* @constructor
* @param {Graph} graph - A graph instance.
* @param {object} boundaries - The graph boundaries.
*/
var QuadTree = function () {
function QuadTree(boundaries) {
function QuadTree(params) {
_classCallCheck(this, QuadTree);
params = params || {};
// Allocating the underlying byte array

@@ -220,8 +310,12 @@ var L = Math.pow(4, MAX_LEVEL);

this.containers = {};
this.cache = null;
this.lastRectangle = null;
if (boundaries) this.resize(boundaries);
if (params.boundaries) this.resize(params.boundaries);
if (typeof params.filter === 'function') this.nodeFilter = params.filter;
}
_createClass(QuadTree, [{
key: "add",
key: 'add',
value: function add(key, x, y, size) {

@@ -233,3 +327,3 @@ insertNode(MAX_LEVEL, this.data, this.containers, key, x, y, size);

}, {
key: "resize",
key: 'resize',
value: function resize(boundaries) {

@@ -247,3 +341,3 @@ this.clear();

}, {
key: "clear",
key: 'clear',
value: function clear() {

@@ -255,3 +349,3 @@ this.containers = {};

}, {
key: "point",
key: 'point',
value: function point(x, y) {

@@ -263,7 +357,5 @@ var nodes = [];

while (level <= MAX_LEVEL) {
do {
if (this.containers[block]) nodes.push.apply(nodes, this.containers[block]);
// TODO: should probably use a do...while to avoid useless last op
var quad = pointIsInQuad(x, y, this.data[block + X_OFFSET], this.data[block + Y_OFFSET], this.data[block + WIDTH_OFFSET], this.data[block + HEIGHT_OFFSET]);

@@ -273,6 +365,32 @@

level++;
}
} while (level <= MAX_LEVEL);
return nodes;
}
}, {
key: 'rectangle',
value: function rectangle(x1, y1, x2, y2, height) {
var lr = this.lastRectangle;
if (lr && x1 === lr.x1 && x2 === lr.x2 && y1 === lr.y1 && y2 === lr.y2 && height === lr.height) {
return this.cache;
}
this.lastRectangle = {
x1: x1,
y1: y1,
x2: x2,
y2: y2,
height: height
};
// Is the rectangle axis aligned?
if (!isAxisAligned(x1, y1, x2, y2)) throw new Error('sigma/quadtree.rectangle: shifted view is not yet implemented.');
var collectedNodes = getNodesInAxisAlignedRectangleArea(MAX_LEVEL, this.data, this.containers, x1, y1, Math.abs(x1 - x2) || Math.abs(y1 - y2), height);
this.cache = collectedNodes;
return this.cache;
}
}]);

@@ -279,0 +397,0 @@

@@ -6,5 +6,8 @@ 'use strict';

});
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
exports.createElement = createElement;
exports.getPixelRatio = getPixelRatio;
exports.createNodeRescalingFunction = createNodeRescalingFunction;
exports.createNormalizationFunction = createNormalizationFunction;
/**

@@ -56,59 +59,38 @@ * Sigma.js Rendering Utils

/**
* Default rescale options.
*/
var DEFAULT_NODE_RESCALE_OPTIONS = {
mode: 'inside',
margin: 0,
minSize: 1,
maxSize: 8
};
var DEFAULT_EDGE_RESCALE_OPTIONS = {
minSize: 0.5,
maxSize: 1
};
// TODO: should we let the user handle size through, for instance, d3 scales?
// TODO: should we put the rescaling in the camera itself?
/**
* Factory returning a function rescaling the given node's position and/or size.
* Factory returning a function normalizing the given node's position & size.
*
* @param {object} options - Options.
* @param {object} extent - Extent of the graph.
* @return {function}
*/
function createNodeRescalingFunction(options, extent) {
options = options || {};
function createNormalizationFunction(extent) {
var _extent$x = _slicedToArray(extent.x, 2),
minX = _extent$x[0],
maxX = _extent$x[1],
_extent$y = _slicedToArray(extent.y, 2),
minY = _extent$y[0],
maxY = _extent$y[1];
var mode = options.mode || DEFAULT_NODE_RESCALE_OPTIONS.mode,
height = options.height || 1,
width = options.width || 1;
var ratio = Math.max(maxX - minX, maxY - minY);
var maxX = extent.maxX,
maxY = extent.maxY,
minX = extent.minX,
minY = extent.minY;
var dX = (maxX + minX) / 2,
dY = (maxY + minY) / 2;
var hx = (maxX + minX) / 2,
hy = (maxY + minY) / 2;
var scale = mode === 'outside' ? Math.max(width / Math.max(maxX - minX, 1), height / Math.max(maxY - minY, 1)) : Math.min(width / Math.max(maxX - minX, 1), height / Math.max(maxY - minY, 1));
var fn = function fn(data) {
return {
x: (data.x - hx) * scale,
y: (data.y - hy) * scale
x: 0.5 + (data.x - dX) / ratio,
y: 0.5 + (data.y - dY) / ratio
};
};
// TODO: unit test this
fn.inverse = function (data) {
return {
x: data.x / scale + hx,
y: data.y / scale + hy
x: dX + ratio * (data.x - 0.5),
y: dY + ratio * (data.y - 0.5)
};
};
fn.ratio = ratio;
return fn;
}

@@ -9,4 +9,6 @@ 'use strict';

var _glMatrix = require('gl-matrix');
var _extent = require('graphology-metrics/extent');
var _extent2 = _interopRequireDefault(_extent);
var _renderer = require('../../renderer');

@@ -28,3 +30,3 @@

var _node = require('./programs/node');
var _node = require('./programs/node.fast');

@@ -51,2 +53,4 @@ var _node2 = _interopRequireDefault(_node);

var _labels = require('../../heuristics/labels');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

@@ -69,6 +73,14 @@

*/
var WEBGL_OVERSAMPLING_RATIO = 2;
var PIXEL_RATIO = (0, _utils2.getPixelRatio)();
var WEBGL_OVERSAMPLING_RATIO = (0, _utils2.getPixelRatio)();
/**
* Defaults.
*/
var DEFAULT_SETTINGS = {
hideEdgesOnMove: false,
hideLabelsOnMove: false
};
/**
* Main class.

@@ -83,8 +95,12 @@ *

function WebGLRenderer(container) {
function WebGLRenderer(container, settings) {
_classCallCheck(this, WebGLRenderer);
// Validating
var _this = _possibleConstructorReturn(this, (WebGLRenderer.__proto__ || Object.getPrototypeOf(WebGLRenderer)).call(this));
settings = settings || {};
_this.settings = (0, _utils.assign)({}, DEFAULT_SETTINGS, settings);
// Validating
if (!(container instanceof HTMLElement)) throw new Error('sigma/renderers/webgl: container should be an html element.');

@@ -100,22 +116,13 @@

// Indices
// TODO: this could be improved by key => index => floatArray
// TODO: the cache should erase keys on node delete
_this.quadtree = new _quadtree2.default();
_this.nodeArray = null;
_this.nodeIndicesArray = null;
_this.nodeOrder = {};
_this.nodeDataCache = {};
_this.edgeArray = null;
_this.edgeIndicesArray = null;
_this.edgeOrder = {};
_this.nodePrograms = {
def: new _node2.default()
};
_this.edgePrograms = {
def: new _edge2.default()
};
// Normalization function
_this.normalizationFunction = null;
// TODO: if we drop size scaling => this should become "rescalingFunction"
_this.nodeRescalingFunction = null;
// Starting dimensions

@@ -127,3 +134,6 @@ _this.width = 0;

_this.highlightedNodes = new Set();
_this.previousVisibleNodes = new Set();
_this.displayedLabels = new Set();
_this.hoveredNode = null;
_this.wasRenderedInThisFrame = false;
_this.renderFrame = null;

@@ -133,3 +143,2 @@ _this.renderHighlightedNodesFrame = null;

_this.needToSoftProcess = false;
_this.pixel = new Uint8Array(4);

@@ -143,2 +152,21 @@ // Initializing contexts

// Blending
var gl = _this.contexts.nodes;
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
gl.enable(gl.BLEND);
gl = _this.contexts.edges;
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
gl.enable(gl.BLEND);
// Loading programs
_this.nodePrograms = {
def: new _node2.default(_this.contexts.nodes)
};
_this.edgePrograms = {
def: new _edge2.default(_this.contexts.edges)
};
// Initial resize

@@ -163,9 +191,3 @@ _this.resize();

_this.bindEventHandlers();
// Loading programs
for (var k in _this.nodePrograms) {
_this.nodePrograms[k].load(_this.contexts.nodes);
}for (var _k in _this.edgePrograms) {
_this.edgePrograms[_k].load(_this.contexts.edges);
}return _this;
return _this;
}

@@ -179,8 +201,8 @@

/**
* Method used to test a pixel of the given context.
* Internal function used to create a canvas context and add the relevant
* DOM elements.
*
* @param {WebGLContext} gl - Context.
* @param {number} x - Client x.
* @param {number} y - Client y.
* @return {boolean}
* @param {string} id - Context's id.
* @param {boolean} webgl - Whether the context is a webgl or canvas one.
* @return {WebGLRenderer}
*/

@@ -190,19 +212,2 @@

_createClass(WebGLRenderer, [{
key: 'testPixel',
value: function testPixel(gl, x, y) {
(0, _utils3.extractPixel)(gl, x * WEBGL_OVERSAMPLING_RATIO, (this.height - y) * WEBGL_OVERSAMPLING_RATIO, this.pixel);
return this.pixel[3] !== 0;
}
/**
* Internal function used to create a canvas context and add the relevant
* DOM elements.
*
* @param {string} id - Context's id.
* @param {boolean} webgl - Whether the context is a webgl or canvas one.
* @return {WebGLRenderer}
*/
}, {
key: 'createContext',

@@ -223,7 +228,17 @@ value: function createContext(id) {

var contextOptions = {
preserveDrawingBuffer: true
preserveDrawingBuffer: true,
antialias: false
};
var context = element.getContext(webgl ? 'webgl' : '2d', contextOptions);
var context = void 0;
if (webgl) {
context = element.getContext('webgl', contextOptions);
// Edge, I am looking right at you...
if (!context) context = element.getContext('experimental-webgl', contextOptions);
} else {
context = element.getContext('2d', contextOptions);
}
this.contexts[id] = context;

@@ -265,2 +280,10 @@

// Handling window resize
this.listeners.handleResize = function () {
_this3.needToSoftProcess = true;
_this3.scheduleRender();
};
window.addEventListener('resize', this.listeners.handleResize);
// Function checking if the mouse is on the given node

@@ -274,5 +297,6 @@ var mouseIsOnNode = function mouseIsOnNode(mouseX, mouseY, nodeX, nodeY, size) {

var mouseGraphPosition = _this3.camera.displayToGraph(mouseX, mouseY);
var mouseGraphPosition = _this3.camera.viewportToGraph(_this3, mouseX, mouseY);
return _this3.quadtree.point(mouseGraphPosition.x, mouseGraphPosition.y);
// TODO: minus 1? lol
return _this3.quadtree.point(mouseGraphPosition.x, 1 - mouseGraphPosition.y);
};

@@ -285,5 +309,7 @@

// give some boost but this slows things down for WebGL empirically.
// TODO: this should be a method from the camera (or can be passed to graph to display somehow)
var sizeRatio = Math.pow(_this3.camera.getState().ratio, 0.5);
var quadNodes = getQuadNodes(e.clientX, e.clientY);
var quadNodes = getQuadNodes(e.x, e.y);

@@ -295,7 +321,8 @@ for (var i = 0, l = quadNodes.length; i < l; i++) {

var pos = _this3.camera.graphToDisplay(data.x, data.y);
var pos = _this3.camera.graphToViewport(_this3, data.x, data.y);
var size = data.size / sizeRatio;
if (mouseIsOnNode(e.clientX, e.clientY, pos.x, pos.y, size)) {
// TODO: we should get the nearest node instead
if (mouseIsOnNode(e.x, e.y, pos.x, pos.y, size)) {
_this3.hoveredNode = node;

@@ -312,7 +339,7 @@

var _pos = _this3.camera.graphToDisplay(_data.x, _data.y);
var _pos = _this3.camera.graphToViewport(_this3, _data.x, _data.y);
var _size = _data.size / sizeRatio;
if (!mouseIsOnNode(e.clientX, e.clientY, _pos.x, _pos.y, _size)) {
if (!mouseIsOnNode(e.x, e.y, _pos.x, _pos.y, _size)) {
_this3.hoveredNode = null;

@@ -330,3 +357,3 @@

var quadNodes = getQuadNodes(e.clientX, e.clientY);
var quadNodes = getQuadNodes(e.x, e.y);

@@ -338,7 +365,7 @@ for (var i = 0, l = quadNodes.length; i < l; i++) {

var pos = _this3.camera.graphToDisplay(data.x, data.y);
var pos = _this3.camera.graphToViewport(_this3, data.x, data.y);
var size = data.size / sizeRatio;
if (mouseIsOnNode(e.clientX, e.clientY, pos.x, pos.y, size)) return _this3.emit('downNode', { node: node });
if (mouseIsOnNode(e.x, e.y, pos.x, pos.y, size)) return _this3.emit('downNode', { node: node });
}

@@ -351,3 +378,3 @@ };

var quadNodes = getQuadNodes(e.clientX, e.clientY);
var quadNodes = getQuadNodes(e.x, e.y);

@@ -359,7 +386,7 @@ for (var i = 0, l = quadNodes.length; i < l; i++) {

var pos = _this3.camera.graphToDisplay(data.x, data.y);
var pos = _this3.camera.graphToViewport(_this3, data.x, data.y);
var size = data.size / sizeRatio;
if (mouseIsOnNode(e.clientX, e.clientY, pos.x, pos.y, size)) return _this3.emit('clickNode', { node: node });
if (mouseIsOnNode(e.x, e.y, pos.x, pos.y, size)) return _this3.emit('clickNode', { node: node });
}

@@ -429,31 +456,19 @@

var extent = this.sigma.getGraphExtent();
// TODO: possible to index this somehow using two byte arrays or so
var extent = (0, _extent2.default)(graph, ['x', 'y']);
// Rescaling function
this.nodeRescalingFunction = (0, _utils2.createNodeRescalingFunction)({ width: this.width, height: this.height }, extent);
this.normalizationFunction = (0, _utils2.createNormalizationFunction)(extent);
var minRescaled = this.nodeRescalingFunction({
x: extent.minX,
y: extent.minY
});
var maxRescaled = this.nodeRescalingFunction({
x: extent.maxX,
y: extent.maxY
});
this.quadtree.resize({
x: minRescaled.x,
y: minRescaled.y,
width: maxRescaled.x - minRescaled.x,
height: maxRescaled.y - minRescaled.y
x: 0,
y: 0,
width: 1,
height: 1
});
this.nodeRescaleCache = {};
var nodeProgram = this.nodePrograms.def;
if (!keepArrays) {
this.nodeArray = new Float32Array(_node2.default.POINTS * _node2.default.ATTRIBUTES * graph.order);
nodeProgram.allocate(graph.order);
this.nodeOrder = {};

@@ -471,19 +486,21 @@ }

var rescaledData = this.nodeRescalingFunction(data);
var rescaledData = this.normalizationFunction(data);
// TODO: Optimize this to be save a loop and one object
// TODO: Optimize this to save a loop and one object, by using a reversed assign
var displayData = (0, _utils.assign)({}, data, rescaledData);
this.quadtree.add(node, displayData.x, displayData.y, displayData.size);
// TODO: this size normalization does not work
this.quadtree.add(node, displayData.x, 1 - displayData.y, displayData.size / this.width);
this.nodeDataCache[node] = displayData;
nodeProgram.process(this.nodeArray, displayData, i * _node2.default.POINTS * _node2.default.ATTRIBUTES);
nodeProgram.process(displayData, i);
}
nodeProgram.bufferData();
var edgeProgram = this.edgePrograms.def;
if (!keepArrays) {
this.edgeArray = new Float32Array(_edge2.default.POINTS * _edge2.default.ATTRIBUTES * graph.size);
edgeProgram.allocate(graph.size);
this.edgeOrder = {};

@@ -504,8 +521,10 @@ }

edgeProgram.process(this.edgeArray, sourceData, targetData, _data2, _i * _edge2.default.POINTS * _edge2.default.ATTRIBUTES);
edgeProgram.process(sourceData, targetData, _data2, _i);
}
// Computing edge indices if necessary
if (!keepArrays && typeof edgeProgram.computeIndices === 'function') this.edgeIndicesArray = edgeProgram.computeIndices(this.edgeArray);
if (!keepArrays && typeof edgeProgram.computeIndices === 'function') this.edgeIndicesArray = edgeProgram.computeIndices();
edgeProgram.bufferData();
return this;

@@ -528,3 +547,3 @@ }

nodeProgram.process(this.nodeArray, data, this.nodeOrder[key] * _node2.default.POINTS * _node2.default.ATTRIBUTES);
nodeProgram.process(data, this.nodeOrder[key]);

@@ -553,3 +572,3 @@ return this;

edgeProgram.process(this.edgeArray, sourceData, targetData, data, this.edgeOrder[key] * _edge2.default.POINTS * _edge2.default.ATTRIBUTES);
edgeProgram.process(sourceData, targetData, data, this.edgeOrder[key]);

@@ -635,2 +654,6 @@ return this;

// Resizing camera
// TODO: maybe move this elsewhere
if (this.camera) this.camera.resize({ width: this.width, height: this.height });
// Sizing dom elements

@@ -712,2 +735,5 @@ for (var id in this.elements) {

// TODO: improve this heuristic
var moving = this.camera.isAnimated() || this.captors.mouse.isMoving || this.captors.mouse.hasDragged || this.captors.mouse.wheelLock;
// First we need to resize

@@ -721,22 +747,11 @@ this.resize();

var cameraState = this.camera.getState(),
cameraMatrix = (0, _utils3.matrixFromCamera)(cameraState);
cameraMatrix = (0, _utils3.matrixFromCamera)(cameraState, { width: this.width, height: this.height });
var translation = _glMatrix.mat3.fromTranslation(_glMatrix.mat3.create(), [this.width / 2, this.height / 2]);
var program = void 0;
_glMatrix.mat3.multiply(cameraMatrix, translation, cameraMatrix);
var program = void 0,
gl = void 0;
// Drawing nodes
gl = this.contexts.nodes;
program = this.nodePrograms.def;
// Blending
// TODO: check the purpose of this
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
gl.enable(gl.BLEND);
// TODO: should probably use another name for the `program` abstraction
program.render(gl, this.nodeArray, {
program.render({
matrix: cameraMatrix,

@@ -751,13 +766,41 @@ width: this.width,

// Drawing edges
gl = this.contexts.edges;
program = this.edgePrograms.def;
if (!this.settings.hideEdgesOnMove || !moving) {
program = this.edgePrograms.def;
program.render(gl, this.edgeArray, {
matrix: cameraMatrix,
width: this.width,
height: this.height,
ratio: cameraState.ratio,
edgesPowRatio: 0.5,
scalingRatio: WEBGL_OVERSAMPLING_RATIO,
indices: this.edgeIndicesArray
program.render({
matrix: cameraMatrix,
width: this.width,
height: this.height,
ratio: cameraState.ratio,
nodesPowRatio: 0.5,
edgesPowRatio: 0.5,
scalingRatio: WEBGL_OVERSAMPLING_RATIO
});
}
// Do not display labels on move per setting
if (this.settings.hideLabelsOnMove && moving) return this;
// Finding visible nodes to display their labels
var visibleNodes = void 0;
if (cameraState.ratio >= 1) {
// Camera is unzoomed so no need to ask the quadtree for visible nodes
visibleNodes = this.sigma.getGraph().nodes();
} else {
// Let's ask the quadtree
var viewRectangle = this.camera.viewRectangle(this);
visibleNodes = this.quadtree.rectangle(viewRectangle.x1, 1 - viewRectangle.y1, viewRectangle.x2, 1 - viewRectangle.y2, viewRectangle.height);
}
// Selecting labels to draw
var labelsToDisplay = (0, _labels.labelsToDisplayFromGrid)({
cache: this.nodeDataCache,
camera: this.camera,
displayedLabels: this.displayedLabels,
previousVisibleNodes: this.previousVisibleNodes,
visibleNodes: visibleNodes
});

@@ -767,13 +810,12 @@

// TODO: POW RATIO is currently default 0.5 and harcoded
var nodes = this.sigma.getGraph().nodes(),
context = this.contexts.labels;
var context = this.contexts.labels;
var sizeRatio = Math.pow(cameraState.ratio, 0.5);
for (var i = 0, l = nodes.length; i < l; i++) {
var data = this.nodeDataCache[nodes[i]];
for (var i = 0, l = labelsToDisplay.length; i < l; i++) {
var data = this.nodeDataCache[labelsToDisplay[i]];
var _camera$graphToDispla = this.camera.graphToDisplay(data.x, data.y),
x = _camera$graphToDispla.x,
y = _camera$graphToDispla.y;
var _camera$graphToViewpo = this.camera.graphToViewport(this, data.x, data.y),
x = _camera$graphToViewpo.x,
y = _camera$graphToViewpo.y;

@@ -786,3 +828,4 @@ // TODO: we can cache the labels we need to render until the camera's ratio changes

// TODO: this is the label threshold hardcoded
if (size < 8) continue;
// if (size < 8)
// continue;

@@ -797,2 +840,6 @@ (0, _label2.default)(context, {

// Caching visible nodes and displayed labels
this.previousVisibleNodes = new Set(visibleNodes);
this.displayedLabels = new Set(labelsToDisplay);
// Rendering highlighted nodes

@@ -828,5 +875,5 @@ this.renderHighlightedNodes();

var _camera$graphToDispla2 = camera.graphToDisplay(data.x, data.y),
x = _camera$graphToDispla2.x,
y = _camera$graphToDispla2.y;
var _camera$graphToViewpo2 = camera.graphToViewport(_this5, data.x, data.y),
x = _camera$graphToViewpo2.x,
y = _camera$graphToViewpo2.y;

@@ -860,4 +907,6 @@ var size = data.size / sizeRatio;

// A frame is already scheduled
if (this.renderFrame) return this;
// Let's schedule a frame
this.renderFrame = requestAnimationFrame(function () {

@@ -889,3 +938,3 @@

if (this.renderHighlightedNodesFrame) return this;
if (this.renderHighlightedNodesFrame || this.renderFrame) return this;

@@ -892,0 +941,0 @@ this.renderHighlightedNodesFrame = requestAnimationFrame(function () {

@@ -30,3 +30,3 @@ 'use strict';

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /**
* Sigma.js WebGL Renderer Node Program
* Sigma.js WebGL Renderer Edge Program
* =====================================

@@ -48,12 +48,45 @@ *

var POINTS = 4,
ATTRIBUTES = 6;
var EdgeProgram = function (_Program) {
_inherits(EdgeProgram, _Program);
function EdgeProgram() {
function EdgeProgram(gl) {
_classCallCheck(this, EdgeProgram);
var _this = _possibleConstructorReturn(this, (EdgeProgram.__proto__ || Object.getPrototypeOf(EdgeProgram)).call(this));
// Binding context
var _this = _possibleConstructorReturn(this, (EdgeProgram.__proto__ || Object.getPrototypeOf(EdgeProgram)).call(this, gl, _edgeVert2.default, _edgeFrag2.default));
_this.vertexShaderSource = _edgeVert2.default;
_this.fragmentShaderSource = _edgeFrag2.default;
_this.gl = gl;
// Array data
_this.array = null;
_this.indicesArray = null;
// Initializing buffers
_this.buffer = gl.createBuffer();
_this.indicesBuffer = gl.createBuffer();
// Locations
_this.positionLocation = gl.getAttribLocation(_this.program, 'a_position');
_this.normalLocation = gl.getAttribLocation(_this.program, 'a_normal');
_this.thicknessLocation = gl.getAttribLocation(_this.program, 'a_thickness');
_this.colorLocation = gl.getAttribLocation(_this.program, 'a_color');
_this.resolutionLocation = gl.getUniformLocation(_this.program, 'u_resolution');
_this.ratioLocation = gl.getUniformLocation(_this.program, 'u_ratio');
_this.matrixLocation = gl.getUniformLocation(_this.program, 'u_matrix');
_this.scaleLocation = gl.getUniformLocation(_this.program, 'u_scale');
_this.bind();
// Enabling the OES_element_index_uint extension
// NOTE: on older GPUs, this means that really large graphs won't
// have all their edges rendered. But it seems that the
// `OES_element_index_uint` is quite everywhere so we'll handle
// the potential issue if it really arises.
var extension = gl.getExtension('OES_element_index_uint');
_this.canUse32BitsIndices = !!extension;
_this.IndicesArray = _this.canUse32BitsIndices ? Uint32Array : Uint16Array;
_this.indicesType = _this.canUse32BitsIndices ? gl.UNSIGNED_INT : gl.UNSIGNED_SHORT;
return _this;

@@ -63,8 +96,32 @@ }

_createClass(EdgeProgram, [{
key: 'bind',
value: function bind() {
var gl = this.gl;
gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer);
// Bindings
gl.enableVertexAttribArray(this.positionLocation);
gl.enableVertexAttribArray(this.normalLocation);
gl.enableVertexAttribArray(this.thicknessLocation);
gl.enableVertexAttribArray(this.colorLocation);
gl.vertexAttribPointer(this.positionLocation, 2, gl.FLOAT, false, ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 0);
gl.vertexAttribPointer(this.normalLocation, 2, gl.FLOAT, false, ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 8);
gl.vertexAttribPointer(this.thicknessLocation, 1, gl.FLOAT, false, ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 16);
gl.vertexAttribPointer(this.colorLocation, 1, gl.FLOAT, false, ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 20);
}
}, {
key: 'allocate',
value: function allocate(capacity) {
this.array = new Float32Array(POINTS * ATTRIBUTES * capacity);
}
}, {
key: 'process',
value: function process(array, sourceData, targetData, data, i) {
value: function process(sourceData, targetData, data, offset) {
if (sourceData.hidden || targetData.hidden || data.hidden) {
for (var l = i + EdgeProgram.POINTS * EdgeProgram.ATTRIBUTES; i < l; i++) {
array[i] = 0;
for (var l = i + POINTS * ATTRIBUTES; i < l; i++) {
this.array[i] = 0;
}

@@ -95,2 +152,6 @@ }

var i = POINTS * ATTRIBUTES * offset;
var array = this.array;
// First point

@@ -126,68 +187,56 @@ array[i++] = x1;

array[i++] = thickness;
array[i++] = color;
array[i] = color;
}
}, {
key: 'computeIndices',
value: function computeIndices(array) {
var l = array.length / EdgeProgram.ATTRIBUTES;
value: function computeIndices() {
var l = this.array.length / ATTRIBUTES;
var size = l + l / 2;
var indices = new Uint16Array(size);
var indices = new this.IndicesArray(size);
for (var i = 0, c = 0; i < size; i += 4) {
indices[c++] = i;
indices[c++] = i + 1;
indices[c++] = i + 2;
indices[c++] = i + 2;
indices[c++] = i + 1;
indices[c++] = i + 3;
for (var _i = 0, c = 0; _i < size; _i += 4) {
indices[c++] = _i;
indices[c++] = _i + 1;
indices[c++] = _i + 2;
indices[c++] = _i + 2;
indices[c++] = _i + 1;
indices[c++] = _i + 3;
}
return indices;
this.indicesArray = indices;
}
}, {
key: 'bufferData',
value: function bufferData() {
var gl = this.gl;
// Vertices data
gl.bufferData(gl.ARRAY_BUFFER, this.array, gl.DYNAMIC_DRAW);
// Indices data
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indicesArray, gl.STATIC_DRAW);
}
}, {
key: 'render',
value: function render(gl, array, params) {
value: function render(params) {
var gl = this.gl;
var program = this.program;
gl.useProgram(program);
// Attribute locations
var positionLocation = gl.getAttribLocation(program, 'a_position'),
normalLocation = gl.getAttribLocation(program, 'a_normal'),
thicknessLocation = gl.getAttribLocation(program, 'a_thickness'),
colorLocation = gl.getAttribLocation(program, 'a_color'),
resolutionLocation = gl.getUniformLocation(program, 'u_resolution'),
ratioLocation = gl.getUniformLocation(program, 'u_ratio'),
matrixLocation = gl.getUniformLocation(program, 'u_matrix');
// Creating buffer:
var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, array, gl.STATIC_DRAW);
// Binding uniforms
gl.uniform2f(resolutionLocation, params.width, params.height);
gl.uniform1f(ratioLocation, params.ratio / Math.pow(params.ratio, params.edgesPowRatio));
// TODO: precise the uniform names
gl.uniform2f(this.resolutionLocation, params.width, params.height);
gl.uniform1f(this.ratioLocation,
// 1 / Math.pow(params.ratio, params.edgesPowRatio)
params.ratio);
gl.uniformMatrix3fv(matrixLocation, false, params.matrix);
gl.uniformMatrix3fv(this.matrixLocation, false, params.matrix);
// Binding attributes:
gl.enableVertexAttribArray(positionLocation);
gl.enableVertexAttribArray(normalLocation);
gl.enableVertexAttribArray(thicknessLocation);
gl.enableVertexAttribArray(colorLocation);
gl.uniform1f(this.scaleLocation, params.scalingRatio);
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, EdgeProgram.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 0);
gl.vertexAttribPointer(normalLocation, 2, gl.FLOAT, false, EdgeProgram.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 8);
gl.vertexAttribPointer(thicknessLocation, 1, gl.FLOAT, false, EdgeProgram.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 16);
gl.vertexAttribPointer(colorLocation, 1, gl.FLOAT, false, EdgeProgram.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 20);
// Creating indices buffer:
var indicesBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indicesBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, params.indices, gl.STATIC_DRAW);
// Drawing:
gl.drawElements(gl.TRIANGLES, params.indices.length, gl.UNSIGNED_SHORT, 0);
gl.drawElements(gl.TRIANGLES, this.indicesArray.length, this.indicesType, 0);
}

@@ -199,6 +248,2 @@ }]);

exports.default = EdgeProgram;
EdgeProgram.POINTS = 4;
EdgeProgram.ATTRIBUTES = 6;
exports.default = EdgeProgram;

@@ -44,12 +44,46 @@ 'use strict';

var POINTS = 3,
ATTRIBUTES = 5;
var NodeProgram = function (_Program) {
_inherits(NodeProgram, _Program);
function NodeProgram() {
function NodeProgram(gl) {
_classCallCheck(this, NodeProgram);
var _this = _possibleConstructorReturn(this, (NodeProgram.__proto__ || Object.getPrototypeOf(NodeProgram)).call(this));
// Binding context
var _this = _possibleConstructorReturn(this, (NodeProgram.__proto__ || Object.getPrototypeOf(NodeProgram)).call(this, gl, _nodeVert2.default, _nodeFrag2.default));
_this.vertexShaderSource = _nodeVert2.default;
_this.fragmentShaderSource = _nodeFrag2.default;
_this.gl = gl;
// Array data
_this.array = null;
// Initializing buffers
_this.buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, _this.buffer);
// Locations
_this.positionLocation = gl.getAttribLocation(_this.program, 'a_position');
_this.sizeLocation = gl.getAttribLocation(_this.program, 'a_size');
_this.colorLocation = gl.getAttribLocation(_this.program, 'a_color');
_this.angleLocation = gl.getAttribLocation(_this.program, 'a_angle');
_this.resolutionLocation = gl.getUniformLocation(_this.program, 'u_resolution');
_this.matrixLocation = gl.getUniformLocation(_this.program, 'u_matrix');
_this.ratioLocation = gl.getUniformLocation(_this.program, 'u_ratio');
_this.scaleLocation = gl.getUniformLocation(_this.program, 'u_scale');
// Bindings
gl.enableVertexAttribArray(_this.positionLocation);
gl.enableVertexAttribArray(_this.sizeLocation);
gl.enableVertexAttribArray(_this.colorLocation);
gl.enableVertexAttribArray(_this.angleLocation);
gl.vertexAttribPointer(_this.positionLocation, 2, gl.FLOAT, false, ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 0);
gl.vertexAttribPointer(_this.sizeLocation, 1, gl.FLOAT, false, ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 8);
gl.vertexAttribPointer(_this.colorLocation, 1, gl.FLOAT, false, ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 12);
gl.vertexAttribPointer(_this.angleLocation, 1, gl.FLOAT, false, ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 16);
return _this;

@@ -59,6 +93,15 @@ }

_createClass(NodeProgram, [{
key: 'allocate',
value: function allocate(capacity) {
this.array = new Float32Array(POINTS * ATTRIBUTES * capacity);
}
}, {
key: 'process',
value: function process(array, data, i) {
value: function process(data, offset) {
var color = (0, _utils.floatColor)(data.color);
var i = offset * POINTS * ATTRIBUTES;
var array = this.array;
array[i++] = data.x;

@@ -80,45 +123,26 @@ array[i++] = data.y;

array[i++] = color;
array[i++] = ANGLE_3;
array[i] = ANGLE_3;
}
}, {
key: 'bufferData',
value: function bufferData() {
var gl = this.gl;
gl.bufferData(gl.ARRAY_BUFFER, this.array, gl.DYNAMIC_DRAW);
}
}, {
key: 'render',
value: function render(gl, array, params) {
value: function render(params) {
var gl = this.gl;
var program = this.program;
gl.useProgram(program);
// Attribute locations
var positionLocation = gl.getAttribLocation(program, 'a_position'),
sizeLocation = gl.getAttribLocation(program, 'a_size'),
colorLocation = gl.getAttribLocation(program, 'a_color'),
angleLocation = gl.getAttribLocation(program, 'a_angle'),
resolutionLocation = gl.getUniformLocation(program, 'u_resolution'),
matrixLocation = gl.getUniformLocation(program, 'u_matrix'),
ratioLocation = gl.getUniformLocation(program, 'u_ratio'),
scaleLocation = gl.getUniformLocation(program, 'u_scale');
gl.uniform2f(this.resolutionLocation, params.width, params.height);
gl.uniform1f(this.ratioLocation, 1 / Math.pow(params.ratio, params.nodesPowRatio));
gl.uniform1f(this.scaleLocation, params.scalingRatio);
gl.uniformMatrix3fv(this.matrixLocation, false, params.matrix);
var buffer = gl.createBuffer();
// TODO: might be possible not to buffer data each time if only the camera changes
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, array, gl.DYNAMIC_DRAW);
gl.uniform2f(resolutionLocation, params.width, params.height);
gl.uniform1f(ratioLocation, 1 / Math.pow(params.ratio, params.nodesPowRatio));
gl.uniform1f(scaleLocation, params.scalingRatio);
gl.uniformMatrix3fv(matrixLocation, false, params.matrix);
gl.enableVertexAttribArray(positionLocation);
gl.enableVertexAttribArray(sizeLocation);
gl.enableVertexAttribArray(colorLocation);
gl.enableVertexAttribArray(angleLocation);
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, NodeProgram.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 0);
gl.vertexAttribPointer(sizeLocation, 1, gl.FLOAT, false, NodeProgram.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 8);
gl.vertexAttribPointer(colorLocation, 1, gl.FLOAT, false, NodeProgram.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 12);
gl.vertexAttribPointer(angleLocation, 1, gl.FLOAT, false, NodeProgram.ATTRIBUTES * Float32Array.BYTES_PER_ELEMENT, 16);
gl.drawArrays(gl.TRIANGLES, 0, array.length / NodeProgram.ATTRIBUTES);
gl.drawArrays(gl.TRIANGLES, 0, this.array.length / ATTRIBUTES);
}

@@ -130,6 +154,2 @@ }]);

exports.default = NodeProgram;
NodeProgram.POINTS = 3;
NodeProgram.ATTRIBUTES = 5;
exports.default = NodeProgram;

@@ -15,4 +15,8 @@ 'use strict';

exports.createCompoundProgram = createCompoundProgram;
var _utils = require('../shaders/utils');
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

@@ -26,16 +30,21 @@

var Program = function () {
function Program() {
function Program(gl, vertexShaderSource, fragmentShaderSource) {
_classCallCheck(this, Program);
this.vertexShaderSource = vertexShaderSource;
this.fragmentShaderSource = fragmentShaderSource;
this.load(gl);
}
/**
* Method used to load the program into a webgl context.
*
* @param {WebGLContext} gl - The WebGL context.
* @return {WebGLProgram}
*/
_createClass(Program, [{
key: 'load',
/**
* Method used to load the program into a webgl context.
*
* @param {WebGLContext} gl - The WebGL context.
* @return {WebGLProgram}
*/
value: function load(gl) {

@@ -54,2 +63,68 @@ this.vertexShader = (0, _utils.loadVertexShader)(gl, this.vertexShaderSource);

exports.default = Program;
/**
* Helper function combining two or more programs into a single compound one.
* Note that this is more a quick & easy way to combine program than a really
* performant option. More performant programs can be written entirely.
*
* @param {array} programClasses - Program classes to combine.
* @return {function}
*/
exports.default = Program;
function createCompoundProgram(programClasses) {
return function () {
function CompoundProgram(gl) {
_classCallCheck(this, CompoundProgram);
this.programs = programClasses.map(function (ProgramClass) {
return new ProgramClass(gl);
});
}
_createClass(CompoundProgram, [{
key: 'allocate',
value: function allocate(capacity) {
this.programs.forEach(function (program) {
return program.allocate(capacity);
});
}
}, {
key: 'process',
value: function process() {
var args = arguments;
this.programs.forEach(function (program) {
return program.process.apply(program, _toConsumableArray(args));
});
}
}, {
key: 'computeIndices',
value: function computeIndices() {
this.programs.forEach(function (program) {
if (typeof program.computeIndices === 'function') program.computeIndices();
});
}
}, {
key: 'bufferData',
value: function bufferData() {
this.programs.forEach(function (program) {
return program.bufferData();
});
}
}, {
key: 'render',
value: function render() {
var args = arguments;
this.programs.forEach(function (program) {
program.bind();
program.bufferData();
program.render.apply(program, _toConsumableArray(args));
});
}
}]);
return CompoundProgram;
}();
}

@@ -37,3 +37,3 @@ 'use strict';

gl.deleteShader(shader);
throw new Error('sigma/renderers/weblg/shaders/utils.loadShader: error while compiling the shader:\n' + infoLog);
throw new Error('sigma/renderers/weblg/shaders/utils.loadShader: error while compiling the shader:\n' + infoLog + '\n' + source);
}

@@ -40,0 +40,0 @@

@@ -10,3 +10,3 @@ 'use strict';

var _glMatrix = require('gl-matrix');
var _matrices = require('./matrices');

@@ -71,3 +71,3 @@ /**

// TODO: it's possible to optimize this drastically!
function matrixFromCamera(state) {
function matrixFromCamera(state, dimensions) {
var angle = state.angle,

@@ -77,12 +77,21 @@ ratio = state.ratio,

y = state.y;
var width = dimensions.width,
height = dimensions.height;
var matrix = _glMatrix.mat3.create(),
scale = _glMatrix.mat3.fromScaling(_glMatrix.mat3.create(), [1 / ratio, 1 / ratio]),
rotation = _glMatrix.mat3.fromRotation(_glMatrix.mat3.create(), -angle),
translation = _glMatrix.mat3.fromTranslation(_glMatrix.mat3.create(), [-x, -y]);
var matrix = (0, _matrices.identity)();
_glMatrix.mat3.multiply(matrix, scale, rotation);
_glMatrix.mat3.multiply(matrix, matrix, translation);
var smallestDimension = Math.min(width, height);
var cameraCentering = (0, _matrices.translate)((0, _matrices.identity)(), -x, -y),
cameraScaling = (0, _matrices.scale)((0, _matrices.identity)(), 1 / ratio),
cameraRotation = (0, _matrices.rotate)((0, _matrices.identity)(), -angle),
viewportScaling = (0, _matrices.scale)((0, _matrices.identity)(), 2 * (smallestDimension / width), 2 * (smallestDimension / height));
// Logical order is reversed
(0, _matrices.multiply)(matrix, viewportScaling);
(0, _matrices.multiply)(matrix, cameraRotation);
(0, _matrices.multiply)(matrix, cameraScaling);
(0, _matrices.multiply)(matrix, cameraCentering);
return matrix;

@@ -89,0 +98,0 @@ }

@@ -118,59 +118,2 @@ 'use strict';

}
/**
* Method returning the extent of the bound graph.
*
* @return {object} - The graph's extent.
*/
}, {
key: 'getGraphExtent',
value: function getGraphExtent() {
var graph = this.graph;
var nodes = graph.nodes(),
edges = graph.edges();
var maxX = -Infinity,
maxY = -Infinity,
minX = Infinity,
minY = Infinity,
maxNodeSize = -Infinity,
maxEdgeSize = -Infinity;
for (var i = 0, l = nodes.length; i < l; i++) {
var node = nodes[i];
var data = this.getNodeData(node);
if (data.x > maxX) maxX = data.x;
if (data.y > maxY) maxY = data.y;
if (data.x < minX) minX = data.x;
if (data.y < minY) minY = data.y;
var size = data.size || 1;
if (size > maxNodeSize) maxNodeSize = size;
}
for (var _i = 0, _l = edges.length; _i < _l; _i++) {
var edge = edges[_i];
var _data = this.getEdgeData(edge);
var _size = _data.size || 1;
if (_size > maxEdgeSize) maxEdgeSize = _size;
}
return {
maxX: maxX,
maxY: maxY,
minX: minX,
minY: minY,
maxNodeSize: maxNodeSize,
maxEdgeSize: maxEdgeSize
};
}
}]);

@@ -177,0 +120,0 @@

@@ -1,13 +0,18 @@

var path = require('path');
var path = require('path'),
glob = require('glob');
var shaders = glob.sync(path.join(__dirname, 'src', 'renderers', 'webgl', 'shaders', '*.glsl'));
var entry = {};
shaders.forEach(function(p) {
entry[path.basename(p, '.glsl')] = p;
});
module.exports = {
entry: {
'node.vert': './src/renderers/webgl/shaders/node.vert.glsl',
'edge.vert': './src/renderers/webgl/shaders/edge.vert.glsl',
'node.frag': './src/renderers/webgl/shaders/node.frag.glsl',
'edge.frag': './src/renderers/webgl/shaders/edge.frag.glsl'
},
entry: entry,
output: {
path: path.join(__dirname, 'renderers', 'webgl', 'shaders'),
filename: '[name].glsl'
filename: '[name].glsl',
libraryTarget: 'commonjs2'
},

@@ -14,0 +19,0 @@ module: {

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc