diff --git a/bin/documentation.js b/bin/documentation.js index 589a9bd..bef1fa6 100755 --- a/bin/documentation.js +++ b/bin/documentation.js @@ -9,6 +9,7 @@ var documentation = require('../'), highlight = require('../streams/highlight.js'), htmlOutput = require('../streams/output/html.js'), lint = require('../streams/lint.js'), + github = require('../streams/github.js'), fs = require('fs'), vfs = require('vinyl-fs'), normalize = require('../streams/normalize.js'), @@ -31,6 +32,10 @@ var yargs = require('yargs') .describe('p', 'generate documentation tagged as private') .alias('p', 'private') + .boolean('g') + .describe('g', 'infer links to github in documentation') + .alias('g', 'github') + .describe('o', 'output location. omit for stdout, otherwise is a filename for single-file outputs and a directory name for multi-file outputs like html') .alias('o', 'output') .default('o', 'stdout') @@ -74,6 +79,7 @@ if (!formatter) { var docStream = documentation(inputs) .pipe(normalize()) .pipe(argv.lint ? lint() : new PassThrough({ objectMode: true })) + .pipe(argv.g ? github() : new PassThrough({ objectMode: true })) .pipe(flatten()) .pipe(filterAccess(argv.private ? [] : undefined)) .pipe(formatter); diff --git a/package.json b/package.json index b929bca..7b77de3 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "doctrine": "^0.6.4", "espree": "^1.12.2", "extend": "^2.0.0", + "github-url-from-git": "^1.4.0", "handlebars": "^3.0.0", "highlight.js": "^8.4.0", "module-deps": "^3.7.3", diff --git a/share/html/assets/style.css b/share/html/assets/style.css index b15e039..525fb94 100644 --- a/share/html/assets/style.css +++ b/share/html/assets/style.css @@ -8,13 +8,16 @@ font-size:80%; } +.fade { + opacity:0.50; +} + .button-indent { padding: .25rem 1.5rem; font-size: 90%; } .section-indent { - padding-left: 1rem; border-left: 2px solid #eee; } diff --git a/share/html/section.hbs b/share/html/section.hbs index b1e3bc5..c44097b 100644 --- a/share/html/section.hbs +++ b/share/html/section.hbs @@ -1,4 +1,9 @@
+ {{#if context.github}} +
+ {{{context.path}}} +
+ {{/if}}

diff --git a/streams/github.js b/streams/github.js new file mode 100644 index 0000000..749d3f7 --- /dev/null +++ b/streams/github.js @@ -0,0 +1,62 @@ +'use strict'; + +var through = require('through'); +var exec = require('child_process').exec; +var path = require('path'); +var fs = require('fs'); +var urlFromGit = require('github-url-from-git'); + +function findGit(filename, relative) { + relative = relative || '.git'; + var newPath = path.resolve(filename, relative); + if (fs.existsSync(newPath)) { + return newPath; + } else if (newPath === '/') { + return null; + } + return findGit(filename, '../' + relative); +} + +function makeGetBase() { + var base, root; + return function (file, callback) { + if (base && root) return callback(base, root); + root = path.dirname(findGit(file)); + var cwd = { cwd: root }; + exec('git rev-parse HEAD', cwd, function (error, head, stderr) { + if (error || stderr) { + console.error(error, stderr); return; + } + exec('git config --get remote.origin.url', cwd, function (error, remote, stderr) { + if (error || stderr) { + console.error(error, stderr); return; + } + base = urlFromGit(remote.trim()) + '/blob/' + head.trim() + '/'; + callback(base, root); + }); + }); + }; +} + +/** + * Create a transform stream that attempts to link code to its + * place on GitHub. + * + * @name linkGitHub + * @return {stream.Transform} + */ +module.exports = function () { + var getBase = makeGetBase(); + return through(function (comment) { + this.pause(); + getBase(comment.context.file, function (base, root) { + comment.context.path = comment.context.file.replace(root + '/', ''); + comment.context.github = base + + comment.context.file.replace(root + '/', '') + + '#L' + comment.context.loc.start.line + '-' + + 'L' + comment.context.loc.end.line; + this.resume(); + this.push(comment); + }.bind(this)); + }); +};