├── .README.md ├── .babelrc ├── .eslintrc ├── README.md ├── bin └── node-readme.js ├── dist ├── .README.md ├── index.js └── macros │ ├── author.js │ ├── badge.js │ ├── dependencies.js │ ├── index.js │ ├── license.js │ └── scripts.js ├── package.json └── src ├── .README.md ├── index.js └── macros ├── author.js ├── badge.js ├── dependencies.js ├── index.js ├── license.js └── scripts.js /.README.md: -------------------------------------------------------------------------------- 1 | # ${pkg.name} 2 | 3 | ${badge('npm')} ${badge('license')} ${badge('github-issues')} ${badge('circleci')} 4 | 5 | ${pkg.description} 6 | 7 | ${badge('nodei')} 8 | 9 | ## Features 10 | 11 | - reads most of the data from package.json 12 | - list npm commands 13 | - author & licence 14 | - use a customizable ES6 template 15 | - badges 16 | 17 | ## Install 18 | 19 | `npm install --save-dev ${pkg.name}` 20 | 21 | ## Usage 22 | 23 | Add a command in your package.json : 24 | ``` 25 | "scripts": { 26 | "readme": "node ./node_modules/.bin/node-readme" 27 | }, 28 | ``` 29 | 30 | Then run `npm run readme` to generate your README.md. 31 | 32 | ## Custom Template 33 | 34 | You can copy and customize the [default README template](./src/.README.md) and add it to your project as `.README.md`. 35 | 36 | It uses the [Javascript ES6 syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/template_strings) and you can use these macros and variables : 37 | 38 | ### Badges 39 | 40 | - `badge('npm')` : show npm version 41 | - `badge('nodei')` : show npm dashboard image 42 | - `badge('travis-status')` : show travis build status 43 | - `badge('license')` : show license type 44 | - `badge('github-issues')` : show # of github issues 45 | - `badge('github-stars')` : show # of github stars 46 | - `badge('github-forks')` : show # of github forks 47 | - `badge('circleci')` : show circleci status 48 | - all status from [stability-badges](https://github.com/badges/stability-badges) 49 | 50 | ### Others 51 | - `scripts()` : list of npm scripts 52 | - `license()`: show license type + link 53 | - `dependencies()` : list of project dependencies 54 | - `pkg` : direct access to package.json 55 | 56 | ## Scripts 57 | 58 | ${scripts()} 59 | 60 | ## Dependencies 61 | 62 | ${dependencies()} 63 | 64 | ## Contributing 65 | 66 | Contributions welcome; Please submit all pull requests against the master branch. If your pull request contains JavaScript patches or features, you should include relevant unit tests. Please check the [Contributing Guidelines](contributng.md) for more details. Thanks! 67 | 68 | ## Author 69 | 70 | ${pkg.author.name} <${pkg.author.email}> ${pkg.author.url} 71 | 72 | ## License 73 | 74 | ${license()} 75 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "stage": 0, 3 | "optional": [], 4 | "env": { 5 | "production": { 6 | "optional": [] 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "env": { 4 | "browser": true, 5 | "node": true 6 | }, 7 | "ecmaFeatures": { 8 | "classes": true, 9 | "jsx": true, 10 | "modules": true 11 | }, 12 | "plugins": [ 13 | ], 14 | "rules": { 15 | "quotes": [2, "single"], 16 | "eol-last": [0], 17 | "no-mixed-requires": [0], 18 | "no-underscore-dangle": [0] 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # node-readme 2 | 3 | ![npm](https://img.shields.io/npm/v/node-readme.svg) ![license](https://img.shields.io/npm/l/node-readme.svg) ![github-issues](https://img.shields.io/github/issues/revolunet/node-readme.svg) ![Circle CI build status](https://circleci.com/gh/revolunet/node-readme.svg?style=svg) 4 | 5 | Generate your JS project README.md using an ES6 template 6 | 7 | ![nodei.co](https://nodei.co/npm/node-readme.png?downloads=true&downloadRank=true&stars=true) 8 | 9 | ## Features 10 | 11 | - reads most of the data from package.json 12 | - list npm commands 13 | - author & licence 14 | - use a customizable ES6 template 15 | - badges 16 | 17 | ## Install 18 | 19 | `npm install --save-dev node-readme` 20 | 21 | ## Usage 22 | 23 | Add a command in your package.json : 24 | ``` 25 | "scripts": { 26 | "readme": "node ./node_modules/.bin/node-readme" 27 | }, 28 | ``` 29 | 30 | Then run `npm run readme` to generate your README.md. 31 | 32 | ## Custom Template 33 | 34 | You can copy and customize the [default README template](./src/.README.md) and add it to your project as `.README.md`. 35 | 36 | It uses the [Javascript ES6 syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/template_strings) and you can use these macros and variables : 37 | 38 | ### Badges 39 | 40 | - `badge('npm')` : show npm version 41 | - `badge('nodei')` : show npm dashboard image 42 | - `badge('travis-status')` : show travis build status 43 | - `badge('license')` : show license type 44 | - `badge('github-issues')` : show # of github issues 45 | - `badge('github-stars')` : show # of github stars 46 | - `badge('github-forks')` : show # of github forks 47 | - `badge('circleci')` : show circleci status 48 | - all status from [stability-badges](https://github.com/badges/stability-badges) 49 | 50 | ### Others 51 | - `scripts()` : list of npm scripts 52 | - `license()`: show license type + link 53 | - `dependencies()` : list of project dependencies 54 | - `pkg` : direct access to package.json 55 | 56 | ## Scripts 57 | 58 | - **npm run readme** : `node bin/node-readme.js` 59 | - **npm run build** : `babel -d dist/ src/ && cp ./src/.README.md ./dist/.README.md` 60 | 61 | ## Dependencies 62 | 63 | Package | Version | Dev 64 | --- |:---:|:---: 65 | [es6-template-strings](https://www.npmjs.com/package/es6-template-strings) | 1.0.0 | ✖ 66 | [es6-templates](https://www.npmjs.com/package/es6-templates) | 0.2.2 | ✖ 67 | [oss-license-name-to-url](https://www.npmjs.com/package/oss-license-name-to-url) | 1.2.1 | ✖ 68 | [babel](https://www.npmjs.com/package/babel) | 5.6.14 | ✔ 69 | [babel-eslint](https://www.npmjs.com/package/babel-eslint) | 3.1.23 | ✔ 70 | 71 | 72 | ## Contributing 73 | 74 | Contributions welcome; Please submit all pull requests against the master branch. If your pull request contains JavaScript patches or features, you should include relevant unit tests. Please check the [Contributing Guidelines](contributng.md) for more details. Thanks! 75 | 76 | ## Author 77 | 78 | Julien Bouquillon http://github.com/revolunet 79 | 80 | ## License 81 | 82 | - **MIT** : http://opensource.org/licenses/MIT 83 | -------------------------------------------------------------------------------- /bin/node-readme.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | require('../dist').generate(); 4 | -------------------------------------------------------------------------------- /dist/.README.md: -------------------------------------------------------------------------------- 1 | # ${pkg.name} 2 | 3 | ${badge('npm')} ${badge('npm-license')} ${badge('github-issues')} ${badge('circleci')} 4 | 5 | ${pkg.description} 6 | 7 | ${badge('nodei')} 8 | 9 | ${badge('travis-status')} 10 | ${badge('github-stars')} 11 | ${badge('github-forks')} 12 | 13 | ${badge('github-forks')} 14 | 15 | ${badge('dependencies')} 16 | ${badge('devDependencies')} 17 | 18 | ## Features 19 | 20 | 21 | ## Install 22 | 23 | `npm install --save ${pkg.name}` 24 | 25 | 26 | ## Scripts 27 | 28 | ${scripts()} 29 | 30 | ## Dependencies 31 | 32 | ${dependencies()} 33 | 34 | ## Contributing 35 | 36 | Contributions welcome; Please submit all pull requests against the master branch. If your pull request contains JavaScript patches or features, you should include relevant unit tests. Please check the [Contributing Guidelines](contributng.md) for more details. Thanks! 37 | 38 | ## Author 39 | 40 | ${author()} 41 | 42 | ## License 43 | 44 | ${license()} 45 | -------------------------------------------------------------------------------- /dist/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, '__esModule', { 4 | value: true 5 | }); 6 | 7 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; 8 | 9 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } } 10 | 11 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 12 | 13 | var _path = require('path'); 14 | 15 | var _path2 = _interopRequireDefault(_path); 16 | 17 | var _fs = require('fs'); 18 | 19 | var _fs2 = _interopRequireDefault(_fs); 20 | 21 | var _es6TemplateStrings = require('es6-template-strings'); 22 | 23 | var _es6TemplateStrings2 = _interopRequireDefault(_es6TemplateStrings); 24 | 25 | var _macros = require('./macros'); 26 | 27 | var macros = _interopRequireWildcard(_macros); 28 | 29 | /** 30 | * convert input ES6 template and convert to markdown 31 | * - adds some data in template scope and macros from ./macros 32 | */ 33 | function toMarkdown(templateContents, data) { 34 | // bould all functions in ./macros and pass the current scope (data + macros) 35 | var boundMacros = {}; 36 | Object.keys(macros).forEach(function (key, idx) { 37 | boundMacros[key] = function (options) { 38 | return (macros[key] || function () { 39 | return ''; 40 | })(options, scope); 41 | }; 42 | }); 43 | var scope = _extends({}, data, boundMacros); 44 | var markdown = (0, _es6TemplateStrings2['default'])(templateContents, scope); 45 | return markdown; 46 | } 47 | 48 | /** 49 | * Generates markdown from given ES6 template file 50 | * resolve the path from root project directory 51 | * fallbacks to default if any 52 | */ 53 | function compile(userPath, fallbackPath, cb) { 54 | var userTemplate = _path2['default'].join(process.cwd(), userPath); 55 | _fs2['default'].exists(userTemplate, function (exists) { 56 | var sourceTemplate = exists ? userTemplate : fallbackPath ? fallbackPath : null; 57 | if (sourceTemplate) { 58 | _fs2['default'].readFile(sourceTemplate, function (err, contents) { 59 | if (err) { 60 | throw 'cannot read ' + sourceTemplate; 61 | } 62 | var data = { 63 | pkg: require(_path2['default'].join(process.cwd(), 'package.json')) 64 | }; 65 | cb(toMarkdown(contents, data)); 66 | }); 67 | return; 68 | } 69 | cb(); 70 | }); 71 | } 72 | 73 | /** 74 | * create the `README.md` file from the main template 75 | * `.README.md` is the current directory 76 | * or the default node-readme `src/.README.md` template 77 | */ 78 | function createReadme() { 79 | var overwrite = arguments[0] === undefined ? true : arguments[0]; 80 | 81 | compile('.README.md', _path2['default'].join(__dirname, './.README.md'), function (markdown) { 82 | var destination = _path2['default'].join(process.cwd(), './README.md'); 83 | _fs2['default'].exists(destination, function (exists) { 84 | if (exists && !overwrite) { 85 | throw destination + ' already exists'; 86 | } 87 | _fs2['default'].writeFile(destination, markdown, function (err) { 88 | if (err) throw err; 89 | console.log('README.md created'); 90 | }); 91 | }); 92 | }); 93 | } 94 | 95 | exports['default'] = { 96 | generate: createReadme 97 | }; 98 | module.exports = exports['default']; -------------------------------------------------------------------------------- /dist/macros/author.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, '__esModule', { 4 | value: true 5 | }); 6 | exports['default'] = author; 7 | 8 | function author(options, scope) { 9 | if (typeof scope.pkg.author === 'string') { 10 | return scope.pkg.author; 11 | } else if (typeof scope.pkg.author === 'object') { 12 | return scope.pkg.author.name + ' <' + scope.pkg.author.email + '> ' + scope.pkg.author.url; 13 | } else if (typeof scope.pkg.authors === 'object') { 14 | return scope.pkg.authors.map(function (author) { 15 | return ' - ' + author.name + ' <' + author.email + '> ' + author.url; 16 | }).join(' - '); 17 | } 18 | } 19 | 20 | module.exports = exports['default']; -------------------------------------------------------------------------------- /dist/macros/badge.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, '__esModule', { 4 | value: true 5 | }); 6 | exports['default'] = badge; 7 | 8 | function image(src) { 9 | var title = arguments[1] === undefined ? '' : arguments[1]; 10 | 11 | return '![' + title + '](' + src + ')'; 12 | } 13 | 14 | function getRepoPath(npmRepository) { 15 | var githubRepo = undefined; 16 | var re = /^.*[\/:]([^/]+\/[^/]+?)(\.git)?$/i; 17 | 18 | if (typeof npmRepository === 'string') { 19 | githubRepo = npmRepository; 20 | } else { 21 | githubRepo = npmRepository.url; 22 | } 23 | if (githubRepo.indexOf('http') === 0 || githubRepo.indexOf('git') === 0) { 24 | return githubRepo.match(re)[1]; 25 | } 26 | return githubRepo; 27 | } 28 | 29 | var badges = { 30 | 'npm': function npm(scope) { 31 | return image('https://img.shields.io/npm/v/' + scope.pkg.name + '.svg', 'npm'); 32 | }, 33 | 'nodei': function nodei(scope) { 34 | return image('https://nodei.co/npm/' + scope.pkg.name + '.png?downloads=true&downloadRank=true&stars=true', 'nodei.co'); 35 | }, 36 | 'travis-status': function travisStatus(scope) { 37 | return image('https://img.shields.io/travis/' + getRepoPath(scope.pkg.repository) + '.svg', 'travis-status'); 38 | }, 39 | 'github-issues': function githubIssues(scope) { 40 | return image('https://img.shields.io/github/issues/' + getRepoPath(scope.pkg.repository) + '.svg', 'github-issues'); 41 | }, 42 | 'npm-license': function npmLicense(scope) { 43 | return image('https://img.shields.io/npm/l/' + scope.pkg.name + '.svg', 'license'); 44 | }, 45 | 'license': function license(scope) { 46 | return image('https://img.shields.io/npm/l/' + scope.pkg.name + '.svg', 'license'); 47 | }, 48 | 'github-license': function githubLicense(scope) { 49 | return image('https://img.shields.io/github/license/' + getRepoPath(scope.pkg.repository) + '.svg', 'stars'); 50 | }, 51 | 'github-stars': function githubStars(scope) { 52 | return image('https://img.shields.io/github/stars/' + getRepoPath(scope.pkg.repository) + '.svg', 'stars'); 53 | }, 54 | 'github-forks': function githubForks(scope) { 55 | return image('https://img.shields.io/github/forks/' + getRepoPath(scope.pkg.repository) + '.svg', 'forks'); 56 | }, 57 | 'circleci': function circleci(scope) { 58 | return image('https://circleci.com/gh/' + getRepoPath(scope.pkg.repository) + '.svg?style=svg', 'Circle CI build status'); 59 | }, 60 | 'dependencies': function dependencies(scope) { 61 | return image('https://david-dm.org/' + getRepoPath(scope.pkg.repository) + '/status.svg'); 62 | }, 63 | 'devDependencies': function devDependencies(scope) { 64 | return image('https://david-dm.org/' + getRepoPath(scope.pkg.repository) + '/dev-status.svg'); 65 | }, 66 | 'deprecated': function deprecated(scope) { 67 | return image('http://badges.github.io/stability-badges/dist/deprecated.svg'); 68 | //https://david-dm.org/${getRepoPath(scope.pkg.repository)}/dev-status.svg`); 69 | }, 70 | 'experimental': function experimental(scope) { 71 | return image('http://badges.github.io/stability-badges/dist/experimental.svg'); 72 | }, 73 | 'unstable': function unstable(scope) { 74 | return image('http://badges.github.io/stability-badges/dist/unstable.svg'); 75 | }, 76 | 'stable': function stable(scope) { 77 | return image('http://badges.github.io/stability-badges/dist/stable.svg'); 78 | }, 79 | 'locked': function locked(scope) { 80 | return image('http://badges.github.io/stability-badges/dist/locked.svg'); 81 | } 82 | }; 83 | 84 | function badge(type, scope) { 85 | return badges[type] ? badges[type](scope) : ''; 86 | } 87 | 88 | module.exports = exports['default']; -------------------------------------------------------------------------------- /dist/macros/dependencies.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, '__esModule', { 4 | value: true 5 | }); 6 | exports['default'] = dependencies; 7 | 8 | function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } } 9 | 10 | function singleDep(name, version) { 11 | var dev = arguments[2] === undefined ? false : arguments[2]; 12 | 13 | var check = dev ? '✔' : '✖'; 14 | return '[' + name + '](https://www.npmjs.com/package/' + name + ') | ' + version + ' | ' + check; 15 | } 16 | 17 | function dependenciesList(obj) { 18 | var dev = arguments[1] === undefined ? false : arguments[1]; 19 | 20 | if (!obj) { 21 | obj = {}; 22 | } 23 | return Object.keys(obj).map(function (name) { 24 | return singleDep(name, obj[name], dev); 25 | }); 26 | } 27 | 28 | function dependencies(options, scope) { 29 | var dependencies = [].concat(_toConsumableArray(dependenciesList(scope.pkg.dependencies)), _toConsumableArray(dependenciesList(scope.pkg.devDependencies, true))); 30 | return 'Package | Version | Dev\n--- |:---:|:---:\n' + dependencies.join('\n') + '\n'; 31 | } 32 | 33 | module.exports = exports['default']; -------------------------------------------------------------------------------- /dist/macros/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, '__esModule', { 4 | value: true 5 | }); 6 | 7 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } 8 | 9 | var _scripts2 = require('./scripts'); 10 | 11 | var _scripts3 = _interopRequireDefault(_scripts2); 12 | 13 | exports.scripts = _scripts3['default']; 14 | 15 | var _badge2 = require('./badge'); 16 | 17 | var _badge3 = _interopRequireDefault(_badge2); 18 | 19 | exports.badge = _badge3['default']; 20 | 21 | var _license2 = require('./license'); 22 | 23 | var _license3 = _interopRequireDefault(_license2); 24 | 25 | exports.license = _license3['default']; 26 | 27 | var _author2 = require('./author'); 28 | 29 | var _author3 = _interopRequireDefault(_author2); 30 | 31 | exports.author = _author3['default']; 32 | 33 | var _dependencies2 = require('./dependencies'); 34 | 35 | var _dependencies3 = _interopRequireDefault(_dependencies2); 36 | 37 | exports.dependencies = _dependencies3['default']; -------------------------------------------------------------------------------- /dist/macros/license.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, '__esModule', { 4 | value: true 5 | }); 6 | exports['default'] = license; 7 | var licenseUrl = require('oss-license-name-to-url'); 8 | 9 | function singleLicense(name) { 10 | var url = licenseUrl(name); 11 | return ' - **' + name + '** : ' + url; 12 | } 13 | 14 | function license(options, scope) { 15 | if (scope.pkg.license) { 16 | return singleLicense(scope.pkg.license); 17 | } else if (scope.pkg.licenses) { 18 | return scope.pkg.licenses.map(function (license) { 19 | return singleLicense(license.type); 20 | }).join(';'); 21 | } 22 | } 23 | 24 | module.exports = exports['default']; -------------------------------------------------------------------------------- /dist/macros/scripts.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, '__esModule', { 4 | value: true 5 | }); 6 | exports['default'] = scripts; 7 | 8 | function scripts(options, scope) { 9 | var scripts = scope.pkg.scripts; 10 | if (scripts && Object.keys(scripts).length > 0) { 11 | return '' + Object.keys(scripts).map(function (key, index) { 12 | return ' - **npm run ' + key + '** : `' + scripts[key] + '`'; 13 | }).join('\n'); 14 | } 15 | return ''; 16 | } 17 | 18 | module.exports = exports['default']; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-readme", 3 | "version": "0.1.9", 4 | "description": "Generate your JS project README.md using an ES6 template", 5 | "license": "MIT", 6 | "repository": "revolunet/node-readme", 7 | "author": { 8 | "name": "Julien Bouquillon", 9 | "email": "julien@bouquillon.com", 10 | "url": "http://github.com/revolunet" 11 | }, 12 | "engines": { 13 | "node": ">=0.10.0" 14 | }, 15 | "main": "dist/index.js", 16 | "bin": { 17 | "node-readme": "bin/node-readme.js" 18 | }, 19 | "scripts": { 20 | "readme": "node bin/node-readme.js", 21 | "build": "babel -d dist/ src/ && cp ./src/.README.md ./dist/.README.md" 22 | }, 23 | "keywords": [ 24 | "node", 25 | "readme", 26 | "doc", 27 | "babel" 28 | ], 29 | "dependencies": { 30 | "es6-template-strings": "1.0.0", 31 | "es6-templates": "0.2.2", 32 | "oss-license-name-to-url": "1.2.1" 33 | }, 34 | "devDependencies": { 35 | "babel": "5.6.14", 36 | "babel-eslint": "3.1.23" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/.README.md: -------------------------------------------------------------------------------- 1 | # ${pkg.name} 2 | 3 | ${badge('npm')} ${badge('npm-license')} ${badge('github-issues')} ${badge('circleci')} 4 | 5 | ${pkg.description} 6 | 7 | ${badge('nodei')} 8 | 9 | ${badge('travis-status')} 10 | ${badge('github-stars')} 11 | ${badge('github-forks')} 12 | 13 | ${badge('github-forks')} 14 | 15 | ${badge('dependencies')} 16 | ${badge('devDependencies')} 17 | 18 | ## Features 19 | 20 | 21 | ## Install 22 | 23 | `npm install --save ${pkg.name}` 24 | 25 | 26 | ## Scripts 27 | 28 | ${scripts()} 29 | 30 | ## Dependencies 31 | 32 | ${dependencies()} 33 | 34 | ## Contributing 35 | 36 | Contributions welcome; Please submit all pull requests against the master branch. If your pull request contains JavaScript patches or features, you should include relevant unit tests. Please check the [Contributing Guidelines](contributng.md) for more details. Thanks! 37 | 38 | ## Author 39 | 40 | ${author()} 41 | 42 | ## License 43 | 44 | ${license()} 45 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | 2 | import path from 'path'; 3 | import fs from 'fs' 4 | import template from 'es6-template-strings'; 5 | import * as macros from "./macros"; 6 | 7 | /** 8 | * convert input ES6 template and convert to markdown 9 | * - adds some data in template scope and macros from ./macros 10 | */ 11 | function toMarkdown(templateContents, data) { 12 | // bould all functions in ./macros and pass the current scope (data + macros) 13 | let boundMacros = {}; 14 | Object.keys(macros).forEach((key, idx) => { 15 | boundMacros[key] = options => (macros[key] || function(){ return '';})(options, scope); 16 | }); 17 | let scope = { ...data, ...boundMacros}; 18 | let markdown = template(templateContents, scope); 19 | return markdown; 20 | } 21 | 22 | /** 23 | * Generates markdown from given ES6 template file 24 | * resolve the path from root project directory 25 | * fallbacks to default if any 26 | */ 27 | function compile(userPath, fallbackPath, cb) { 28 | let userTemplate = path.join(process.cwd(), userPath); 29 | fs.exists(userTemplate, function (exists) { 30 | let sourceTemplate = exists ? userTemplate : fallbackPath ? fallbackPath : null; 31 | if (sourceTemplate) { 32 | fs.readFile(sourceTemplate, function (err, contents) { 33 | if (err) { 34 | throw 'cannot read ' + sourceTemplate; 35 | } 36 | let data = { 37 | pkg: require(path.join(process.cwd(), 'package.json')) 38 | }; 39 | cb(toMarkdown(contents, data)); 40 | }); 41 | return; 42 | } 43 | cb(); 44 | }); 45 | } 46 | 47 | /** 48 | * create the `README.md` file from the main template 49 | * `.README.md` is the current directory 50 | * or the default node-readme `src/.README.md` template 51 | */ 52 | function createReadme(overwrite=true) { 53 | compile('.README.md', path.join(__dirname, './.README.md'), function(markdown) { 54 | let destination = path.join(process.cwd(), './README.md'); 55 | fs.exists(destination, function (exists) { 56 | if (exists && !overwrite) { 57 | throw destination + ' already exists'; 58 | } 59 | fs.writeFile(destination, markdown, function (err) { 60 | if (err) throw err; 61 | console.log('README.md created'); 62 | }); 63 | }); 64 | }); 65 | } 66 | 67 | export default { 68 | generate: createReadme 69 | }; 70 | -------------------------------------------------------------------------------- /src/macros/author.js: -------------------------------------------------------------------------------- 1 | 2 | export default function author(options, scope) { 3 | if (typeof scope.pkg.author === 'string') { 4 | return scope.pkg.author; 5 | } else if (typeof scope.pkg.author === 'object') { 6 | return `${scope.pkg.author.name} <${scope.pkg.author.email}> ${scope.pkg.author.url}` 7 | } else if (typeof scope.pkg.authors === 'object') { 8 | return scope.pkg.authors.map(author => ` - ${author.name} <${author.email}> ${author.url}`).join(' - ') 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/macros/badge.js: -------------------------------------------------------------------------------- 1 | 2 | function image(src, title='') { 3 | return `![${title}](${src})`; 4 | } 5 | 6 | function getRepoPath(npmRepository) { 7 | let githubRepo; 8 | const re = /^.*[\/:]([^/]+\/[^/]+?)(\.git)?$/i; 9 | 10 | if (typeof npmRepository === 'string') { 11 | githubRepo = npmRepository; 12 | } else { 13 | githubRepo = npmRepository.url; 14 | } 15 | if (githubRepo.indexOf('http') === 0 || githubRepo.indexOf('git') === 0 ) { 16 | return githubRepo.match(re)[1]; 17 | } 18 | return githubRepo; 19 | } 20 | 21 | const badges = { 22 | 'npm': scope => { 23 | return image(`https://img.shields.io/npm/v/${scope.pkg.name}.svg`, 'npm'); 24 | }, 25 | 'nodei': scope => { 26 | return image(`https://nodei.co/npm/${scope.pkg.name}.png?downloads=true&downloadRank=true&stars=true`, 'nodei.co'); 27 | }, 28 | 'travis-status': scope => { 29 | return image(`https://img.shields.io/travis/${getRepoPath(scope.pkg.repository)}.svg`, 'travis-status'); 30 | }, 31 | 'github-issues': scope => { 32 | return image(`https://img.shields.io/github/issues/${getRepoPath(scope.pkg.repository)}.svg`, 'github-issues'); 33 | }, 34 | 'npm-license': scope => { 35 | return image(`https://img.shields.io/npm/l/${scope.pkg.name}.svg`, 'license'); 36 | }, 37 | 'license': scope => { 38 | return image(`https://img.shields.io/npm/l/${scope.pkg.name}.svg`, 'license'); 39 | }, 40 | 'github-license': scope => { 41 | return image(`https://img.shields.io/github/license/${getRepoPath(scope.pkg.repository)}.svg`, 'stars'); 42 | }, 43 | 'github-stars': scope => { 44 | return image(`https://img.shields.io/github/stars/${getRepoPath(scope.pkg.repository)}.svg`, 'stars'); 45 | }, 46 | 'github-forks': scope => { 47 | return image(`https://img.shields.io/github/forks/${getRepoPath(scope.pkg.repository)}.svg`, 'forks'); 48 | }, 49 | 'circleci': scope => { 50 | return image(`https://circleci.com/gh/${getRepoPath(scope.pkg.repository)}.svg?style=svg`, 'Circle CI build status'); 51 | }, 52 | 'dependencies': scope => { 53 | return image(`https://david-dm.org/${getRepoPath(scope.pkg.repository)}/status.svg`); 54 | }, 55 | 'devDependencies': scope => { 56 | return image(`https://david-dm.org/${getRepoPath(scope.pkg.repository)}/dev-status.svg`); 57 | }, 58 | 'deprecated': scope => { 59 | return image(`http://badges.github.io/stability-badges/dist/deprecated.svg`); 60 | //https://david-dm.org/${getRepoPath(scope.pkg.repository)}/dev-status.svg`); 61 | }, 62 | 'experimental': scope => { 63 | return image(`http://badges.github.io/stability-badges/dist/experimental.svg`); 64 | }, 65 | 'unstable': scope => { 66 | return image(`http://badges.github.io/stability-badges/dist/unstable.svg`); 67 | }, 68 | 'stable': scope => { 69 | return image(`http://badges.github.io/stability-badges/dist/stable.svg`); 70 | }, 71 | 'locked': scope => { 72 | return image(`http://badges.github.io/stability-badges/dist/locked.svg`); 73 | } 74 | }; 75 | 76 | export default function badge(type, scope) { 77 | return badges[type]?badges[type](scope):''; 78 | } 79 | -------------------------------------------------------------------------------- /src/macros/dependencies.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | function singleDep(name, version, dev=false) { 4 | let check = dev?'✔':'✖'; 5 | return `[${name}](https://www.npmjs.com/package/${name}) | ${version} | ${check}`; 6 | } 7 | 8 | function dependenciesList(obj, dev=false) { 9 | if (!obj) { 10 | obj = {}; 11 | } 12 | return Object.keys(obj).map(name => { 13 | return singleDep(name, obj[name], dev); 14 | }); 15 | } 16 | 17 | export default function dependencies(options, scope) { 18 | let dependencies = [...dependenciesList(scope.pkg.dependencies), ...dependenciesList(scope.pkg.devDependencies, true)]; 19 | return `Package | Version | Dev 20 | --- |:---:|:---: 21 | ${dependencies.join('\n')} 22 | `; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/macros/index.js: -------------------------------------------------------------------------------- 1 | 2 | export scripts from './scripts'; 3 | export badge from './badge'; 4 | export license from './license'; 5 | export author from './author'; 6 | export dependencies from './dependencies'; 7 | -------------------------------------------------------------------------------- /src/macros/license.js: -------------------------------------------------------------------------------- 1 | var licenseUrl = require('oss-license-name-to-url'); 2 | 3 | function singleLicense(name) { 4 | var url = licenseUrl(name); 5 | return ` - **${name}** : ${url}`; 6 | } 7 | 8 | export default function license(options, scope) { 9 | if (scope.pkg.license) { 10 | return singleLicense(scope.pkg.license); 11 | } else if (scope.pkg.licenses) { 12 | return scope.pkg.licenses.map(license=>singleLicense(license.type)).join('\;'); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/macros/scripts.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | export default function scripts(options, scope) { 4 | let scripts = scope.pkg.scripts; 5 | if (scripts && Object.keys(scripts).length > 0) { 6 | return `${Object.keys(scripts).map((key, index)=>` - **npm run ${key}** : \`${scripts[key]}\``).join('\n')}`; 7 | } 8 | return ''; 9 | } 10 | --------------------------------------------------------------------------------