Skip to content

Instantly share code, notes, and snippets.

@jrideout
Created September 24, 2013 03:17
Show Gist options
  • Save jrideout/6679959 to your computer and use it in GitHub Desktop.
Save jrideout/6679959 to your computer and use it in GitHub Desktop.
MD API parser tools
var esprima = require('esprima'),
escodegen = require('escodegen');
var api = {};
var insert = function (str, fragments) {
var i, fragment, pos;
// Sort in descending order since a fragment needs to be
// inserted from the last one, to prevent offsetting the others.
fragments.sort(function (a, b) {
return b.index - a.index;
});
for (i = 0; i < fragments.length; i += 1) {
fragment = fragments[i];
pos = Math.floor(fragment.index);
str = str.slice(0, pos) + fragment.text + str.slice(pos);
}
return str;
};
var instrumentSource = function (source, fileName) {
var syntax = esprima.parse(source, {
raw: true,
tokens: true,
range: true,
loc: true,
comment: true
});
syntax = escodegen.attachComments(syntax, syntax.comments, syntax.tokens);
var lclass, frags = [];
function embed(node) {
if (node.type == 'AssignmentExpression') {
var leftName = escodegen.generate(node.left),
left = leftName.split('.');
if (left[0] == 'dc') {
lclass = left[1];
try {
frags.push({
index: node.range[0],
text: api[left[1]]['class']
});
} catch (e) {}
} else if (left[0] == '_chart') {
if (api[lclass] && api[lclass][left[1]]) {
try {
frags.push({
index: node.range[0],
text: api[lclass][left[1]]
});
} catch (e) {
//console.log(e);
}
}
}
embed(node.right);
} else {
for (var i in node) {
if (typeof (node[i]) == 'object' && node[i]) {
embed(node[i]);
}
}
}
}
embed(syntax);
try {
frags.map(function (f) {
f.text = "/**\n" + f.text + "**/\n";
var offset = f.index - source.lastIndexOf('\n', f.index);
offset = new Array(offset).join(' ');
f.text = f.text.replace(/(\r\n|\n|\r)/gm, "\n" + offset);
f.text = f.text.replace(/\n\s+\n/gm,"\n\n");
return f;
});
} catch (e) {
//console.log(e);
}
return insert(source, frags);
};
//##### dc specific code
var fs = require('fs'),
files = require("../Gruntfile").jsFiles, //fs.readdirSync(dir).map(function(f){return dir + f;});
relativeDir = '../';
//files = ['src/pie-chart.js'];
var apiRaw = require('./api.json');
apiRaw.children.forEach(function (c) {
if (!c.class) return;
api[c.class] = {
class: c.text
};
c.children.forEach(function (m) {
api[c.class][m.meth] = m.text;
});
});
files.forEach(function (file) {
console.log("Instrumenting " + file)
var rawSource = fs.readFileSync(relativeDir + file, 'utf-8');
try {
var s = instrumentSource(rawSource, file);
//console.log(s);
var r = fs.writeFileSync(relativeDir + file, s);
console.log(" Wrote to " + file);
} catch (e) {
//console.log(e);
console.log(" Ignoring: " + file + " (unable to parse)");
}
});
use DDP;
use JSON::XS;
use Modern::Perl;
my $api = {name=>'base',text=>'',level=>0,children=>[]};
my $l = $api;
$l->{parent} = $l;
while (<>) {
my $text = $_;
my ($level, $name) = $text =~ /^(#+) (.*)/;
if ($level) {
$level = length($1);
my $newLevel = {name=>$name,text=>$text,level=>$level,children=>[]};
my ($class) = $name =~ /a name="([^"]+)"/;
if ($class) {
$class =~ s/-(\w)/\U$1/g;
$newLevel->{class} = $class;
}
my ($meth) = $name =~ /\.([a-zA-Z.]+)/;
$newLevel->{meth} = $meth if $meth;
$newLevel->{parent} = $l if ($level > $l->{level});
$newLevel->{parent} = $l->{parent} if ($level == $l->{level});
$newLevel->{parent} = $l->{parent}{parent} if ($level < $l->{level});
if ($meth && $l->{class} && $meth eq $l->{class}) {
$l->{text} .= $text;
} else {
push @{$newLevel->{parent}{children}}, $newLevel;
$l = $newLevel;
}
} else {
$l->{text} .= $text;
}
}
sub removeParent {
my ($n) = @_;
delete $n->{parent};
foreach my $c (@{$n->{children}}) {
removeParent($c);
}
}
removeParent($api);
print encode_json($api);
#p $api;
#
sub rebuild {
my ($n) = @_;
say '#' x $n->{level}, ' ', $n->{name};
say $n->{class} if $n->{class};
print $n->{text};
foreach my $c (@{$n->{children}}) {
rebuild($c);
}
}
#rebuild($api);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment