Created
February 4, 2017 20:14
-
-
Save nhz-io/b34da04d83009d7217d4e401f7694ce8 to your computer and use it in GitHub Desktop.
Code Histogram created by nhz-io - https://repl.it/F5Qs/98
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.histogram { | |
margin: 0; | |
padding: 0; | |
box-sizing: border-box; | |
display: inline-block; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<meta name="viewport" content="width=device-width"> | |
<title>repl.it</title> | |
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/4.5.0/d3.js"></script> | |
<script src="//cdnjs.cloudflare.com/ajax/libs/esprima/2.7.3/esprima.js"></script> | |
<link href="index.css" rel="stylesheet" type="text/css" /> | |
</head> | |
<body> | |
<div class="histogram" data-url="index.js" style="font-size:12px;color:#222;width:800px;height:20px" data-fill="rgba(100,100,0,0.3)"></div> | |
<script src="index.js"></script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function* map(list, fn) { | |
let i = 0 | |
for (const item of list) { | |
yield fn.call(this, item, i, list) | |
i++ | |
} | |
} | |
function* keys(target) { | |
if (typeof target === 'undefined') { | |
return yield* [] | |
} | |
if (typeof target !== 'object') { | |
return yield* [] | |
} | |
for (const key in target) { | |
if (target.hasOwnProperty(key)) { | |
yield key | |
} | |
} | |
} | |
function* values(target) { | |
if (typeof target === 'undefined') { | |
return yield* [] | |
} | |
if (typeof target !== 'object') { | |
return yield* [target] | |
} | |
if (Array.isArray(target)) { | |
return yield* target | |
} | |
for (const key in target) { | |
if (target.hasOwnProperty(key)) { | |
yield target[key] | |
} | |
} | |
} | |
function* nodes(start) { | |
if (start && start.type && start.range && start.range.length) { | |
if (start.type !== 'Program') { | |
yield start | |
} | |
} | |
if (!start || typeof start !== 'object') { | |
return | |
} | |
for (const value of values(start)) { | |
yield* nodes(value) | |
} | |
} | |
d3.selectAll('.histogram').each(function () { | |
const url = this.getAttribute('data-url') | |
const width = parseInt(this.style.width || 500) | |
const height = parseInt(this.style.height || 30) | |
const fillStyle = this.getAttribute('data-fill') || 'rgba(0,0,0,0.08)' | |
const fontSize = parseInt(this.style.fontSize || 18) | |
const fontFamily = this.style.fontFamily || 'Monospace' | |
const textColor = this.style.color || 'black' | |
d3.text(url, (err, res) => { | |
if (err) { | |
throw err | |
} | |
const ast = esprima.parse(res, {range: true}) | |
const list = Array.from(nodes(ast)) | |
const types = [] | |
const typedNodes = {} | |
const min = list.sort((a, b) => a.range[0] - b.range[0])[0].range[0] | |
const max = list.sort((a, b) => b.range[1] - a.range[1])[0].range[1] | |
console.log(min, max) | |
for (const item of list) { | |
const type = item.type | |
if (types.indexOf(type) === -1) { | |
types.push(type) | |
} | |
typedNodes[type] = typedNodes[type] || [] | |
typedNodes[type].push(item) | |
} | |
const data = Array.from( | |
map(types, type => ({type, nodes: typedNodes[type]})) | |
) | |
const groups = d3.select(this).selectAll('canvas').data([types]) | |
groups.enter() | |
.append('canvas') | |
.attr('width', width) | |
.attr('height', () => (height + fontSize + 10) * types.length + fontSize + 8) | |
.each(function () { | |
const ctx = this.getContext('2d') | |
ctx.font = `${fontSize}px ${fontFamily}` | |
const min = list.sort((a, b) => a.range[0] - b.range[0])[0].range[0] | |
const max = list.sort((a, b) => b.range[1] - a.range[1])[0].range[1] | |
const s = d3.scaleLinear().domain([min, max]).range([1, width]) | |
ctx.fillStyle = 'white' | |
ctx.fillRect(0, 0, width, (height + fontSize + 10) * types.length + fontSize + 8) | |
ctx.fillStyle = textColor | |
ctx.fillText(url, 2, fontSize + 2) | |
types.forEach((type, i) => { | |
let y = (fontSize + 10 + height) * i + fontSize + 8 | |
ctx.fillStyle = fillStyle | |
ctx.fillRect(0, y, width, 1) | |
y += fontSize + 4 | |
ctx.fillStyle = textColor | |
ctx.fillText(`${type} (${typedNodes[type].length})`, 2, y) | |
y += 4 | |
ctx.fillStyle = fillStyle | |
typedNodes[type].forEach(node => { | |
const width = s(node.range[1] - node.range[0]) - 1 | |
ctx.fillRect( | |
s(node.range[0]), | |
y, | |
width < 1 ? 1 : width, | |
height | |
) | |
}) | |
}) | |
}) | |
groups.exit().remove() | |
}) | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment