Socket
Socket
Sign inDemoInstall

readme-md-generator

Package Overview
Dependencies
9
Maintainers
1
Versions
20
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.4.1 to 0.5.0

.git/logs/refs/heads/preview/readme

12

.eslintrc.js

@@ -9,4 +9,14 @@ module.exports = {

rules: {
semi: ['error', 'never'],
'no-use-before-define': ['error', { functions: false }],
'comma-dangle': 0,
'no-var': 2,
'prefer-const': 2
'prefer-const': 2,
'operator-linebreak': 0,
'no-confusing-arrow': 0,
'implicit-arrow-linebreak': 0,
indent: 0,
'no-param-reassign': 0,
'function-paren-newline': 0,
'arrow-parens': 0
},

@@ -13,0 +23,0 @@ parserOptions: {

# Changelog
<a name="0.5.0"></a>
## 0.5.0 (2019-06-27)
### Added
- ✨ Get author name from package.json even if author prop is an object ([#75](https://github.com/kefranabg/readme-md-generator/issues/75)) [[688c338](https://github.com/kefranabg/readme-md-generator/commit/688c33833188a5487ff6df024d4993404ee0406c)]
- ✨ Allow user to specify path to custom README template ([#68](https://github.com/kefranabg/readme-md-generator/issues/68)) [[e0d66c0](https://github.com/kefranabg/readme-md-generator/commit/e0d66c002c8108ff3ae142979a5c8003a28a8107)]
- ✨ Allow user to choose a non HTML README template ([#80](https://github.com/kefranabg/readme-md-generator/issues/80)) [[6d5c884](https://github.com/kefranabg/readme-md-generator/commit/6d5c8848c476fc2770204f215ddd6f48d539b4e0)]
### Changed
- ⬆️ Update inquirer to the latest version ([#67](https://github.com/kefranabg/readme-md-generator/issues/67)) [[59f69e5](https://github.com/kefranabg/readme-md-generator/commit/59f69e51ec1caae17230d9331a2c14b04bd2825e)]
- ⬆️ Update eslint to the latest version ([#70](https://github.com/kefranabg/readme-md-generator/issues/70)) [[88c96ac](https://github.com/kefranabg/readme-md-generator/commit/88c96ac31acfa12381a33d39a2953f3405053870)]
- ♻️ Refactoring inquirer code ([#69](https://github.com/kefranabg/readme-md-generator/issues/69)) [[802d57d](https://github.com/kefranabg/readme-md-generator/commit/802d57d8af2e2cdcdbddea86c2fa2225db6d4516)]
<a name="0.4.1"></a>

@@ -24,3 +40,3 @@

- 📝 Update README [[0dff1e5](https://github.com/kefranabg/readme-md-generator/commit/0dff1e5562404559b2ad64ccf0c8fc3d1df73f92)]
- docs: add kefranabg as a contributor ([#57](https://github.com/kefranabg/readme-md-generator/issues/57)) [[e5d9d53](https://github.com/kefranabg/readme-md-generator/commit/e5d9d5376b8341e06005e497728935c2874631b6)]
- 📝 add kefranabg as a contributor ([#57](https://github.com/kefranabg/readme-md-generator/issues/57)) [[e5d9d53](https://github.com/kefranabg/readme-md-generator/commit/e5d9d5376b8341e06005e497728935c2874631b6)]
- 👥 Add contributors [[2533cd8](https://github.com/kefranabg/readme-md-generator/commit/2533cd8f2c8c78a043e67ca2bead9b4606606121)]

@@ -27,0 +43,0 @@

6

package.json
{
"name": "readme-md-generator",
"version": "0.4.1",
"version": "0.5.0",
"description": "CLI that generates beautiful README.md files.",

@@ -14,3 +14,3 @@ "main": "src/index.js",

"git-repo-name": "^1.0.1",
"inquirer": "~6.3.1",
"inquirer": "~6.4.1",
"load-json-file": "^6.0.0",

@@ -24,3 +24,3 @@ "lodash": "^4.17.11",

"codecov": "^3.5.0",
"eslint": "^5.3.0",
"eslint": "^6.0.0",
"eslint-config-airbnb-base": "^13.1.0",

@@ -27,0 +27,0 @@ "eslint-plugin-import": "^2.17.3",

@@ -8,7 +8,10 @@ <h1 align="center">Welcome to readme-md-generator 👋</h1>

<a href="https://github.com/kefranabg/readme-md-generator/blob/master/LICENSE">
<img alt="License: MIT" src="https://img.shields.io/badge/License-MIT-yellow.svg" target="_blank" />
<img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-yellow.svg" target="_blank" />
</a>
<a href="https://codecov.io/gh/kefranabg/readme-md-generator">
<img src="https://codecov.io/gh/kefranabg/readme-md-generator/branch/master/graph/badge.svg" />
</a>
</a>
<a href="https://github.com/frinyvonnick/gitmoji-changelog">
<img src="https://img.shields.io/badge/changelog-gitmoji-brightgreen.svg" alt="gitmoji-changelog">
</a>
<a href="https://twitter.com/FranckAbgrall">

@@ -26,3 +29,3 @@ <img alt="Twitter: FranckAbgrall" src="https://img.shields.io/twitter/follow/FranckAbgrall.svg?style=social" target="_blank" />

<p align="center">
<img width="700" align="center" src="https://user-images.githubusercontent.com/9840435/59459416-07f1e580-8e1d-11e9-89e7-6a5e6b373e93.gif" alt="demo"/>
<img width="700" align="center" src="https://user-images.githubusercontent.com/9840435/60266022-72a82400-98e7-11e9-9958-f9004c2f97e1.gif" alt="demo"/>
</p>

@@ -33,3 +36,3 @@

<p align="center">
<img width="700" src="https://user-images.githubusercontent.com/9840435/59458494-d7a94780-8e1a-11e9-9103-42639c347c38.jpg" alt="cli output"/>
<img width="700" src="https://user-images.githubusercontent.com/9840435/60266090-9cf9e180-98e7-11e9-9cac-3afeec349bbc.jpg" alt="cli output"/>
</p>

@@ -72,3 +75,3 @@

OR use default values for all questions (`-y, --yes`):
Or use default values for all questions (`-y`):

@@ -79,2 +82,10 @@ ```sh

Use your own `ejs` README template (`-p`):
```sh
npx readme-md-generator -p path/to/my/own/template.md
```
You can find [ejs README template examples here](https://github.com/kefranabg/readme-md-generator/tree/master/templates).
## 🤝 Contributing

@@ -97,2 +108,4 @@

<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>

@@ -99,0 +112,0 @@ </table>

@@ -1,72 +0,29 @@

const inquirer = require('inquirer')
const { isNil } = require('lodash')
const readme = require('./readme')
const projectInfos = require('./project-infos')
const questionsBuilders = require('./questions')
const infos = require('./project-infos')
const utils = require('./utils')
const askQuestions = require('./ask-questions')
/**
* Ask user questions and return context to generate a README
*
* @param {Object} projectInfos
*/
const askQuestions = async (projectInfos, skipQuestions) => {
let answersContext = {
isGithubRepos: projectInfos.isGithubRepos,
repositoryUrl: projectInfos.repositoryUrl,
projectPrerequisites: undefined
}
for (const questionBuilder of Object.values(questionsBuilders)) {
const question = questionBuilder(projectInfos, answersContext)
if (!isNil(question)) {
const currentAnswerContext = skipQuestions
? { [question.name]: getDefaultAnswer(question) }
: await inquirer.prompt([question])
answersContext = {
...answersContext,
...currentAnswerContext
}
}
}
return answersContext
}
/**
* Get the default answer depending on the question type
*
* @param {Object} question
*/
const getDefaultAnswer = question => {
switch (question.type) {
case 'input':
return question.default || ''
case 'checkbox':
return question.choices
.filter(choice => choice.checked)
.map(choice => choice.value)
default:
return undefined
}
}
/**
* Main process:
* 1) Gather project infos
* 2) Ask user questions
* 3) Build README content
* 4) Create README.md file
* 1) Get README template path
* 2) Gather project infos
* 3) Ask user questions
* 4) Build README content
* 5) Create README.md file
*
* @param {Object} args
*/
const mainProcess = async ({ template, yes }) => {
const projectInformations = await projectInfos.getProjectInfos()
const answersContext = await cli.askQuestions(projectInformations, yes)
module.exports = async ({ customTemplatePath, useDefaultAnswers }) => {
const templatePath = await readme.getReadmeTemplatePath(
customTemplatePath,
useDefaultAnswers
)
const projectInformations = await infos.getProjectInfos()
const answersContext = await askQuestions(
projectInformations,
useDefaultAnswers
)
const readmeContent = await readme.buildReadmeContent(
answersContext,
template
templatePath
)

@@ -78,9 +35,1 @@

}
const cli = {
mainProcess,
getDefaultAnswer,
askQuestions
}
module.exports = cli
const inquirer = require('inquirer')
const cli = require('./cli')
const projectInfos = require('./project-infos')
const mainProcess = require('./cli')
const infos = require('./project-infos')
const readme = require('./readme')
const utils = require('./utils')
const questions = require('./questions')
const askQuestions = require('./ask-questions')
const realAskQuestions = cli.askQuestions
inquirer.prompt = jest.fn(items =>
Promise.resolve(
items.reduce((result, item) => {
result[item.name] = 'value'
return result
}, {})
)
)
inquirer.prompt = jest.fn(([question]) =>
Promise.resolve({ [question.name]: 'value' })
jest.mock('./ask-questions', () =>
jest.fn(() => Promise.resolve({ projectName: 'readme-md-generator' }))
)

@@ -34,141 +41,40 @@

describe('cli', () => {
beforeEach(() => {
inquirer.prompt.mockClear()
describe('mainProcess', () => {
afterEach(() => {
askQuestions.mockClear()
})
describe('mainProcess', () => {
const answersContext = { projectName: 'readme-md-generator' }
it('should call main functions with correct args', async () => {
const customTemplatePath = undefined
const useDefaultAnswers = true
const projectInformations = { name: 'readme-md-generator' }
const readmeContent = 'content'
const templatePath = 'path/to/template'
infos.getProjectInfos = jest.fn(() => Promise.resolve(projectInformations))
readme.buildReadmeContent = jest.fn(() => Promise.resolve(readmeContent))
readme.getReadmeTemplatePath = jest.fn(() => Promise.resolve(templatePath))
readme.writeReadme = jest.fn()
utils.showEndMessage = jest.fn()
beforeAll(() => {
cli.askQuestions = jest.fn(() => Promise.resolve(answersContext))
})
await mainProcess({ customTemplatePath, useDefaultAnswers })
afterEach(() => {
cli.askQuestions.mockClear()
})
afterAll(() => {
cli.askQuestions = realAskQuestions
})
it('should call main functions with correct args', async () => {
const template = 'default'
const projectInformations = { name: 'readme-md-generator' }
const readmeContent = 'content'
projectInfos.getProjectInfos = jest.fn(() =>
Promise.resolve(projectInformations)
)
readme.buildReadmeContent = jest.fn(() => Promise.resolve(readmeContent))
readme.writeReadme = jest.fn()
utils.showEndMessage = jest.fn()
await cli.mainProcess({ template })
expect(projectInfos.getProjectInfos).toHaveBeenCalledTimes(1)
expect(cli.askQuestions).toHaveBeenNthCalledWith(
1,
projectInformations,
undefined
)
expect(readme.buildReadmeContent).toHaveBeenNthCalledWith(
1,
answersContext,
template
)
expect(readme.writeReadme).toHaveBeenNthCalledWith(1, readmeContent)
expect(utils.showEndMessage).toHaveBeenCalledTimes(1)
})
it('should forward --yes option to askQuestions', async () => {
const template = 'default'
const projectInformations = { name: 'readme-md-generator' }
const skipQuestions = true
utils.showEndMessage = jest.fn()
await cli.mainProcess({ template, yes: skipQuestions })
expect(cli.askQuestions).toHaveBeenNthCalledWith(
1,
projectInformations,
skipQuestions
)
})
expect(readme.getReadmeTemplatePath).toHaveBeenNthCalledWith(
1,
customTemplatePath,
useDefaultAnswers
)
expect(infos.getProjectInfos).toHaveBeenCalledTimes(1)
expect(askQuestions).toHaveBeenNthCalledWith(
1,
projectInformations,
useDefaultAnswers
)
expect(readme.buildReadmeContent).toHaveBeenNthCalledWith(
1,
{ projectName: 'readme-md-generator' },
templatePath
)
expect(readme.writeReadme).toHaveBeenNthCalledWith(1, readmeContent)
expect(utils.showEndMessage).toHaveBeenCalledTimes(1)
})
describe('getDefaultAnswer', () => {
it('should handle input prompts correctly', () => {
const question = { type: 'input', default: 'default' }
const result = cli.getDefaultAnswer(question)
expect(result).toEqual(question.default)
})
it('should handle choices prompts correctly', () => {
const value = { name: 'name', value: 'value' }
const question = {
type: 'checkbox',
choices: [{ value, checked: true }, { checked: false }]
}
const result = cli.getDefaultAnswer(question)
expect(result).toEqual([value])
})
it('should return empty string for non-defaulted fields', () => {
const question = { type: 'input' }
const result = cli.getDefaultAnswer(question)
expect(result).toEqual('')
})
it('should return undefined for invalid types', () => {
const question = { type: 'invalid' }
const result = cli.getDefaultAnswer(question)
expect(result).toEqual(undefined)
})
})
describe('askQuestions', () => {
it('should call all builder functions exported by questions', async () => {
const projectInfos = { name: 'readme-md-generator' }
await cli.askQuestions(projectInfos)
expect(questions.askProjectName).toHaveBeenCalledTimes(1)
expect(questions.askProjectVersion).toHaveBeenCalledTimes(1)
expect(questions.askProjectDescription).toHaveBeenCalledTimes(1)
})
it('should use default values with --yes option', async () => {
const projectInfos = { name: 'readme-md-generator' }
const result = await cli.askQuestions(projectInfos, true)
expect(inquirer.prompt).not.toHaveBeenCalled()
expect(result).toEqual({
projectName: 'defaultProjectName',
projectVersion: '',
projectDescription: [{ name: 'choiceOne', value: 1 }],
isGithubRepos: undefined,
repositoryUrl: undefined,
projectPrerequisites: undefined
})
})
it('should return merged contexts', async () => {
const projectInfos = { name: 'readme-md-generator' }
const context = await cli.askQuestions(projectInfos)
expect(context).toEqual({
projectName: 'value',
projectVersion: 'value',
projectDescription: 'value',
isGithubRepos: undefined,
repositoryUrl: undefined,
projectPrerequisites: undefined
})
})
})
})
#!/usr/bin/env node
const yargs = require('yargs')
const { noop } = require('lodash')
const { mainProcess } = require('./cli')
const mainProcess = require('./cli')
yargs
.usage('Usage: $0 <command> [options]')
.command(
'$0 [template]',
'Generate README.md from a template',
command =>
command.positional('template', {
desc: 'The name of template you want to use',
default: 'default'
}),
args => mainProcess(args)
)
.command('$0', 'Generate README.md', noop, args => {
const { path: customTemplatePath, yes: useDefaultAnswers } = args
mainProcess({ customTemplatePath, useDefaultAnswers })
})
.string('p')
.alias('p', 'path')
.describe('path', 'Path to your own template')
.boolean('yes')

@@ -20,0 +18,0 @@ .alias('y', 'yes')

@@ -99,2 +99,20 @@ const isNil = require('lodash/isNil')

/**
* Get project author name from package.json
*
* @param packageJson
* @returns {string} authorName
*/
const getAuthorName = packageJson => {
if (has(packageJson, 'author.name')) {
return get(packageJson, 'author.name', undefined)
}
if (has(packageJson, 'author') && typeof packageJson.author === 'string') {
return get(packageJson, 'author', undefined)
}
return undefined
}
/**
* Get project informations from git and package.json

@@ -109,3 +127,3 @@ */

const engines = get(packageJson, 'engines', undefined)
const author = get(packageJson, 'author', undefined)
const author = getAuthorName(packageJson)
const version = get(packageJson, 'version', undefined)

@@ -112,0 +130,0 @@ const licenseName = get(packageJson, 'license', undefined)

@@ -275,3 +275,59 @@ const ora = require('ora')

})
it('should return correct infos when author is defined as an object', async () => {
const packgeJsonInfos = {
name: 'readme-md-generator',
version: '0.1.3',
description: 'CLI that generates beautiful README.md files.',
author: {
name: 'Franck Abgrall',
email: 'abgrallkefran@gmail.com',
url: ''
},
license: 'MIT',
homepage: 'https://github.com/kefranabg/readme-md-generator',
repository: {
type: 'git',
url: 'git+https://github.com/kefranabg/readme-md-generator.git'
},
bugs: {
url: 'https://github.com/kefranabg/readme-md-generator/issues'
},
engines: {
npm: '>=5.5.0',
node: '>=9.3.0'
}
}
utils.getPackageJson.mockReturnValueOnce(Promise.resolve(packgeJsonInfos))
childProcess.execSync.mockReturnValue(
'https://github.com/kefranabg/readme-md-generator.git'
)
const projectInfos = await getProjectInfos()
expect(projectInfos).toEqual({
name: 'readme-md-generator',
description: 'CLI that generates beautiful README.md files.',
version: '0.1.3',
author: 'Franck Abgrall',
repositoryUrl: 'https://github.com/kefranabg/readme-md-generator',
homepage: 'https://github.com/kefranabg/readme-md-generator',
contributingUrl:
'https://github.com/kefranabg/readme-md-generator/issues',
githubUsername: 'kefranabg',
engines: {
npm: '>=5.5.0',
node: '>=9.3.0'
},
licenseName: 'MIT',
licenseUrl:
'https://github.com/kefranabg/readme-md-generator/blob/master/LICENSE',
documentationUrl:
'https://github.com/kefranabg/readme-md-generator#readme',
isGithubRepos: true,
usage: undefined,
testCommand: undefined
})
})
})
})

@@ -0,1 +1,2 @@

/* eslint-disable global-require */
module.exports = {

@@ -2,0 +3,0 @@ askProjectName: require('./project-name'),

const isEmpty = require('lodash/isEmpty')
module.exports = (projectInfos, answersContext) =>
isEmpty(answersContext.licenseName)
? undefined
: {
type: 'input',
message: '📝 License url (use empty value to skip)',
name: 'licenseUrl',
default: projectInfos.licenseUrl
}
module.exports = projectInfos => ({
type: 'input',
message: '📝 License url (use empty value to skip)',
name: 'licenseUrl',
default: projectInfos.licenseUrl,
when: answersContext => !isEmpty(answersContext.licenseName)
})

@@ -8,24 +8,40 @@ const askLicenseUrl = require('./license-url')

const projectInfos = { licenseUrl }
const result = askLicenseUrl(projectInfos)
expect(result).toEqual(
expect.objectContaining({
type: 'input',
message: '📝 License url (use empty value to skip)',
name: 'licenseUrl',
default: licenseUrl
})
)
})
it('should show this question if licenseName is defined', () => {
const projectInfos = {
licenseUrl:
'https://github.com/kefranabg/readme-md-generator/blob/master/LICENSE'
}
const answersContext = { licenseName: 'MIT' }
const result = askLicenseUrl(projectInfos, answersContext)
const question = askLicenseUrl(projectInfos)
const result = question.when(answersContext)
expect(result).toEqual({
type: 'input',
message: '📝 License url (use empty value to skip)',
name: 'licenseUrl',
default: licenseUrl
})
expect(result).toBe(true)
})
it('should return undefined', () => {
const licenseUrl =
'https://github.com/kefranabg/readme-md-generator/blob/master/LICENSE'
const projectInfos = { licenseUrl }
const answersContext = { licenseName: '' }
it('should not show this question if licenseName is not defined', () => {
const projectInfos = {
licenseUrl:
'https://github.com/kefranabg/readme-md-generator/blob/master/LICENSE'
}
const answersContext = {}
const result = askLicenseUrl(projectInfos, answersContext)
const question = askLicenseUrl(projectInfos)
const result = question.when(answersContext)
expect(result).toBe(undefined)
expect(result).toBe(false)
})
})

@@ -10,10 +10,12 @@ const isEmpty = require('lodash/isEmpty')

const buildFormattedChoices = engines =>
Object.keys(engines).map(key => ({
name: `${key} ${engines[key]}`,
value: {
name: key,
value: engines[key]
},
checked: true
}))
isNil(engines)
? null
: Object.keys(engines).map(key => ({
name: `${key} ${engines[key]}`,
value: {
name: key,
value: engines[key]
},
checked: true
}))

@@ -28,10 +30,8 @@ /**

module.exports = projectInfos =>
hasProjectInfosEngines(projectInfos)
? {
type: 'checkbox',
message: '⚠️ Project prerequisites',
name: 'projectPrerequisites',
choices: buildFormattedChoices(projectInfos.engines)
}
: undefined
module.exports = projectInfos => ({
type: 'checkbox',
message: '⚠️ Project prerequisites',
name: 'projectPrerequisites',
choices: buildFormattedChoices(projectInfos.engines),
when: () => hasProjectInfosEngines(projectInfos)
})

@@ -13,37 +13,53 @@ const askProjectPrerequisites = require('./project-prerequisites')

expect(result).toEqual({
type: 'checkbox',
message: '⚠️ Project prerequisites',
name: 'projectPrerequisites',
choices: [
{
checked: true,
name: 'npm >=5.5.0',
value: { name: 'npm', value: '>=5.5.0' }
},
{
checked: true,
name: 'node >= 9.3.0',
value: { name: 'node', value: '>= 9.3.0' }
}
]
})
expect(result).toEqual(
expect.objectContaining({
type: 'checkbox',
message: '⚠️ Project prerequisites',
name: 'projectPrerequisites',
choices: [
{
checked: true,
name: 'npm >=5.5.0',
value: { name: 'npm', value: '>=5.5.0' }
},
{
checked: true,
name: 'node >= 9.3.0',
value: { name: 'node', value: '>= 9.3.0' }
}
]
})
)
})
it('should return undefined when engines property is empty object', () => {
const engines = {}
const projectInfos = { engines }
it('should not show the question when engines property is empty object', () => {
const projectInfos = { engines: {} }
const result = askProjectPrerequisites(projectInfos)
const question = askProjectPrerequisites(projectInfos)
const result = question.when()
expect(result).toEqual(undefined)
expect(result).toEqual(false)
})
it('should return undefined when engines property is not defined', () => {
it('should not show the question when engines property is not defined', () => {
const projectInfos = {}
const result = askProjectPrerequisites(projectInfos)
const question = askProjectPrerequisites(projectInfos)
const result = question.when()
expect(result).toEqual(undefined)
expect(result).toEqual(false)
})
it('should show the question when engines property is defined and not empty', () => {
const projectInfos = {
engines: {
node: '>=10'
}
}
const question = askProjectPrerequisites(projectInfos)
const result = question.when()
expect(result).toEqual(true)
})
})
const ejs = require('ejs')
const path = require('path')
const ora = require('ora')

@@ -7,3 +6,6 @@ const { promisify } = require('util')

const fs = require('fs')
const { isNil } = require('lodash')
const chooseTemplate = require('./choose-template')
const README_PATH = 'README.md'

@@ -47,13 +49,9 @@

/**
* 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)

@@ -68,6 +66,41 @@

/**
* Validate template path
*
* @param {string} templatePath
*/
const validateReadmeTemplatePath = templatePath => {
const spinner = ora('Resolving README template path').start()
try {
fs.lstatSync(templatePath).isFile()
} catch (err) {
spinner.fail(`The template path '${templatePath}' is not valid.`)
throw err
}
spinner.succeed('README template path resolved')
}
/**
* Get readme template path
* (either a custom template, or a template that user will choose from prompt)
*
* @param {String} customTemplate
*/
const getReadmeTemplatePath = async (customTemplate, useDefaultAnswers) => {
const templatePath = isNil(customTemplate)
? await chooseTemplate(useDefaultAnswers)
: customTemplate
validateReadmeTemplatePath(templatePath)
return templatePath
}
module.exports = {
writeReadme,
buildReadmeContent,
README_PATH
README_PATH,
getReadmeTemplatePath
}
const fs = require('fs')
const ora = require('ora')
const path = require('path')
const chooseTemplate = require('./choose-template')
jest.mock('ora')
const defaultTemplatePath = path.resolve(__dirname, '../templates/default.md')
const defaultNoHtmlTemplatePath = path.resolve(
__dirname,
'../templates/default-no-html.md'
)
chooseTemplate.mockReturnValue(defaultTemplatePath)
const { writeReadme, buildReadmeContent, README_PATH } = require('./readme')
const {
writeReadme,
buildReadmeContent,
README_PATH,
getReadmeTemplatePath
} = require('./readme')

@@ -26,3 +38,3 @@ describe('readme', () => {

const readmeContent = 'content'
fs.writeFile = jest.fn((path, content, cb) => cb(null, 'done'))
fs.writeFile = jest.fn((_, __, cb) => cb(null, 'done'))

@@ -56,3 +68,3 @@ await writeReadme(readmeContent)

const readmeContent = 'content'
fs.writeFile = jest.fn((path, content, cb) => cb(null, 'done'))
fs.writeFile = jest.fn((_, __, cb) => cb(null, 'done'))

@@ -68,3 +80,2 @@ await writeReadme(readmeContent)

describe('buildReadmeContent', () => {
const templateName = 'default'
const context = {

@@ -104,3 +115,3 @@ isGithubRepos: true,

it('should call ora with correct parameters in success case', async () => {
await buildReadmeContent(context, templateName)
await buildReadmeContent(context, defaultTemplatePath)

@@ -113,4 +124,4 @@ expect(ora).toHaveBeenCalledTimes(1)

it('should return readme template content', async () => {
const result = await buildReadmeContent(context, templateName)
it('should return readme default template content', async () => {
const result = await buildReadmeContent(context, defaultTemplatePath)

@@ -120,2 +131,11 @@ expect(result).toMatchSnapshot()

it('should return readme default template no html content', async () => {
const result = await buildReadmeContent(
context,
defaultNoHtmlTemplatePath
)
expect(result).toMatchSnapshot()
})
it('should call ora with correct parameters in fail case', async () => {

@@ -127,3 +147,3 @@ fs.readFile = jest.fn(() => {

try {
await buildReadmeContent(context, templateName)
await buildReadmeContent(context, defaultTemplatePath)
// eslint-disable-next-line no-empty

@@ -138,2 +158,61 @@ } catch (err) {}

})
describe('getReadmeTemplatePath', () => {
it('should return template that user has selected', async () => {
const useDefaultAnswers = false
const actualResult = await getReadmeTemplatePath(
undefined,
useDefaultAnswers
)
expect(actualResult).toEqual(defaultTemplatePath)
expect(chooseTemplate).toHaveBeenNthCalledWith(1, useDefaultAnswers)
})
it('should return custom template path if customTemplatePath is defined', async () => {
const customTemplatePath = defaultTemplatePath
const actualResult = await getReadmeTemplatePath(
customTemplatePath,
false
)
expect(actualResult).toEqual(customTemplatePath)
expect(chooseTemplate).not.toHaveBeenCalled()
})
it('should throw an error if customTemplate is defined but invalid', () => {
const wrongPath = 'wrong path'
expect(getReadmeTemplatePath(wrongPath, false)).rejects.toThrow()
})
it('should call ora with correct parameters in fail case', async () => {
const wrongPath = 'wrong path'
try {
await getReadmeTemplatePath(wrongPath, false)
// 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 () => {
await getReadmeTemplatePath(defaultTemplatePath, false)
expect(ora).toHaveBeenNthCalledWith(1, 'Resolving README template path')
expect(succeed).toHaveBeenNthCalledWith(
1,
'README template path resolved'
)
})
})
})
jest.mock('ora')
jest.mock('./choose-template')

@@ -27,6 +27,3 @@ const loadJsonFile = require('load-json-file')

*/
const getPackageJsonName = (packageJson = {}) => {
return packageJson.name || undefined
}
const getPackageJsonName = (packageJson = {}) => packageJson.name || undefined
/**

@@ -69,2 +66,36 @@ * Get git repository name

/**
* Get the default answer depending on the question type
*
* @param {Object} question
*/
const getDefaultAnswer = (question, answersContext) => {
if (question.when && !question.when(answersContext)) return undefined
switch (question.type) {
case 'input':
return question.default || ''
case 'checkbox':
return question.choices
.filter(choice => choice.checked)
.map(choice => choice.value)
default:
return undefined
}
}
/**
* Get default question's answers
*
* @param {Array} questions
*/
const getDefaultAnswers = questions =>
questions.reduce(
(answersContext, question) => ({
...answersContext,
[question.name]: getDefaultAnswer(question, answersContext)
}),
{}
)
module.exports = {

@@ -75,3 +106,5 @@ getPackageJson,

END_MSG,
BOXEN_CONFIG
BOXEN_CONFIG,
getDefaultAnswers,
getDefaultAnswer
}

@@ -5,2 +5,3 @@ const loadJsonFile = require('load-json-file')

const getReposName = require('git-repo-name')
const { isNil } = require('lodash')

@@ -15,3 +16,5 @@ const realPathBasename = path.basename

END_MSG,
BOXEN_CONFIG
BOXEN_CONFIG,
getDefaultAnswer,
getDefaultAnswers
} = require('./utils')

@@ -115,2 +118,84 @@

})
describe('getDefaultAnswer', () => {
it('should handle input prompts correctly', () => {
const question = { type: 'input', default: 'default' }
const result = getDefaultAnswer(question)
expect(result).toEqual(question.default)
})
it('should handle choices prompts correctly', () => {
const value = { name: 'name', value: 'value' }
const question = {
type: 'checkbox',
choices: [{ value, checked: true }, { checked: false }]
}
const result = getDefaultAnswer(question)
expect(result).toEqual([value])
})
it('should return empty string for non-defaulted fields', () => {
const question = { type: 'input' }
const result = getDefaultAnswer(question)
expect(result).toEqual('')
})
it('should return undefined for invalid types', () => {
const question = { type: 'invalid' }
const result = getDefaultAnswer(question)
expect(result).toEqual(undefined)
})
it('should return undefined if when function is defined and return false', () => {
const answersContext = {}
const question = {
type: 'input',
when: ansewersContext => !isNil(ansewersContext.licenseUrl)
}
const result = getDefaultAnswer(question, answersContext)
expect(result).toEqual(undefined)
})
it('should return correct value if when function is defined and return true', () => {
const answersContext = { licenseUrl: 'licenseUrl' }
const question = {
type: 'input',
default: 'default',
when: ansewersContext => !isNil(ansewersContext.licenseUrl)
}
const result = getDefaultAnswer(question, answersContext)
expect(result).toEqual('default')
})
})
describe('getDefaultAnswers', () => {
it('should return default answers from questions', () => {
const questions = [
{
type: 'input',
name: 'questionOne',
default: 'answer 1'
},
{
type: 'input',
name: 'questionTwo',
default: 'answer 2'
}
]
const result = getDefaultAnswers(questions)
expect(result).toEqual({
questionOne: 'answer 1',
questionTwo: 'answer 2'
})
})
})
})

@@ -40,3 +40,3 @@ <h1 align="center">Welcome to <%= projectName %> 👋</h1>

<% } -%>
<% if (projectPrerequisites) { -%>
<% if (projectPrerequisites && projectPrerequisites.length) { -%>

@@ -43,0 +43,0 @@ ## Prerequisites

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc