Comparing version 0.1.1 to 2.0.0
@@ -10,14 +10,14 @@ (function webpackUniversalModuleDefinition(root, factory) { | ||
root["labelgun"] = factory(root["rbush"]); | ||
})(this, function(__WEBPACK_EXTERNAL_MODULE_0__) { | ||
})(this, function(__WEBPACK_EXTERNAL_MODULE_1__) { | ||
return /******/ (function(modules) { // webpackBootstrap | ||
/******/ // The module cache | ||
/******/ var installedModules = {}; | ||
/******/ | ||
/******/ // The require function | ||
/******/ function __webpack_require__(moduleId) { | ||
/******/ | ||
/******/ // Check if module is in cache | ||
/******/ if(installedModules[moduleId]) | ||
/******/ if(installedModules[moduleId]) { | ||
/******/ return installedModules[moduleId].exports; | ||
/******/ } | ||
/******/ // Create a new module (and put it into the cache) | ||
@@ -29,23 +29,20 @@ /******/ var module = installedModules[moduleId] = { | ||
/******/ }; | ||
/******/ | ||
/******/ // Execute the module function | ||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); | ||
/******/ | ||
/******/ // Flag the module as loaded | ||
/******/ module.l = true; | ||
/******/ | ||
/******/ // Return the exports of the module | ||
/******/ return module.exports; | ||
/******/ } | ||
/******/ | ||
/******/ | ||
/******/ // expose the modules object (__webpack_modules__) | ||
/******/ __webpack_require__.m = modules; | ||
/******/ | ||
/******/ // expose the module cache | ||
/******/ __webpack_require__.c = installedModules; | ||
/******/ // identity function for calling harmony imports with the correct context | ||
/******/ __webpack_require__.i = function(value) { return value; }; | ||
/******/ | ||
/******/ // define getter function for harmony exports | ||
@@ -61,3 +58,3 @@ /******/ __webpack_require__.d = function(exports, name, getter) { | ||
/******/ }; | ||
/******/ | ||
/******/ // getDefaultExport function for compatibility with non-harmony modules | ||
@@ -71,11 +68,11 @@ /******/ __webpack_require__.n = function(module) { | ||
/******/ }; | ||
/******/ | ||
/******/ // Object.prototype.hasOwnProperty.call | ||
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; | ||
/******/ | ||
/******/ // __webpack_public_path__ | ||
/******/ __webpack_require__.p = ""; | ||
/******/ | ||
/******/ // Load entry module and return exports | ||
/******/ return __webpack_require__(__webpack_require__.s = 1); | ||
/******/ return __webpack_require__(__webpack_require__.s = 0); | ||
/******/ }) | ||
@@ -85,13 +82,7 @@ /************************************************************************/ | ||
/* 0 */ | ||
/***/ function(module, exports) { | ||
/***/ (function(module, exports, __webpack_require__) { | ||
module.exports = __WEBPACK_EXTERNAL_MODULE_0__; | ||
"use strict"; | ||
/***/ }, | ||
/* 1 */ | ||
/***/ function(module, exports, __webpack_require__) { | ||
"use strict"; | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { | ||
@@ -103,3 +94,3 @@ value: true | ||
var _rbush = __webpack_require__(0); | ||
var _rbush = __webpack_require__(1); | ||
@@ -114,3 +105,10 @@ var _rbush2 = _interopRequireDefault(_rbush); | ||
/** Class representing a labelgun instance */ | ||
var labelgun = function () { | ||
/** | ||
* @summary create a label gun instance with a hide and show label callback | ||
* @param {function} hideLabel the function responsible for hiding the label on hide event | ||
* @param {function} showLabel the function responsible for showing the label on show event | ||
*/ | ||
function labelgun(hideLabel, showLabel) { | ||
@@ -127,12 +125,11 @@ _classCallCheck(this, labelgun); | ||
this.showLabel = showLabel; | ||
var self = this; | ||
} | ||
/** | ||
* @name _total | ||
* @summary get the total hidden or shown labels in the tree | ||
* @param {string} state whether to return 'hide' or 'show' state label totals | ||
* @returns {number} total number of labels of taht state | ||
*/ | ||
* @name _total | ||
* @summary get the total hidden or shown labels in the tree | ||
* @param {string} state whether to return 'hide' or 'show' state label totals | ||
* @returns {number} total number of labels of that state | ||
* @private | ||
*/ | ||
@@ -177,7 +174,7 @@ | ||
/** | ||
* @name getLabelsByState | ||
* @summary provided a state get all labels of that state | ||
* @returns {array} | ||
* @private | ||
*/ | ||
* @name getLabelsByState | ||
* @summary provided a state get all labels of that state | ||
* @returns {array} | ||
* @private | ||
*/ | ||
@@ -197,6 +194,6 @@ }, { | ||
/** | ||
* @name getHidden | ||
* @summary Return | ||
* @returns {array} | ||
*/ | ||
* @name getHidden | ||
* @summary Return | ||
* @returns {array} | ||
*/ | ||
@@ -234,2 +231,4 @@ }, { | ||
var self = collisions.indexOf(label); | ||
// Remove the label if it's colliding with itself | ||
if (self !== undefined) collisions.splice(self, 1); | ||
@@ -241,3 +240,3 @@ return collisions; | ||
* @name getLabel | ||
* @summary Convience function to return a label by ID | ||
* @summary Convenience function to return a label by ID | ||
* @param {string} id the ID of the label to get | ||
@@ -265,5 +264,5 @@ * @returns {object} | ||
/** | ||
* @name forceLabelStates | ||
* @name updateLabelStates | ||
* @summary Allows you to set a state for all current labels | ||
* @param {string} forceState the class of which to change the label to | ||
* @param {string} [forceState] the class of which to change the label to | ||
* @returns {undefined} | ||
@@ -273,4 +272,4 @@ */ | ||
}, { | ||
key: "forceLabelStates", | ||
value: function forceLabelStates(forceState) { | ||
key: "updateLabelStates", | ||
value: function updateLabelStates(forceState) { | ||
var _this = this; | ||
@@ -301,4 +300,4 @@ | ||
/** | ||
* @name _setupLabelStates | ||
* @summary Clears current tree and readds all stations | ||
* @name setupLabelStates | ||
* @summary Setups the labels depending on whether all have changed or some have changed | ||
* @returns {undefined} | ||
@@ -336,3 +335,3 @@ */ | ||
topRight: [label.maxX, label.maxY] | ||
}, label._id, label.weight, label.labelObject, label.name, label.isDragged); | ||
}, label.id, label.weight, label.labelObject, label.name, label.isDragged); | ||
}); | ||
@@ -343,4 +342,4 @@ } | ||
/** | ||
* @name _resetTree | ||
* @summary Clears current tree and redraws projection overlay | ||
* @name update | ||
* @summary Sets all labels to change and reruns the whole show/hide procedure | ||
* @returns {undefined} | ||
@@ -356,5 +355,12 @@ */ | ||
this.handleExCollisions(); | ||
this._hideShownCollisions(); // HACK ALERT: why is this necessary ? :( | ||
this.forceLabelStates(); | ||
this._hideShownCollisions(); // TODO: why is this necessary ? :( | ||
this.updateLabelStates(); | ||
} | ||
/** | ||
* @name handleExCollisions | ||
* @summary Checks to see if a previously hidden/collided label is now able to be shown and then changes there state | ||
* @returns {undefined} | ||
*/ | ||
}, { | ||
@@ -366,3 +372,18 @@ key: "handleExCollisions", | ||
this.getHidden().forEach(function (hidden) { | ||
_this3._handleExCollisions(hidden); | ||
if (hidden.state === "hide") { | ||
var stillCollides = false; | ||
var hiddenLabels = _this3.tree.search(hidden); | ||
for (var i = 0; i < hiddenLabels.length; i++) { | ||
if (hiddenLabels[i].state !== "hide") { | ||
stillCollides = true; | ||
break; | ||
} | ||
} | ||
if (!stillCollides) { | ||
hidden.state = "show"; | ||
} | ||
} | ||
}); | ||
@@ -373,3 +394,3 @@ } | ||
* @name _resetTree | ||
* @summary Clears current tree and redraws projection overlay | ||
* @summary Clears current tree containing all inputted labels | ||
* @returns {undefined} | ||
@@ -409,3 +430,3 @@ * @private | ||
labelObject: labelObject, | ||
labelName: labelName, | ||
name: labelName, | ||
isDragged: isDragged | ||
@@ -431,3 +452,3 @@ }; | ||
delete this.allLabels[id]; | ||
if (forceUpdate) this.forceLabelStates(true); | ||
if (forceUpdate) this.updateLabelStates(true); | ||
} | ||
@@ -476,3 +497,3 @@ | ||
key: "_handleCollisions", | ||
value: function _handleCollisions(collisions, label, isDragged) { | ||
value: function _handleCollisions(collisions, label) { | ||
var originalWeight = void 0; | ||
@@ -486,2 +507,5 @@ if (label.isDragged) label.weight = Infinity; | ||
originalWeight = collision.weight; | ||
// We set the dragged marker to the highest weight | ||
// and make its weight unbeatable (infinity) | ||
highest = collision; | ||
@@ -504,30 +528,3 @@ highest.weight = Infinity; | ||
/** | ||
* @name _handleExCollisions | ||
* @param {object} hidden hidden label | ||
* @summary Checks to see if a previously hidden/collided label is now able to be shown and then shows | ||
* @returns {undefined} | ||
* @private | ||
*/ | ||
}, { | ||
key: "_handleExCollisions", | ||
value: function _handleExCollisions(hidden) { | ||
if (hidden.state === "hide") { | ||
var stillCollides = false; | ||
var hiddenLabels = this.tree.search(hidden); | ||
for (var i = 0; i < hiddenLabels.length; i++) { | ||
if (hiddenLabels[i].state !== "hide") { | ||
stillCollides = true; | ||
break; | ||
} | ||
} | ||
if (!stillCollides) { | ||
hidden.state = "show"; | ||
} | ||
} | ||
} | ||
/** | ||
* @name _ingestLabel | ||
* @name ingestLabel | ||
* @param {object} boundingBox | ||
@@ -539,3 +536,3 @@ * @param {string} id | ||
* @param {boolean} isDragged | ||
* @summary Creates a label if it does not already exsist, then adds it to the tree, and renders it based on whether it can be shown | ||
* @summary Creates a label if it does not already exist, then adds it to the tree, and renders it based on whether it can be shown | ||
* @returns {object} | ||
@@ -547,8 +544,16 @@ */ | ||
value: function ingestLabel(boundingBox, id, weight, labelObject, labelName, isDragged) { | ||
var label = this._makeLabel(boundingBox, id, weight, labelObject, labelName, isDragged); | ||
// If there is already a label in the tree, remove it | ||
var oldLabel = this.allLabels[id]; | ||
if (oldLabel) this.removeFromTree(oldLabel); | ||
// Add the new label to the tree | ||
var label = this._makeLabel(boundingBox, id, weight, labelObject, labelName, isDragged); | ||
this._addToTree(label); | ||
// Get all of its collisions | ||
var collisions = this.getCollisions(id); | ||
if (!collisions.length || isDragged) { | ||
// If the collisions are non existance we can show it | ||
if (!collisions.length) { | ||
label.state = "show"; | ||
@@ -558,2 +563,3 @@ return; | ||
// Else we need to handle the collisions and decide which one to show | ||
this._handleCollisions(collisions, label, isDragged); | ||
@@ -580,4 +586,10 @@ } | ||
/***/ } | ||
/***/ }), | ||
/* 1 */ | ||
/***/ (function(module, exports) { | ||
module.exports = __WEBPACK_EXTERNAL_MODULE_1__; | ||
/***/ }) | ||
/******/ ]); | ||
}); |
@@ -1,1 +0,1 @@ | ||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("rbush")):"function"==typeof define&&define.amd?define(["rbush"],t):"object"==typeof exports?exports.labelgun=t(require("rbush")):e.labelgun=t(e.rbush)}(this,function(e){return function(e){function t(i){if(a[i])return a[i].exports;var n=a[i]={i:i,l:!1,exports:{}};return e[i].call(n.exports,n,n.exports,t),n.l=!0,n.exports}var a={};return t.m=e,t.c=a,t.i=function(e){return e},t.d=function(e,a,i){t.o(e,a)||Object.defineProperty(e,a,{configurable:!1,enumerable:!0,get:i})},t.n=function(e){var a=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(a,"a",a),a},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=1)}([function(t,a){t.exports=e},function(e,t,a){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function n(e){if(Array.isArray(e)){for(var t=0,a=Array(e.length);t<e.length;t++)a[t]=e[t];return a}return Array.from(e)}function l(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(t,"__esModule",{value:!0});var s=function(){function e(e,t){for(var a=0;a<t.length;a++){var i=t[a];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,a,i){return a&&e(t.prototype,a),i&&e(t,i),t}}(),r=a(0),o=i(r),h=function(){function e(t,a){l(this,e),this.tree=(0,o.default)(6),this.allLabels={},this._point=void 0,this.hasChanged=new Set,this.loaded=!1,this.allChanged=!1,this.hideLabel=t,this.showLabel=a}return s(e,[{key:"_total",value:function(e){var t=0;for(var a in this.allLabels)this.allLabels[a].state==e&&(t+=1);return t}},{key:"totalShown",value:function(){return this._total("show")}},{key:"totalHidden",value:function(){return this._total("hide")}},{key:"_getLabelsByState",value:function(e){var t=[];for(var a in this.allLabels)this.allLabels[a].state==e&&t.push(this.allLabels[a]);return t}},{key:"getHidden",value:function(){return this._getLabelsByState("hide")}},{key:"getShown",value:function(){return this._getLabelsByState("show")}},{key:"getCollisions",value:function(e){var t=this.allLabels[e],a=this.tree.search(t),i=a.indexOf(t);return void 0!==i&&a.splice(i,1),a}},{key:"getLabel",value:function(e){return this.allLabels[e]}},{key:"destroy",value:function(){this._resetTree(),this.allLabels={}}},{key:"forceLabelStates",value:function(e){var t=this;this.tree.all().forEach(function(a){t._labelHasChangedState(a,e)})}},{key:"_labelHasChangedState",value:function(e,t){var a=t||e.state;"show"===a&&this.showLabel(e),"hide"===a&&this.hideLabel(e)}},{key:"setupLabelStates",value:function(){var e=this;if(this.allChanged){this.allChanged=!1,this.hasChanged.clear(),this._resetTree();for(var t in this.allLabels){var a=this.allLabels[t];this.ingestLabel({bottomLeft:[a.minX,a.minY],topRight:[a.maxX,a.maxY]},a.id,a.weight,a.labelObject,a.name,a.isDragged)}}else if(this.hasChanged.size){var i=[].concat(n(this.hasChanged));this.hasChanged.clear(),i.forEach(function(t){var a=e.allLabels[t];e.ingestLabel({bottomLeft:[a.minX,a.minY],topRight:[a.maxX,a.maxY]},a._id,a.weight,a.labelObject,a.name,a.isDragged)})}}},{key:"update",value:function(){this.allChanged=!0,this.setupLabelStates(),this.handleExCollisions(),this._hideShownCollisions(),this.forceLabelStates()}},{key:"handleExCollisions",value:function(){var e=this;this.getHidden().forEach(function(t){e._handleExCollisions(t)})}},{key:"_resetTree",value:function(){this.tree.clear()}},{key:"_makeLabel",value:function(e,t,a,i,n,l){return{minX:e.bottomLeft[0],minY:e.bottomLeft[1],maxX:e.topRight[0],maxY:e.topRight[1],state:"hide",id:t,weight:a||1,labelObject:i,labelName:n,isDragged:l}}},{key:"removeFromTree",value:function(e,t){var a=e.id||e,i=this.allLabels[a];this.tree.remove(i),delete this.allLabels[a],t&&this.forceLabelStates(!0)}},{key:"_addToTree",value:function(e){this.allLabels[e.id]=e,this.tree.insert(e)}},{key:"_hideShownCollisions",value:function(){var e=this;this.getShown().forEach(function(t){e.getCollisions(t.id).forEach(function(e){"show"==e.state&&(e.state="hide")})})}},{key:"_handleCollisions",value:function(e,t,a){var i=void 0;t.isDragged&&(t.weight=1/0);var n=t;e.forEach(function(e){e.isDragged&&(i=e.weight,n=e,n.weight=1/0),e.weight>n.weight?(n.state="hide",n=e):e.state="hide"}),n.state="show",i&&(n.weight=i)}},{key:"_handleExCollisions",value:function(e){if("hide"===e.state){for(var t=!1,a=this.tree.search(e),i=0;i<a.length;i++)if("hide"!==a[i].state){t=!0;break}t||(e.state="show")}}},{key:"ingestLabel",value:function(e,t,a,i,n,l){var s=this._makeLabel(e,t,a,i,n,l),r=this.allLabels[t];r&&this.removeFromTree(r),this._addToTree(s);var o=this.getCollisions(t);return!o.length||l?void(s.state="show"):void this._handleCollisions(o,s,l)}},{key:"labelHasChanged",value:function(e){this.hasChanged.add(e)}}]),e}();t.default=h}])}); | ||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("rbush")):"function"==typeof define&&define.amd?define(["rbush"],t):"object"==typeof exports?exports.labelgun=t(require("rbush")):e.labelgun=t(e.rbush);}(this,function(e){return function(e){function t(i){if(a[i])return a[i].exports;var n=a[i]={i:i,l:!1,exports:{}};return e[i].call(n.exports,n,n.exports,t),n.l=!0,n.exports;}var a={};return t.m=e,t.c=a,t.i=function(e){return e;},t.d=function(e,a,i){t.o(e,a)||Object.defineProperty(e,a,{configurable:!1,enumerable:!0,get:i});},t.n=function(e){var a=e&&e.__esModule?function(){return e.default;}:function(){return e;};return t.d(a,"a",a),a;},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t);},t.p="",t(t.s=1);}([function(t,a){t.exports=e;},function(e,t,a){"use strict";function i(e){return e&&e.__esModule?e:{default:e};}function n(e){if(Array.isArray(e)){for(var t=0,a=Array(e.length);t<e.length;t++)a[t]=e[t];return a;}return Array.from(e);}function l(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function");}Object.defineProperty(t,"__esModule",{value:!0});var s=function(){function e(e,t){for(var a=0;a<t.length;a++){var i=t[a];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i);}}return function(t,a,i){return a&&e(t.prototype,a),i&&e(t,i),t;};}(),r=a(0),o=i(r),h=function(){function e(t,a){l(this,e),this.tree=(0,o.default)(6),this.allLabels={},this._point=void 0,this.hasChanged=new Set,this.loaded=!1,this.allChanged=!1,this.hideLabel=t,this.showLabel=a;}return s(e,[{key:"_total",value:function(e){var t=0;for(var a in this.allLabels)this.allLabels[a].state==e&&(t+=1);return t;}},{key:"totalShown",value:function(){return this._total("show");}},{key:"totalHidden",value:function(){return this._total("hide");}},{key:"_getLabelsByState",value:function(e){var t=[];for(var a in this.allLabels)this.allLabels[a].state==e&&t.push(this.allLabels[a]);return t;}},{key:"getHidden",value:function(){return this._getLabelsByState("hide");}},{key:"getShown",value:function(){return this._getLabelsByState("show");}},{key:"getCollisions",value:function(e){var t=this.allLabels[e],a=this.tree.search(t),i=a.indexOf(t);return void 0!==i&&a.splice(i,1),a;}},{key:"getLabel",value:function(e){return this.allLabels[e];}},{key:"destroy",value:function(){this._resetTree(),this.allLabels={};}},{key:"forceLabelStates",value:function(e){var t=this;this.tree.all().forEach(function(a){t._labelHasChangedState(a,e);});}},{key:"_labelHasChangedState",value:function(e,t){var a=t||e.state;"show"===a&&this.showLabel(e),"hide"===a&&this.hideLabel(e);}},{key:"setupLabelStates",value:function(){var e=this;if(this.allChanged){this.allChanged=!1,this.hasChanged.clear(),this._resetTree();for(var t in this.allLabels){var a=this.allLabels[t];this.ingestLabel({bottomLeft:[a.minX,a.minY],topRight:[a.maxX,a.maxY]},a.id,a.weight,a.labelObject,a.name,a.isDragged);}}else if(this.hasChanged.size){var i=[].concat(n(this.hasChanged));this.hasChanged.clear(),i.forEach(function(t){var a=e.allLabels[t];e.ingestLabel({bottomLeft:[a.minX,a.minY],topRight:[a.maxX,a.maxY]},a._id,a.weight,a.labelObject,a.name,a.isDragged);});}}},{key:"update",value:function(){this.allChanged=!0,this.setupLabelStates(),this.handleExCollisions(),this._hideShownCollisions(),this.forceLabelStates();}},{key:"handleExCollisions",value:function(){var e=this;this.getHidden().forEach(function(t){e._handleExCollisions(t);});}},{key:"_resetTree",value:function(){this.tree.clear();}},{key:"_makeLabel",value:function(e,t,a,i,n,l){return{minX:e.bottomLeft[0],minY:e.bottomLeft[1],maxX:e.topRight[0],maxY:e.topRight[1],state:"hide",id:t,weight:a||1,labelObject:i,labelName:n,isDragged:l};}},{key:"removeFromTree",value:function(e,t){var a=e.id||e,i=this.allLabels[a];this.tree.remove(i),delete this.allLabels[a],t&&this.forceLabelStates(!0);}},{key:"_addToTree",value:function(e){this.allLabels[e.id]=e,this.tree.insert(e);}},{key:"_hideShownCollisions",value:function(){var e=this;this.getShown().forEach(function(t){e.getCollisions(t.id).forEach(function(e){"show"==e.state&&(e.state="hide");});});}},{key:"_handleCollisions",value:function(e,t,a){var i=void 0;t.isDragged&&(t.weight=1/0);var n=t;e.forEach(function(e){e.isDragged&&(i=e.weight,n=e,n.weight=1/0),e.weight>n.weight?(n.state="hide",n=e):e.state="hide";}),n.state="show",i&&(n.weight=i);}},{key:"_handleExCollisions",value:function(e){if("hide"===e.state){for(var t=!1,a=this.tree.search(e),i=0;i<a.length;i++)if("hide"!==a[i].state){t=!0;break;}t||(e.state="show");}}},{key:"ingestLabel",value:function(e,t,a,i,n,l){var s=this._makeLabel(e,t,a,i,n,l),r=this.allLabels[t];r&&this.removeFromTree(r),this._addToTree(s);var o=this.getCollisions(t);return!o.length||l?void(s.state="show"):void this._handleCollisions(o,s,l);}},{key:"labelHasChanged",value:function(e){this.hasChanged.add(e);}}]),e;}();t.default=h;}]);}); |
{ | ||
"name": "labelgun", | ||
"version": "0.1.1", | ||
"version": "2.0.0", | ||
"description": "A mapping library agnostic labelling engine", | ||
"main": "lib/labelgun.js", | ||
"scripts": { | ||
"test": "jasmine" | ||
"test": "jasmine", | ||
"coverage": "istanbul cover jasmine -x 'spec/**/*.js'", | ||
"coverage-verbose": "istanbul cover jasmine -v -i 'src/labelgun.js'", | ||
"watch": "webpack --watch", | ||
"build": "webpack", | ||
"build-prod": "webpack --env.minified", | ||
"build-both": "webpack && webpack --env.minified", | ||
"doc": "jsdoc src/labelgun.js --destination doc/documentation" | ||
}, | ||
@@ -12,13 +19,17 @@ "author": "James Milner <james.milner@geovation.uk> (http://geovation.uk/)", | ||
"repository": { | ||
"type": "git", | ||
"url": "git@github.com:Geovation/labelgun.git" | ||
"type": "git", | ||
"url": "git@github.com:Geovation/labelgun.git" | ||
}, | ||
"devDependencies": { | ||
"babel-core": "^6.17.0", | ||
"babel-loader": "^6.2.5", | ||
"babel-preset-es2015": "^6.16.0", | ||
"jasmine": "^2.5.2", | ||
"webpack": "^2.1.0-beta.28", | ||
"systemjs": "^0.19.39", | ||
"whatwg-fetch": "^2.0.1" | ||
"babel-core": "^6.26.0", | ||
"babel-loader": "^7.1.1", | ||
"babel-preset-env": "^1.6.0", | ||
"babel-preset-es2015": "^6.24.1", | ||
"eslint": "^4.4.1", | ||
"istanbul": "^0.4.5", | ||
"jasmine": "^2.7.0", | ||
"jsdoc": "^3.5.4", | ||
"systemjs": "^0.20.17", | ||
"webpack": "^3.5.5", | ||
"whatwg-fetch": "^2.0.3" | ||
}, | ||
@@ -25,0 +36,0 @@ "dependencies": { |
@@ -12,42 +12,74 @@ ![labelgun](logo.png) | ||
<br><br> | ||
![Labelgun example in leaflet](labelgun.gif) | ||
### Install | ||
You can install all the necessary dependencies with npm | ||
## Using Labelgun | ||
### Use | ||
You can use labelgun in your project via npm such as: | ||
`npm install labelgun --save` | ||
You can also use a auto-generated CDN thanks to unpkg : | ||
`https://unpkg.com/labelgun@0.1.1/lib/labelgun.js` | ||
### Demo | ||
A nice interactive way to play with the demos is to use a hot reloading web server such as live-server: | ||
`npm install -g live-server` | ||
`live-server` | ||
## Develop | ||
### Building | ||
We can install all the required dependencies using node and npm: | ||
`npm install` | ||
### Develop | ||
Labelgun is transpiled from ES6 using babel presets for Webpack 2. You can build the source using: | ||
Labelgun is transpiled from ES6 using babel presets for Webpack 2. You can build the source using | ||
`npm run build` | ||
`webpack` | ||
or: | ||
or | ||
`npm run build-prod` | ||
`webpack --env.minified` | ||
For the minified version. You can also watch the file with: | ||
For the minified version. | ||
`npm run watch` | ||
### Test | ||
### Tests | ||
Labelgun uses Jasmine for testing. You can do an npm install and then use: | ||
`jasmine` | ||
`npm run test` | ||
at the command line. Tests are found in the `spec` folder | ||
at the command line. Tests are found in the `spec` folder. We can also run test coverage as so: | ||
### Demo | ||
`npm run coverage` | ||
A nice interactive way to play with the demos is to use a hot reloading web server such as live-server: | ||
### GitHub Pages & NPM | ||
`npm install -g live-server` | ||
GitHub pages deployment: | ||
`live-server` | ||
`git subtree push --prefix examples origin gh-pages` | ||
### npm | ||
NPM updating: | ||
Labelgun is hosted on npm. You can install via: | ||
`npm publish` | ||
`npm install labelgun --save` | ||
## Users | ||
- [Vroom](http://vroom-project.org/) - Vehicle routing optimisation software | ||
- [OL Mapbox Style](https://github.com/boundlessgeo/ol-mapbox-style) - Use Mapbox Style objects with OpenLayers | ||
Using Labelgun? Open a pull request and let us know! | ||
## Acknowledgements | ||
@@ -54,0 +86,0 @@ Labelgun as an open source project was made possible thanks to [Podaris](http://www.podaris.com). |
@@ -1,28 +0,27 @@ | ||
var labelgun = require("../lib/labelgun"); | ||
describe('labelgun', function() { | ||
describe("labelgun", function() { | ||
it('should import correctly', function(){ | ||
it("should import correctly", function(){ | ||
expect(labelgun).not.toBeUndefined(); | ||
expect(labelgun).not.toBeNull(); | ||
expect(labelgun).not.toBeUndefined(); | ||
expect(labelgun).not.toBeNull(); | ||
}); | ||
it('should accept hide and show functions in constructor', function(){ | ||
it("should accept hide and show functions in constructor", function(){ | ||
var hideLabel = function(){ return false; } | ||
var showLabel = function(){ return true; } | ||
var labelEngine = new labelgun.default(hideLabel, showLabel); | ||
var hideLabel = function(){ return false; }; | ||
var showLabel = function(){ return true; }; | ||
var labelEngine = new labelgun.default(hideLabel, showLabel); | ||
expect(labelEngine.hideLabel()).toBe(false); | ||
expect(labelEngine.showLabel()).toBe(true); | ||
expect(labelEngine.hideLabel()).toBe(false); | ||
expect(labelEngine.showLabel()).toBe(true); | ||
}); | ||
it('should ingest a single label', function(){ | ||
it("should ingest a single label", function(){ | ||
var hideLabel = function(){ return false; } | ||
var showLabel = function(){ return true; } | ||
var hideLabel = function(){ return false; }; | ||
var showLabel = function(){ return true; }; | ||
var labelEngine = new labelgun.default(hideLabel, showLabel); | ||
@@ -42,3 +41,3 @@ | ||
false | ||
) | ||
); | ||
@@ -50,6 +49,6 @@ expect(labelEngine.tree.all().length).toBe(1); | ||
it('should ingest many labels (10)', function(){ | ||
it("should ingest many labels (10)", function(){ | ||
var hideLabel = function(){ return false; } | ||
var showLabel = function(){ return true; } | ||
var hideLabel = function(){ return false; }; | ||
var showLabel = function(){ return true; }; | ||
var labelEngine = new labelgun.default(hideLabel, showLabel); | ||
@@ -72,3 +71,3 @@ var boundingBox; | ||
false | ||
) | ||
); | ||
@@ -82,6 +81,6 @@ } | ||
it('should ingest many labels (10)', function(){ | ||
it("should return the total shown and hidden correctly", function(){ | ||
var hideLabel = function(){ return false; } | ||
var showLabel = function(){ return true; } | ||
var hideLabel = function(){ return false; }; | ||
var showLabel = function(){ return true; }; | ||
var labelEngine = new labelgun.default(hideLabel, showLabel); | ||
@@ -100,2 +99,92 @@ var boundingBox; | ||
i, //id | ||
1, // Weight | ||
{}, // label object | ||
"Test", | ||
false | ||
); | ||
} | ||
expect(labelEngine.totalShown()).toBe(1); | ||
expect(labelEngine.totalHidden()).toBe(9); | ||
}); | ||
it("should return the total shown and hidden correctly", function(){ | ||
var hideLabel = function(){ return false; }; | ||
var showLabel = function(){ return true; }; | ||
var labelEngine = new labelgun.default(hideLabel, showLabel); | ||
var boundingBox; | ||
for (var i=0; i < 10; i++) { | ||
boundingBox = { | ||
bottomLeft : [i, i], | ||
topRight : [i + 1.0, i + 1.0] | ||
}; | ||
labelEngine.ingestLabel( | ||
boundingBox, | ||
i, //id | ||
1, // Weight | ||
{}, // label object | ||
"Test", | ||
false | ||
); | ||
} | ||
expect(labelEngine.getShown().length).toBe(1); | ||
expect(labelEngine.getHidden().length).toBe(9); | ||
}); | ||
it("should return the correct number of collisions", function(){ | ||
var hideLabel = function(){ return false; }; | ||
var showLabel = function(){ return true; }; | ||
var labelEngine = new labelgun.default(hideLabel, showLabel); | ||
var boundingBox; | ||
for (var i=0; i < 10; i++) { | ||
boundingBox = { | ||
bottomLeft : [i + 1.0, i + 1.0 ], | ||
topRight : [i + 2.0, i + 2.0] | ||
}; | ||
labelEngine.ingestLabel( | ||
boundingBox, | ||
i, //id | ||
1, // Weight | ||
{}, // label object | ||
"Test", | ||
false | ||
); | ||
} | ||
expect(labelEngine.getCollisions(0).length).toBe(1); | ||
}); | ||
it("should destroy labelgun data", function(){ | ||
var hideLabel = function(){ return false; }; | ||
var showLabel = function(){ return true; }; | ||
var labelEngine = new labelgun.default(hideLabel, showLabel); | ||
var boundingBox; | ||
for (var i=0; i < 10; i++) { | ||
boundingBox = { | ||
bottomLeft : [i, i], | ||
topRight : [i + 1.0, i + 1.0] | ||
}; | ||
labelEngine.ingestLabel( | ||
boundingBox, | ||
i, //id | ||
parseInt(Math.random() * (5 - 1) + 1), // Weight | ||
@@ -105,3 +194,3 @@ {}, // label object | ||
false | ||
) | ||
); | ||
@@ -112,9 +201,12 @@ } | ||
expect(Object.keys(labelEngine.allLabels).length).toBe(10); | ||
labelEngine.destroy(); | ||
expect(Object.keys(labelEngine.allLabels).length).toBe(0); | ||
expect(labelEngine.tree.all().length).toBe(0); | ||
}); | ||
it('should show highest weighted label and hide others', function(){ | ||
it("should show highest weighted label and hide others", function(){ | ||
var hideLabel = function(){ return false; } | ||
var showLabel = function(){ return true; } | ||
var hideLabel = function(){ return false; }; | ||
var showLabel = function(){ return true; }; | ||
var labelEngine = new labelgun.default(hideLabel, showLabel); | ||
@@ -137,3 +229,3 @@ var boundingBox; | ||
false | ||
) | ||
); | ||
@@ -144,5 +236,5 @@ } | ||
expect(Object.keys(labelEngine.allLabels).length).toBe(10); | ||
for (var i=0; i < 10; i++) { | ||
if (i === 9) expect(labelEngine.allLabels[9].state).toBe("show"); | ||
else expect(labelEngine.allLabels[i].state).toBe("hide"); | ||
for (var j = 0; j < 10; j++) { | ||
if (j === 9) expect(labelEngine.allLabels[9].state).toBe("show"); | ||
else expect(labelEngine.allLabels[j].state).toBe("hide"); | ||
} | ||
@@ -152,6 +244,6 @@ | ||
it('overlapping labels should be hidden', function(){ | ||
it("overlapping labels should be hidden", function(){ | ||
var hideLabel = function(){ return false; } | ||
var showLabel = function(){ return true; } | ||
var hideLabel = function(){ return false; }; | ||
var showLabel = function(){ return true; }; | ||
var labelEngine = new labelgun.default(hideLabel, showLabel); | ||
@@ -174,3 +266,3 @@ var boundingBox; | ||
false | ||
) | ||
); | ||
@@ -192,6 +284,6 @@ } | ||
it('no shown labels should collide after their collisions have been dealt with', function(){ | ||
it("no shown labels should collide after their collisions have been dealt with", function(){ | ||
var hideLabel = function(){ return false; } | ||
var showLabel = function(){ return true; } | ||
var hideLabel = function(){ return false; }; | ||
var showLabel = function(){ return true; }; | ||
var labelEngine = new labelgun.default(hideLabel, showLabel); | ||
@@ -216,3 +308,3 @@ var boundingBox; | ||
false | ||
) | ||
); | ||
@@ -232,10 +324,10 @@ } | ||
}); | ||
}) | ||
}); | ||
}); | ||
it('overlapping labels should all be hidden except the one with the highest weight', function(){ | ||
it("overlapping labels should all be hidden except the one with the highest weight", function(){ | ||
var hideLabel = function(){ return false; } | ||
var showLabel = function(){ return true; } | ||
var hideLabel = function(){ return false; }; | ||
var showLabel = function(){ return true; }; | ||
var labelEngine = new labelgun.default(hideLabel, showLabel); | ||
@@ -259,3 +351,3 @@ var boundingBox; | ||
false | ||
) | ||
); | ||
@@ -270,3 +362,3 @@ } | ||
for (key in labelEngine.allLabels) { | ||
for (var key in labelEngine.allLabels) { | ||
var label = labelEngine.allLabels[key]; | ||
@@ -282,3 +374,103 @@ if (label.id === i - 1) { | ||
it("dragged labels should always be shown over none dragged", function(){ | ||
var hideLabel = function(){ return false; }; | ||
var showLabel = function(){ return true; }; | ||
var labelEngine = new labelgun.default(hideLabel, showLabel); | ||
var boundingBox; | ||
var n = 1000; | ||
boundingBox = { | ||
bottomLeft : [0, 0], | ||
topRight : [1.0, 1.0] | ||
}; | ||
labelEngine.ingestLabel( | ||
boundingBox, | ||
500, //id | ||
0, // Weight | ||
{}, // label object | ||
"Test", | ||
true | ||
); | ||
for (var i = 0; i < n; i++) { | ||
if (i !== 500) { | ||
boundingBox = { | ||
bottomLeft : [0, 0], | ||
topRight : [1.0, 1.0] | ||
}; | ||
labelEngine.ingestLabel( | ||
boundingBox, | ||
i, //id | ||
i, // Weight | ||
{}, // label object | ||
"Test", | ||
false | ||
); | ||
} | ||
} | ||
labelEngine.update(); | ||
expect(labelEngine.tree.all().length).toBe(n); | ||
expect(Object.keys(labelEngine.allLabels).length).toBe(n); | ||
expect(labelEngine.getShown().length).toBe(1); | ||
for (var key in labelEngine.allLabels) { | ||
var label = labelEngine.allLabels[key]; | ||
if (label.id === 500) { | ||
expect(label.state).toBe("show"); | ||
} else { | ||
expect(label.state).toBe("hide"); | ||
} | ||
} | ||
}); | ||
it("should allow for setting one label as changed", function(){ | ||
var hideLabel = function(){ return false; }; | ||
var showLabel = function(){ return true; }; | ||
var labelEngine = new labelgun.default(hideLabel, showLabel); | ||
var boundingBox; | ||
var n = 10; | ||
for (var i = 0; i < n; i++) { | ||
boundingBox = { | ||
bottomLeft : [0, 0], | ||
topRight : [1, 1] | ||
}; | ||
labelEngine.ingestLabel( | ||
boundingBox, | ||
i, //id | ||
1, // Weight | ||
{}, // label object | ||
"Test", | ||
false | ||
); | ||
} | ||
labelEngine.allLabels[5].weight = 1000; | ||
labelEngine.labelHasChanged(5); | ||
expect(labelEngine.hasChanged.size).toBe(1); | ||
labelEngine.setupLabelStates(); | ||
expect(labelEngine.getShown().length).toBe(1); | ||
expect(typeof(labelEngine.getShown()[0])).toBe("object"); | ||
expect(labelEngine.getShown()[0].id).toBe(5); | ||
}); | ||
}); |
@@ -1,4 +0,11 @@ | ||
import rbush from 'rbush'; | ||
import rbush from "rbush"; | ||
export default class labelgun { | ||
/** Class representing a labelgun instance */ | ||
class labelgun { | ||
/** | ||
* @summary create a label gun instance with a hide and show label callback | ||
* @param {function} hideLabel the function responsible for hiding the label on hide event | ||
* @param {function} showLabel the function responsible for showing the label on show event | ||
*/ | ||
constructor(hideLabel, showLabel) { | ||
@@ -15,11 +22,10 @@ | ||
const self = this; | ||
} | ||
/** | ||
/** | ||
* @name _total | ||
* @summary get the total hidden or shown labels in the tree | ||
* @param {string} state whether to return 'hide' or 'show' state label totals | ||
* @returns {number} total number of labels of taht state | ||
* @returns {number} total number of labels of that state | ||
* @private | ||
*/ | ||
@@ -56,3 +62,3 @@ _total(state) { | ||
/** | ||
/** | ||
* @name getLabelsByState | ||
@@ -73,3 +79,3 @@ * @summary provided a state get all labels of that state | ||
/** | ||
/** | ||
* @name getHidden | ||
@@ -99,7 +105,9 @@ * @summary Return | ||
getCollisions(id) { | ||
var label = this.allLabels[id]; | ||
var collisions = this.tree.search(label); | ||
var self = collisions.indexOf(label); | ||
if (self !== undefined) collisions.splice(self, 1); | ||
return collisions; | ||
var label = this.allLabels[id]; | ||
var collisions = this.tree.search(label); | ||
var self = collisions.indexOf(label); | ||
// Remove the label if it's colliding with itself | ||
if (self !== undefined) collisions.splice(self, 1); | ||
return collisions; | ||
} | ||
@@ -109,3 +117,3 @@ | ||
* @name getLabel | ||
* @summary Convience function to return a label by ID | ||
* @summary Convenience function to return a label by ID | ||
* @param {string} id the ID of the label to get | ||
@@ -127,9 +135,9 @@ * @returns {object} | ||
/** | ||
* @name forceLabelStates | ||
* @name updateLabelStates | ||
* @summary Allows you to set a state for all current labels | ||
* @param {string} forceState the class of which to change the label to | ||
* @param {string} [forceState] the class of which to change the label to | ||
* @returns {undefined} | ||
*/ | ||
forceLabelStates(forceState) { | ||
this.tree.all().forEach(label => { | ||
updateLabelStates(forceState) { | ||
this.tree.all().forEach(label => { | ||
this._labelHasChangedState(label, forceState); | ||
@@ -154,4 +162,4 @@ }); | ||
/** | ||
* @name _setupLabelStates | ||
* @summary Clears current tree and readds all stations | ||
* @name setupLabelStates | ||
* @summary Setups the labels depending on whether all have changed or some have changed | ||
* @returns {undefined} | ||
@@ -197,3 +205,3 @@ */ | ||
}, | ||
label._id, | ||
label.id, | ||
label.weight, | ||
@@ -212,4 +220,4 @@ label.labelObject, | ||
/** | ||
* @name _resetTree | ||
* @summary Clears current tree and redraws projection overlay | ||
* @name update | ||
* @summary Sets all labels to change and reruns the whole show/hide procedure | ||
* @returns {undefined} | ||
@@ -219,13 +227,34 @@ */ | ||
this.allChanged = true; | ||
this.setupLabelStates(); | ||
this.handleExCollisions(); | ||
this._hideShownCollisions(); // HACK ALERT: why is this necessary ? :( | ||
this.forceLabelStates(); | ||
this.allChanged = true; | ||
this.setupLabelStates(); | ||
this.handleExCollisions(); | ||
this._hideShownCollisions(); // TODO: why is this necessary ? :( | ||
this.updateLabelStates(); | ||
} | ||
/** | ||
* @name handleExCollisions | ||
* @summary Checks to see if a previously hidden/collided label is now able to be shown and then changes there state | ||
* @returns {undefined} | ||
*/ | ||
handleExCollisions() { | ||
this.getHidden().forEach(hidden => { | ||
this._handleExCollisions(hidden); | ||
if (hidden.state === "hide") { | ||
let stillCollides = false; | ||
const hiddenLabels = this.tree.search(hidden); | ||
for (var i=0; i < hiddenLabels.length; i++){ | ||
if (hiddenLabels[i].state !== "hide") { | ||
stillCollides = true; | ||
break; | ||
} | ||
} | ||
if (!stillCollides) { | ||
hidden.state = "show"; | ||
} | ||
} | ||
}); | ||
@@ -236,3 +265,3 @@ } | ||
* @name _resetTree | ||
* @summary Clears current tree and redraws projection overlay | ||
* @summary Clears current tree containing all inputted labels | ||
* @returns {undefined} | ||
@@ -266,3 +295,3 @@ * @private | ||
labelObject : labelObject, | ||
labelName : labelName, | ||
name : labelName, | ||
isDragged : isDragged | ||
@@ -285,3 +314,3 @@ }; | ||
delete this.allLabels[id]; | ||
if (forceUpdate) this.forceLabelStates(true); | ||
if (forceUpdate) this.updateLabelStates(true); | ||
} | ||
@@ -302,11 +331,10 @@ | ||
_hideShownCollisions() { | ||
// This method shouldn't have to exist... | ||
this.getShown().forEach((label) => { | ||
this.getCollisions(label.id).forEach((collision) => { | ||
if (collision.state == "show") { | ||
collision.state = "hide"; | ||
} | ||
this.getCollisions(label.id).forEach((collision) => { | ||
if (collision.state == "show") { | ||
collision.state = "hide"; | ||
} | ||
}); | ||
}); | ||
}); | ||
} | ||
@@ -323,3 +351,3 @@ | ||
*/ | ||
_handleCollisions(collisions, label, isDragged) { | ||
_handleCollisions(collisions, label) { | ||
let originalWeight; | ||
@@ -331,15 +359,18 @@ if (label.isDragged) label.weight = Infinity; | ||
if (collision.isDragged) { | ||
originalWeight = collision.weight; | ||
highest = collision; | ||
highest.weight = Infinity; | ||
} | ||
if (collision.isDragged) { | ||
originalWeight = collision.weight; | ||
if (collision.weight > highest.weight) { | ||
highest.state = "hide"; | ||
highest = collision; | ||
} else { | ||
collision.state = "hide"; | ||
} | ||
// We set the dragged marker to the highest weight | ||
// and make its weight unbeatable (infinity) | ||
highest = collision; | ||
highest.weight = Infinity; | ||
} | ||
if (collision.weight > highest.weight) { | ||
highest.state = "hide"; | ||
highest = collision; | ||
} else { | ||
collision.state = "hide"; | ||
} | ||
}); | ||
@@ -352,27 +383,3 @@ | ||
/** | ||
* @name _handleExCollisions | ||
* @param {object} hidden hidden label | ||
* @summary Checks to see if a previously hidden/collided label is now able to be shown and then shows | ||
* @returns {undefined} | ||
* @private | ||
*/ | ||
_handleExCollisions(hidden) { | ||
if (hidden.state === "hide") { | ||
let stillCollides = false; | ||
const hiddenLabels = this.tree.search(hidden); | ||
for (var i=0; i < hiddenLabels.length; i++){ | ||
if (hiddenLabels[i].state !== "hide") { | ||
stillCollides = true; | ||
break; | ||
} | ||
} | ||
if (!stillCollides) { | ||
hidden.state = "show"; | ||
} | ||
} | ||
} | ||
/** | ||
* @name _ingestLabel | ||
* @name ingestLabel | ||
* @param {object} boundingBox | ||
@@ -384,12 +391,20 @@ * @param {string} id | ||
* @param {boolean} isDragged | ||
* @summary Creates a label if it does not already exsist, then adds it to the tree, and renders it based on whether it can be shown | ||
* @summary Creates a label if it does not already exist, then adds it to the tree, and renders it based on whether it can be shown | ||
* @returns {object} | ||
*/ | ||
ingestLabel(boundingBox, id, weight, labelObject, labelName, isDragged) { | ||
const label = this._makeLabel(boundingBox, id, weight, labelObject, labelName, isDragged); | ||
// If there is already a label in the tree, remove it | ||
const oldLabel = this.allLabels[id]; | ||
if (oldLabel) this.removeFromTree(oldLabel); | ||
// Add the new label to the tree | ||
const label = this._makeLabel(boundingBox, id, weight, labelObject, labelName, isDragged); | ||
this._addToTree(label); | ||
// Get all of its collisions | ||
var collisions = this.getCollisions(id); | ||
if (!collisions.length || isDragged) { | ||
// If the collisions are non existance we can show it | ||
if (!collisions.length) { | ||
label.state = "show"; | ||
@@ -399,2 +414,3 @@ return; | ||
// Else we need to handle the collisions and decide which one to show | ||
this._handleCollisions(collisions, label, isDragged); | ||
@@ -414,1 +430,3 @@ | ||
} | ||
export default labelgun; |
@@ -1,4 +0,4 @@ | ||
'use strict'; | ||
"use strict"; | ||
var webpack = require('webpack'); | ||
var webpack = require("webpack"); | ||
@@ -37,23 +37,23 @@ module.exports = function(env) { | ||
{ | ||
rbush: "rbush" | ||
rbush: "rbush" | ||
} | ||
], | ||
module: { | ||
rules: [{ | ||
use : [ | ||
{ | ||
loader: "babel-loader", | ||
options: { | ||
compact: false, // because I want readable output, | ||
presets: ['es2015'] | ||
} | ||
rules: [ | ||
{ | ||
test: /\.js$/, | ||
exclude: /(node_modules|bower_components)/, | ||
use: { | ||
loader: "babel-loader", | ||
options: { | ||
presets: ["env"] | ||
} | ||
] | ||
}] | ||
} | ||
} | ||
] | ||
} | ||
} // End of config | ||
}; // End of config | ||
return config; | ||
} | ||
}; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
Mixed license
License(Experimental) Package contains multiple licenses.
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
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
52
4825
2
89
6886821
11
1