UNPKG

grunt-readme

Version:

Grunt plugin for generating a README from templates, including an optional table of contents. No Gruntfile config is necessary, just choose a starter template and you'll be ready to go.

190 lines (158 loc) 5.28 kB
/*! * Utils * https://github.com/assemble/grunt-readme * Copyright (c) 2013 Jon Schlinkert, Brian Woodward, contributors. * Licensed under the MIT license. */ 'use strict'; // node_modules var grunt = require('grunt'); var acorn = require('acorn'); var path = require('path'); var load = require('resolve-dep'); var _ = grunt.util._; // Export the utils module. exports = module.exports = {}; // Metadata // var config = require(path.resolve(process.cwd(),'package.json')); var config; if(grunt.file.exists(path.resolve(process.cwd(), 'package.json'))) { config = grunt.file.readJSON(path.resolve(process.cwd(),'package.json')); } else { config = require('./pkg.js'); } /** * `{% _.resolve("module-name") %}` * * Automagically include a template from node_modules. The * path to the template must be defined in the `main` property * of the package.json in the npm module. A potential use case * for this option is to include fragments or "partials" that * are used in multiple projects. */ exports.resolve = function (patterns) { return load.all(patterns).map(function(file) { return grunt.file.read(file).replace(/^#/gm, '##'); }); }; /** * Access properties from package.json * @param {Object|String|Array} key * @param {Number} opts Indentation for stringified JSON * @return {Object} */ exports.pkg = function (key, opts) { opts = opts || 2; if (_.isUndefined(key)) { return JSON.stringify(config, null, opts) || {}; } else if (_.isString(config[key])) { return config[key] || ""; } else if (_.isObject(config[key])) { return JSON.stringify(config[key], null, opts) || {}; } else { return null; } }; /** * Add a copyright statement, with author and year(s) in effect. * @param {Number} startYear Optional parameter to define the start year of the project. * @return {String} Complete copyright statement. * @example * {%= _.copyright() %} => Copyright (c) 2013 Jeffrey Herb, contributors. * {%= _.copyright('2012') %} => Copyright (c) 2012-2013 Jeffrey Herb, contributors. */ exports.copyright = function (startYear) { var author = config.author ? (config.author.name || config.author) : name; var today = grunt.template.today('yyyy') + ' '; var date = startYear ? startYear + '-' + today : today; return 'Copyright (c) ' + date + author + ', contributors.'; }; exports.license = function (prepend) { prepend = prepend || "Released under the "; if(config.licenses) { return prepend + _.pluck(config.licenses, "type").join(", ") + " license" + (config.licenses.length === 1 ? '' : 's'); } else if(config.license) { return prepend + config.license.type + " license"; } else { return; } }; exports.username = function () { if(config.homepage) { return config.homepage.replace(/^([^:]+):\/\/(?:.+)\/(.+)\/(?:.+)/, '$2'); } else { return config.repository.url.replace(/^([^:]+):(.+)/, '$1'); } }; exports.homepage = function () { if(config.homepage) { return config.homepage; } else { return config.repository.url.replace(/^git@([^:]+):(.+)(?:.git)/, 'https://$1/$2'); } }; exports.contributors = function (sep) { sep = sep || ""; if(config.contributors) { return _.pluck(config.contributors, "name").join("\n") + sep; } else {return; } }; /** * _.safename("helper-foo") * @param {[type]} name The name to be modified * @return {[type]} The "safe" short version of the name * @example: "grunt-readme" => "readme" * @example: "helper-foo" => "foo" */ exports.safename = function (name, patterns) { var prefixes = ['grunt', 'helper', 'handlebars-helper', 'mixin', 'assemble-contrib', 'assemble']; var blacklist = _.unique(_.flatten(_.union([], prefixes, patterns || []))); var re = new RegExp('^(?:' + blacklist.join('|') + ')[-_]?'); return name.replace(re, '').replace(/[\W_]+/g, '_').replace(/^(\d)/, '_$1'); }; exports.shortname = function (name, patterns) { return _.safename(name, patterns); }; /** * jsdocs * @param {[type]} file [description] * @return {[type]} [description] */ exports.jsdocs = function (file) { var output = ''; var comments = []; function onComment(block, text, start, end, startLine, endLine) { if (block) { comments.push({ text: text, start: startLine, end: endLine }); } }; /* * Parse the given file into an ast */ var opts = { locations: true, onComment: onComment, sourceFile: file }; var ast = acorn.parse(grunt.file.read(file), opts); /* * Output comment block with link to source code */ if(file[0] !== '/') file = '/' + file; for (var i = 0; i < comments.length; i++) { output += '\n\n'; output += '```js\n'; output += '/*' + comments[i].text + '*/\n'; output += '```\n'; output += '[View Source Code]({0}{1}#L{2}-{3})'. replace('{0}', _.homepage()). replace('{1}', file). replace('{2}', comments[i].start.line). replace('{3}', comments[i].end.line); } return output; };