├── .gitignore ├── favicon.ico ├── images ├── twig.png ├── faker.png ├── jquery.png └── uptime.png ├── stylesheets ├── .DS_Store ├── style.css └── bootstrap-responsive.min.css ├── javascripts ├── d3 │ ├── .DS_Store │ ├── detector.js │ └── d3.geom.js ├── dataConverter.js └── CodeFlower.js ├── README.md ├── LICENSE ├── data ├── uptime.json ├── jquery.json ├── faker.json ├── twig.json ├── doctrine2.json ├── lichess.json └── propel2.json ├── index.html └── data.json /.gitignore: -------------------------------------------------------------------------------- 1 | _site 2 | -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fzaninotto/CodeFlower/HEAD/favicon.ico -------------------------------------------------------------------------------- /images/twig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fzaninotto/CodeFlower/HEAD/images/twig.png -------------------------------------------------------------------------------- /images/faker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fzaninotto/CodeFlower/HEAD/images/faker.png -------------------------------------------------------------------------------- /images/jquery.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fzaninotto/CodeFlower/HEAD/images/jquery.png -------------------------------------------------------------------------------- /images/uptime.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fzaninotto/CodeFlower/HEAD/images/uptime.png -------------------------------------------------------------------------------- /stylesheets/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fzaninotto/CodeFlower/HEAD/stylesheets/.DS_Store -------------------------------------------------------------------------------- /javascripts/d3/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fzaninotto/CodeFlower/HEAD/javascripts/d3/.DS_Store -------------------------------------------------------------------------------- /stylesheets/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: 'Rosario', sans-serif; 3 | } 4 | 5 | #visualization { 6 | overflow: auto; 7 | } 8 | 9 | h1 { 10 | font-size: 62px; 11 | font-weight: 300; 12 | letter-spacing: -2px; 13 | line-height: 1em; 14 | margin: 1em 0; 15 | } 16 | 17 | textarea { 18 | width: 98%; 19 | height: 200px; 20 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | CodeFlower 2 | ========== 3 | 4 | This experiment visualizes source repositories using an interactive tree. Each disc represents a file, with a radius proportional to the number of lines of code (loc). All rendering is done client-side, in JavaScript. Built with d3.js, inspired by Code Swarm and Gource, published with the MIT open-source license. 5 | 6 | Interact with CodeFlowers, see examples, and build your own at [https://www.redotheweb.com/CodeFlower/](https://www.redotheweb.com/CodeFlower/). 7 | 8 | ![fzaninotto/uptime](./images/uptime.png) 9 | ![fzaninotto/faker](./images/faker.png) 10 | ![jquery/jquery](./images/jquery.png) 11 | ![fabpot/twig](./images/twig.png) 12 | 13 | You might also like [DependencyWheel](https://github.com/fzaninotto/DependencyWheel), another d3.js visualization for indirect dependencies in software packages. 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Francois Zaninotto 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /javascripts/dataConverter.js: -------------------------------------------------------------------------------- 1 | var convertToJSON = function(data, origin) { 2 | return (origin == 'cloc') ? convertFromClocToJSON(data) : convertFromWcToJSON(data); 3 | }; 4 | 5 | /** 6 | * Convert the output of cloc in csv to JSON format 7 | * 8 | * > cloc . --csv --exclude-dir=vendor,tmp --by-file --report-file=data.cloc 9 | */ 10 | var convertFromClocToJSON = function(data) { 11 | var lines = data.split("\n"); 12 | lines.shift(); // drop the header line 13 | 14 | var json = {}; 15 | lines.forEach(function(line) { 16 | var cols = line.split(','); 17 | var filename = cols[1]; 18 | if (!filename) return; 19 | var elements = filename.split(/[\/\\]/); 20 | var current = json; 21 | elements.forEach(function(element) { 22 | if (!current[element]) { 23 | current[element] = {}; 24 | } 25 | current = current[element]; 26 | }); 27 | current.language = cols[0]; 28 | current.size = parseInt(cols[4], 10); 29 | }); 30 | 31 | json = getChildren(json)[0]; 32 | json.name = 'root'; 33 | 34 | return json; 35 | }; 36 | 37 | /** 38 | * Convert the output of wc to JSON format 39 | * 40 | * > git ls-files | xargs wc -l 41 | */ 42 | var convertFromWcToJSON = function(data) { 43 | var lines = data.split("\n"); 44 | 45 | var json = {}; 46 | var filename, size, cols, elements, current; 47 | lines.forEach(function(line) { 48 | cols = line.trim().split(' '); 49 | size = parseInt(cols[0], 10); 50 | if (!size) return; 51 | filename = cols[1]; 52 | if (filename === "total") return; 53 | if (!filename) return; 54 | elements = filename.split(/[\/\\]/); 55 | current = json; 56 | elements.forEach(function(element) { 57 | if (!current[element]) { 58 | current[element] = {}; 59 | } 60 | current = current[element]; 61 | }); 62 | current.size = size; 63 | }); 64 | 65 | json.children = getChildren(json); 66 | json.name = 'root'; 67 | 68 | return json; 69 | }; 70 | 71 | /** 72 | * Convert a simple json object into another specifying children as an array 73 | * Works recursively 74 | * 75 | * example input: 76 | * { a: { b: { c: { size: 12 }, d: { size: 34 } }, e: { size: 56 } } } 77 | * example output 78 | * { name: a, children: [ 79 | * { name: b, children: [ 80 | * { name: c, size: 12 }, 81 | * { name: d, size: 34 } 82 | * ] }, 83 | * { name: e, size: 56 } 84 | * ] } } 85 | */ 86 | var getChildren = function(json) { 87 | var children = []; 88 | if (json.language) return children; 89 | for (var key in json) { 90 | var child = { name: key }; 91 | if (json[key].size) { 92 | // value node 93 | child.size = json[key].size; 94 | child.language = json[key].language; 95 | } else { 96 | // children node 97 | var childChildren = getChildren(json[key]); 98 | if (childChildren) child.children = childChildren; 99 | } 100 | children.push(child); 101 | delete json[key]; 102 | } 103 | return children; 104 | }; 105 | 106 | // Recursively count all elements in a tree 107 | var countElements = function(node) { 108 | var nbElements = 1; 109 | if (node.children) { 110 | nbElements += node.children.reduce(function(p, v) { return p + countElements(v); }, 0); 111 | } 112 | return nbElements; 113 | }; 114 | -------------------------------------------------------------------------------- /data/uptime.json: -------------------------------------------------------------------------------- 1 | {"name":"root","children":[{"name":"app","children":[{"name":"dashboard","children":[{"name":"public","children":[{"name":"stylesheets","children":[{"name":"bootstrap.css","size":4945,"language":"CSS"},{"name":"style.css","size":254,"language":"CSS"},{"name":"jquery.tagsinput.css","size":7,"language":"CSS"}],"size":5206},{"name":"javascripts","children":[{"name":"dateNavigation.js","size":155,"language":"Javascript"},{"name":"dateInterval.js","size":83,"language":"Javascript"},{"name":"bootstrap-affix.js","size":56,"language":"Javascript"},{"name":"bootstrap-button.js","size":52,"language":"Javascript"},{"name":"uptimeBar.js","size":47,"language":"Javascript"},{"name":"checkState.js","size":31,"language":"Javascript"},{"name":"flashcanvas","children":[{"name":"canvas2png.js","size":27,"language":"Javascript"},{"name":"flashcanvas.js","size":21,"language":"Javascript"}],"size":48},{"name":"statNavigation.js","size":26,"language":"Javascript"},{"name":"flotr2.min.js","size":3,"language":"Javascript"},{"name":"jquery.min.js","size":3,"language":"Javascript"},{"name":"jquery.tablesorter.min.js","size":1,"language":"Javascript"},{"name":"moment.min.js","size":1,"language":"Javascript"},{"name":"ejs.min.js","size":1,"language":"Javascript"},{"name":"jquery.tagsinput.min.js","size":1,"language":"Javascript"}],"size":508}],"size":5714},{"name":"app.js","size":126,"language":"Javascript"}],"size":5840},{"name":"api","children":[{"name":"routes","children":[{"name":"check.js","size":95,"language":"Javascript"},{"name":"ping.js","size":68,"language":"Javascript"},{"name":"tag.js","size":64,"language":"Javascript"}],"size":227},{"name":"app.js","size":59,"language":"Javascript"}],"size":286}],"size":6126},{"name":"lib","children":[{"name":"qosAggregator.js","size":476,"language":"Javascript"},{"name":"intervalBuilder.js","size":144,"language":"Javascript"},{"name":"monitor.js","size":109,"language":"Javascript"},{"name":"pollers","children":[{"name":"https.js","size":81,"language":"Javascript"},{"name":"http.js","size":80,"language":"Javascript"},{"name":"icmp.js","size":53,"language":"Javascript"},{"name":"udp.js","size":47,"language":"Javascript"},{"name":"base.js","size":33,"language":"Javascript"}],"size":294},{"name":"proxy.js","size":61,"language":"Javascript"},{"name":"analyzer.js","size":40,"language":"Javascript"},{"name":"timer.js","size":15,"language":"Javascript"}],"size":1139},{"name":"models","children":[{"name":"check.js","size":313,"language":"Javascript"},{"name":"tag.js","size":176,"language":"Javascript"},{"name":"migrations","children":[{"name":"upgrade2to3.js","size":137,"language":"Javascript"}],"size":137},{"name":"checkEvent.js","size":56,"language":"Javascript"},{"name":"ping.js","size":51,"language":"Javascript"},{"name":"checkYearlyStat.js","size":16,"language":"Javascript"},{"name":"tagYearlyStat.js","size":16,"language":"Javascript"},{"name":"checkMonthlyStat.js","size":16,"language":"Javascript"},{"name":"tagMonthlyStat.js","size":16,"language":"Javascript"},{"name":"tagDailyStat.js","size":15,"language":"Javascript"},{"name":"checkHourlyStat.js","size":15,"language":"Javascript"},{"name":"tagHourlyStat.js","size":15,"language":"Javascript"},{"name":"checkDailyStat.js","size":15,"language":"Javascript"}],"size":857},{"name":"test","children":[{"name":"lib","children":[{"name":"test_intervalBuilder.js","size":133,"language":"Javascript"}],"size":133}],"size":133},{"name":"fixtures","children":[{"name":"computeStats.js","size":117,"language":"Javascript"},{"name":"populate.js","size":70,"language":"Javascript"},{"name":"fixEvents.js","size":28,"language":"Javascript"},{"name":"dummyTargetUdp.js","size":19,"language":"Javascript"},{"name":"dummyTarget.js","size":13,"language":"Javascript"}],"size":247},{"name":"plugins","children":[{"name":"console","children":[{"name":"index.js","size":86,"language":"Javascript"}],"size":86},{"name":"email","children":[{"name":"index.js","size":36,"language":"Javascript"}],"size":36}],"size":122},{"name":"app.js","size":75,"language":"Javascript"},{"name":"config","children":[{"name":"default.yaml","size":36,"language":"YAML"},{"name":"test.yaml","size":4,"language":"YAML"}],"size":40},{"name":"bootstrap.js","size":32,"language":"Javascript"},{"name":"monitor.js","size":4,"language":"Javascript"},{"name":"makefile","size":3,"language":"make"}],"size":8778} -------------------------------------------------------------------------------- /javascripts/CodeFlower.js: -------------------------------------------------------------------------------- 1 | var CodeFlower = function(selector, w, h) { 2 | this.w = w; 3 | this.h = h; 4 | 5 | d3.select(selector).selectAll("svg").remove(); 6 | 7 | this.svg = d3.select(selector).append("svg:svg") 8 | .attr('width', w) 9 | .attr('height', h); 10 | 11 | this.svg.append("svg:rect") 12 | .style("stroke", "#999") 13 | .style("fill", "#fff") 14 | .attr('width', w) 15 | .attr('height', h); 16 | 17 | this.force = d3.layout.force() 18 | .on("tick", this.tick.bind(this)) 19 | .charge(function(d) { return d._children ? -d.size / 100 : -40; }) 20 | .linkDistance(function(d) { return d.target._children ? 80 : 25; }) 21 | .size([h, w]); 22 | }; 23 | 24 | CodeFlower.prototype.update = function(json) { 25 | if (json) this.json = json; 26 | 27 | this.json.fixed = true; 28 | this.json.x = this.w / 2; 29 | this.json.y = this.h / 2; 30 | 31 | var nodes = this.flatten(this.json); 32 | var links = d3.layout.tree().links(nodes); 33 | var total = nodes.length || 1; 34 | 35 | // remove existing text (will readd it afterwards to be sure it's on top) 36 | this.svg.selectAll("text").remove(); 37 | 38 | // Restart the force layout 39 | this.force 40 | .gravity(Math.atan(total / 50) / Math.PI * 0.4) 41 | .nodes(nodes) 42 | .links(links) 43 | .start(); 44 | 45 | // Update the links 46 | this.link = this.svg.selectAll("line.link") 47 | .data(links, function(d) { return d.target.name; }); 48 | 49 | // Enter any new links 50 | this.link.enter().insert("svg:line", ".node") 51 | .attr("class", "link") 52 | .attr("x1", function(d) { return d.source.x; }) 53 | .attr("y1", function(d) { return d.source.y; }) 54 | .attr("x2", function(d) { return d.target.x; }) 55 | .attr("y2", function(d) { return d.target.y; }); 56 | 57 | // Exit any old links. 58 | this.link.exit().remove(); 59 | 60 | // Update the nodes 61 | this.node = this.svg.selectAll("circle.node") 62 | .data(nodes, function(d) { return d.name; }) 63 | .classed("collapsed", function(d) { return d._children ? 1 : 0; }); 64 | 65 | this.node.transition() 66 | .attr("r", function(d) { return d.children ? 3.5 : Math.pow(d.size, 2/5) || 1; }); 67 | 68 | // Enter any new nodes 69 | this.node.enter().append('svg:circle') 70 | .attr("class", "node") 71 | .classed('directory', function(d) { return (d._children || d.children) ? 1 : 0; }) 72 | .attr("r", function(d) { return d.children ? 3.5 : Math.pow(d.size, 2/5) || 1; }) 73 | .style("fill", function color(d) { 74 | return "hsl(" + parseInt(360 / total * d.id, 10) + ",90%,70%)"; 75 | }) 76 | .call(this.force.drag) 77 | .on("click", this.click.bind(this)) 78 | .on("mouseover", this.mouseover.bind(this)) 79 | .on("mouseout", this.mouseout.bind(this)); 80 | 81 | // Exit any old nodes 82 | this.node.exit().remove(); 83 | 84 | this.text = this.svg.append('svg:text') 85 | .attr('class', 'nodetext') 86 | .attr('dy', 0) 87 | .attr('dx', 0) 88 | .attr('text-anchor', 'middle'); 89 | 90 | return this; 91 | }; 92 | 93 | CodeFlower.prototype.flatten = function(root) { 94 | var nodes = [], i = 0; 95 | 96 | function recurse(node) { 97 | if (node.children) { 98 | node.size = node.children.reduce(function(p, v) { 99 | return p + recurse(v); 100 | }, 0); 101 | } 102 | if (!node.id) node.id = ++i; 103 | nodes.push(node); 104 | return node.size; 105 | } 106 | 107 | root.size = recurse(root); 108 | return nodes; 109 | }; 110 | 111 | CodeFlower.prototype.click = function(d) { 112 | // Toggle children on click. 113 | if (d.children) { 114 | d._children = d.children; 115 | d.children = null; 116 | } else { 117 | d.children = d._children; 118 | d._children = null; 119 | } 120 | this.update(); 121 | }; 122 | 123 | CodeFlower.prototype.mouseover = function(d) { 124 | this.text.attr('transform', 'translate(' + d.x + ',' + (d.y - 5 - (d.children ? 3.5 : Math.sqrt(d.size) / 2)) + ')') 125 | .text(d.name + ": " + d.size + " loc") 126 | .style('display', null); 127 | }; 128 | 129 | CodeFlower.prototype.mouseout = function(d) { 130 | this.text.style('display', 'none'); 131 | }; 132 | 133 | CodeFlower.prototype.tick = function() { 134 | var h = this.h; 135 | var w = this.w; 136 | this.link.attr("x1", function(d) { return d.source.x; }) 137 | .attr("y1", function(d) { return d.source.y; }) 138 | .attr("x2", function(d) { return d.target.x; }) 139 | .attr("y2", function(d) { return d.target.y; }); 140 | 141 | this.node.attr("transform", function(d) { 142 | return "translate(" + Math.max(5, Math.min(w - 5, d.x)) + "," + Math.max(5, Math.min(h - 5, d.y)) + ")"; 143 | }); 144 | }; 145 | 146 | CodeFlower.prototype.cleanup = function() { 147 | this.update([]); 148 | this.force.stop(); 149 | }; -------------------------------------------------------------------------------- /data/jquery.json: -------------------------------------------------------------------------------- 1 | {"name":"root","children":[{"name":"speed","children":[{"name":"jquery-basis.js","size":4304,"language":"Javascript"},{"name":"filter.html","size":181,"language":"HTML"},{"name":"find.html","size":177,"language":"HTML"},{"name":"benchmarker.js","size":139,"language":"Javascript"},{"name":"css.html","size":68,"language":"HTML"},{"name":"index.html","size":62,"language":"HTML"},{"name":"benchmarker.css","size":52,"language":"CSS"},{"name":"event.html","size":46,"language":"HTML"},{"name":"slice.vs.concat.html","size":37,"language":"HTML"},{"name":"closest.html","size":36,"language":"HTML"},{"name":"benchmark.js","size":12,"language":"Javascript"}],"size":5114},{"name":"test","children":[{"name":"unit","children":[{"name":"event.js","size":1926,"language":"Javascript"},{"name":"ajax.js","size":1745,"language":"Javascript"},{"name":"effects.js","size":1617,"language":"Javascript"},{"name":"manipulation.js","size":1566,"language":"Javascript"},{"name":"core.js","size":1006,"language":"Javascript"},{"name":"attributes.js","size":971,"language":"Javascript"},{"name":"css.js","size":738,"language":"Javascript"},{"name":"traversing.js","size":545,"language":"Javascript"},{"name":"data.js","size":490,"language":"Javascript"},{"name":"offset.js","size":418,"language":"Javascript"},{"name":"deferred.js","size":346,"language":"Javascript"},{"name":"dimensions.js","size":325,"language":"Javascript"},{"name":"callbacks.js","size":271,"language":"Javascript"},{"name":"queue.js","size":247,"language":"Javascript"},{"name":"selector.js","size":127,"language":"Javascript"},{"name":"serialize.js","size":96,"language":"Javascript"},{"name":"support.js","size":31,"language":"Javascript"},{"name":"exports.js","size":5,"language":"Javascript"},{"name":"deprecated.js","size":1,"language":"Javascript"}],"size":12471},{"name":"index.html","size":288,"language":"HTML"},{"name":"data","children":[{"name":"testrunner.js","size":245,"language":"Javascript"},{"name":"testinit.js","size":202,"language":"Javascript"},{"name":"testsuite.css","size":112,"language":"CSS"},{"name":"selector","children":[{"name":"html5_selector.html","size":94,"language":"HTML"},{"name":"sizzle_cache.html","size":19,"language":"HTML"}],"size":113},{"name":"offset","children":[{"name":"table.html","size":43,"language":"HTML"},{"name":"absolute.html","size":41,"language":"HTML"},{"name":"scroll.html","size":39,"language":"HTML"},{"name":"fixed.html","size":34,"language":"HTML"},{"name":"relative.html","size":31,"language":"HTML"},{"name":"static.html","size":31,"language":"HTML"},{"name":"body.html","size":26,"language":"HTML"}],"size":245},{"name":"manipulation","children":[{"name":"iframe-denied.html","size":33,"language":"HTML"}],"size":33},{"name":"support","children":[{"name":"bodyBackground.html","size":27,"language":"HTML"},{"name":"shrinkWrapBlocks.html","size":23,"language":"HTML"},{"name":"csp.php","size":17,"language":"PHP"},{"name":"testElementCrash.html","size":17,"language":"HTML"},{"name":"csp.js","size":3,"language":"Javascript"}],"size":87},{"name":"with_fries.xml","size":25,"language":"XML"},{"name":"ajax","children":[{"name":"unreleasedXHR.html","size":24,"language":"HTML"}],"size":24},{"name":"name.php","size":23,"language":"PHP"},{"name":"core","children":[{"name":"cc_on.html","size":22,"language":"HTML"}],"size":22},{"name":"dimensions","children":[{"name":"documentSmall.html","size":21,"language":"HTML"},{"name":"documentLarge.html","size":17,"language":"HTML"}],"size":38},{"name":"readywaitloader.js","size":19,"language":"Javascript"},{"name":"event","children":[{"name":"onbeforeunload.html","size":19,"language":"HTML"},{"name":"syncReady.html","size":17,"language":"HTML"},{"name":"promiseReady.html","size":16,"language":"HTML"},{"name":"longLoadScript.php","size":4,"language":"PHP"}],"size":56},{"name":"etag.php","size":16,"language":"PHP"},{"name":"if_modified_since.php","size":15,"language":"PHP"},{"name":"jsonp.php","size":14,"language":"PHP"},{"name":"params_html.php","size":12,"language":"PHP"},{"name":"json.php","size":12,"language":"PHP"},{"name":"text.php","size":12,"language":"PHP"},{"name":"headers.php","size":12,"language":"PHP"},{"name":"script.php","size":11,"language":"PHP"},{"name":"dashboard.xml","size":11,"language":"XML"},{"name":"iframe.html","size":8,"language":"HTML"},{"name":"test.php","size":7,"language":"PHP"},{"name":"with_fries_over_jsonp.php","size":7,"language":"PHP"},{"name":"test.html","size":7,"language":"HTML"},{"name":"cleanScript.html","size":7,"language":"HTML"},{"name":"test2.html","size":5,"language":"HTML"},{"name":"errorWithJSON.php","size":4,"language":"PHP"},{"name":"atom+xml.php","size":4,"language":"PHP"},{"name":"statusText.php","size":3,"language":"PHP"},{"name":"errorWithText.php","size":3,"language":"PHP"},{"name":"test.js","size":3,"language":"Javascript"},{"name":"test3.html","size":3,"language":"HTML"},{"name":"nocontent.php","size":3,"language":"PHP"},{"name":"badjson.js","size":1,"language":"Javascript"},{"name":"badcall.js","size":1,"language":"Javascript"},{"name":"readywaitasset.js","size":1,"language":"Javascript"},{"name":"evalScript.php","size":1,"language":"PHP"},{"name":"echoQuery.php","size":1,"language":"PHP"},{"name":"json_obj.js","size":1,"language":"Javascript"},{"name":"jquery-1.8.2.ajax_xhr.min.js","size":1,"language":"Javascript"},{"name":"echoData.php","size":1,"language":"PHP"},{"name":"name.html","size":1,"language":"HTML"}],"size":1432},{"name":"delegatetest.html","size":214,"language":"HTML"},{"name":"hovertest.html","size":148,"language":"HTML"},{"name":"networkerror.html","size":76,"language":"HTML"},{"name":"localfile.html","size":74,"language":"HTML"},{"name":"readywait.html","size":61,"language":"HTML"},{"name":"xhtml.php","size":4,"language":"PHP"},{"name":"jquery.js","size":4,"language":"Javascript"}],"size":14772},{"name":"src","children":[{"name":"event.js","size":588,"language":"Javascript"},{"name":"effects.js","size":560,"language":"Javascript"},{"name":"ajax.js","size":525,"language":"Javascript"},{"name":"core.js","size":518,"language":"Javascript"},{"name":"manipulation.js","size":454,"language":"Javascript"},{"name":"css.js","size":389,"language":"Javascript"},{"name":"attributes.js","size":374,"language":"Javascript"},{"name":"traversing.js","size":226,"language":"Javascript"},{"name":"data.js","size":202,"language":"Javascript"},{"name":"callbacks.js","size":138,"language":"Javascript"},{"name":"offset.js","size":121,"language":"Javascript"},{"name":"queue.js","size":117,"language":"Javascript"},{"name":"deferred.js","size":103,"language":"Javascript"},{"name":"selector-native.js","size":100,"language":"Javascript"},{"name":"ajax","children":[{"name":"xhr.js","size":82,"language":"Javascript"},{"name":"script.js","size":51,"language":"Javascript"},{"name":"jsonp.js","size":50,"language":"Javascript"}],"size":183},{"name":"serialize.js","size":71,"language":"Javascript"},{"name":"support.js","size":60,"language":"Javascript"},{"name":"dimensions.js","size":25,"language":"Javascript"},{"name":"event-alias.js","size":12,"language":"Javascript"},{"name":"sizzle-jquery.js","size":8,"language":"Javascript"},{"name":"exports.js","size":8,"language":"Javascript"},{"name":"outro.js","size":1,"language":"Javascript"},{"name":"intro.js","size":1,"language":"Javascript"},{"name":"deprecated.js","size":1,"language":"Javascript"}],"size":4785},{"name":"Gruntfile.js","size":335,"language":"Javascript"},{"name":"build","children":[{"name":"release.js","size":193,"language":"Javascript"},{"name":"release-notes.js","size":46,"language":"Javascript"}],"size":239}],"size":25245} -------------------------------------------------------------------------------- /data/faker.json: -------------------------------------------------------------------------------- 1 | {"name":"root","children":[{"name":"src","children":[{"name":"Faker","children":[{"name":"Provider","children":[{"name":"sk_SK","children":[{"name":"Address.php","size":337,"language":"PHP"},{"name":"Person.php","size":129,"language":"PHP"},{"name":"Company.php","size":49,"language":"PHP"},{"name":"Internet.php","size":22,"language":"PHP"},{"name":"PhoneNumber.php","size":13,"language":"PHP"}],"size":550},{"name":"ua_UA","children":[{"name":"Address.php","size":319,"language":"PHP"},{"name":"Transliteration.php","size":47,"language":"PHP"},{"name":"Person.php","size":39,"language":"PHP"},{"name":"Company.php","size":35,"language":"PHP"},{"name":"Internet.php","size":22,"language":"PHP"},{"name":"PhoneNumber.php","size":22,"language":"PHP"}],"size":484},{"name":"da_DK","children":[{"name":"Address.php","size":179,"language":"PHP"},{"name":"Person.php","size":145,"language":"PHP"},{"name":"Company.php","size":34,"language":"PHP"},{"name":"Internet.php","size":33,"language":"PHP"},{"name":"PhoneNumber.php","size":13,"language":"PHP"}],"size":404},{"name":"de_DE","children":[{"name":"Person.php","size":172,"language":"PHP"},{"name":"Address.php","size":73,"language":"PHP"},{"name":"Internet.php","size":27,"language":"PHP"},{"name":"PhoneNumber.php","size":18,"language":"PHP"},{"name":"Company.php","size":12,"language":"PHP"}],"size":302},{"name":"de_AT","children":[{"name":"Person.php","size":170,"language":"PHP"},{"name":"Address.php","size":87,"language":"PHP"}],"size":257},{"name":"Lorem.php","size":138,"language":"PHP"},{"name":"ru_RU","children":[{"name":"Address.php","size":132,"language":"PHP"},{"name":"Person.php","size":74,"language":"PHP"},{"name":"Internet.php","size":19,"language":"PHP"},{"name":"PhoneNumber.php","size":12,"language":"PHP"}],"size":237},{"name":"fr_FR","children":[{"name":"Company.php","size":117,"language":"PHP"},{"name":"Address.php","size":93,"language":"PHP"},{"name":"PhoneNumber.php","size":39,"language":"PHP"},{"name":"Person.php","size":30,"language":"PHP"},{"name":"Internet.php","size":27,"language":"PHP"}],"size":306},{"name":"pt_BR","children":[{"name":"Address.php","size":110,"language":"PHP"},{"name":"Person.php","size":88,"language":"PHP"},{"name":"Company.php","size":51,"language":"PHP"},{"name":"PhoneNumber.php","size":29,"language":"PHP"}],"size":278},{"name":"bg_BG","children":[{"name":"Person.php","size":107,"language":"PHP"},{"name":"Internet.php","size":21,"language":"PHP"},{"name":"PhoneNumber.php","size":18,"language":"PHP"}],"size":146},{"name":"nl_NL","children":[{"name":"Person.php","size":87,"language":"PHP"},{"name":"Address.php","size":83,"language":"PHP"},{"name":"PhoneNumber.php","size":32,"language":"PHP"},{"name":"Company.php","size":12,"language":"PHP"},{"name":"Internet.php","size":8,"language":"PHP"}],"size":222},{"name":"UserAgent.php","size":86,"language":"PHP"},{"name":"DateTime.php","size":85,"language":"PHP"},{"name":"Internet.php","size":85,"language":"PHP"},{"name":"cs_CZ","children":[{"name":"Person.php","size":83,"language":"PHP"},{"name":"Internet.php","size":22,"language":"PHP"},{"name":"PhoneNumber.php","size":12,"language":"PHP"}],"size":117},{"name":"nl_BE","children":[{"name":"Address.php","size":82,"language":"PHP"},{"name":"Internet.php","size":27,"language":"PHP"},{"name":"PhoneNumber.php","size":18,"language":"PHP"},{"name":"Person.php","size":11,"language":"PHP"},{"name":"Company.php","size":10,"language":"PHP"}],"size":148},{"name":"it_IT","children":[{"name":"Address.php","size":80,"language":"PHP"},{"name":"Person.php","size":69,"language":"PHP"},{"name":"Company.php","size":50,"language":"PHP"},{"name":"PhoneNumber.php","size":19,"language":"PHP"},{"name":"Internet.php","size":8,"language":"PHP"}],"size":226},{"name":"es_ES","children":[{"name":"Address.php","size":79,"language":"PHP"},{"name":"Company.php","size":61,"language":"PHP"},{"name":"Person.php","size":31,"language":"PHP"},{"name":"PhoneNumber.php","size":27,"language":"PHP"}],"size":198},{"name":"en_US","children":[{"name":"Address.php","size":79,"language":"PHP"},{"name":"Person.php","size":79,"language":"PHP"},{"name":"Company.php","size":49,"language":"PHP"},{"name":"PhoneNumber.php","size":31,"language":"PHP"}],"size":238},{"name":"Base.php","size":78,"language":"PHP"},{"name":"es_AR","children":[{"name":"Address.php","size":77,"language":"PHP"},{"name":"Person.php","size":74,"language":"PHP"},{"name":"Company.php","size":51,"language":"PHP"},{"name":"PhoneNumber.php","size":40,"language":"PHP"}],"size":242},{"name":"en_GB","children":[{"name":"Address.php","size":73,"language":"PHP"},{"name":"PhoneNumber.php","size":17,"language":"PHP"},{"name":"Internet.php","size":8,"language":"PHP"}],"size":98},{"name":"fi_FI","children":[{"name":"Address.php","size":71,"language":"PHP"},{"name":"Person.php","size":66,"language":"PHP"},{"name":"Company.php","size":49,"language":"PHP"},{"name":"PhoneNumber.php","size":18,"language":"PHP"},{"name":"Internet.php","size":8,"language":"PHP"}],"size":212},{"name":"Address.php","size":70,"language":"PHP"},{"name":"pl_PL","children":[{"name":"Person.php","size":45,"language":"PHP"},{"name":"Internet.php","size":22,"language":"PHP"},{"name":"PhoneNumber.php","size":12,"language":"PHP"}],"size":79},{"name":"sr_Cyrl_RS","children":[{"name":"Address.php","size":40,"language":"PHP"},{"name":"Person.php","size":14,"language":"PHP"}],"size":54},{"name":"sr_Latn_RS","children":[{"name":"Address.php","size":40,"language":"PHP"},{"name":"Person.php","size":14,"language":"PHP"}],"size":54},{"name":"sr_RS","children":[{"name":"Address.php","size":40,"language":"PHP"},{"name":"Person.php","size":14,"language":"PHP"}],"size":54},{"name":"Miscellaneous.php","size":35,"language":"PHP"},{"name":"tr_TR","children":[{"name":"Person.php","size":32,"language":"PHP"},{"name":"PhoneNumber.php","size":9,"language":"PHP"},{"name":"Internet.php","size":6,"language":"PHP"}],"size":47},{"name":"Uuid.php","size":30,"language":"PHP"},{"name":"Person.php","size":23,"language":"PHP"},{"name":"Company.php","size":18,"language":"PHP"},{"name":"PhoneNumber.php","size":10,"language":"PHP"}],"size":5611},{"name":"ORM","children":[{"name":"Propel","children":[{"name":"EntityPopulator.php","size":136,"language":"PHP"},{"name":"ColumnTypeGuesser.php","size":63,"language":"PHP"},{"name":"Populator.php","size":58,"language":"PHP"}],"size":257},{"name":"Doctrine","children":[{"name":"EntityPopulator.php","size":132,"language":"PHP"},{"name":"Populator.php","size":52,"language":"PHP"},{"name":"ColumnTypeGuesser.php","size":42,"language":"PHP"}],"size":226},{"name":"Mandango","children":[{"name":"EntityPopulator.php","size":80,"language":"PHP"},{"name":"Populator.php","size":39,"language":"PHP"},{"name":"ColumnTypeGuesser.php","size":30,"language":"PHP"}],"size":149}],"size":632},{"name":"Guesser","children":[{"name":"Name.php","size":57,"language":"PHP"}],"size":57},{"name":"Generator.php","size":52,"language":"PHP"},{"name":"Documentor.php","size":49,"language":"PHP"},{"name":"Factory.php","size":37,"language":"PHP"}],"size":6438},{"name":"autoload.php","size":17,"language":"PHP"}],"size":6455},{"name":"test","children":[{"name":"Faker","children":[{"name":"GeneratorTest.php","size":106,"language":"PHP"},{"name":"Provider","children":[{"name":"BaseTest.php","size":101,"language":"PHP"},{"name":"LoremTest.php","size":81,"language":"PHP"},{"name":"fr_FR","children":[{"name":"CompanyTest.php","size":68,"language":"PHP"}],"size":68},{"name":"UserAgentTest.php","size":30,"language":"PHP"},{"name":"PersonTest.php","size":21,"language":"PHP"},{"name":"UuidTest.php","size":21,"language":"PHP"},{"name":"LocalizationTest.php","size":14,"language":"PHP"}],"size":336},{"name":"PHPUnit","children":[{"name":"Framework","children":[{"name":"Constraint","children":[{"name":"IsValidSirenSiret.php","size":24,"language":"PHP"},{"name":"IsValidSiren.php","size":11,"language":"PHP"},{"name":"IsValidSiret.php","size":11,"language":"PHP"}],"size":46}],"size":46}],"size":46}],"size":488},{"name":"test.php","size":37,"language":"PHP"},{"name":"documentor.php","size":11,"language":"PHP"}],"size":536},{"name":".travis.yml","size":3,"language":"YAML"}],"size":6994} -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CodeFlower Source code visualization 6 | 7 | 8 | 9 | 10 | 11 | 12 | 40 | 41 | 42 |
43 |
44 |

