parser.js |
|
---|---|
ParserThis takes the output of a file,
and attempts to group it into sections of We reconcile the new chunks with the html produced from the docs (by piping it through
|
var method = require('./utils').method,
path = require('path'),
child_proc = require('child_process'),
spawn = child_proc.spawn,
showdown = require('./../vendor/showdown').Showdown; |
|
const highlight_start = '<div class="highlight"><pre>';
const highlight_end = '</pre></div>';
var Parser = function(destination, extensions) { |
we take an instance of Destination to let us rewrite file: style links in the documentation. |
this.extensions = extensions;
this.destination = destination;
};
Parser.prototype.match = function(pathname) { |
|
return path.extname(pathname) in this.extensions;
};
Parser.prototype.parse = method(function(self, meta, source) { |
Parse the incoming source into an array of arrays -- |
var symbol = meta.symbol, |
split the source into lines, python-style |
lines = source.toString().split('\n'),
sections = [],
has_code = '',
docs_text = '',
code_text = ''; |
This resets our |
var save = function(docs, code) {
sections.push([docs || '', code || '']);
has_code = docs_text = code_text = '';
}; |
match comments with any amount of preceding whitespace, and a single (optional) space after the symbol. |
var comment_match = new RegExp('\\s*'+symbol+'\\s?'); |
iterate over the lines, building up |
lines.forEach(function(line) {
if(line.match(comment_match)) {
has_code &&
save(docs_text, code_text); |
rewrite file: type links using destination |
docs_text += line.replace(comment_match, '').
replace(/\(file:(.*?)\)/g, function(all, link) {
return '('+self.destination.rewrite_url(link)+')';
})+'\n';
} else {
has_code = true;
code_text += line + '\n';
}
}); |
one final save to make sure we've got the last of our code and docs. |
save(docs_text, code_text);
return sections;
});
Parser.prototype.fail = function(exit) { |
return a callback for when things go horribly wrong. |
return function(text) {
exit(new Error('pygmentize error:\n'+text));
};
};
Parser.prototype.accumulate = function(into) { |
return a callback that just keeps pushing data into
the provided array.
Weirdness Alert: Since |
return function(data) {
into.push(data);
};
};
Parser.prototype.compile = method(function(self, file, source, callback) { |
Load up our extension, parse our source using that metadata, and
spit the pertinent bits into |
var ext = path.extname(file.path),
meta = self.extensions[ext],
language = meta.language,
sections = self.parse(meta, source), |
Weirdness: As above, so below. This is the |
into = [];
var pygments = spawn('pygmentize', ['-l', language, '-f', 'html', '-O', 'encoding=utf-8']); |
fail using our provided callback |
pygments.stderr.on('data', self.fail(callback)); |
accumulate using our accumulate function that does pass-by-reference-magic. |
pygments.stdout.on('data', self.accumulate(into)); |
and when we're done, use that array in a closure returned by |
pygments.on('exit', self.finish_compilation(into, meta, sections, callback)); |
NOTE: We don't write to |
|
write our chunks to |
pygments.stdin.write(sections.map(function(s) { return s[1] || ''; }).join('\n'+meta.symbol+'DIVIDER\n'));
pygments.stdin.end();
});
Parser.prototype.finish_compilation = method(function(self, results, meta, sections, ready) {
return function() {
var symbol = meta.symbol,
divider_html = new RegExp('\\n*<span class="c1?">'+symbol+'DIVIDER<\\/span>\\n*'), |
get rid of the highlights, and split by our expected divider html. |
bits = results.
join('').
replace(highlight_start, '').
replace(highlight_end, '').
split(divider_html); |
map our sections to a [{doc:dochtml, code:codehtml}, ...] format, replacing the highlights in for each code block. |
var parts = sections.slice().map(function(section, index) {
var doc_html = section[0] && showdown.makeHtml(section[0]),
code_html = highlight_start + bits[index] + highlight_end;
return {doc:doc_html, code:code_html};
}); |
let the world know how awesome our |
ready(null, parts);
};
});
exports.Parser = Parser;
|