diff --git a/.all-contributorsrc b/.all-contributorsrc index a0a5235..1e7f673 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -77,6 +77,16 @@ "test", "ideas" ] + }, + { + "login": "hgb123", + "name": "Bao Ho", + "avatar_url": "https://avatars0.githubusercontent.com/u/18468577?v=4", + "profile": "https://github.com/hgb123", + "contributions": [ + "code", + "test" + ] } ], "contributorsPerLine": 7, diff --git a/README.md b/README.md index 065fd04..b548f50 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,7 @@ Feel free to check [issues page](https://github.com/kefranabg/readme-md-generato Samuel Sharpe
Samuel Sharpe

📖 Alecsandru Patrascu
Alecsandru Patrascu

💻 Milad Nekofar
Milad Nekofar

💻 ⚠️ 🤔 + Bao Ho
Bao Ho

💻 ⚠️ diff --git a/src/cli.js b/src/cli.js index d30acda..35b4d0b 100644 --- a/src/cli.js +++ b/src/cli.js @@ -48,12 +48,12 @@ const askQuestions = async (projectInfos, skipQuestions) => { * * @param {Object} args */ -const mainProcess = async ({ template, yes }) => { +const mainProcess = async ({ templatePath, yes }) => { const projectInformations = await infos.getProjectInfos() const answersContext = await cli.askQuestions(projectInformations, yes) const readmeContent = await readme.buildReadmeContent( answersContext, - template + templatePath ) await readme.writeReadme(readmeContent) diff --git a/src/cli.spec.js b/src/cli.spec.js index b6e37b8..d61e4e6 100644 --- a/src/cli.spec.js +++ b/src/cli.spec.js @@ -57,7 +57,7 @@ describe('cli', () => { }) it('should call main functions with correct args', async () => { - const template = 'default' + const templatePath = 'default' const projectInformations = { name: 'readme-md-generator' } const readmeContent = 'content' projectInfos.getProjectInfos = jest.fn(() => @@ -67,7 +67,7 @@ describe('cli', () => { readme.writeReadme = jest.fn() utils.showEndMessage = jest.fn() - await cli.mainProcess({ template }) + await cli.mainProcess({ templatePath }) expect(projectInfos.getProjectInfos).toHaveBeenCalledTimes(1) expect(cli.askQuestions).toHaveBeenNthCalledWith( @@ -78,19 +78,19 @@ describe('cli', () => { expect(readme.buildReadmeContent).toHaveBeenNthCalledWith( 1, answersContext, - template + templatePath ) expect(readme.writeReadme).toHaveBeenNthCalledWith(1, readmeContent) expect(utils.showEndMessage).toHaveBeenCalledTimes(1) }) it('should forward --yes option to askQuestions', async () => { - const template = 'default' + const templatePath = 'default' const projectInformations = { name: 'readme-md-generator' } const skipQuestions = true utils.showEndMessage = jest.fn() - await cli.mainProcess({ template, yes: skipQuestions }) + await cli.mainProcess({ templatePath, yes: skipQuestions }) expect(cli.askQuestions).toHaveBeenNthCalledWith( 1, diff --git a/src/index.js b/src/index.js index 7876b5d..2424d61 100755 --- a/src/index.js +++ b/src/index.js @@ -3,6 +3,7 @@ const yargs = require('yargs') const { mainProcess } = require('./cli') +const { getReadmeTemplatePath } = require('./readme') yargs .usage('Usage: $0 [options]') @@ -14,8 +15,14 @@ yargs desc: 'The name of template you want to use', default: 'default' }), - args => mainProcess(args) + args => { + const templatePath = getReadmeTemplatePath(args) + mainProcess({ templatePath, yes: args.yes }) + } ) + .string('p') + .alias('p', 'path') + .describe('path', 'Path to your own template') .boolean('yes') .alias('y', 'yes') .describe('yes', 'Use default values for all fields') diff --git a/src/readme.js b/src/readme.js index 1de4320..1ad45cb 100644 --- a/src/readme.js +++ b/src/readme.js @@ -1,9 +1,10 @@ const ejs = require('ejs') -const path = require('path') const ora = require('ora') const { promisify } = require('util') const getYear = require('date-fns/get_year') const fs = require('fs') +const path = require('path') +const { isNil } = require('lodash') const README_PATH = 'README.md' @@ -43,17 +44,13 @@ const getReadmeTemplate = async templatePath => { } /** - * Build README content with the given answersContext and templateName + * Build README content with the given context and templatePath * * @param {Object} context - * @param {string} templateName + * @param {string} templatePath */ -const buildReadmeContent = async (context, templateName) => { +const buildReadmeContent = async (context, templatePath) => { const currentYear = getYear(new Date()) - const templatePath = path.resolve( - __dirname, - `../templates/${templateName}.md` - ) const template = await getReadmeTemplate(templatePath) return ejs.render(template, { @@ -63,8 +60,36 @@ const buildReadmeContent = async (context, templateName) => { }) } +/** + * Get path to the readme template + * + * @param {string} availableTemplate + * @param {string} customTemplate + */ +const getReadmeTemplatePath = args => { + const spinner = ora('Resolving README template path').start() + + const { template: availableTemplate, path: customTemplate } = args + + const templatePath = isNil(customTemplate) + ? path.resolve(__dirname, `../templates/${availableTemplate}.md`) + : customTemplate + + try { + fs.lstatSync(templatePath).isFile() + } catch (err) { + spinner.fail(`The template path '${templatePath}' is not valid.`) + throw err + } + + spinner.succeed('README template path resolved') + + return templatePath +} + module.exports = { writeReadme, buildReadmeContent, - README_PATH + README_PATH, + getReadmeTemplatePath } diff --git a/src/readme.spec.js b/src/readme.spec.js index 38863ab..eda8145 100644 --- a/src/readme.spec.js +++ b/src/readme.spec.js @@ -1,9 +1,15 @@ const fs = require('fs') const ora = require('ora') +const path = require('path') jest.mock('ora') -const { writeReadme, buildReadmeContent, README_PATH } = require('./readme') +const { + writeReadme, + buildReadmeContent, + README_PATH, + getReadmeTemplatePath +} = require('./readme') describe('readme', () => { const succeed = jest.fn() @@ -63,7 +69,7 @@ describe('readme', () => { }) describe('buildReadmeContent', () => { - const templateName = 'default' + const templatePath = path.resolve(__dirname, `../templates/default.md`) const context = { isGithubRepos: true, repositoryUrl: 'https://github.com/kefranabg/readme-md-generator', @@ -98,7 +104,7 @@ describe('readme', () => { }) it('should call ora with correct parameters in success case', async () => { - await buildReadmeContent(context, templateName) + await buildReadmeContent(context, templatePath) expect(ora).toHaveBeenCalledTimes(1) expect(ora).toHaveBeenCalledWith('Loading README template') @@ -107,7 +113,7 @@ describe('readme', () => { }) it('should return readme template content', async () => { - const result = await buildReadmeContent(context, templateName) + const result = await buildReadmeContent(context, templatePath) expect(result).toMatchSnapshot() }) @@ -118,7 +124,7 @@ describe('readme', () => { }) try { - await buildReadmeContent(context, templateName) + await buildReadmeContent(context, templatePath) // eslint-disable-next-line no-empty } catch (err) {} @@ -128,4 +134,65 @@ describe('readme', () => { expect(fail).toHaveBeenCalledWith('README template loading fail') }) }) + + describe('getReadmeTemplatePath', () => { + it('should return default template path if customTemplate is undefined', () => { + const args = { template: 'default' } + const actualResult = getReadmeTemplatePath(args) + const expectedResult = path.resolve(__dirname, `../templates/default.md`) + + expect(actualResult).toEqual(expectedResult) + }) + + it('should return custom template path if customTemplate is defined', () => { + const customTemplatePath = path.resolve( + __dirname, + `../templates/default.md` + ) + const args = { template: 'default', path: customTemplatePath } + const expectedResult = customTemplatePath + const actualResult = getReadmeTemplatePath(args) + + expect(actualResult).toEqual(expectedResult) + }) + + it('should throw an error if customTemplate is defined but invalid', () => { + const args = { template: 'default', path: 'wrong path' } + + expect(() => getReadmeTemplatePath(args)).toThrow() + }) + + it('should call ora with correct parameters in fail case', async () => { + const args = { template: 'default', path: 'wrong path' } + + try { + getReadmeTemplatePath(args) + // eslint-disable-next-line no-empty + } catch (err) {} + + expect(ora).toHaveBeenNthCalledWith(1, 'Resolving README template path') + expect(fail).toHaveBeenNthCalledWith( + 1, + "The template path 'wrong path' is not valid." + ) + }) + + it('should call ora with correct parameters in success case', async () => { + const args = { + template: 'default', + path: path.resolve(__dirname, `../templates/default.md`) + } + + try { + getReadmeTemplatePath(args) + // eslint-disable-next-line no-empty + } catch (err) {} + + expect(ora).toHaveBeenNthCalledWith(1, 'Resolving README template path') + expect(succeed).toHaveBeenNthCalledWith( + 1, + 'README template path resolved' + ) + }) + }) })