CodeFlower Source code visualization

45 |

This experiment visualizes source repositories using an interactive tree. Each disc represents a file, with a radius proportional to the number of lines of code (loc). All rendering is done client-side, in JavaScript. Try hovering on nodes to see the loc number, clicking on directory nodes to fold them, dragging nodes to rearrange the layout, and changing project to see different tree structures. Built with d3.js. Inspired by Code Swarm and Gource.

46 |
47 |
48 | 49 | 62 |
63 |
64 |
65 |

Purpose

66 | 71 |

CodeFlowers tries to answer these needs. Also, it tries to make code look beautiful, but that's another story.

72 |

Usage

73 |

To create a CodeFlower, include the CodeFlower.js file together with d3.js, just like in this page. Create a new CodeFlower instance using a CSS selector (of the div where the flower should be inserted), and the width and height of the desired visualization. Then, bind JSON data to the flower using CodeFlower.update(), and you're done.

74 |
 75 | var myFlower = new CodeFlower("#visualization", 300, 200);
 76 | myflower.update(jsonData);
 77 |         
78 |

Input data format

79 |

The jsonData format taken as input to update() is extremely simple. It's a JavaScript object representing a file tree structure. Each node must have a name (the file or directory name), leaf nodes must have a size (the number of lines of code or the file), and directory nodes must have a children property containing an array of nodes. As an example, here is the input for the currently displayed CodeFlower. You can modify it at will and click the update button to see the effect of your changes on the CodeFlower.

