Repository: fzaninotto/DependencyWheel
Branch: master
Commit: c7a1f4a1672d
Files: 7
Total size: 21.6 KB
Directory structure:
gitextract_bh_4ohqv/
├── LICENSE
├── README.md
├── data/
│ └── composer.json
├── index.html
├── js/
│ ├── composerBuilder.js
│ └── d3.dependencyWheel.js
└── package.json
================================================
FILE CONTENTS
================================================
================================================
FILE: LICENSE
================================================
Copyright (c) 2013 Francois Zaninotto
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
================================================
FILE: README.md
================================================
Dependency Wheel
================
This experiment visualizes package dependencies using an interactive disc. Each disc section represents a dependency, and links between arcs materialize these dependencies. All rendering is done client-side, in JavaScript. Built with <a href="https://github.com/mbostock/d3">d3.js</a>, published with the MIT open-source license.
Interact with DependencyWheels, see examples, and build your own at [http://fzaninotto.github.com/DependencyWheel](http://fzaninotto.github.com/DependencyWheel).

================================================
FILE: data/composer.json
================================================
{
"name": "sylius/sylius",
"type": "project",
"description": "Modern ecommerce for Symfony2",
"license": "MIT",
"homepage": "http://sylius.org",
"authors": [
{
"name": "Paweł Jędrzejewski",
"homepage": "http://pjedrzejewski.com"
},
{
"name": "Sylius project",
"homepage": "http://sylius.org"
},
{
"name": "Community contributions",
"homepage": "http://github.com/Sylius/Sylius/contributors"
}
],
"require": {
"php": ">=5.3.3",
"athari/yalinqo": "*@dev",
"doctrine/doctrine-bundle": "1.2.*@dev",
"doctrine/doctrine-fixtures-bundle": "2.2.*",
"doctrine/orm": "~2.3",
"friendsofsymfony/rest-bundle": "0.13.*",
"friendsofsymfony/user-bundle": "2.0.*@dev",
"fzaninotto/faker": "1.2.*",
"incenteev/composer-parameter-handler": "~2.0",
"jms/serializer-bundle": "0.12.*",
"jms/translation-bundle": "1.1.*",
"knplabs/knp-menu-bundle": "*@dev",
"knplabs/knp-gaufrette-bundle": "*@dev",
"knplabs/knp-snappy-bundle": "*@dev",
"liip/doctrine-cache-bundle": "*",
"liip/imagine-bundle": "0.9.*",
"mathiasverraes/money": "*@dev",
"omnipay/omnipay": "*@dev",
"sensio/distribution-bundle": "2.3.*",
"stof/doctrine-extensions-bundle": "1.1.*",
"symfony/assetic-bundle": "2.3.*",
"symfony/intl": "~2.3",
"symfony/monolog-bundle": "2.3.*",
"symfony/swiftmailer-bundle": "2.3.*",
"symfony/symfony": "~2.3",
"twig/extensions": "1.0.*",
"white-october/pagerfanta-bundle": "1.0.*@dev"
},
"require-dev": {
"behat/behat": "2.4.*@stable",
"behat/symfony2-extension": "*",
"behat/mink-extension": "*",
"behat/mink-browserkit-driver": "*",
"phpspec/phpspec": "2.0.*@dev",
"behat/mink-selenium2-driver": "*"
},
"scripts": {
"post-install-cmd": [
"Incenteev\\ParameterHandler\\ScriptHandler::buildParameters",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile"
],
"post-update-cmd": [
"Incenteev\\ParameterHandler\\ScriptHandler::buildParameters",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::buildBootstrap",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::clearCache",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installAssets",
"Sensio\\Bundle\\DistributionBundle\\Composer\\ScriptHandler::installRequirementsFile"
]
},
"autoload": {
"psr-0": { "Sylius\\": "src/" }
},
"config": {
"bin-dir": "bin"
},
"extra": {
"symfony-app-dir": "app",
"symfony-web-dir": "web",
"incenteev-parameters": {
"file": "app/config/parameters.yml"
}
}
}
================================================
FILE: index.html
================================================
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en-us" prefix="og: http://ogp.me/ns#">
<!-- Use the Source, Luke -->
<head>
<title>DependencyWheel: An Interactive Visualization Of Package Dependencies</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta charset="utf-8">
<link rel="stylesheet" href="css/bootstrap.min.css">
<link href='http://fonts.googleapis.com/css?family=Rosario:400,700' rel='stylesheet' type='text/css'>
<style>
h1, p, li {
font-family: 'Rosario', sans-serif;
}
h1 {
font-size: 4em;
font-weight: 300;
letter-spacing: -2px;
line-height: 1em;
margin: 1em 0;
}
#chart_placeholder {
text-align: center;
margin-bottom: 20px;
}
.dependencyWheel {
font: 10px sans-serif;
}
form .btn-primary {
margin-top: 25px;
}
</style>
</head>
<body>
<div class="container">
<h1>DependencyWheel: An Interactive Visualization Of Package Dependencies</h1>
<p class="lead">Modern development use package managers (composer, npm, bundler, etc.). Applications depend on a large number of packages, which depend themselves on other packages. The Dependency Wheel visualization attempts to reveal the entire dependency tree of any PHP library using Composer for dependency management. Each chord in the disc represents a dependency. Try hovering on packages to mask other dependencies. All rendering is done client-side, in JavaScript. Built with <a href="https://github.com/mbostock/d3">d3.js</a></p>
<div id="chart_placeholder"></div>
<p>Do you want to try it out with another project? Paste the <code>composer.json</code> and <code>composer.lock</code> of any PHP project below to see its Dependency Wheel:</p>
<form role="form" id="composerRedraw" class="clearfix">
<div class="form-group col-lg-4">
<label for="composerJson">composer.json</label>
<textarea required type="text" class="form-control" id="composerJson"></textarea>
</div>
<div class="form-group col-lg-4">
<label for="composerLock">composer.lock</label>
<textarea required type="text" class="form-control" id="composerLock"></textarea>
</div>
<div class="form-group col-lg-4">
<button type="submit" class="btn btn-lg btn-primary">Refresh</button>
</div>
</form>
<h2>Purpose</h2>
<ul class="list-unstyled">
<li>Did you ever dive into an existing project and wonder how much code is hidden behind a given dependency?</li>
<li>Did you ever wonder if a package present in the <code>vendor/</code> directory is actually useful?</li>
<li>Did you ever look for a visualization that would help you understand the mess that's in a <code>composer.json</code>?</li>
</ul>
<p>DependencyWheel tries to answer these needs. Also, it tries to make dependencies look beautiful, but that's another story.</p>
<h2>Usage</h2>
<p>To create a DependencyWheel, include the <code>d3.dependencyWheel.js</code> file together with <code>d3.js</code>, just like in this page. Create a new instance of the dependency wheel chart constructor, then make a d3 selection using a CSS selector (of the div where the wheel should be inserted), attach dependency data, and call the chart on the selection.</p>
<pre>
var chart = d3.chart.dependencyWheel();
d3.select('#chart_placeholder')
.datum(data)
.call(chart);
</pre>
<p>The data must be a matrix of dependencies. The first item must be the main package. For instance, if the main package depends on packages A and B, and package A also depends on package B, you should build the data as follows:</p>
<pre>
var data = {
packageNames: ['Main', 'A', 'B'],
matrix: [[0, 1, 1], // Main depends on A and B
[0, 0, 1], // A depends on B
[0, 0, 0]] // B doesn't depend on A or Main
};
</pre>
<p>For more information about the matrix format, check the <a href="https://github.com/mbostock/d3/wiki/Chord-Layout">d3 Chord Layout</a> documentation.</p>
<p>DependencyWheel comes with a utility to transform data from <code>composer.json</code> and <code>composer.lock</code> files into a matrix and a list of package names. You first need to include the <code>composerBuilder.js</code> script provided in this repository, and then call:</p>
<pre>
var data = buildMatrixFromComposerJsonAndLock(composerjson, composerlock);
d3.select('#chart_placeholder')
.datum(data)
.call(chart);
</pre>
<p>DependencyWheel follows the <a href="http://bost.ocks.org/mike/chart/">d3.js reusable charts</a> pattern to let you customize the chart at will:</p>
<pre>
var chart = d3.chart.dependencyWheel()
.width(700) // also used for height, since the wheel is in a a square
.margin(150) // used to display package names
.padding(.02); // separating groups in the wheel
</pre>
<h2>Sharing your DependencyWheels</h2>
<p>The best way to share your DependencyWheels is to use <a href="http://pages.github.com/">GitHub Pages</a>, just like this very page. So just fork the <a href="https://github.com/fzaninotto/DependencyWheel">fzaninotto/DependencyWheel</a> repository, add your own JSON data under the <code>data/</code> directory, commit the code, and push to the <code>gh-pages</code> branch. GitHub will publish the result for you.</p>
<h2>Licence</h2>
<p>All this work is open-source, published by <a href="https://twitter.com/francoisz">François Zaninotto</a> under the MIT license. Sponsored by <a href="http://marmelab.com">marmelab</a>.</p>
<div class="col-md-6 col-md-offset-3">
<br/>
<div class="panel panel-default">
<div class="panel-heading">Tip</div>
<div class="panel-body">
If you like the DependencyWheel, you may also like another visualization I made with d3.js called <a href="http://redotheweb.com/CodeFlower/">CodeFlower</a>.
</div>
</div>
</div>
</div>
<a href="https://github.com/fzaninotto/DependencyWheel"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_orange_ff7600.png" alt="Fork me on GitHub"></a>
<script src="js/d3.v4.min.js"></script>
<script src="js/d3.dependencyWheel.js"></script>
<script src="js/composerBuilder.js"></script>
<script>
var gitHubApiUrl = 'https://api.github.com/repos/';
var getData = function(target, callback) {
var responses = {
composerjson: null,
composerlock: null
};
var checkFinished = function() {
if (responses.composerjson && responses.composerlock) {
callback(responses.composerjson, responses.composerlock);
}
}
d3.xhr(gitHubApiUrl + target + '/contents/composer.json', 'application/vnd.github.VERSION.raw', function(err, composerjson) {
responses.composerjson = JSON.parse(composerjson.responseText);
checkFinished();
});
d3.xhr(gitHubApiUrl + target + '/contents/composer.lock', 'application/vnd.github.VERSION.raw', function(err, composerlock) {
responses.composerlock = JSON.parse(composerlock.responseText);
checkFinished();
});
};
var chart = d3.chart.dependencyWheel();
d3.json('data/composer.json', function(composerjson) {
d3.json('data/composer.lock', function(composerlock) {
var data = buildMatrixFromComposerJsonAndLock(composerjson, composerlock);
d3.select('#chart_placeholder')
.datum(data)
.call(chart);
});
});
document.getElementById('composerRedraw').addEventListener('submit', function(e) {
e.preventDefault();
var composerjson = JSON.parse(document.getElementById('composerJson').value);
var composerlock = JSON.parse(document.getElementById('composerLock').value);
var data = buildMatrixFromComposerJsonAndLock(composerjson, composerlock);
d3.select('#chart_placeholder svg').remove();
d3.select('#chart_placeholder')
.datum(data)
.call(chart);
}, false);
</script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-26354577-2']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</body>
</html>
================================================
FILE: js/composerBuilder.js
================================================
var buildMatrixFromComposerJson = function(composerjson) {
var n = Object.keys(composerjson.require).length;
var matrix = [];
matrix[0] = [0];
var increment = 0;
// only the first element depends on others
for (var i=1; i < n; i++) {
matrix[0][i] = 1 + increment;
increment += 0.001;
matrix[i] = Array.apply(null, new Array(n)).map(Number.prototype.valueOf,0);
matrix[i][0] = 1;
}
var packageNames = Object.keys(composerjson.require);
packageNames.unshift(composerjson.name);
return {
matrix: matrix,
packageNames: packageNames
}
};
var buildMatrixFromComposerJsonAndLock = function(composerjson, composerlock) {
var packages = composerlock.packages;
composerjson.isMain = true;
packages.unshift(composerjson);
var indexByName = {};
var packageNames = {};
var matrix = [];
var n = 0;
var replaces = {};
// List the replacements
packages.forEach(function(p) {
if (!p.replace) return;
for (replaced in p.replace) {
replaces[replaced] = p.name;
}
});
// update required packages with replacements
packages.forEach(function(p) {
for (packageName in p.require) {
if (packageName in replaces) {
p.require[replaces[packageName]] = p.require[packageName];
delete p.require[packageName];
}
}
});
// Compute a unique index for each package name.
packages.forEach(function(p) {
packageName = p.name;
if (!(packageName in indexByName)) {
packageNames[n] = packageName;
indexByName[packageName] = n++;
}
});
// Construct a square matrix counting package requires.
packages.forEach(function(p) {
var source = indexByName[p.name];
var row = matrix[source];
if (!row) {
row = matrix[source] = [];
for (var i = -1; ++i < n;) row[i] = 0;
}
for (packageName in p.require) {
row[indexByName[packageName]]++;
}
});
// add small increment to equally weighted dependencies to force order
matrix.forEach(function(row, index) {
var increment = 0.001;
for (var i = -1; ++i < n;) {
var ii = (i + index) % n;
if (row[ii] == 1) {
row[ii] += increment;
increment += 0.001;
}
}
});
return {
matrix: matrix,
packageNames: packageNames
}
};
================================================
FILE: js/d3.dependencyWheel.js
================================================
d3.chart = d3.chart || {};
/**
* Dependency wheel chart for d3.js
*
* Usage:
* var chart = d3.chart.dependencyWheel();
* d3.select('#chart_placeholder')
* .datum({
* packageNames: [the name of the packages in the matrix],
* matrix: [your dependency matrix]
* })
* .call(chart);
*
* // Data must be a matrix of dependencies. The first item must be the main package.
* // For instance, if the main package depends on packages A and B, and package A
* // also depends on package B, you should build the data as follows:
*
* var data = {
* packageNames: ['Main', 'A', 'B'],
* matrix: [[0, 1, 1], // Main depends on A and B
* [0, 0, 1], // A depends on B
* [0, 0, 0]] // B doesn't depend on A or Main
* };
*
* // You can customize the chart width, margin (used to display package names),
* // and padding (separating groups in the wheel)
* var chart = d3.chart.dependencyWheel().width(700).margin(150).padding(.02);
*
* @author François Zaninotto
* @license MIT
* @see https://github.com/fzaninotto/DependencyWheel for complete source and license
*/
d3.chart.dependencyWheel = function(options) {
var width = 700;
var margin = 150;
var padding = 0.02;
function chart(selection) {
selection.each(function(data) {
var matrix = data.matrix;
var packageNames = data.packageNames;
var radius = width / 2 - margin;
// create the layout
var chord = d3.chord()
.padAngle(padding)
.sortSubgroups(d3.descending);
// Select the svg element, if it exists.
var svg = d3.select(this).selectAll("svg").data([data]);
// Otherwise, create the skeletal chart.
var gEnter = svg.enter().append("svg:svg")
.attr("width", width)
.attr("height", width)
.attr("class", "dependencyWheel")
.append("g")
.attr("transform", "translate(" + (width / 2) + "," + (width / 2) + ")");
var arc = d3.arc()
.innerRadius(radius)
.outerRadius(radius + 20);
var fill = function(d) {
if (d.index === 0) return '#ccc';
return "hsl(" + parseInt(((packageNames[d.index][0].charCodeAt() - 97) / 26) * 360, 10) + ",90%,70%)";
};
// Returns an event handler for fading a given chord group.
var fade = function(opacity) {
return function(g, i) {
gEnter.selectAll(".chord")
.filter(function(d) {
return d.source.index != i && d.target.index != i;
})
.transition()
.style("opacity", opacity);
var groups = [];
gEnter.selectAll(".chord")
.filter(function(d) {
if (d.source.index == i) {
groups.push(d.target.index);
}
if (d.target.index == i) {
groups.push(d.source.index);
}
});
groups.push(i);
var length = groups.length;
gEnter.selectAll('.group')
.filter(function(d) {
for (var i = 0; i < length; i++) {
if(groups[i] == d.index) return false;
}
return true;
})
.transition()
.style("opacity", opacity);
};
};
var chordResult = chord(matrix);
var rootGroup = chordResult.groups[0];
var rotation = - (rootGroup.endAngle - rootGroup.startAngle) / 2 * (180 / Math.PI);
var g = gEnter.selectAll("g.group")
.data(chordResult.groups)
.enter().append("svg:g")
.attr("class", "group")
.attr("transform", function(d) {
return "rotate(" + rotation + ")";
});
g.append("svg:path")
.style("fill", fill)
.style("stroke", fill)
.attr("d", arc)
.style("cursor", "pointer")
.on("mouseover", fade(0.1))
.on("mouseout", fade(1));
g.append("svg:text")
.each(function(d) { d.angle = (d.startAngle + d.endAngle) / 2; })
.attr("dy", ".35em")
.attr("text-anchor", function(d) { return d.angle > Math.PI ? "end" : null; })
.attr("transform", function(d) {
return "rotate(" + (d.angle * 180 / Math.PI - 90) + ")" +
"translate(" + (radius + 26) + ")" +
(d.angle > Math.PI ? "rotate(180)" : "");
})
.style("cursor", "pointer")
.text(function(d) { return packageNames[d.index]; })
.on("mouseover", fade(0.1))
.on("mouseout", fade(1));
gEnter.selectAll("path.chord")
.data(chordResult)
.enter().append("svg:path")
.attr("class", "chord")
.style("stroke", function(d) { return d3.rgb(fill(d.source)).darker(); })
.style("fill", function(d) { return fill(d.source); })
.attr("d", d3.ribbon().radius(radius))
.attr("transform", function(d) {
return "rotate(" + rotation + ")";
})
.style("opacity", 1);
});
}
chart.width = function(value) {
if (!arguments.length) return width;
width = value;
return chart;
};
chart.margin = function(value) {
if (!arguments.length) return margin;
margin = value;
return chart;
};
chart.padding = function(value) {
if (!arguments.length) return padding;
padding = value;
return chart;
};
return chart;
};
================================================
FILE: package.json
================================================
{
"name": "d3-dependency-wheel",
"version": "1.1.0",
"description": "Dependency Wheel",
"main": "js/d3.dependencyWheel.js",
"repository": {
"type": "git",
"url": "git+https://github.com/fzaninotto/DependencyWheel.git"
},
"license": "MIT",
"bugs": {
"url": "https://github.com/fzaninotto/DependencyWheel/issues"
},
"homepage": "https://github.com/fzaninotto/DependencyWheel#readme"
}
gitextract_bh_4ohqv/ ├── LICENSE ├── README.md ├── data/ │ └── composer.json ├── index.html ├── js/ │ ├── composerBuilder.js │ └── d3.dependencyWheel.js └── package.json
SYMBOL INDEX (1 symbols across 1 files)
FILE: js/d3.dependencyWheel.js
function chart (line 40) | function chart(selection) {
Condensed preview — 7 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (24K chars).
[
{
"path": "LICENSE",
"chars": 1062,
"preview": "Copyright (c) 2013 Francois Zaninotto\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof t"
},
{
"path": "README.md",
"chars": 646,
"preview": "Dependency Wheel\n================\n\nThis experiment visualizes package dependencies using an interactive disc. Each disc "
},
{
"path": "data/composer.json",
"chars": 3748,
"preview": "{\n \"name\": \"sylius/sylius\",\n \"type\": \"project\",\n \"description\": \"Modern ecommerce for Symfony2\",\n"
},
{
"path": "index.html",
"chars": 8458,
"preview": "<!DOCTYPE html>\n<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en-us\" prefix=\"og: http://ogp.me/ns#\">\n "
},
{
"path": "js/composerBuilder.js",
"chars": 2291,
"preview": "var buildMatrixFromComposerJson = function(composerjson) {\n var n = Object.keys(composerjson.require).length;\n var mat"
},
{
"path": "js/d3.dependencyWheel.js",
"chars": 5434,
"preview": "d3.chart = d3.chart || {};\n\n/**\n * Dependency wheel chart for d3.js\n *\n * Usage:\n * var chart = d3.chart.dependencyWheel"
},
{
"path": "package.json",
"chars": 447,
"preview": "{\n \"name\": \"d3-dependency-wheel\",\n \"version\": \"1.1.0\",\n \"description\": \"Dependency Wheel\",\n \"main\": \"js/d3.d"
}
]
About this extraction
This page contains the full source code of the fzaninotto/DependencyWheel GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 7 files (21.6 KB), approximately 5.9k tokens, and a symbol index with 1 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.