├── .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 | 
9 | 
10 | 
11 | 
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 |
64 |
65 |
Purpose
66 |
67 | Did you ever dive into an existing project and wish you could have a bird's eye view of the whole code?
68 | Did you ever have to refactor a large application and wish you knew where to start?
69 | Did you ever look for a visualization that would help you communicate visually with your teammates about a repository?
70 |
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 |
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 |
108 | Origin: cloc
109 | Origin: wc
110 |
111 |
112 |
113 | Convert
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 |
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': /