80 |
81 |
82 | 83 |
84 | 85 |
86 |
87 |
88 |

Generating JSON for a project

89 |

It's easy to generate loc metrics for any project, whatever the language. You can use wc, but this method requires cleaning the output and counts comments and blanks together with actual lines of code. Alternatively, you can use cloc (http://cloc.sourceforge.net/), which is open-source and makes the difference between real source code and comments. Here are three examples using GitHub as a source.

90 |
 91 | # Using curl and cloc (fast, accurate)
 92 | $ curl https://nodeload.github.com/symfony/symfony/tar.gz/master | tar xvz
 93 | $ cloc symfony-master --csv --by-file --report-file=symfony.cloc
 94 | 
 95 | # Using git clone and cloc (slow, accurate)
 96 | $ git clone git://github.com/symfony/symfony.git
 97 | $ cloc symfony --csv --by-file --report-file=symfony.cloc
 98 | 
 99 | # Using git clone and wc (slow, inaccurate)
100 | $ git clone git://github.com/symfony/symfony.git
101 | $ cd symfony
102 | $ git ls-files | xargs wc -l > symfony.wc
103 |         
104 |

Once you have a loc metrics file, paste its content below and click on the convert button. This will update the CodeFlower and the JSON textarea, to let you save data for your own CodeFlowers.

