detecti-cli 2.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. detecti/__init__.py +0 -0
  2. detecti/cli.py +649 -0
  3. detecti/config.py +188 -0
  4. detecti/core/__init__.py +1 -0
  5. detecti/core/database/__init__.py +5 -0
  6. detecti/core/database/config_db.py +73 -0
  7. detecti/core/database/schema.py +136 -0
  8. detecti/core/database/storage.py +1388 -0
  9. detecti/core/engine.py +1032 -0
  10. detecti/core/models.py +278 -0
  11. detecti/data/config.sqlite +0 -0
  12. detecti/data/dbs/.gitkeep +2 -0
  13. detecti/data/dbs/example.com.sqlite +0 -0
  14. detecti/modules/__init__.py +29 -0
  15. detecti/modules/base.py +57 -0
  16. detecti/modules/censys.py +813 -0
  17. detecti/modules/crtsh.py +98 -0
  18. detecti/modules/exploitdb.py +138 -0
  19. detecti/modules/masscan.py +561 -0
  20. detecti/modules/nuclei.py +449 -0
  21. detecti/modules/nvd.py +300 -0
  22. detecti/modules/reverse_whois.py +225 -0
  23. detecti/modules/shodan.py +412 -0
  24. detecti/reporters/__init__.py +7 -0
  25. detecti/reporters/csv_reporter.py +74 -0
  26. detecti/reporters/html_reporter.py +356 -0
  27. detecti/reporters/json_reporter.py +26 -0
  28. detecti/reporters/markdown_reporter.py +203 -0
  29. detecti/utils/__init__.py +1 -0
  30. detecti/utils/http.py +294 -0
  31. detecti/utils/logger.py +378 -0
  32. detecti/utils/setup.py +453 -0
  33. detecti/web/__init__.py +6 -0
  34. detecti/web/api/__init__.py +1 -0
  35. detecti/web/api/auth.py +109 -0
  36. detecti/web/api/graph_builder.py +901 -0
  37. detecti/web/api/routes.py +1602 -0
  38. detecti/web/process_manager.py +283 -0
  39. detecti/web/server.py +183 -0
  40. detecti/web/static/android-chrome-192x192.png +0 -0
  41. detecti/web/static/android-chrome-512x512.png +0 -0
  42. detecti/web/static/apple-touch-icon.png +0 -0
  43. detecti/web/static/css/__init__.py +1 -0
  44. detecti/web/static/css/dashboard.css +3802 -0
  45. detecti/web/static/favicon-16x16.png +0 -0
  46. detecti/web/static/favicon-32x32.png +0 -0
  47. detecti/web/static/favicon.ico +0 -0
  48. detecti/web/static/img/DetecTI_Security_Logo.png +0 -0
  49. detecti/web/static/img/detecti-ico.png +0 -0
  50. detecti/web/static/index.html +677 -0
  51. detecti/web/static/js/__init__.py +1 -0
  52. detecti/web/static/js/api.js +177 -0
  53. detecti/web/static/js/cytoscape-cose-bilkent.js +458 -0
  54. detecti/web/static/js/cytoscape-dagre.js +397 -0
  55. detecti/web/static/js/cytoscape.min.js +31 -0
  56. detecti/web/static/js/dagre.min.js +3809 -0
  57. detecti/web/static/js/graph.js +7439 -0
  58. detecti/web/static/js/lucide.min.js +12 -0
  59. detecti/web/static/login.html +290 -0
  60. detecti/web/static/site.webmanifest +1 -0
  61. detecti_cli-2.0.0.dist-info/METADATA +554 -0
  62. detecti_cli-2.0.0.dist-info/RECORD +64 -0
  63. detecti_cli-2.0.0.dist-info/WHEEL +4 -0
  64. detecti_cli-2.0.0.dist-info/entry_points.txt +3 -0
