Source file src/cmd/vendor/github.com/google/pprof/third_party/d3flamegraph/d3_flame_graph.go

     1  // A D3.js plugin that produces flame graphs from hierarchical data.
     2  // https://github.com/spiermar/d3-flame-graph
     3  // Version 2.0.0-alpha4
     4  // See LICENSE file for license details
     5  
     6  package d3flamegraph
     7  
     8  // JSSource returns the d3-flamegraph.js file
     9  const JSSource = `
    10  (function (global, factory) {
    11  	typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('d3')) :
    12  	typeof define === 'function' && define.amd ? define(['exports', 'd3'], factory) :
    13  	(factory((global.d3 = global.d3 || {}),global.d3));
    14  }(this, (function (exports,d3) { 'use strict';
    15  
    16  var d3__default = 'default' in d3 ? d3['default'] : d3;
    17  
    18  var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
    19  
    20  
    21  
    22  
    23  
    24  function createCommonjsModule(fn, module) {
    25  	return module = { exports: {} }, fn(module, module.exports), module.exports;
    26  }
    27  
    28  var d3Tip = createCommonjsModule(function (module) {
    29  // d3.tip
    30  // Copyright (c) 2013 Justin Palmer
    31  //
    32  // Tooltips for d3.js SVG visualizations
    33  
    34  (function (root, factory) {
    35    if (typeof undefined === 'function' && undefined.amd) {
    36      // AMD. Register as an anonymous module with d3 as a dependency.
    37      undefined(['d3'], factory);
    38    } else if ('object' === 'object' && module.exports) {
    39      // CommonJS
    40      var d3$$1 = d3__default;
    41      module.exports = factory(d3$$1);
    42    } else {
    43      // Browser global.
    44      root.d3.tip = factory(root.d3);
    45    }
    46  }(commonjsGlobal, function (d3$$1) {
    47  
    48    // Public - contructs a new tooltip
    49    //
    50    // Returns a tip
    51    return function() {
    52      var direction = d3_tip_direction,
    53          offset    = d3_tip_offset,
    54          html      = d3_tip_html,
    55          node      = initNode(),
    56          svg       = null,
    57          point     = null,
    58          target    = null;
    59  
    60      function tip(vis) {
    61        svg = getSVGNode(vis);
    62        point = svg.createSVGPoint();
    63        document.body.appendChild(node);
    64      }
    65  
    66      // Public - show the tooltip on the screen
    67      //
    68      // Returns a tip
    69      tip.show = function() {
    70        var args = Array.prototype.slice.call(arguments);
    71        if(args[args.length - 1] instanceof SVGElement) target = args.pop();
    72  
    73        var content = html.apply(this, args),
    74            poffset = offset.apply(this, args),
    75            dir     = direction.apply(this, args),
    76            nodel   = getNodeEl(),
    77            i       = directions.length,
    78            coords,
    79            scrollTop  = document.documentElement.scrollTop || document.body.scrollTop,
    80            scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
    81  
    82        nodel.html(content)
    83          .style('opacity', 1).style('pointer-events', 'all');
    84  
    85        while(i--) nodel.classed(directions[i], false);
    86        coords = direction_callbacks.get(dir).apply(this);
    87        nodel.classed(dir, true)
    88        	.style('top', (coords.top +  poffset[0]) + scrollTop + 'px')
    89        	.style('left', (coords.left + poffset[1]) + scrollLeft + 'px');
    90  
    91        return tip;
    92      };
    93  
    94      // Public - hide the tooltip
    95      //
    96      // Returns a tip
    97      tip.hide = function() {
    98        var nodel = getNodeEl();
    99        nodel.style('opacity', 0).style('pointer-events', 'none');
   100        return tip
   101      };
   102  
   103      // Public: Proxy attr calls to the d3 tip container.  Sets or gets attribute value.
   104      //
   105      // n - name of the attribute
   106      // v - value of the attribute
   107      //
   108      // Returns tip or attribute value
   109      tip.attr = function(n, v) {
   110        if (arguments.length < 2 && typeof n === 'string') {
   111          return getNodeEl().attr(n)
   112        } else {
   113          var args =  Array.prototype.slice.call(arguments);
   114          d3$$1.selection.prototype.attr.apply(getNodeEl(), args);
   115        }
   116  
   117        return tip
   118      };
   119  
   120      // Public: Proxy style calls to the d3 tip container.  Sets or gets a style value.
   121      //
   122      // n - name of the property
   123      // v - value of the property
   124      //
   125      // Returns tip or style property value
   126      tip.style = function(n, v) {
   127        if (arguments.length < 2 && typeof n === 'string') {
   128          return getNodeEl().style(n)
   129        } else {
   130          var args = Array.prototype.slice.call(arguments);
   131          d3$$1.selection.prototype.style.apply(getNodeEl(), args);
   132        }
   133  
   134        return tip
   135      };
   136  
   137      // Public: Set or get the direction of the tooltip
   138      //
   139      // v - One of n(north), s(south), e(east), or w(west), nw(northwest),
   140      //     sw(southwest), ne(northeast) or se(southeast)
   141      //
   142      // Returns tip or direction
   143      tip.direction = function(v) {
   144        if (!arguments.length) return direction
   145        direction = v == null ? v : functor(v);
   146  
   147        return tip
   148      };
   149  
   150      // Public: Sets or gets the offset of the tip
   151      //
   152      // v - Array of [x, y] offset
   153      //
   154      // Returns offset or
   155      tip.offset = function(v) {
   156        if (!arguments.length) return offset
   157        offset = v == null ? v : functor(v);
   158  
   159        return tip
   160      };
   161  
   162      // Public: sets or gets the html value of the tooltip
   163      //
   164      // v - String value of the tip
   165      //
   166      // Returns html value or tip
   167      tip.html = function(v) {
   168        if (!arguments.length) return html
   169        html = v == null ? v : functor(v);
   170  
   171        return tip
   172      };
   173  
   174      // Public: destroys the tooltip and removes it from the DOM
   175      //
   176      // Returns a tip
   177      tip.destroy = function() {
   178        if(node) {
   179          getNodeEl().remove();
   180          node = null;
   181        }
   182        return tip;
   183      };
   184  
   185      function d3_tip_direction() { return 'n' }
   186      function d3_tip_offset() { return [0, 0] }
   187      function d3_tip_html() { return ' ' }
   188  
   189      var direction_callbacks = d3$$1.map({
   190        n:  direction_n,
   191        s:  direction_s,
   192        e:  direction_e,
   193        w:  direction_w,
   194        nw: direction_nw,
   195        ne: direction_ne,
   196        sw: direction_sw,
   197        se: direction_se
   198      }),
   199  
   200      directions = direction_callbacks.keys();
   201  
   202      function direction_n() {
   203        var bbox = getScreenBBox();
   204        return {
   205          top:  bbox.n.y - node.offsetHeight,
   206          left: bbox.n.x - node.offsetWidth / 2
   207        }
   208      }
   209  
   210      function direction_s() {
   211        var bbox = getScreenBBox();
   212        return {
   213          top:  bbox.s.y,
   214          left: bbox.s.x - node.offsetWidth / 2
   215        }
   216      }
   217  
   218      function direction_e() {
   219        var bbox = getScreenBBox();
   220        return {
   221          top:  bbox.e.y - node.offsetHeight / 2,
   222          left: bbox.e.x
   223        }
   224      }
   225  
   226      function direction_w() {
   227        var bbox = getScreenBBox();
   228        return {
   229          top:  bbox.w.y - node.offsetHeight / 2,
   230          left: bbox.w.x - node.offsetWidth
   231        }
   232      }
   233  
   234      function direction_nw() {
   235        var bbox = getScreenBBox();
   236        return {
   237          top:  bbox.nw.y - node.offsetHeight,
   238          left: bbox.nw.x - node.offsetWidth
   239        }
   240      }
   241  
   242      function direction_ne() {
   243        var bbox = getScreenBBox();
   244        return {
   245          top:  bbox.ne.y - node.offsetHeight,
   246          left: bbox.ne.x
   247        }
   248      }
   249  
   250      function direction_sw() {
   251        var bbox = getScreenBBox();
   252        return {
   253          top:  bbox.sw.y,
   254          left: bbox.sw.x - node.offsetWidth
   255        }
   256      }
   257  
   258      function direction_se() {
   259        var bbox = getScreenBBox();
   260        return {
   261          top:  bbox.se.y,
   262          left: bbox.e.x
   263        }
   264      }
   265  
   266      function initNode() {
   267        var node = d3$$1.select(document.createElement('div'));
   268        node.style('position', 'absolute').style('top', 0).style('opacity', 0)
   269        	.style('pointer-events', 'none').style('box-sizing', 'border-box');
   270  
   271        return node.node()
   272      }
   273  
   274      function getSVGNode(el) {
   275        el = el.node();
   276        if(el.tagName.toLowerCase() === 'svg')
   277          return el
   278  
   279        return el.ownerSVGElement
   280      }
   281  
   282      function getNodeEl() {
   283        if(node === null) {
   284          node = initNode();
   285          // re-add node to DOM
   286          document.body.appendChild(node);
   287        }
   288        return d3$$1.select(node);
   289      }
   290  
   291      // Private - gets the screen coordinates of a shape
   292      //
   293      // Given a shape on the screen, will return an SVGPoint for the directions
   294      // n(north), s(south), e(east), w(west), ne(northeast), se(southeast), nw(northwest),
   295      // sw(southwest).
   296      //
   297      //    +-+-+
   298      //    |   |
   299      //    +   +
   300      //    |   |
   301      //    +-+-+
   302      //
   303      // Returns an Object {n, s, e, w, nw, sw, ne, se}
   304      function getScreenBBox() {
   305        var targetel   = target || d3$$1.event.target;
   306  
   307        while ('undefined' === typeof targetel.getScreenCTM && 'undefined' === targetel.parentNode) {
   308            targetel = targetel.parentNode;
   309        }
   310  
   311        var bbox       = {},
   312            matrix     = targetel.getScreenCTM(),
   313            tbbox      = targetel.getBBox(),
   314            width      = tbbox.width,
   315            height     = tbbox.height,
   316            x          = tbbox.x,
   317            y          = tbbox.y;
   318  
   319        point.x = x;
   320        point.y = y;
   321        bbox.nw = point.matrixTransform(matrix);
   322        point.x += width;
   323        bbox.ne = point.matrixTransform(matrix);
   324        point.y += height;
   325        bbox.se = point.matrixTransform(matrix);
   326        point.x -= width;
   327        bbox.sw = point.matrixTransform(matrix);
   328        point.y -= height / 2;
   329        bbox.w  = point.matrixTransform(matrix);
   330        point.x += width;
   331        bbox.e = point.matrixTransform(matrix);
   332        point.x -= width / 2;
   333        point.y -= height / 2;
   334        bbox.n = point.matrixTransform(matrix);
   335        point.y += height;
   336        bbox.s = point.matrixTransform(matrix);
   337  
   338        return bbox
   339      }
   340  
   341      // Private - replace D3JS 3.X d3.functor() function
   342      function functor(v) {
   343      	return typeof v === "function" ? v : function() {
   344          return v
   345      	}
   346      }
   347  
   348      return tip
   349    };
   350  
   351  }));
   352  });
   353  
   354  var flamegraph = function () {
   355    var w = 960; // graph width
   356    var h = null; // graph height
   357    var c = 18; // cell height
   358    var selection = null; // selection
   359    var tooltip = true; // enable tooltip
   360    var title = ''; // graph title
   361    var transitionDuration = 750;
   362    var transitionEase = d3.easeCubic; // tooltip offset
   363    var sort = false;
   364    var inverted = false; // invert the graph direction
   365    var clickHandler = null;
   366    var minFrameSize = 0;
   367    var details = null;
   368  
   369    var tip = d3Tip()
   370      .direction('s')
   371      .offset([8, 0])
   372      .attr('class', 'd3-flame-graph-tip')
   373      .html(function (d) { return label(d) });
   374  
   375    var svg;
   376  
   377    function name (d) {
   378      return d.data.n || d.data.name
   379    }
   380  
   381    function libtype (d) {
   382      return d.data.l || d.data.libtype
   383    }
   384  
   385    function children (d) {
   386      return d.c || d.children
   387    }
   388  
   389    function value (d) {
   390      return d.v || d.value
   391    }
   392  
   393    var label = function (d) {
   394      return name(d) + ' (' + d3.format('.3f')(100 * (d.x1 - d.x0), 3) + '%, ' + value(d) + ' samples)'
   395    };
   396  
   397    function setDetails (t) {
   398      if (details) { details.innerHTML = t; }
   399    }
   400  
   401    var colorMapper = function (d) {
   402      return d.highlight ? '#E600E6' : colorHash(name(d), libtype(d))
   403    };
   404  
   405    function generateHash (name) {
   406      // Return a vector (0.0->1.0) that is a hash of the input string.
   407      // The hash is computed to favor early characters over later ones, so
   408      // that strings with similar starts have similar vectors. Only the first
   409      // 6 characters are considered.
   410      const MAX_CHAR = 6;
   411  
   412      var hash = 0;
   413      var maxHash = 0;
   414      var weight = 1;
   415      var mod = 10;
   416  
   417      if (name) {
   418        for (var i = 0; i < name.length; i++) {
   419          if (i > MAX_CHAR) { break }
   420          hash += weight * (name.charCodeAt(i) % mod);
   421          maxHash += weight * (mod - 1);
   422          weight *= 0.70;
   423        }
   424        if (maxHash > 0) { hash = hash / maxHash; }
   425      }
   426      return hash
   427    }
   428  
   429    function colorHash (name, libtype) {
   430      // Return a color for the given name and library type. The library type
   431      // selects the hue, and the name is hashed to a color in that hue.
   432  
   433      var r;
   434      var g;
   435      var b;
   436  
   437      // Select hue. Order is important.
   438      var hue;
   439      if (typeof libtype === 'undefined' || libtype === '') {
   440        // default when libtype is not in use
   441        hue = 'warm';
   442      } else {
   443        hue = 'red';
   444        if (name.match(/::/)) {
   445          hue = 'yellow';
   446        }
   447        if (libtype === 'kernel') {
   448          hue = 'orange';
   449        } else if (libtype === 'jit') {
   450          hue = 'green';
   451        } else if (libtype === 'inlined') {
   452          hue = 'aqua';
   453        }
   454      }
   455  
   456      // calculate hash
   457      var vector = 0;
   458      if (name) {
   459        var nameArr = name.split('` + "`" + `');
   460        if (nameArr.length > 1) {
   461          name = nameArr[nameArr.length - 1]; // drop module name if present
   462        }
   463        name = name.split('(')[0]; // drop extra info
   464        vector = generateHash(name);
   465      }
   466  
   467      // calculate color
   468      if (hue === 'red') {
   469        r = 200 + Math.round(55 * vector);
   470        g = 50 + Math.round(80 * vector);
   471        b = g;
   472      } else if (hue === 'orange') {
   473        r = 190 + Math.round(65 * vector);
   474        g = 90 + Math.round(65 * vector);
   475        b = 0;
   476      } else if (hue === 'yellow') {
   477        r = 175 + Math.round(55 * vector);
   478        g = r;
   479        b = 50 + Math.round(20 * vector);
   480      } else if (hue === 'green') {
   481        r = 50 + Math.round(60 * vector);
   482        g = 200 + Math.round(55 * vector);
   483        b = r;
   484      } else if (hue === 'aqua') {
   485        r = 50 + Math.round(60 * vector);
   486        g = 165 + Math.round(55 * vector);
   487        b = g;
   488      } else {
   489        // original warm palette
   490        r = 200 + Math.round(55 * vector);
   491        g = 0 + Math.round(230 * (1 - vector));
   492        b = 0 + Math.round(55 * (1 - vector));
   493      }
   494  
   495      return 'rgb(' + r + ',' + g + ',' + b + ')'
   496    }
   497  
   498    function hide (d) {
   499      d.data.hide = true;
   500      if (children(d)) {
   501        children(d).forEach(hide);
   502      }
   503    }
   504  
   505    function show (d) {
   506      d.data.fade = false;
   507      d.data.hide = false;
   508      if (children(d)) {
   509        children(d).forEach(show);
   510      }
   511    }
   512  
   513    function getSiblings (d) {
   514      var siblings = [];
   515      if (d.parent) {
   516        var me = d.parent.children.indexOf(d);
   517        siblings = d.parent.children.slice(0);
   518        siblings.splice(me, 1);
   519      }
   520      return siblings
   521    }
   522  
   523    function hideSiblings (d) {
   524      var siblings = getSiblings(d);
   525      siblings.forEach(function (s) {
   526        hide(s);
   527      });
   528      if (d.parent) {
   529        hideSiblings(d.parent);
   530      }
   531    }
   532  
   533    function fadeAncestors (d) {
   534      if (d.parent) {
   535        d.parent.data.fade = true;
   536        fadeAncestors(d.parent);
   537      }
   538    }
   539  
   540    // function getRoot (d) {
   541    //   if (d.parent) {
   542    //     return getRoot(d.parent)
   543    //   }
   544    //   return d
   545    // }
   546  
   547    function zoom (d) {
   548      tip.hide(d);
   549      hideSiblings(d);
   550      show(d);
   551      fadeAncestors(d);
   552      update();
   553      if (typeof clickHandler === 'function') {
   554        clickHandler(d);
   555      }
   556    }
   557  
   558    function searchTree (d, term) {
   559      var re = new RegExp(term);
   560      var searchResults = [];
   561  
   562      function searchInner (d) {
   563        var label = name(d);
   564  
   565        if (children(d)) {
   566          children(d).forEach(function (child) {
   567            searchInner(child);
   568          });
   569        }
   570  
   571        if (label.match(re)) {
   572          d.highlight = true;
   573          searchResults.push(d);
   574        } else {
   575          d.highlight = false;
   576        }
   577      }
   578  
   579      searchInner(d);
   580      return searchResults
   581    }
   582  
   583    function clear (d) {
   584      d.highlight = false;
   585      if (children(d)) {
   586        children(d).forEach(function (child) {
   587          clear(child);
   588        });
   589      }
   590    }
   591  
   592    function doSort (a, b) {
   593      if (typeof sort === 'function') {
   594        return sort(a, b)
   595      } else if (sort) {
   596        return d3.ascending(name(a), name(b))
   597      }
   598    }
   599  
   600    var p = d3.partition();
   601  
   602    function filterNodes (root) {
   603      var nodeList = root.descendants();
   604      if (minFrameSize > 0) {
   605        var kx = w / (root.x1 - root.x0);
   606        nodeList = nodeList.filter(function (el) {
   607          return ((el.x1 - el.x0) * kx) > minFrameSize
   608        });
   609      }
   610      return nodeList
   611    }
   612  
   613    function update () {
   614      selection.each(function (root) {
   615        var x = d3.scaleLinear().range([0, w]);
   616        var y = d3.scaleLinear().range([0, c]);
   617  
   618        if (sort) root.sort(doSort);
   619        root.sum(function (d) {
   620          if (d.fade || d.hide) {
   621            return 0
   622          }
   623          // The node's self value is its total value minus all children.
   624          var v = value(d);
   625          if (children(d)) {
   626            var c = children(d);
   627            for (var i = 0; i < c.length; i++) {
   628              v -= value(c[i]);
   629            }
   630          }
   631          return v
   632        });
   633        p(root);
   634  
   635        var kx = w / (root.x1 - root.x0);
   636        function width (d) { return (d.x1 - d.x0) * kx }
   637  
   638        var descendants = filterNodes(root);
   639        var g = d3.select(this).select('svg').selectAll('g').data(descendants, function (d) { return d.id });
   640  
   641        g.transition()
   642          .duration(transitionDuration)
   643          .ease(transitionEase)
   644          .attr('transform', function (d) { return 'translate(' + x(d.x0) + ',' + (inverted ? y(d.depth) : (h - y(d.depth) - c)) + ')' });
   645  
   646        g.select('rect')
   647          .attr('width', width);
   648  
   649        var node = g.enter()
   650          .append('svg:g')
   651          .attr('transform', function (d) { return 'translate(' + x(d.x0) + ',' + (inverted ? y(d.depth) : (h - y(d.depth) - c)) + ')' });
   652  
   653        node.append('svg:rect')
   654          .transition()
   655          .delay(transitionDuration / 2)
   656          .attr('width', width);
   657  
   658        if (!tooltip) { node.append('svg:title'); }
   659  
   660        node.append('foreignObject')
   661          .append('xhtml:div');
   662  
   663        // Now we have to re-select to see the new elements (why?).
   664        g = d3.select(this).select('svg').selectAll('g').data(descendants, function (d) { return d.id });
   665  
   666        g.attr('width', width)
   667          .attr('height', function (d) { return c })
   668          .attr('name', function (d) { return name(d) })
   669          .attr('class', function (d) { return d.data.fade ? 'frame fade' : 'frame' });
   670  
   671        g.select('rect')
   672          .attr('height', function (d) { return c })
   673          .attr('fill', function (d) { return colorMapper(d) });
   674  
   675        if (!tooltip) {
   676          g.select('title')
   677            .text(label);
   678        }
   679  
   680        g.select('foreignObject')
   681          .attr('width', width)
   682          .attr('height', function (d) { return c })
   683          .select('div')
   684          .attr('class', 'd3-flame-graph-label')
   685          .style('display', function (d) { return (width(d) < 35) ? 'none' : 'block' })
   686          .transition()
   687          .delay(transitionDuration)
   688          .text(name);
   689  
   690        g.on('click', zoom);
   691  
   692        g.exit()
   693          .remove();
   694  
   695        g.on('mouseover', function (d) {
   696          if (tooltip) tip.show(d, this);
   697          setDetails(label(d));
   698        }).on('mouseout', function (d) {
   699          if (tooltip) tip.hide(d);
   700          setDetails('');
   701        });
   702      });
   703    }
   704  
   705    function merge (data, samples) {
   706      samples.forEach(function (sample) {
   707        var node = data.find(function (element) {
   708          return (element.name === sample.name)
   709        });
   710  
   711        if (node) {
   712          if (node.original) {
   713            node.original += sample.value;
   714          } else {
   715            node.value += sample.value;
   716          }
   717          if (sample.children) {
   718            if (!node.children) {
   719              node.children = [];
   720            }
   721            merge(node.children, sample.children);
   722          }
   723        } else {
   724          data.push(sample);
   725        }
   726      });
   727    }
   728  
   729    function s4 () {
   730      return Math.floor((1 + Math.random()) * 0x10000)
   731        .toString(16)
   732        .substring(1)
   733    }
   734  
   735    function injectIds (node) {
   736      node.id = s4() + '-' + s4() + '-' + '-' + s4() + '-' + s4();
   737      var children = node.c || node.children || [];
   738      for (var i = 0; i < children.length; i++) {
   739        injectIds(children[i]);
   740      }
   741    }
   742  
   743    function chart (s) {
   744      var root = d3.hierarchy(
   745        s.datum(), function (d) { return children(d) }
   746      );
   747      injectIds(root);
   748      selection = s.datum(root);
   749  
   750      if (!arguments.length) return chart
   751  
   752      if (!h) {
   753        h = (root.height + 2) * c;
   754      }
   755  
   756      selection.each(function (data) {
   757        if (!svg) {
   758          svg = d3.select(this)
   759            .append('svg:svg')
   760            .attr('width', w)
   761            .attr('height', h)
   762            .attr('class', 'partition d3-flame-graph')
   763            .call(tip);
   764  
   765          svg.append('svg:text')
   766            .attr('class', 'title')
   767            .attr('text-anchor', 'middle')
   768            .attr('y', '25')
   769            .attr('x', w / 2)
   770            .attr('fill', '#808080')
   771            .text(title);
   772        }
   773      });
   774  
   775      // first draw
   776      update();
   777    }
   778  
   779    chart.height = function (_) {
   780      if (!arguments.length) { return h }
   781      h = _;
   782      return chart
   783    };
   784  
   785    chart.width = function (_) {
   786      if (!arguments.length) { return w }
   787      w = _;
   788      return chart
   789    };
   790  
   791    chart.cellHeight = function (_) {
   792      if (!arguments.length) { return c }
   793      c = _;
   794      return chart
   795    };
   796  
   797    chart.tooltip = function (_) {
   798      if (!arguments.length) { return tooltip }
   799      if (typeof _ === 'function') {
   800        tip = _;
   801      }
   802      tooltip = !!_;
   803      return chart
   804    };
   805  
   806    chart.title = function (_) {
   807      if (!arguments.length) { return title }
   808      title = _;
   809      return chart
   810    };
   811  
   812    chart.transitionDuration = function (_) {
   813      if (!arguments.length) { return transitionDuration }
   814      transitionDuration = _;
   815      return chart
   816    };
   817  
   818    chart.transitionEase = function (_) {
   819      if (!arguments.length) { return transitionEase }
   820      transitionEase = _;
   821      return chart
   822    };
   823  
   824    chart.sort = function (_) {
   825      if (!arguments.length) { return sort }
   826      sort = _;
   827      return chart
   828    };
   829  
   830    chart.inverted = function (_) {
   831      if (!arguments.length) { return inverted }
   832      inverted = _;
   833      return chart
   834    };
   835  
   836    chart.label = function (_) {
   837      if (!arguments.length) { return label }
   838      label = _;
   839      return chart
   840    };
   841  
   842    chart.search = function (term) {
   843      var searchResults = [];
   844      selection.each(function (data) {
   845        searchResults = searchTree(data, term);
   846        update();
   847      });
   848      return searchResults
   849    };
   850  
   851    chart.clear = function () {
   852      selection.each(function (data) {
   853        clear(data);
   854        update();
   855      });
   856    };
   857  
   858    chart.zoomTo = function (d) {
   859      zoom(d);
   860    };
   861  
   862    chart.resetZoom = function () {
   863      selection.each(function (data) {
   864        zoom(data); // zoom to root
   865      });
   866    };
   867  
   868    chart.onClick = function (_) {
   869      if (!arguments.length) {
   870        return clickHandler
   871      }
   872      clickHandler = _;
   873      return chart
   874    };
   875  
   876    chart.merge = function (samples) {
   877      var newRoot; // Need to re-create hierarchy after data changes.
   878      selection.each(function (root) {
   879        merge([root.data], [samples]);
   880        newRoot = d3.hierarchy(root.data, function (d) { return children(d) });
   881        injectIds(newRoot);
   882      });
   883      selection = selection.datum(newRoot);
   884      update();
   885    };
   886  
   887    chart.color = function (_) {
   888      if (!arguments.length) { return colorMapper }
   889      colorMapper = _;
   890      return chart
   891    };
   892  
   893    chart.minFrameSize = function (_) {
   894      if (!arguments.length) { return minFrameSize }
   895      minFrameSize = _;
   896      return chart
   897    };
   898  
   899    chart.details = function (_) {
   900      if (!arguments.length) { return details }
   901      details = _;
   902      return chart
   903    };
   904  
   905    return chart
   906  };
   907  
   908  exports.flamegraph = flamegraph;
   909  
   910  Object.defineProperty(exports, '__esModule', { value: true });
   911  
   912  })));
   913  `
   914  
   915  // CSSSource returns the d3-flamegraph.css file
   916  const CSSSource = `
   917  .d3-flame-graph rect {
   918    stroke: #EEEEEE;
   919    fill-opacity: .8;
   920  }
   921  
   922  .d3-flame-graph rect:hover {
   923    stroke: #474747;
   924    stroke-width: 0.5;
   925    cursor: pointer;
   926  }
   927  
   928  .d3-flame-graph-label {
   929    pointer-events: none;
   930    white-space: nowrap;
   931    text-overflow: ellipsis;
   932    overflow: hidden;
   933    font-size: 12px;
   934    font-family: Verdana;
   935    margin-left: 4px;
   936    margin-right: 4px;
   937    line-height: 1.5;
   938    padding: 0 0 0;
   939    font-weight: 400;
   940    color: black;
   941    text-align: left;
   942  }
   943  
   944  .d3-flame-graph .fade {
   945    opacity: 0.6 !important;
   946  }
   947  
   948  .d3-flame-graph .title {
   949    font-size: 20px;
   950    font-family: Verdana;
   951  }
   952  
   953  .d3-flame-graph-tip {
   954    line-height: 1;
   955    font-family: Verdana;
   956    font-size: 12px;
   957    padding: 12px;
   958    background: rgba(0, 0, 0, 0.8);
   959    color: #fff;
   960    border-radius: 2px;
   961    pointer-events: none;
   962  }
   963  
   964  /* Creates a small triangle extender for the tooltip */
   965  .d3-flame-graph-tip:after {
   966    box-sizing: border-box;
   967    display: inline;
   968    font-size: 10px;
   969    width: 100%;
   970    line-height: 1;
   971    color: rgba(0, 0, 0, 0.8);
   972    position: absolute;
   973    pointer-events: none;
   974  }
   975  
   976  /* Northward tooltips */
   977  .d3-flame-graph-tip.n:after {
   978    content: "\25BC";
   979    margin: -1px 0 0 0;
   980    top: 100%;
   981    left: 0;
   982    text-align: center;
   983  }
   984  
   985  /* Eastward tooltips */
   986  .d3-flame-graph-tip.e:after {
   987    content: "\25C0";
   988    margin: -4px 0 0 0;
   989    top: 50%;
   990    left: -8px;
   991  }
   992  
   993  /* Southward tooltips */
   994  .d3-flame-graph-tip.s:after {
   995    content: "\25B2";
   996    margin: 0 0 1px 0;
   997    top: -8px;
   998    left: 0;
   999    text-align: center;
  1000  }
  1001  
  1002  /* Westward tooltips */
  1003  .d3-flame-graph-tip.w:after {
  1004    content: "\25B6";
  1005    margin: -4px 0 0 -1px;
  1006    top: 50%;
  1007    left: 100%;
  1008  }
  1009  `
  1010  

View as plain text