Skip to content

Commit

Permalink
✨ Allow user to specify path to custom README template (#68)
Browse files Browse the repository at this point in the history
  • Loading branch information
hgb123 authored and kefranabg committed Jun 23, 2019
1 parent 688c338 commit e0d66c0
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 22 deletions.
10 changes: 10 additions & 0 deletions .all-contributorsrc
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ Feel free to check [issues page](https://github.com/kefranabg/readme-md-generato
<td align="center"><a href="https://github.com/samit4me"><img src="https://avatars3.githubusercontent.com/u/3248531?v=4" width="75px;" alt="Samuel Sharpe"/><br /><sub><b>Samuel Sharpe</b></sub></a><br /><a href="https://github.com/kefranabg/readme-md-generator/commits?author=samit4me" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/apatrascu"><img src="https://avatars3.githubusercontent.com/u/1193770?v=4" width="75px;" alt="Alecsandru Patrascu"/><br /><sub><b>Alecsandru Patrascu</b></sub></a><br /><a href="https://github.com/kefranabg/readme-md-generator/commits?author=apatrascu" title="Code">💻</a></td>
<td align="center"><a href="http://milad.nekofar.com"><img src="https://avatars3.githubusercontent.com/u/147401?v=4" width="75px;" alt="Milad Nekofar"/><br /><sub><b>Milad Nekofar</b></sub></a><br /><a href="https://github.com/kefranabg/readme-md-generator/commits?author=nekofar" title="Code">💻</a> <a href="https://github.com/kefranabg/readme-md-generator/commits?author=nekofar" title="Tests">⚠️</a> <a href="#ideas-nekofar" title="Ideas, Planning, & Feedback">🤔</a></td>
<td align="center"><a href="https://github.com/hgb123"><img src="https://avatars0.githubusercontent.com/u/18468577?v=4" width="75px;" alt="Bao Ho"/><br /><sub><b>Bao Ho</b></sub></a><br /><a href="https://github.com/kefranabg/readme-md-generator/commits?author=hgb123" title="Code">💻</a> <a href="https://github.com/kefranabg/readme-md-generator/commits?author=hgb123" title="Tests">⚠️</a></td>
</tr>
</table>

Expand Down
4 changes: 2 additions & 2 deletions src/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
10 changes: 5 additions & 5 deletions src/cli.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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(() =>
Expand All @@ -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(
Expand All @@ -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,
Expand Down
9 changes: 8 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
const yargs = require('yargs')

const { mainProcess } = require('./cli')
const { getReadmeTemplatePath } = require('./readme')

yargs
.usage('Usage: $0 <command> [options]')
Expand All @@ -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')
Expand Down
43 changes: 34 additions & 9 deletions src/readme.js
Original file line number Diff line number Diff line change
@@ -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'

Expand Down Expand Up @@ -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, {
Expand All @@ -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
}
77 changes: 72 additions & 5 deletions src/readme.spec.js
Original file line number Diff line number Diff line change
@@ -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()
Expand Down Expand Up @@ -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',
Expand Down Expand Up @@ -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')
Expand All @@ -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()
})
Expand All @@ -118,7 +124,7 @@ describe('readme', () => {
})

try {
await buildReadmeContent(context, templateName)
await buildReadmeContent(context, templatePath)
// eslint-disable-next-line no-empty
} catch (err) {}

Expand All @@ -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'
)
})
})
})

0 comments on commit e0d66c0

Please sign in to comment.