105 |
106 |
107 | 111 | 112 |
113 | 114 |
115 |
116 |
117 |

Sharing your CodeFlowers

118 |

The best way to share your CodeFlowers is to use GitHub Pages, just like this very page. So just fork the fzaninotto/CodeFlower repository, add your own JSON data under the data directory, update the options of the dropdown list in the index.html file accordingly, commit the code, and push to the gh-pages branch. GitHub will publish the result for you.

119 |

Licence

120 |

All this work is open-source, published by François Zaninotto under the MIT license. That means that nothing prevents you from growing as many CodeFlowers as you want!

121 | Fork me on GitHub 122 | 123 |
Tip: If you like the CodeFlower, you may also like another visualization I made with d3.js called DependencyWheel.
124 |
125 |
126 | 127 | 128 | 129 | 130 | 131 | 166 | 167 | 168 | -------------------------------------------------------------------------------- /data.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "root", 3 | "children": [{ 4 | "name": "app", 5 | "children": [{ 6 | "name": "dashboard", 7 | "children": [{ 8 | "name": "public", 9 | "children": [{ 10 | "name": "stylesheets", 11 | "children": [{ 12 | "name": "bootstrap.css", 13 | "size": 4945, 14 | "language": "CSS" 15 | }, { 16 | "name": "style.css", 17 | "size": 254, 18 | "language": "CSS" 19 | }, { 20 | "name": "jquery.tagsinput.css", 21 | "size": 7, 22 | "language": "CSS" 23 | }], 24 | "size": 5206 25 | }, { 26 | "name": "javascripts", 27 | "children": [{ 28 | "name": "dateNavigation.js", 29 | "size": 155, 30 | "language": "Javascript" 31 | }, { 32 | "name": "dateInterval.js", 33 | "size": 83, 34 | "language": "Javascript" 35 | }, { 36 | "name": "bootstrap-affix.js", 37 | "size": 56, 38 | "language": "Javascript" 39 | }, { 40 | "name": "bootstrap-button.js", 41 | "size": 52, 42 | "language": "Javascript" 43 | }, { 44 | "name": "uptimeBar.js", 45 | "size": 47, 46 | "language": "Javascript" 47 | }, { 48 | "name": "checkState.js", 49 | "size": 31, 50 | "language": "Javascript" 51 | }, { 52 | "name": "flashcanvas", 53 | "children": [{ 54 | "name": "canvas2png.js", 55 | "size": 27, 56 | "language": "Javascript" 57 | }, { 58 | "name": "flashcanvas.js", 59 | "size": 21, 60 | "language": "Javascript" 61 | }], 62 | "size": 48 63 | }, { 64 | "name": "statNavigation.js", 65 | "size": 26, 66 | "language": "Javascript" 67 | }, { 68 | "name": "flotr2.min.js", 69 | "size": 3, 70 | "language": "Javascript" 71 | }, { 72 | "name": "jquery.min.js", 73 | "size": 3, 74 | "language": "Javascript" 75 | }, { 76 | "name": "jquery.tablesorter.min.js", 77 | "size": 1, 78 | "language": "Javascript" 79 | }, { 80 | "name": "moment.min.js", 81 | "size": 1, 82 | "language": "Javascript" 83 | }, { 84 | "name": "ejs.min.js", 85 | "size": 1, 86 | "language": "Javascript" 87 | }, { 88 | "name": "jquery.tagsinput.min.js", 89 | "size": 1, 90 | "language": "Javascript" 91 | }], 92 | "size": 508 93 | }], 94 | "size": 5714 95 | }, { 96 | "name": "app.js", 97 | "size": 126, 98 | "language": "Javascript" 99 | }], 100 | "size": 5840 101 | }, { 102 | "name": "api", 103 | "children": [{ 104 | "name": "routes", 105 | "children": [{ 106 | "name": "check.js", 107 | "size": 95, 108 | "language": "Javascript" 109 | }, { 110 | "name": "ping.js", 111 | "size": 68, 112 | "language": "Javascript" 113 | }, { 114 | "name": "tag.js", 115 | "size": 64, 116 | "language": "Javascript" 117 | }], 118 | "size": 227 119 | }, { 120 | "name": "app.js", 121 | "size": 59, 122 | "language": "Javascript" 123 | }], 124 | "size": 286 125 | }], 126 | "size": 6126 127 | }, { 128 | "name": "lib", 129 | "children": [{ 130 | "name": "qosAggregator.js", 131 | "size": 476, 132 | "language": "Javascript" 133 | }, { 134 | "name": "intervalBuilder.js", 135 | "size": 144, 136 | "language": "Javascript" 137 | }, { 138 | "name": "monitor.js", 139 | "size": 109, 140 | "language": "Javascript" 141 | }, { 142 | "name": "pollers", 143 | "children": [{ 144 | "name": "https.js", 145 | "size": 81, 146 | "language": "Javascript" 147 | }, { 148 | "name": "http.js", 149 | "size": 80, 150 | "language": "Javascript" 151 | }, { 152 | "name": "icmp.js", 153 | "size": 53, 154 | "language": "Javascript" 155 | }, { 156 | "name": "udp.js", 157 | "size": 47, 158 | "language": "Javascript" 159 | }, { 160 | "name": "base.js", 161 | "size": 33, 162 | "language": "Javascript" 163 | }], 164 | "size": 294 165 | }, { 166 | "name": "proxy.js", 167 | "size": 61, 168 | "language": "Javascript" 169 | }, { 170 | "name": "analyzer.js", 171 | "size": 40, 172 | "language": "Javascript" 173 | }, { 174 | "name": "timer.js", 175 | "size": 15, 176 | "language": "Javascript" 177 | }], 178 | "size": 1139 179 | }, { 180 | "name": "models", 181 | "children": [{ 182 | "name": "check.js", 183 | "size": 313, 184 | "language": "Javascript" 185 | }, { 186 | "name": "tag.js", 187 | "size": 176, 188 | "language": "Javascript" 189 | }, { 190 | "name": "migrations", 191 | "children": [{ 192 | "name": "upgrade2to3.js", 193 | "size": 137, 194 | "language": "Javascript" 195 | }], 196 | "size": 137 197 | }, { 198 | "name": "checkEvent.js", 199 | "size": 56, 200 | "language": "Javascript" 201 | }, { 202 | "name": "ping.js", 203 | "size": 51, 204 | "language": "Javascript" 205 | }, { 206 | "name": "checkYearlyStat.js", 207 | "size": 16, 208 | "language": "Javascript" 209 | }, { 210 | "name": "tagYearlyStat.js", 211 | "size": 16, 212 | "language": "Javascript" 213 | }, { 214 | "name": "checkMonthlyStat.js", 215 | "size": 16, 216 | "language": "Javascript" 217 | }, { 218 | "name": "tagMonthlyStat.js", 219 | "size": 16, 220 | "language": "Javascript" 221 | }, { 222 | "name": "tagDailyStat.js", 223 | "size": 15, 224 | "language": "Javascript" 225 | }, { 226 | "name": "checkHourlyStat.js", 227 | "size": 15, 228 | "language": "Javascript" 229 | }, { 230 | "name": "tagHourlyStat.js", 231 | "size": 15, 232 | "language": "Javascript" 233 | }, { 234 | "name": "checkDailyStat.js", 235 | "size": 15, 236 | "language": "Javascript" 237 | }], 238 | "size": 857 239 | }, { 240 | "name": "test", 241 | "children": [{ 242 | "name": "lib", 243 | "children": [{ 244 | "name": "test_intervalBuilder.js", 245 | "size": 133, 246 | "language": "Javascript" 247 | }], 248 | "size": 133 249 | }], 250 | "size": 133 251 | }, { 252 | "name": "fixtures", 253 | "children": [{ 254 | "name": "computeStats.js", 255 | "size": 117, 256 | "language": "Javascript" 257 | }, { 258 | "name": "populate.js", 259 | "size": 70, 260 | "language": "Javascript" 261 | }, { 262 | "name": "fixEvents.js", 263 | "size": 28, 264 | "language": "Javascript" 265 | }, { 266 | "name": "dummyTargetUdp.js", 267 | "size": 19, 268 | "language": "Javascript" 269 | }, { 270 | "name": "dummyTarget.js", 271 | "size": 13, 272 | "language": "Javascript" 273 | }], 274 | "size": 247 275 | }, { 276 | "name": "plugins", 277 | "children": [{ 278 | "name": "console", 279 | "children": [{ 280 | "name": "index.js", 281 | "size": 86, 282 | "language": "Javascript" 283 | }], 284 | "size": 86 285 | }, { 286 | "name": "email", 287 | "children": [{ 288 | "name": "index.js", 289 | "size": 36, 290 | "language": "Javascript" 291 | }], 292 | "size": 36 293 | }], 294 | "size": 122 295 | }, { 296 | "name": "app.js", 297 | "size": 75, 298 | "language": "Javascript" 299 | }, { 300 | "name": "config", 301 | "children": [{ 302 | "name": "default.yaml", 303 | "size": 36, 304 | "language": "YAML" 305 | }, { 306 | "name": "test.yaml", 307 | "size": 4, 308 | "language": "YAML" 309 | }], 310 | "size": 40 311 | }, { 312 | "name": "bootstrap.js", 313 | "size": 32, 314 | "language": "Javascript" 315 | }, { 316 | "name": "monitor.js", 317 | "size": 4, 318 | "language": "Javascript" 319 | }, { 320 | "name": "makefile", 321 | "size": 3, 322 | "language": "make" 323 | }], 324 | "nbFiles": 81, 325 | "size": 8778 326 | } -------------------------------------------------------------------------------- /data/twig.json: -------------------------------------------------------------------------------- 1 | {"name":"root","children":[{"name":"ext","children":[{"name":"twig","children":[{"name":"twig.c","size":763,"language":"C"},{"name":"php_twig.h","size":11,"language":"C/C++ Header"},{"name":"config.m4","size":5,"language":"m4"}],"size":779}],"size":779},{"name":"lib","children":[{"name":"Twig","children":[{"name":"Extension","children":[{"name":"Core.php","size":705,"language":"PHP"},{"name":"Sandbox.php","size":73,"language":"PHP"},{"name":"Staging.php","size":62,"language":"PHP"},{"name":"Escaper.php","size":45,"language":"PHP"},{"name":"Debug.php","size":40,"language":"PHP"},{"name":"StringLoader.php","size":31,"language":"PHP"},{"name":"Optimizer.php","size":17,"language":"PHP"}],"size":973},{"name":"Environment.php","size":640,"language":"PHP"},{"name":"ExpressionParser.php","size":462,"language":"PHP"},{"name":"Lexer.php","size":310,"language":"PHP"},{"name":"Node","children":[{"name":"Module.php","size":287,"language":"PHP"},{"name":"Expression","children":[{"name":"Call.php","size":138,"language":"PHP"},{"name":"Name.php","size":66,"language":"PHP"},{"name":"Array.php","size":59,"language":"PHP"},{"name":"GetAttr.php","size":34,"language":"PHP"},{"name":"MethodCall.php","size":29,"language":"PHP"},{"name":"BlockReference.php","size":28,"language":"PHP"},{"name":"Test","children":[{"name":"Defined.php","size":27,"language":"PHP"},{"name":"Sameas.php","size":14,"language":"PHP"},{"name":"Divisibleby.php","size":14,"language":"PHP"},{"name":"Constant.php","size":14,"language":"PHP"},{"name":"Even.php","size":13,"language":"PHP"},{"name":"Odd.php","size":13,"language":"PHP"},{"name":"Null.php","size":12,"language":"PHP"}],"size":107},{"name":"Parent.php","size":25,"language":"PHP"},{"name":"Function.php","size":23,"language":"PHP"},{"name":"Filter.php","size":23,"language":"PHP"},{"name":"Binary.php","size":23,"language":"PHP"},{"name":"Conditional.php","size":20,"language":"PHP"},{"name":"Test.php","size":20,"language":"PHP"},{"name":"Filter","children":[{"name":"Default.php","size":20,"language":"PHP"}],"size":20},{"name":"Binary","children":[{"name":"Power.php","size":18,"language":"PHP"},{"name":"In.php","size":18,"language":"PHP"},{"name":"NotIn.php","size":18,"language":"PHP"},{"name":"Range.php","size":18,"language":"PHP"},{"name":"FloorDiv.php","size":14,"language":"PHP"},{"name":"Or.php","size":8,"language":"PHP"},{"name":"GreaterEqual.php","size":8,"language":"PHP"},{"name":"BitwiseXor.php","size":8,"language":"PHP"},{"name":"Mul.php","size":8,"language":"PHP"},{"name":"Greater.php","size":8,"language":"PHP"},{"name":"Sub.php","size":8,"language":"PHP"},{"name":"Add.php","size":8,"language":"PHP"},{"name":"Equal.php","size":8,"language":"PHP"},{"name":"And.php","size":8,"language":"PHP"},{"name":"BitwiseAnd.php","size":8,"language":"PHP"},{"name":"Div.php","size":8,"language":"PHP"},{"name":"Mod.php","size":8,"language":"PHP"},{"name":"Concat.php","size":8,"language":"PHP"},{"name":"BitwiseOr.php","size":8,"language":"PHP"},{"name":"LessEqual.php","size":8,"language":"PHP"},{"name":"NotEqual.php","size":8,"language":"PHP"},{"name":"Less.php","size":8,"language":"PHP"}],"size":222},{"name":"Unary.php","size":18,"language":"PHP"},{"name":"TempName.php","size":16,"language":"PHP"},{"name":"Constant.php","size":12,"language":"PHP"},{"name":"ExtensionReference.php","size":12,"language":"PHP"},{"name":"AssignName.php","size":12,"language":"PHP"},{"name":"Unary","children":[{"name":"Not.php","size":8,"language":"PHP"},{"name":"Pos.php","size":8,"language":"PHP"},{"name":"Neg.php","size":8,"language":"PHP"}],"size":24}],"size":931},{"name":"For.php","size":75,"language":"PHP"},{"name":"Include.php","size":69,"language":"PHP"},{"name":"Macro.php","size":68,"language":"PHP"},{"name":"Set.php","size":65,"language":"PHP"},{"name":"If.php","size":41,"language":"PHP"},{"name":"SandboxedModule.php","size":37,"language":"PHP"},{"name":"ForLoop.php","size":32,"language":"PHP"},{"name":"Import.php","size":27,"language":"PHP"},{"name":"Sandbox.php","size":26,"language":"PHP"},{"name":"SandboxedPrint.php","size":24,"language":"PHP"},{"name":"SetTemp.php","size":24,"language":"PHP"},{"name":"Block.php","size":21,"language":"PHP"},{"name":"Embed.php","size":20,"language":"PHP"},{"name":"Print.php","size":17,"language":"PHP"},{"name":"Do.php","size":17,"language":"PHP"},{"name":"Spaceless.php","size":17,"language":"PHP"},{"name":"Text.php","size":17,"language":"PHP"},{"name":"Flush.php","size":15,"language":"PHP"},{"name":"BlockReference.php","size":15,"language":"PHP"},{"name":"AutoEscape.php","size":12,"language":"PHP"},{"name":"Body.php","size":4,"language":"PHP"},{"name":"Expression.php","size":4,"language":"PHP"}],"size":1865},{"name":"Parser.php","size":278,"language":"PHP"},{"name":"Template.php","size":226,"language":"PHP"},{"name":"NodeVisitor","children":[{"name":"Optimizer.php","size":145,"language":"PHP"},{"name":"SafeAnalysis.php","size":109,"language":"PHP"},{"name":"Escaper.php","size":107,"language":"PHP"},{"name":"Sandbox.php","size":44,"language":"PHP"}],"size":405},{"name":"Compiler.php","size":137,"language":"PHP"},{"name":"Token.php","size":134,"language":"PHP"},{"name":"Node.php","size":120,"language":"PHP"},{"name":"Loader","children":[{"name":"Filesystem.php","size":118,"language":"PHP"},{"name":"Chain.php","size":81,"language":"PHP"},{"name":"Array.php","size":44,"language":"PHP"},{"name":"String.php","size":20,"language":"PHP"}],"size":263},{"name":"Error.php","size":118,"language":"PHP"},{"name":"Test","children":[{"name":"IntegrationTestCase.php","size":110,"language":"PHP"},{"name":"NodeTestCase.php","size":37,"language":"PHP"},{"name":"Method.php","size":17,"language":"PHP"},{"name":"Node.php","size":17,"language":"PHP"},{"name":"Function.php","size":15,"language":"PHP"}],"size":196},{"name":"Sandbox","children":[{"name":"SecurityPolicy.php","size":88,"language":"PHP"},{"name":"SecurityPolicyInterface.php","size":7,"language":"PHP"},{"name":"SecurityError.php","size":4,"language":"PHP"}],"size":99},{"name":"TokenParser","children":[{"name":"For.php","size":83,"language":"PHP"},{"name":"If.php","size":49,"language":"PHP"},{"name":"Block.php","size":43,"language":"PHP"},{"name":"AutoEscape.php","size":40,"language":"PHP"},{"name":"Include.php","size":36,"language":"PHP"},{"name":"Set.php","size":36,"language":"PHP"},{"name":"Use.php","size":36,"language":"PHP"},{"name":"From.php","size":34,"language":"PHP"},{"name":"Macro.php","size":32,"language":"PHP"},{"name":"Embed.php","size":29,"language":"PHP"},{"name":"Sandbox.php","size":29,"language":"PHP"},{"name":"Filter.php","size":24,"language":"PHP"},{"name":"Spaceless.php","size":20,"language":"PHP"},{"name":"Extends.php","size":20,"language":"PHP"},{"name":"Import.php","size":17,"language":"PHP"},{"name":"Do.php","size":14,"language":"PHP"},{"name":"Flush.php","size":13,"language":"PHP"}],"size":555},{"name":"TokenParserBroker.php","size":76,"language":"PHP"},{"name":"SimpleFilter.php","size":68,"language":"PHP"},{"name":"TokenStream.php","size":67,"language":"PHP"},{"name":"SimpleFunction.php","size":58,"language":"PHP"},{"name":"Filter.php","size":54,"language":"PHP"},{"name":"NodeTraverser.php","size":46,"language":"PHP"},{"name":"Function.php","size":44,"language":"PHP"},{"name":"Extension.php","size":35,"language":"PHP"},{"name":"SimpleTest.php","size":27,"language":"PHP"},{"name":"Markup.php","size":19,"language":"PHP"},{"name":"Autoloader.php","size":18,"language":"PHP"},{"name":"Filter","children":[{"name":"Node.php","size":17,"language":"PHP"},{"name":"Method.php","size":17,"language":"PHP"},{"name":"Function.php","size":15,"language":"PHP"}],"size":49},{"name":"Function","children":[{"name":"Node.php","size":17,"language":"PHP"},{"name":"Method.php","size":17,"language":"PHP"},{"name":"Function.php","size":15,"language":"PHP"}],"size":49},{"name":"Test.php","size":16,"language":"PHP"},{"name":"ExtensionInterface.php","size":13,"language":"PHP"},{"name":"FilterInterface.php","size":12,"language":"PHP"},{"name":"TemplateInterface.php","size":10,"language":"PHP"},{"name":"FunctionInterface.php","size":10,"language":"PHP"},{"name":"TokenParser.php","size":9,"language":"PHP"},{"name":"Error","children":[{"name":"Loader.php","size":8,"language":"PHP"},{"name":"Syntax.php","size":4,"language":"PHP"},{"name":"Runtime.php","size":4,"language":"PHP"}],"size":16},{"name":"TokenParserInterface.php","size":7,"language":"PHP"},{"name":"TokenParserBrokerInterface.php","size":7,"language":"PHP"},{"name":"NodeVisitorInterface.php","size":7,"language":"PHP"},{"name":"NodeInterface.php","size":7,"language":"PHP"},{"name":"LoaderInterface.php","size":7,"language":"PHP"},{"name":"CompilerInterface.php","size":6,"language":"PHP"},{"name":"TestInterface.php","size":5,"language":"PHP"},{"name":"LexerInterface.php","size":5,"language":"PHP"},{"name":"FunctionCallableInterface.php","size":5,"language":"PHP"},{"name":"TestCallableInterface.php","size":5,"language":"PHP"},{"name":"FilterCallableInterface.php","size":5,"language":"PHP"},{"name":"ParserInterface.php","size":5,"language":"PHP"},{"name":"ExistsLoaderInterface.php","size":5,"language":"PHP"},{"name":"NodeOutputInterface.php","size":4,"language":"PHP"}],"size":7557}],"size":7557},{"name":"test","children":[{"name":"Twig","children":[{"name":"Tests","children":[{"name":"TemplateTest.php","size":425,"language":"PHP"},{"name":"escapingTest.php","size":251,"language":"PHP"},{"name":"ExpressionParserTest.php","size":225,"language":"PHP"},{"name":"LexerTest.php","size":212,"language":"PHP"},{"name":"EnvironmentTest.php","size":186,"language":"PHP"},{"name":"Node","children":[{"name":"ForTest.php","size":169,"language":"PHP"},{"name":"ModuleTest.php","size":136,"language":"PHP"},{"name":"SandboxedModuleTest.php","size":124,"language":"PHP"},{"name":"Expression","children":[{"name":"FilterTest.php","size":86,"language":"PHP"},{"name":"FunctionTest.php","size":62,"language":"PHP"},{"name":"TestTest.php","size":41,"language":"PHP"},{"name":"GetAttrTest.php","size":38,"language":"PHP"},{"name":"ConditionalTest.php","size":28,"language":"PHP"},{"name":"NameTest.php","size":27,"language":"PHP"},{"name":"ArrayTest.php","size":27,"language":"PHP"},{"name":"Binary","children":[{"name":"MulTest.php","size":25,"language":"PHP"},{"name":"DivTest.php","size":25,"language":"PHP"},{"name":"ConcatTest.php","size":25,"language":"PHP"},{"name":"FloorDivTest.php","size":25,"language":"PHP"},{"name":"SubTest.php","size":25,"language":"PHP"},{"name":"ModTest.php","size":25,"language":"PHP"},{"name":"AddTest.php","size":25,"language":"PHP"},{"name":"AndTest.php","size":25,"language":"PHP"},{"name":"OrTest.php","size":25,"language":"PHP"}],"size":225},{"name":"Unary","children":[{"name":"NegTest.php","size":22,"language":"PHP"},{"name":"PosTest.php","size":22,"language":"PHP"},{"name":"NotTest.php","size":22,"language":"PHP"}],"size":66},{"name":"ConstantTest.php","size":20,"language":"PHP"},{"name":"AssignNameTest.php","size":20,"language":"PHP"},{"name":"ParentTest.php","size":19,"language":"PHP"},{"name":"PHP53","children":[{"name":"FunctionInclude.php","size":4,"language":"PHP"},{"name":"FilterInclude.php","size":4,"language":"PHP"},{"name":"TestInclude.php","size":4,"language":"PHP"}],"size":12}],"size":671},{"name":"IfTest.php","size":69,"language":"PHP"},{"name":"IncludeTest.php","size":63,"language":"PHP"},{"name":"SetTest.php","size":52,"language":"PHP"},{"name":"MacroTest.php","size":47,"language":"PHP"},{"name":"SandboxTest.php","size":32,"language":"PHP"},{"name":"BlockTest.php","size":29,"language":"PHP"},{"name":"ImportTest.php","size":28,"language":"PHP"},{"name":"SpacelessTest.php","size":27,"language":"PHP"},{"name":"AutoEscapeTest.php","size":23,"language":"PHP"},{"name":"DoTest.php","size":22,"language":"PHP"},{"name":"SandboxedPrintTest.php","size":22,"language":"PHP"},{"name":"BlockReferenceTest.php","size":22,"language":"PHP"},{"name":"PrintTest.php","size":20,"language":"PHP"},{"name":"TextTest.php","size":19,"language":"PHP"}],"size":1575},{"name":"IntegrationTest.php","size":163,"language":"PHP"},{"name":"Extension","children":[{"name":"SandboxTest.php","size":161,"language":"PHP"},{"name":"CoreTest.php","size":86,"language":"PHP"}],"size":247},{"name":"ParserTest.php","size":126,"language":"PHP"},{"name":"ErrorTest.php","size":124,"language":"PHP"},{"name":"NodeVisitor","children":[{"name":"OptimizerTest.php","size":73,"language":"PHP"}],"size":73},{"name":"Loader","children":[{"name":"FilesystemTest.php","size":69,"language":"PHP"},{"name":"ArrayTest.php","size":61,"language":"PHP"},{"name":"ChainTest.php","size":38,"language":"PHP"},{"name":"Fixtures","children":[{"name":"named","children":[{"name":"index.html","size":1,"language":"HTML"}],"size":1},{"name":"normal","children":[{"name":"index.html","size":1,"language":"HTML"}],"size":1},{"name":"normal_bis","children":[{"name":"index.html","size":1,"language":"HTML"}],"size":1},{"name":"named_final","children":[{"name":"index.html","size":1,"language":"HTML"}],"size":1},{"name":"normal_ter","children":[{"name":"index.html","size":1,"language":"HTML"}],"size":1},{"name":"named_bis","children":[{"name":"index.html","size":1,"language":"HTML"}],"size":1},{"name":"named_ter","children":[{"name":"index.html","size":1,"language":"HTML"}],"size":1},{"name":"normal_final","children":[{"name":"index.html","size":1,"language":"HTML"}],"size":1}],"size":8}],"size":176},{"name":"FileCachingTest.php","size":58,"language":"PHP"},{"name":"TokenStreamTest.php","size":47,"language":"PHP"},{"name":"Fixtures","children":[{"name":"filters","children":[{"name":"batch_float.php","size":31,"language":"PHP"}],"size":31},{"name":"errors","children":[{"name":"index.html","size":7,"language":"HTML"},{"name":"base.html","size":1,"language":"HTML"}],"size":8}],"size":39},{"name":"CompilerTest.php","size":19,"language":"PHP"},{"name":"NativeExtensionTest.php","size":16,"language":"PHP"},{"name":"AutoloaderTest.php","size":10,"language":"PHP"}],"size":3972}],"size":3972},{"name":"bootstrap.php","size":3,"language":"PHP"}],"size":3975},{"name":".travis.yml","size":11,"language":"YAML"}],"size":12322} -------------------------------------------------------------------------------- /javascripts/d3/detector.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Chrome AppSniffer 3 | * 4 | * Detect apps run on current page and send back to background page. 5 | * Some part of this script was refered from Wappalyzer Firefox Addon. 6 | * 7 | * @author Bao Nguyen 8 | * @license GPLv3 9 | **/ 10 | 11 | (function () { 12 | var _apps = {}; 13 | var doc = document.documentElement; 14 | var a 15 | 16 | // 1: detect by meta tags, the first matching group will be version 17 | var metas = doc.getElementsByTagName("meta"); 18 | var meta_tests = { 19 | 'generator': { 20 | 'Joomla': /joomla!?\s*([\d\.]+)?/i, 21 | 'vBulletin': /vBulletin\s*(.*)/i, 22 | 'WordPress': /WordPress\s*(.*)/i, 23 | 'XOOPS': /xoops/i, 24 | 'Plone': /plone/i, 25 | 'MediaWiki': /MediaWiki/i, 26 | 'CMSMadeSimple': /CMS Made Simple/i, 27 | 'SilverStripe': /SilverStripe/i, 28 | 'Movable Type': /Movable Type/i, 29 | 'Amiro.CMS': /Amiro/i, 30 | 'Koobi': /koobi/i, 31 | 'bbPress': /bbPress/i, 32 | 'DokuWiki': /dokuWiki/i, 33 | 'TYPO3': /TYPO3/i, 34 | 'PHP-Nuke': /PHP-Nuke/i, 35 | 'DotNetNuke': /DotNetNuke/i, 36 | 'Sitefinity': /Sitefinity\s+(.*)/i, 37 | 'WebGUI': /WebGUI/i, 38 | 'ez Publish': /eZ\s*Publish/i, 39 | 'BIGACE': /BIGACE/i, 40 | 'TypePad': /typepad\.com/i, 41 | 'Blogger': /blogger/i, 42 | 'PrestaShop': /PrestaShop/i, 43 | 'SharePoint': /SharePoint/, 44 | 'JaliosJCMS': /Jalios JCMS/i, 45 | 'ZenCart': /zen-cart/i, 46 | 'WPML': /WPML/i, 47 | 'PivotX': /PivotX/i, 48 | 'OpenACS': /OpenACS/i, 49 | 'AlphaCMS': /alphacms\s+(.*)/i, 50 | 'concrete5': /concrete5 -\s*(.*)$/, 51 | 'Webnode': /Webnode/, 52 | 'GetSimple': /GetSimple/, 53 | 'DataLifeEngine': /DataLife Engine/, 54 | 'ClanSphere': /ClanSphere/, 55 | }, 56 | 'copyright': { 57 | 'phpBB': /phpBB/i 58 | }, 59 | 'elggrelease': { 60 | 'Elgg': /.+/ 61 | }, 62 | 'powered-by': { 63 | 'Serendipity': /Serendipity/i, 64 | }, 65 | 'author': { 66 | 'Avactis': /Avactis Team/i 67 | } 68 | }; 69 | 70 | for (var idx in metas) 71 | { 72 | var m = metas[idx]; 73 | var name = m.name ? m.name.toLowerCase() : ""; 74 | 75 | if (!meta_tests[name]) continue; 76 | 77 | for (var t in meta_tests[name]) 78 | { 79 | if (t in _apps) continue; 80 | 81 | var r = meta_tests[name][t].exec(m.content); 82 | if (r) 83 | { 84 | _apps[t] = r[1] ? r[1] : -1; 85 | } 86 | } 87 | } 88 | 89 | // 2: detect by script tags 90 | var scripts = doc.getElementsByTagName("script"); 91 | 92 | var script_tests = { 93 | 'Google Analytics': /google-analytics.com\/(ga|urchin).js/i, 94 | 'Quantcast': /quantserve\.com\/quant\.js/i, 95 | 'Prototype': /prototype\.js/i, 96 | 'Joomla': /\/components\/com_/, 97 | 'Ubercart': /uc_cart/i, 98 | 'Closure': /\/goog\/base\.js/i, 99 | 'MODx': /\/min\/b=.*f=.*/, 100 | 'MooTools': /mootools/i, 101 | 'Dojo': /dojo(\.xd)?\.js/i, 102 | 'script.aculo.us': /scriptaculous\.js/i, 103 | 'Disqus': /disqus.com\/forums/i, 104 | 'GetSatisfaction': /getsatisfaction\.com\/feedback/i, 105 | 'Wibiya': /wibiya\.com\/Loaders\//i, 106 | 'reCaptcha': /(google\.com\/recaptcha|api\.recaptcha\.net\/)/i, 107 | 'Mollom': /mollom\/mollom\.js/i, // only work on Drupal now 108 | 'ZenPhoto': /zp-core\/js/i, 109 | 'Gallery2': /main\.php\?.*g2_.*/i, 110 | 'AdSense': /pagead\/show_ads\.js/, 111 | 'XenForo': /js\/xenforo\//i, 112 | 'Cappuccino': /Frameworks\/Objective-J\/Objective-J\.js/, 113 | 'Avactis': /\/avactis-themes\//i, 114 | 'Volusion': /a\/j\/javascripts\.js/, 115 | 'AddThis': /addthis\.com\/js/, 116 | 'BuySellAds': /buysellads.com\/.*bsa\.js/, 117 | 'Weebly': /weebly\.com\/weebly\//, 118 | 'Bootstrap': /bootstrap-.*\.js/, 119 | 'Jigsy': /javascripts\/asterion\.js/, // may change later 120 | 'Yola': /analytics\.yola\.net/, // may change later 121 | 'Alfresco': /(alfresco)+(-min)?(\/scripts\/menu)?\.js/ // both Alfresco Share and Explorer apps 122 | }; 123 | 124 | for (var idx in scripts) 125 | { 126 | var s = scripts[idx]; 127 | if (!s.src) continue; 128 | s = s.src; 129 | 130 | for (var t in script_tests) 131 | { 132 | if (t in _apps) continue; 133 | if (script_tests[t].test(s)) 134 | { 135 | _apps[t] = -1; 136 | } 137 | } 138 | } 139 | 140 | // 3: detect by domains 141 | 142 | // 4: detect by regexp 143 | var text = document.documentElement.outerHTML; 144 | var text_tests = { 145 | 'SMF': /