@@ -0,0 +1 @@
1
+ # Static JavaScript files for DetecTI-CLI dashboard
@@ -0,0 +1,177 @@
1
+ /**
2
+ * API client for DetecTI-CLI EASM Dashboard
3
+ */
4
+
5
+ class APIClient {
6
+ constructor(baseURL = '/api/v1') {
7
+ this.baseURL = baseURL;
8
+ }
9
+
10
+ async request(endpoint, options = {}) {
11
+ const url = `${this.baseURL}${endpoint}`;
12
+
13
+ try {
14
+ console.log(`Making API request to: ${url}`);
15
+
16
+ const response = await fetch(url, {
17
+ headers: {
18
+ 'Accept': 'application/json',
19
+ ...options.headers
20
+ },
21
+ ...options
22
+ });
23
+
24
+ console.log(`API response status: ${response.status}`);
25
+
26
+ if (!response.ok) {
27
+ const errorText = await response.text();
28
+ console.error(`API error response: ${errorText}`);
29
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
30
+ }
31
+
32
+ const data = await response.json();
33
+ console.log(`API response data:`, data);
34
+ return data;
35
+ } catch (error) {
36
+ console.error(`API request failed: ${endpoint}`, error);
37
+ throw error;
38
+ }
39
+ }
40
+
41
+ async getSummary() {
42
+ return this.request('/summary');
43
+ }
44
+
45
+ async getGraphData() {
46
+ return this.request('/graph');
47
+ }
48
+
49
+ // Removed getLeads() - Lead Selector is now 100% frontend-based using graph data
50
+
51
+ async getAssets() {
52
+ return this.request('/assets');
53
+ }
54
+
55
+ async getDatabases() {
56
+ return this.request('/databases');
57
+ }
58
+
59
+ async selectDatabase(dbName) {
60
+ return this.request('/databases/select', {
61
+ method: 'POST',
62
+ headers: {
63
+ 'Content-Type': 'application/json'
64
+ },
65
+ body: JSON.stringify({ name: dbName })
66
+ });
67
+ }
68
+
69
+ async deleteDatabase(dbName) {
70
+ return this.request('/databases/delete', {
71
+ method: 'POST',
72
+ headers: {
73
+ 'Content-Type': 'application/json'
74
+ },
75
+ body: JSON.stringify({ name: dbName })
76
+ });
77
+ }
78
+
79
+ getExportUrl(format = 'json') {
80
+ return `${this.baseURL}/export?format=${format}`;
81
+ }
82
+
83
+ // Target Management & Active Scan APIs
84
+ async getTargets() {
85
+ return this.request('/targets');
86
+ }
87
+
88
+ async setTarget(target) {
89
+ return this.request('/targets/set', {
90
+ method: 'POST',
91
+ headers: {
92
+ 'Content-Type': 'application/json'
93
+ },
94
+ body: JSON.stringify({ target: target, ip: target })
95
+ });
96
+ }
97
+
98
+ async removeTarget(target) {
99
+ return this.request('/targets/remove', {
100
+ method: 'POST',
101
+ headers: {
102
+ 'Content-Type': 'application/json'
103
+ },
104
+ body: JSON.stringify({ target: target, ip: target })
105
+ });
106
+ }
107
+
108
+ async clearTargets() {
109
+ return this.request('/targets/clear', {
110
+ method: 'POST'
111
+ });
112
+ }
113
+
114
+ async checkScanPermissions() {
115
+ return this.request('/scan/check-permissions');
116
+ }
117
+
118
+ async startActiveScan(config = {}) {
119
+ return this.request('/scan/active', {
120
+ method: 'POST',
121
+ headers: {
122
+ 'Content-Type': 'application/json'
123
+ },
124
+ body: JSON.stringify(config)
125
+ });
126
+ }
127
+
128
+ async startNucleiScan(config = {}) {
129
+ return this.request('/scan/nuclei', {
130
+ method: 'POST',
131
+ headers: {
132
+ 'Content-Type': 'application/json'
133
+ },
134
+ body: JSON.stringify(config)
135
+ });
136
+ }
137
+
138
+ async cancelActiveScan(target = null, all = false, scanType = 'all') {
139
+ return this.request('/scan/cancel', {
140
+ method: 'POST',
141
+ headers: {
142
+ 'Content-Type': 'application/json'
143
+ },
144
+ body: JSON.stringify({ target: target, all: all, scan_type: scanType })
145
+ });
146
+ }
147
+
148
+ async unverifyServices(serviceIds = [], ipAddresses = []) {
149
+ return this.request('/services/unverify', {
150
+ method: 'POST',
151
+ headers: {
152
+ 'Content-Type': 'application/json'
153
+ },
154
+ body: JSON.stringify({
155
+ service_ids: serviceIds,
156
+ ip_addresses: ipAddresses
157
+ })
158
+ });
159
+ }
160
+
161
+ async getScanStatus() {
162
+ return this.request('/scan/status');
163
+ }
164
+
165
+ async getScanLogs(limit = 100, target = null) {
166
+ let endpoint = `/scan/logs?limit=${encodeURIComponent(limit)}`;
167
+ if (target) {
168
+ endpoint += `&target=${encodeURIComponent(target)}`;
169
+ }
170
+ return this.request(endpoint);
171
+ }
172
+ }
173
+
174
+ // Global API client instance
175
+ window.api = new APIClient();
176
+
177
+
@@ -0,0 +1,458 @@
1
+ (function webpackUniversalModuleDefinition(root, factory) {
2
+ if(typeof exports === 'object' && typeof module === 'object')
3
+ module.exports = factory(require("cose-base"));
4
+ else if(typeof define === 'function' && define.amd)
5
+ define(["cose-base"], factory);
6
+ else if(typeof exports === 'object')
7
+ exports["cytoscapeCoseBilkent"] = factory(require("cose-base"));
8
+ else
9
+ root["cytoscapeCoseBilkent"] = factory(root["coseBase"]);
10
+ })(this, function(__WEBPACK_EXTERNAL_MODULE_0__) {
11
+ return /******/ (function(modules) { // webpackBootstrap
12
+ /******/ // The module cache
13
+ /******/ var installedModules = {};
14
+ /******/
15
+ /******/ // The require function
16
+ /******/ function __webpack_require__(moduleId) {
17
+ /******/
18
+ /******/ // Check if module is in cache
19
+ /******/ if(installedModules[moduleId]) {
20
+ /******/ return installedModules[moduleId].exports;
21
+ /******/ }
22
+ /******/ // Create a new module (and put it into the cache)
23
+ /******/ var module = installedModules[moduleId] = {
24
+ /******/ i: moduleId,
25
+ /******/ l: false,
26
+ /******/ exports: {}
27
+ /******/ };
28
+ /******/
29
+ /******/ // Execute the module function
30
+ /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
31
+ /******/
32
+ /******/ // Flag the module as loaded
33
+ /******/ module.l = true;
34
+ /******/
35
+ /******/ // Return the exports of the module
36
+ /******/ return module.exports;
37
+ /******/ }
38
+ /******/
39
+ /******/
40
+ /******/ // expose the modules object (__webpack_modules__)
41
+ /******/ __webpack_require__.m = modules;
42
+ /******/
43
+ /******/ // expose the module cache
44
+ /******/ __webpack_require__.c = installedModules;
45
+ /******/
46
+ /******/ // identity function for calling harmony imports with the correct context
47
+ /******/ __webpack_require__.i = function(value) { return value; };
48
+ /******/
49
+ /******/ // define getter function for harmony exports
50
+ /******/ __webpack_require__.d = function(exports, name, getter) {
51
+ /******/ if(!__webpack_require__.o(exports, name)) {
52
+ /******/ Object.defineProperty(exports, name, {
53
+ /******/ configurable: false,
54
+ /******/ enumerable: true,
55
+ /******/ get: getter
56
+ /******/ });
57
+ /******/ }
58
+ /******/ };
59
+ /******/
60
+ /******/ // getDefaultExport function for compatibility with non-harmony modules
61
+ /******/ __webpack_require__.n = function(module) {
62
+ /******/ var getter = module && module.__esModule ?
63
+ /******/ function getDefault() { return module['default']; } :
64
+ /******/ function getModuleExports() { return module; };
65
+ /******/ __webpack_require__.d(getter, 'a', getter);
66
+ /******/ return getter;
67
+ /******/ };
68
+ /******/
69
+ /******/ // Object.prototype.hasOwnProperty.call
70
+ /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
71
+ /******/
72
+ /******/ // __webpack_public_path__
73
+ /******/ __webpack_require__.p = "";
74
+ /******/
75
+ /******/ // Load entry module and return exports
76
+ /******/ return __webpack_require__(__webpack_require__.s = 1);
77
+ /******/ })
78
+ /************************************************************************/
79
+ /******/ ([
80
+ /* 0 */
81
+ /***/ (function(module, exports) {
82
+
83
+ module.exports = __WEBPACK_EXTERNAL_MODULE_0__;
84
+
85
+ /***/ }),
86
+ /* 1 */
87
+ /***/ (function(module, exports, __webpack_require__) {
88
+
89
+ "use strict";
90
+
91
+
92
+ var LayoutConstants = __webpack_require__(0).layoutBase.LayoutConstants;
93
+ var FDLayoutConstants = __webpack_require__(0).layoutBase.FDLayoutConstants;
94
+ var CoSEConstants = __webpack_require__(0).CoSEConstants;
95
+ var CoSELayout = __webpack_require__(0).CoSELayout;
96
+ var CoSENode = __webpack_require__(0).CoSENode;
97
+ var PointD = __webpack_require__(0).layoutBase.PointD;
98
+ var DimensionD = __webpack_require__(0).layoutBase.DimensionD;
99
+
100
+ var defaults = {
101
+ // Called on `layoutready`
102
+ ready: function ready() {},
103
+ // Called on `layoutstop`
104
+ stop: function stop() {},
105
+ // 'draft', 'default' or 'proof"
106
+ // - 'draft' fast cooling rate
107
+ // - 'default' moderate cooling rate
108
+ // - "proof" slow cooling rate
109
+ quality: 'default',
110
+ // include labels in node dimensions
111
+ nodeDimensionsIncludeLabels: false,
112
+ // number of ticks per frame; higher is faster but more jerky
113
+ refresh: 30,
114
+ // Whether to fit the network view after when done
115
+ fit: true,
116
+ // Padding on fit
117
+ padding: 10,
118
+ // Whether to enable incremental mode
119
+ randomize: true,
120
+ // Node repulsion (non overlapping) multiplier
121
+ nodeRepulsion: 4500,
122
+ // Ideal edge (non nested) length
123
+ idealEdgeLength: 50,
124
+ // Divisor to compute edge forces
125
+ edgeElasticity: 0.45,
126
+ // Nesting factor (multiplier) to compute ideal edge length for nested edges
127
+ nestingFactor: 0.1,
128
+ // Gravity force (constant)
129
+ gravity: 0.25,
130
+ // Maximum number of iterations to perform
131
+ numIter: 2500,
132
+ // For enabling tiling
133
+ tile: true,
134
+ // Type of layout animation. The option set is {'during', 'end', false}
135
+ animate: 'end',
136
+ // Duration for animate:end
137
+ animationDuration: 500,
138
+ // Represents the amount of the vertical space to put between the zero degree members during the tiling operation(can also be a function)
139
+ tilingPaddingVertical: 10,
140
+ // Represents the amount of the horizontal space to put between the zero degree members during the tiling operation(can also be a function)
141
+ tilingPaddingHorizontal: 10,
142
+ // Gravity range (constant) for compounds
143
+ gravityRangeCompound: 1.5,
144
+ // Gravity force (constant) for compounds
145
+ gravityCompound: 1.0,
146
+ // Gravity range (constant)
147
+ gravityRange: 3.8,
148
+ // Initial cooling factor for incremental layout
149
+ initialEnergyOnIncremental: 0.5
150
+ };
151
+
152
+ function extend(defaults, options) {
153
+ var obj = {};
154
+
155
+ for (var i in defaults) {
156
+ obj[i] = defaults[i];
157
+ }
158
+
159
+ for (var i in options) {
160
+ obj[i] = options[i];
161
+ }
162
+
163
+ return obj;
164
+ };
165
+
166
+ function _CoSELayout(_options) {
167
+ this.options = extend(defaults, _options);
168
+ getUserOptions(this.options);
169
+ }
170
+
171
+ var getUserOptions = function getUserOptions(options) {
172
+ if (options.nodeRepulsion != null) CoSEConstants.DEFAULT_REPULSION_STRENGTH = FDLayoutConstants.DEFAULT_REPULSION_STRENGTH = options.nodeRepulsion;
173
+ if (options.idealEdgeLength != null) CoSEConstants.DEFAULT_EDGE_LENGTH = FDLayoutConstants.DEFAULT_EDGE_LENGTH = options.idealEdgeLength;
174
+ if (options.edgeElasticity != null) CoSEConstants.DEFAULT_SPRING_STRENGTH = FDLayoutConstants.DEFAULT_SPRING_STRENGTH = options.edgeElasticity;
175
+ if (options.nestingFactor != null) CoSEConstants.PER_LEVEL_IDEAL_EDGE_LENGTH_FACTOR = FDLayoutConstants.PER_LEVEL_IDEAL_EDGE_LENGTH_FACTOR = options.nestingFactor;
176
+ if (options.gravity != null) CoSEConstants.DEFAULT_GRAVITY_STRENGTH = FDLayoutConstants.DEFAULT_GRAVITY_STRENGTH = options.gravity;
177
+ if (options.numIter != null) CoSEConstants.MAX_ITERATIONS = FDLayoutConstants.MAX_ITERATIONS = options.numIter;
178
+ if (options.gravityRange != null) CoSEConstants.DEFAULT_GRAVITY_RANGE_FACTOR = FDLayoutConstants.DEFAULT_GRAVITY_RANGE_FACTOR = options.gravityRange;
179
+ if (options.gravityCompound != null) CoSEConstants.DEFAULT_COMPOUND_GRAVITY_STRENGTH = FDLayoutConstants.DEFAULT_COMPOUND_GRAVITY_STRENGTH = options.gravityCompound;
180
+ if (options.gravityRangeCompound != null) CoSEConstants.DEFAULT_COMPOUND_GRAVITY_RANGE_FACTOR = FDLayoutConstants.DEFAULT_COMPOUND_GRAVITY_RANGE_FACTOR = options.gravityRangeCompound;
181
+ if (options.initialEnergyOnIncremental != null) CoSEConstants.DEFAULT_COOLING_FACTOR_INCREMENTAL = FDLayoutConstants.DEFAULT_COOLING_FACTOR_INCREMENTAL = options.initialEnergyOnIncremental;
182
+
183
+ if (options.quality == 'draft') LayoutConstants.QUALITY = 0;else if (options.quality == 'proof') LayoutConstants.QUALITY = 2;else LayoutConstants.QUALITY = 1;
184
+
185
+ CoSEConstants.NODE_DIMENSIONS_INCLUDE_LABELS = FDLayoutConstants.NODE_DIMENSIONS_INCLUDE_LABELS = LayoutConstants.NODE_DIMENSIONS_INCLUDE_LABELS = options.nodeDimensionsIncludeLabels;
186
+ CoSEConstants.DEFAULT_INCREMENTAL = FDLayoutConstants.DEFAULT_INCREMENTAL = LayoutConstants.DEFAULT_INCREMENTAL = !options.randomize;
187
+ CoSEConstants.ANIMATE = FDLayoutConstants.ANIMATE = LayoutConstants.ANIMATE = options.animate;
188
+ CoSEConstants.TILE = options.tile;
189
+ CoSEConstants.TILING_PADDING_VERTICAL = typeof options.tilingPaddingVertical === 'function' ? options.tilingPaddingVertical.call() : options.tilingPaddingVertical;
190
+ CoSEConstants.TILING_PADDING_HORIZONTAL = typeof options.tilingPaddingHorizontal === 'function' ? options.tilingPaddingHorizontal.call() : options.tilingPaddingHorizontal;
191
+ };
192
+
193
+ _CoSELayout.prototype.run = function () {
194
+ var ready;
195
+ var frameId;
196
+ var options = this.options;
197
+ var idToLNode = this.idToLNode = {};
198
+ var layout = this.layout = new CoSELayout();
199
+ var self = this;
200
+
201
+ self.stopped = false;
202
+
203
+ this.cy = this.options.cy;
204
+
205
+ this.cy.trigger({ type: 'layoutstart', layout: this });
206
+
207
+ var gm = layout.newGraphManager();
208
+ this.gm = gm;
209
+
210
+ var nodes = this.options.eles.nodes();
211
+ var edges = this.options.eles.edges();
212
+
213
+ this.root = gm.addRoot();
214
+ this.processChildrenList(this.root, this.getTopMostNodes(nodes), layout);
215
+
216
+ for (var i = 0; i < edges.length; i++) {
217
+ var edge = edges[i];
218
+ var sourceNode = this.idToLNode[edge.data("source")];
219
+ var targetNode = this.idToLNode[edge.data("target")];
220
+ if (sourceNode !== targetNode && sourceNode.getEdgesBetween(targetNode).length == 0) {
221
+ var e1 = gm.add(layout.newEdge(), sourceNode, targetNode);
222
+ e1.id = edge.id();
223
+ }
224
+ }
225
+
226
+ var getPositions = function getPositions(ele, i) {
227
+ if (typeof ele === "number") {
228
+ ele = i;
229
+ }
230
+ var theId = ele.data('id');
231
+ var lNode = self.idToLNode[theId];
232
+
233
+ return {
234
+ x: lNode.getRect().getCenterX(),
235
+ y: lNode.getRect().getCenterY()
236
+ };
237
+ };
238
+
239
+ /*
240
+ * Reposition nodes in iterations animatedly
241
+ */
242
+ var iterateAnimated = function iterateAnimated() {
243
+ // Thigs to perform after nodes are repositioned on screen
244
+ var afterReposition = function afterReposition() {
245
+ if (options.fit) {
246
+ options.cy.fit(options.eles, options.padding);
247
+ }
248
+
249
+ if (!ready) {
250
+ ready = true;
251
+ self.cy.one('layoutready', options.ready);
252
+ self.cy.trigger({ type: 'layoutready', layout: self });
253
+ }
254
+ };
255
+
256
+ var ticksPerFrame = self.options.refresh;
257
+ var isDone;
258
+
259
+ for (var i = 0; i < ticksPerFrame && !isDone; i++) {
260
+ isDone = self.stopped || self.layout.tick();
261
+ }
262
+
263
+ // If layout is done
264
+ if (isDone) {
265
+ // If the layout is not a sublayout and it is successful perform post layout.
266
+ if (layout.checkLayoutSuccess() && !layout.isSubLayout) {
267
+ layout.doPostLayout();
268
+ }
269
+
270
+ // If layout has a tilingPostLayout function property call it.
271
+ if (layout.tilingPostLayout) {
272
+ layout.tilingPostLayout();
273
+ }
274
+
275
+ layout.isLayoutFinished = true;
276
+
277
+ self.options.eles.nodes().positions(getPositions);
278
+
279
+ afterReposition();
280
+
281
+ // trigger layoutstop when the layout stops (e.g. finishes)
282
+ self.cy.one('layoutstop', self.options.stop);
283
+ self.cy.trigger({ type: 'layoutstop', layout: self });
284
+
285
+ if (frameId) {
286
+ cancelAnimationFrame(frameId);
287
+ }
288
+
289
+ ready = false;
290
+ return;
291
+ }
292
+
293
+ var animationData = self.layout.getPositionsData(); // Get positions of layout nodes note that all nodes may not be layout nodes because of tiling
294
+
295
+ // Position nodes, for the nodes whose id does not included in data (because they are removed from their parents and included in dummy compounds)
296
+ // use position of their ancestors or dummy ancestors
297
+ options.eles.nodes().positions(function (ele, i) {
298
+ if (typeof ele === "number") {
299
+ ele = i;
300
+ }
301
+ // If ele is a compound node, then its position will be defined by its children
302
+ if (!ele.isParent()) {
303
+ var theId = ele.id();
304
+ var pNode = animationData[theId];
305
+ var temp = ele;
306
+ // If pNode is undefined search until finding position data of its first ancestor (It may be dummy as well)
307
+ while (pNode == null) {
308
+ pNode = animationData[temp.data('parent')] || animationData['DummyCompound_' + temp.data('parent')];
309
+ animationData[theId] = pNode;
310
+ temp = temp.parent()[0];
311
+ if (temp == undefined) {
312
+ break;
313
+ }
314
+ }
315
+ if (pNode != null) {
316
+ return {
317
+ x: pNode.x,
318
+ y: pNode.y
319
+ };
320
+ } else {
321
+ return {
322
+ x: ele.position('x'),
323
+ y: ele.position('y')
324
+ };
325
+ }
326
+ }
327
+ });
328
+
329
+ afterReposition();
330
+
331
+ frameId = requestAnimationFrame(iterateAnimated);
332
+ };
333
+
334
+ /*
335
+ * Listen 'layoutstarted' event and start animated iteration if animate option is 'during'
336
+ */
337
+ layout.addListener('layoutstarted', function () {
338
+ if (self.options.animate === 'during') {
339
+ frameId = requestAnimationFrame(iterateAnimated);
340
+ }
341
+ });
342
+
343
+ layout.runLayout(); // Run cose layout
344
+
345
+ /*
346
+ * If animate option is not 'during' ('end' or false) perform these here (If it is 'during' similar things are already performed)
347
+ */
348
+ if (this.options.animate !== "during") {
349
+ self.options.eles.nodes().not(":parent").layoutPositions(self, self.options, getPositions); // Use layout positions to reposition the nodes it considers the options parameter
350
+ ready = false;
351
+ }
352
+
353
+ return this; // chaining
354
+ };
355
+
356
+ //Get the top most ones of a list of nodes
357
+ _CoSELayout.prototype.getTopMostNodes = function (nodes) {
358
+ var nodesMap = {};
359
+ for (var i = 0; i < nodes.length; i++) {
360
+ nodesMap[nodes[i].id()] = true;
361
+ }
362
+ var roots = nodes.filter(function (ele, i) {
363
+ if (typeof ele === "number") {
364
+ ele = i;
365
+ }
366
+ var parent = ele.parent()[0];
367
+ while (parent != null) {
368
+ if (nodesMap[parent.id()]) {
369
+ return false;
370
+ }
371
+ parent = parent.parent()[0];
372
+ }
373
+ return true;
374
+ });
375
+
376
+ return roots;
377
+ };
378
+
379
+ _CoSELayout.prototype.processChildrenList = function (parent, children, layout) {
380
+ var size = children.length;
381
+ for (var i = 0; i < size; i++) {
382
+ var theChild = children[i];
383
+ var children_of_children = theChild.children();
384
+ var theNode;
385
+
386
+ var dimensions = theChild.layoutDimensions({
387
+ nodeDimensionsIncludeLabels: this.options.nodeDimensionsIncludeLabels
388
+ });
389
+
390
+ if (theChild.outerWidth() != null && theChild.outerHeight() != null) {
391
+ theNode = parent.add(new CoSENode(layout.graphManager, new PointD(theChild.position('x') - dimensions.w / 2, theChild.position('y') - dimensions.h / 2), new DimensionD(parseFloat(dimensions.w), parseFloat(dimensions.h))));
392
+ } else {
393
+ theNode = parent.add(new CoSENode(this.graphManager));
394
+ }
395
+ // Attach id to the layout node
396
+ theNode.id = theChild.data("id");
397
+ // Attach the paddings of cy node to layout node
398
+ theNode.paddingLeft = parseInt(theChild.css('padding'));
399
+ theNode.paddingTop = parseInt(theChild.css('padding'));
400
+ theNode.paddingRight = parseInt(theChild.css('padding'));
401
+ theNode.paddingBottom = parseInt(theChild.css('padding'));
402
+
403
+ //Attach the label properties to compound if labels will be included in node dimensions
404
+ if (this.options.nodeDimensionsIncludeLabels) {
405
+ if (theChild.isParent()) {
406
+ var labelWidth = theChild.boundingBox({ includeLabels: true, includeNodes: false }).w;
407
+ var labelHeight = theChild.boundingBox({ includeLabels: true, includeNodes: false }).h;
408
+ var labelPos = theChild.css("text-halign");
409
+ theNode.labelWidth = labelWidth;
410
+ theNode.labelHeight = labelHeight;
411
+ theNode.labelPos = labelPos;
412
+ }
413
+ }
414
+
415
+ // Map the layout node
416
+ this.idToLNode[theChild.data("id")] = theNode;
417
+
418
+ if (isNaN(theNode.rect.x)) {
419
+ theNode.rect.x = 0;
420
+ }
421
+
422
+ if (isNaN(theNode.rect.y)) {
423
+ theNode.rect.y = 0;
424
+ }
425
+
426
+ if (children_of_children != null && children_of_children.length > 0) {
427
+ var theNewGraph;
428
+ theNewGraph = layout.getGraphManager().add(layout.newGraph(), theNode);
429
+ this.processChildrenList(theNewGraph, children_of_children, layout);
430
+ }
431
+ }
432
+ };
433
+
434
+ /**
435
+ * @brief : called on continuous layouts to stop them before they finish
436
+ */
437
+ _CoSELayout.prototype.stop = function () {
438
+ this.stopped = true;
439
+
440
+ return this; // chaining
441
+ };
442
+
443
+ var register = function register(cytoscape) {
444
+ // var Layout = getLayout( cytoscape );
445
+
446
+ cytoscape('layout', 'cose-bilkent', _CoSELayout);
447
+ };
448
+
449
+ // auto reg for globals
450
+ if (typeof cytoscape !== 'undefined') {
451
+ register(cytoscape);
452
+ }
453
+
454
+ module.exports = register;
455
+
456
+ /***/ })
457
+ /******/ ]);
458
+ });