diff --git a/.all-contributorsrc b/.all-contributorsrc index 54be8e19..3bb30256 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1,10 +1,11 @@ { "projectOwner": "all-contributors", - "projectName": "all-contributors-cli", + "projectName": "cli", "imageSize": 100, "repoType": "github", "commit": false, "contributorsPerLine": 6, + "linkToUsage": true, "files": [ "README.md" ], @@ -549,6 +550,80 @@ "contributions": [ "code" ] + }, + { + "login": "SirWindfield", + "name": "SirWindfield", + "avatar_url": "https://avatars.githubusercontent.com/u/5113257?v=4", + "profile": "https://github.com/SirWindfield", + "contributions": [ + "code" + ] + }, + { + "login": "vapurrmaid", + "name": "G r e y", + "avatar_url": "https://avatars.githubusercontent.com/u/11184711?v=4", + "profile": "https://vapurrmaid.ca", + "contributions": [ + "security" + ] + }, + { + "login": "Lucas-C", + "name": "Lucas Cimon", + "avatar_url": "https://avatars.githubusercontent.com/u/925560?v=4", + "profile": "https://chezsoi.org/lucas/blog/", + "contributions": [ + "doc" + ] + }, + { + "login": "JoshuaKGoldberg", + "name": "Josh Goldberg", + "avatar_url": "https://avatars.githubusercontent.com/u/3335181?v=4", + "profile": "http://www.joshuakgoldberg.com", + "contributions": [ + "bug" + ] + }, + { + "login": "tenshiAMD", + "name": "Angel Aviel Domaoan", + "avatar_url": "https://avatars.githubusercontent.com/u/13580338?v=4", + "profile": "https://tenshiamd.com", + "contributions": [ + "code", + "review", + "doc", + "test" + ] + }, + { + "login": "12rambau", + "name": "Rambaud Pierrick", + "avatar_url": "https://avatars.githubusercontent.com/u/12596392?v=4", + "profile": "https://12rambau.github.io/web-resume/", + "contributions": [ + "code" + ] + }, + { + "login": "klieret", + "name": "Kilian Lieret", + "avatar_url": "https://avatars.githubusercontent.com/u/13602468?v=4", + "profile": "https://www.lieret.net", + "contributions": [ + "bug" + ] + }, + "login": "KnorpelSenf", + "name": "KnorpelSenf", + "avatar_url": "https://avatars.githubusercontent.com/u/12952387?v=4", + "profile": "https://github.com/KnorpelSenf", + "contributions": [ + "bug" + ] } ], "skipCi": true diff --git a/.circleci/config.yml b/.circleci/config.yml index 009ab1e2..ceb88c74 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2,7 +2,7 @@ version: 2.1 docker_defaults: &docker_defaults docker: - - image: circleci/node:12.14.0 + - image: cimg/node:16.17.0 commands: prep_env: diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..03b83160 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @all-contributors/core diff --git a/.nvmrc b/.nvmrc index 65d83ce5..2a4e4ab8 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -12.14.0 +16.17.0 diff --git a/README.md b/README.md index 48cb0bd5..ff9d50b8 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,10 @@ -- [ all-contributors-cli ](#all-contributors-cli) + +- [ + all-contributors-cli +](#all-contributors-cli) - [The problem](#the-problem) - [This solution](#this-solution) - [Using the all-contributors-cli](#using-the-all-contributors-cli) @@ -43,8 +46,8 @@ -[![Build Status](https://img.shields.io/circleci/project/all-contributors/all-contributors-cli/master.svg)](https://circleci.com/gh/all-contributors/workflows/all-contributors-cli/tree/master) -[![Code Coverage](https://img.shields.io/codecov/c/github/all-contributors/all-contributors-cli.svg)](https://codecov.io/github/all-contributors/all-contributors-cli) +[![Build Status](https://dl.circleci.com/status-badge/img/gh/all-contributors/cli/tree/master.svg?style=svg)](https://dl.circleci.com/status-badge/redirect/gh/all-contributors/cli/tree/master) +[![Code Coverage](https://codecov.io/gh/all-contributors/cli/branch/master/graph/badge.svg?token=jHIrCqevli)](https://codecov.io/gh/all-contributors/cli) [![Version](https://img.shields.io/npm/v/all-contributors-cli.svg)](https://www.npmjs.com/package/all-contributors-cli) [![Downloads](https://img.shields.io/npm/dm/all-contributors-cli.svg)](http://www.npmtrends.com/all-contributors-cli) [![AUR Version](https://img.shields.io/aur/version/all-contributors-cli.svg)](https://aur.archlinux.org/packages/all-contributors-cli) @@ -79,86 +82,108 @@ Thanks goes to these wonderful people - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Jeroen Engels

πŸ’» πŸ“– ⚠️

Kent C. Dodds

πŸ“– πŸ’»

JoΓ£o GuimarΓ£es

πŸ’»

Ben Briggs

πŸ’»

Itai Steinherz

πŸ“– πŸ’»

Alex Jover

πŸ’» πŸ“–

Jerod Santo

πŸ’»

Kevin Jalbert

πŸ’»

tunnckoCore

πŸ”§

Mehdi Achour

πŸ’»

Roy Revelt

πŸ›

Chris Vickery

πŸ’»

Bryce Reynolds

πŸ’»

James, please

πŸ€” πŸ’»

Spyros Ioakeimidis

πŸ’»

Fernando Costa

πŸ’»

snipe

πŸ“–

Gant Laborde

πŸ’»

Md Zubair Ahmed

πŸ“– πŸ› πŸ’» ⚠️

Divjot Singh

πŸ“–

JoΓ£o Marques

πŸ’» πŸ“– πŸ€”

Andrew Lisowski

πŸ’» πŸ“– ⚠️

Xianming Zhong

πŸ“–

C.Y.Xu

πŸ’»

Dura

πŸ“–

Jake Bolam

πŸš‡ πŸ’» πŸ“– ⚠️ πŸ‘€ πŸ’¬

Maximilian Berkmann

πŸ’» ⚠️ πŸ“– πŸ”§ 🚧 πŸ‘€ πŸ’¬

tbenning

🎨

ehmicky

πŸ’»

James George

πŸ’»

Nick Schonning

πŸ’»

Cezar Augusto

πŸ“–

Jeppe Reinhold

πŸ’»

Rachel M. Carmena

πŸ’»

simon3000

⚠️

SnOβ‚‚WMaN

πŸ’»

Fabrizio

πŸ› πŸ’»

kharaone

πŸ’»

Marcelo Alves

πŸ’» ⚠️

Anand Chowdhary

⚠️ πŸ› πŸ’»

Nicolas Goutay

πŸ’»

Tyler Krupicka

πŸ’» ⚠️

Stefano Moia

πŸ’»

IlaΓ― Deutel

πŸ“¦

Justin Dalrymple

πŸ’»

Piotr StΔ™pniewski

πŸ› πŸ’» ⚠️

Gregor Martynus

πŸ‘€ πŸ’¬

Jeff Wen

πŸ‘€

PaweΕ‚ Kowalski

πŸ’»

Markus LΓΆning

πŸ’»

David Anson

πŸ›

Jeroen Claassens

πŸ’»

Erek Speed

πŸ’»

Shai Reznik

πŸ› πŸ’» ⚠️

Darek Kay

πŸ’» ⚠️

LaChapeliere

πŸ’»
Jeroen Engels
Jeroen Engels

πŸ’» πŸ“– ⚠️
Kent C. Dodds
Kent C. Dodds

πŸ“– πŸ’»
JoΓ£o GuimarΓ£es
JoΓ£o GuimarΓ£es

πŸ’»
Ben Briggs
Ben Briggs

πŸ’»
Itai Steinherz
Itai Steinherz

πŸ“– πŸ’»
Alex Jover
Alex Jover

πŸ’» πŸ“–
Jerod Santo
Jerod Santo

πŸ’»
Kevin Jalbert
Kevin Jalbert

πŸ’»
tunnckoCore
tunnckoCore

πŸ”§
Mehdi Achour
Mehdi Achour

πŸ’»
Roy Revelt
Roy Revelt

πŸ›
Chris Vickery
Chris Vickery

πŸ’»
Bryce Reynolds
Bryce Reynolds

πŸ’»
James, please
James, please

πŸ€” πŸ’»
Spyros Ioakeimidis
Spyros Ioakeimidis

πŸ’»
Fernando Costa
Fernando Costa

πŸ’»
snipe
snipe

πŸ“–
Gant Laborde
Gant Laborde

πŸ’»
Md Zubair Ahmed
Md Zubair Ahmed

πŸ“– πŸ› πŸ’» ⚠️
Divjot Singh
Divjot Singh

πŸ“–
JoΓ£o Marques
JoΓ£o Marques

πŸ’» πŸ“– πŸ€”
Andrew Lisowski
Andrew Lisowski

πŸ’» πŸ“– ⚠️
Xianming Zhong
Xianming Zhong

πŸ“–
C.Y.Xu
C.Y.Xu

πŸ’»
Dura
Dura

πŸ“–
Jake Bolam
Jake Bolam

πŸš‡ πŸ’» πŸ“– ⚠️ πŸ‘€ πŸ’¬
Maximilian Berkmann
Maximilian Berkmann

πŸ’» ⚠️ πŸ“– πŸ”§ 🚧 πŸ‘€ πŸ’¬
tbenning
tbenning

🎨
ehmicky
ehmicky

πŸ’»
James George
James George

πŸ’»
Nick Schonning
Nick Schonning

πŸ’»
Cezar Augusto
Cezar Augusto

πŸ“–
Jeppe Reinhold
Jeppe Reinhold

πŸ’»
Rachel M. Carmena
Rachel M. Carmena

πŸ’»
simon3000
simon3000

⚠️
SnOβ‚‚WMaN
SnOβ‚‚WMaN

πŸ’»
Fabrizio
Fabrizio

πŸ› πŸ’»
kharaone
kharaone

πŸ’»
Marcelo Alves
Marcelo Alves

πŸ’» ⚠️
Anand Chowdhary
Anand Chowdhary

⚠️ πŸ› πŸ’»
Nicolas Goutay
Nicolas Goutay

πŸ’»
Tyler Krupicka
Tyler Krupicka

πŸ’» ⚠️
Stefano Moia
Stefano Moia

πŸ’»
IlaΓ― Deutel
IlaΓ― Deutel

πŸ“¦
Justin Dalrymple
Justin Dalrymple

πŸ’»
Piotr StΔ™pniewski
Piotr StΔ™pniewski

πŸ› πŸ’» ⚠️
Gregor Martynus
Gregor Martynus

πŸ‘€ πŸ’¬
Jeff Wen
Jeff Wen

πŸ‘€
PaweΕ‚ Kowalski
PaweΕ‚ Kowalski

πŸ’»
Markus LΓΆning
Markus LΓΆning

πŸ’»
David Anson
David Anson

πŸ›
Jeroen Claassens
Jeroen Claassens

πŸ’»
Erek Speed
Erek Speed

πŸ’»
Shai Reznik
Shai Reznik

πŸ› πŸ’» ⚠️
Darek Kay
Darek Kay

πŸ’» ⚠️
LaChapeliere
LaChapeliere

πŸ’»
SirWindfield
SirWindfield

πŸ’»
G r e y
G r e y

πŸ›‘οΈ
Lucas Cimon
Lucas Cimon

πŸ“–
Josh Goldberg
Josh Goldberg

πŸ›
Angel Aviel Domaoan
Angel Aviel Domaoan

πŸ’» πŸ‘€ πŸ“– ⚠️
Rambaud Pierrick
Rambaud Pierrick

πŸ’»
Kilian Lieret
Kilian Lieret

πŸ›
KnorpelSenf
KnorpelSenf

πŸ›
+ + Add your contributions + +
- + + This project follows the diff --git a/assets/logo-small.svg b/assets/logo-small.svg new file mode 100644 index 00000000..b8e512af --- /dev/null +++ b/assets/logo-small.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/other/MAINTAINING.md b/other/MAINTAINING.md index 5232261b..a31d2adf 100644 --- a/other/MAINTAINING.md +++ b/other/MAINTAINING.md @@ -41,8 +41,8 @@ as you want/need to. Nobody can ask any more of you than that. As a maintainer, you're fine to make your branches on the main repo or on your own fork. Either way is fine. -When we receive a pull request, a travis build is kicked off automatically (see the `.travis.yml` -for what runs in the travis build). We avoid merging anything that breaks the travis build. +When we receive a pull request, a Circle CI build is kicked off automatically (see the `.circleci/` +directory for what runs in the CI pipeline). We avoid merging anything that breaks the CI pipeline. Please review PRs and focus on the code rather than the individual. You never know when this is someone's first ever PR and we want their experience to be as positive as possible, so be @@ -56,8 +56,8 @@ about that. ## Release -Our releases are automatic. They happen whenever code lands into `master`. A travis build gets -kicked off and if it's successful, a tool called +Our releases are automatic. They happen whenever code lands into `master`. A Circle CI build +build gets kicked off and if it's successful, a tool called [`semantic-release`](https://github.com/semantic-release/semantic-release) is used to automatically publish a new release to npm as well as a changelog to GitHub. It is only able to determine the version and whether a release is necessary by the git commit messages. With this diff --git a/package.json b/package.json index 1f2364dd..5ff44f18 100644 --- a/package.json +++ b/package.json @@ -43,20 +43,20 @@ "homepage": "https://github.com/all-contributors/all-contributors-cli#readme", "dependencies": { "@babel/runtime": "^7.7.6", - "async": "^3.0.1", + "async": "^3.1.0", "chalk": "^4.0.0", "didyoumean": "^1.2.1", - "inquirer": "^7.0.4", - "json-fixer": "^1.5.1", + "inquirer": "^7.3.3", + "json-fixer": "^1.6.8", "lodash": "^4.11.2", "node-fetch": "^2.6.0", "pify": "^5.0.0", "yargs": "^15.0.1" }, "devDependencies": { - "codecov": "^3.1.0", - "cz-conventional-changelog": "^3.0.0", - "git-cz": "^4.1.0", + "codecov": "^3.8.1", + "cz-conventional-changelog": "^3.3.0", + "git-cz": "^4.7.6", "kcd-scripts": "^6.2.0", "nock": "^12.0.0", "semantic-release": "^17.0.8" diff --git a/src/cli.js b/src/cli.js index 4d356819..1c52e969 100755 --- a/src/cli.js +++ b/src/cli.js @@ -16,22 +16,18 @@ const cwd = process.cwd() const defaultRCFile = path.join(cwd, '.all-contributorsrc') const yargv = yargs + .scriptName('all-contributors') .help('help') .alias('h', 'help') .alias('v', 'version') .version() .recommendCommands() - .command('generate', 'Generate the list of contributors') - .usage('Usage: $0 generate') - .command('add', 'add a new contributor') - .usage('Usage: $0 add ') - .command('init', 'Prepare the project to be used with this tool') - .usage('Usage: $0 init') + .command('generate', `Generate the list of contributors\n\nUSAGE: all-contributors generate`) + .command('add', `Add a new contributor\n\nUSAGE: all-contributors add `) + .command('init', `Prepare the project to be used with this tool\n\nUSAGE: all-contributors init`) .command( 'check', - 'Compares contributors from the repository with the ones credited in .all-contributorsrc', - ) - .usage('Usage: $0 check') + `Compare contributors from the repository with the ones credited in .all-contributorsrc'\n\nUSAGE: all-contributors check`) .boolean('commit') .default('files', ['README.md']) .default('contributorsPerLine', 7) @@ -129,7 +125,7 @@ function checkContributors(argv) { function onError(error) { if (error) { - console.error(error.message) + console.error(error.stack || error.message || error) process.exit(1) } process.exit(0) diff --git a/src/generate/__tests__/__snapshots__/index.js.snap b/src/generate/__tests__/__snapshots__/index.js.snap index 52a0eeb3..b8f576ac 100644 --- a/src/generate/__tests__/__snapshots__/index.js.snap +++ b/src/generate/__tests__/__snapshots__/index.js.snap @@ -11,11 +11,78 @@ These people contributed to the project: - - - - - + + + + + + + +
Kent C. Dodds is awesome!Divjot Singh is awesome!Jeroen Engels is awesome!
Kent C. Dodds is awesome!Divjot Singh is awesome!Jeroen Engels is awesome!
+ + + + + + +Thanks a lot everyone!" +`; + +exports[`replace the content between the ALL-CONTRIBUTORS-LIST tags by a table of contributors with linkToUsage 1`] = ` +"# project + +Description + +## Contributors +These people contributed to the project: + + + + + + + + + + + + + + + + +
Kent C. Dodds is awesome!Divjot Singh is awesome!Jeroen Engels is awesome!
+ + Add your contributions + +
+ + + + + + +Thanks a lot everyone!" +`; + +exports[`replace the content between the ALL-CONTRIBUTORS-LIST tags by a table of contributors without linkToUsage 1`] = ` +"# project + +Description + +## Contributors +These people contributed to the project: + + + + + + + + + + +
Kent C. Dodds is awesome!Divjot Singh is awesome!Jeroen Engels is awesome!
@@ -37,17 +104,90 @@ These people contributed to the project: - - - - - - - - - - - + + + + + + + + + + + + + +
Kent C. Dodds is awesome!Kent C. Dodds is awesome!Kent C. Dodds is awesome!Kent C. Dodds is awesome!Kent C. Dodds is awesome!
Kent C. Dodds is awesome!Kent C. Dodds is awesome!
Kent C. Dodds is awesome!Kent C. Dodds is awesome!Kent C. Dodds is awesome!Kent C. Dodds is awesome!Kent C. Dodds is awesome!
Kent C. Dodds is awesome!Kent C. Dodds is awesome!
+ + + + + + +Thanks a lot everyone!" +`; + +exports[`split contributors into multiples lines when there are too many with linkToUsage 1`] = ` +"# project + +Description + +## Contributors +These people contributed to the project: + + + + + + + + + + + + + + + + + + + + + + +
Kent C. Dodds is awesome!Kent C. Dodds is awesome!Kent C. Dodds is awesome!Kent C. Dodds is awesome!Kent C. Dodds is awesome!
Kent C. Dodds is awesome!Kent C. Dodds is awesome!
+ + Add your contributions + +
+ + + + + + +Thanks a lot everyone!" +`; + +exports[`validate if cell width attribute is floored correctly 1`] = ` +"# project + +Description + +## Contributors +These people contributed to the project: + + + + + + + + + + +
Kent C. Dodds is awesome!Kent C. Dodds is awesome!Kent C. Dodds is awesome!
diff --git a/src/generate/__tests__/fixtures/contributors.json b/src/generate/__tests__/fixtures/contributors.json index 7872bd3b..7ede43c1 100644 --- a/src/generate/__tests__/fixtures/contributors.json +++ b/src/generate/__tests__/fixtures/contributors.json @@ -25,6 +25,11 @@ "avatar_url": "https://avatars1.githubusercontent.com/u/1500684", "contributions": ["translation"] }, + "nocompletename": { + "login": "nocompletename", + "avatar_url": "https://avatars1.githubusercontent.com/u/1500684", + "contributions": ["translation"] + }, "nologin_badrole": { "name": "Wildly Misconfigured", "avatar_url": "https://avatars1.githubusercontent.com/u/1500684", diff --git a/src/generate/__tests__/format-contributor.js b/src/generate/__tests__/format-contributor.js index bb3451ec..c158cb39 100644 --- a/src/generate/__tests__/format-contributor.js +++ b/src/generate/__tests__/format-contributor.js @@ -20,7 +20,7 @@ test('format a simple contributor', () => { const {options} = fixtures() const expected = - '
Kent C. Dodds

πŸ‘€' + 'Kent C. Dodds
Kent C. Dodds

πŸ‘€' expect(formatContributor(options, contributor)).toBe(expected) }) @@ -30,7 +30,7 @@ test('format contributor with complex contribution types', () => { const {options} = fixtures() const expected = - '
Kent C. Dodds

πŸ“– πŸ‘€ πŸ’¬' + 'Kent C. Dodds
Kent C. Dodds

πŸ“– πŸ‘€ πŸ’¬' expect(formatContributor(options, contributor)).toBe(expected) }) @@ -53,7 +53,7 @@ test('default image size to 100', () => { delete options.imageSize const expected = - '
Kent C. Dodds

πŸ‘€' + 'Kent C. Dodds
Kent C. Dodds

πŸ‘€' expect(formatContributor(options, contributor)).toBe(expected) }) @@ -63,7 +63,7 @@ test('format contributor with pipes in their name', () => { const {options} = fixtures() const expected = - '
Who | Needs | Pipes?

πŸ“–' + 'Who | Needs | Pipes?
Who | Needs | Pipes?

πŸ“–' expect(formatContributor(options, contributor)).toBe(expected) }) @@ -73,7 +73,17 @@ test('format contributor with no GitHub account', () => { const {options} = fixtures() const expected = - '
No Github Account
🌍' + 'No Github Account
No Github Account
🌍' + + expect(formatContributor(options, contributor)).toBe(expected) +}) + +test('format contributor with no complete name', () => { + const contributor = contributors.nocompletename + const {options} = fixtures() + + const expected = + 'nocompletename
nocompletename
🌍' expect(formatContributor(options, contributor)).toBe(expected) }) diff --git a/src/generate/__tests__/index.js b/src/generate/__tests__/index.js index ece35d58..eeb285c2 100644 --- a/src/generate/__tests__/index.js +++ b/src/generate/__tests__/index.js @@ -43,6 +43,32 @@ test('replace the content between the ALL-CONTRIBUTORS-LIST tags by a table of c expect(result).toMatchSnapshot() }) +test('replace the content between the ALL-CONTRIBUTORS-LIST tags by a table of contributors with linkToUsage', () => { + const {kentcdodds, bogas04} = contributors + const {options, jfmengels, content} = fixtures() + const contributorList = [kentcdodds, bogas04, jfmengels] + const result = generate( + Object.assign(options, {linkToUsage: true}), + contributorList, + content, + ) + + expect(result).toMatchSnapshot() +}) + +test('replace the content between the ALL-CONTRIBUTORS-LIST tags by a table of contributors without linkToUsage', () => { + const {kentcdodds, bogas04} = contributors + const {options, jfmengels, content} = fixtures() + const contributorList = [kentcdodds, bogas04, jfmengels] + const result = generate( + Object.assign(options, {linkToUsage: false}), + contributorList, + content, + ) + + expect(result).toMatchSnapshot() +}) + test('split contributors into multiples lines when there are too many', () => { const {kentcdodds} = contributors const {options, content} = fixtures() @@ -60,6 +86,27 @@ test('split contributors into multiples lines when there are too many', () => { expect(result).toMatchSnapshot() }) +test('split contributors into multiples lines when there are too many with linkToUsage', () => { + const {kentcdodds} = contributors + const {options, content} = fixtures() + const contributorList = [ + kentcdodds, + kentcdodds, + kentcdodds, + kentcdodds, + kentcdodds, + kentcdodds, + kentcdodds, + ] + const result = generate( + Object.assign(options, {linkToUsage: true}), + contributorList, + content, + ) + + expect(result).toMatchSnapshot() +}) + test('sorts the list of contributors if contributorsSortAlphabetically=true', () => { const {kentcdodds, bogas04} = contributors const {options, jfmengels, content} = fixtures() @@ -191,3 +238,18 @@ test('replace all-contributors badge if present', () => { expect(result).toBe(expected) }) + +test('validate if cell width attribute is floored correctly', () => { + const {kentcdodds} = contributors + const {options, content} = fixtures() + const contributorList = [ + kentcdodds, + kentcdodds, + kentcdodds, + ] + + options.contributorsPerLine = 7 + const result = generate(options, contributorList, content) + + expect(result).toMatchSnapshot() +}) diff --git a/src/generate/format-contributor.js b/src/generate/format-contributor.js index 048d63db..9f489f40 100644 --- a/src/generate/format-contributor.js +++ b/src/generate/format-contributor.js @@ -2,7 +2,7 @@ const _ = require('lodash/fp') const formatContributionType = require('./format-contribution-type') const avatarTemplate = _.template( - '', + '<%= name %>', ) const avatarBlockTemplate = _.template( '<%= avatar %>
<%= name %>
', @@ -17,7 +17,9 @@ const contributorTemplate = _.template( const defaultImageSize = 100 function defaultTemplate(templateData) { - const name = escapeName(templateData.contributor.name) + const rawName = + templateData.contributor.name || templateData.contributor.login + const name = escapeName(rawName) const avatar = avatarTemplate( _.assign(templateData, { name, diff --git a/src/generate/index.js b/src/generate/index.js index cacc21e6..11eaedb0 100644 --- a/src/generate/index.js +++ b/src/generate/index.js @@ -1,9 +1,10 @@ const _ = require('lodash/fp') +const floor = require('lodash/floor') const formatBadge = require('./format-badge') const formatContributor = require('./format-contributor') function injectListBetweenTags(newContent) { - return function(previousContent) { + return function (previousContent) { const tagToLookFor = `' const startOfOpeningTagIndex = previousContent.indexOf( @@ -24,11 +25,17 @@ function injectListBetweenTags(newContent) { ) { return previousContent } + const startIndent = Math.max( + 0, + previousContent.lastIndexOf('\n', startOfOpeningTagIndex), + ) + const nbSpaces = + startOfOpeningTagIndex - Math.min(startOfOpeningTagIndex, startIndent) return [ previousContent.slice(0, endOfOpeningTagIndex + closingTag.length), '\n', '\n', - newContent, + newContent.replace('\n', `\n${' '.repeat(nbSpaces - 1)}`), '', '\n', '\n\n', @@ -37,13 +44,30 @@ function injectListBetweenTags(newContent) { } } -function formatLine(contributors) { - return `${contributors.join( - '\n ', +function formatLine(options, contributors) { + const width = floor(_.divide(100)(options.contributorsPerLine), 2) + const attributes = `align="center" valign="top" width="${width}%"` + + return `${contributors.join( + `\n `, )}` } +function formatFooter(options) { + if (!options.linkToUsage) { + return '' + } + const smallLogoURL = + 'https://raw.githubusercontent.com/all-contributors/all-contributors-cli/1b8533af435da9854653492b1327a23a4dbd0a10/assets/logo-small.svg' + const linkToBotAdd = 'https://all-contributors.js.org/docs/en/bot/usage' + + return `\n \n \n Add your contributions\n \n \n ` +} + function generateContributorsList(options, contributors) { + const tableFooter = formatFooter(options) + let tableFooterContent = '' + return _.flow( _.sortBy(contributor => { if (options.contributorsSortAlphabetically) { @@ -54,16 +78,21 @@ function generateContributorsList(options, contributors) { return formatContributor(options, contributor) }), _.chunk(options.contributorsPerLine), - _.map(formatLine), - _.join('\n \n \n '), + _.map((currentLineContributors) => formatLine( + options, currentLineContributors + )), + _.join('\n \n \n '), newContent => { - return `\n\n \n ${newContent}\n \n
\n\n` + if (options.linkToUsage) { + tableFooterContent = ` \n ${tableFooter}\n \n` + } + return `\n\n \n \n ${newContent}\n \n \n${tableFooterContent}
\n\n` }, )(contributors) } function replaceBadge(newContent) { - return function(previousContent) { + return function (previousContent) { const tagToLookFor = `' const startOfOpeningTagIndex = previousContent.indexOf( @@ -84,10 +113,16 @@ function replaceBadge(newContent) { ) { return previousContent } + const startIndent = Math.max( + 0, + previousContent.lastIndexOf('\n', startOfOpeningTagIndex), + ) + const nbSpaces = + startOfOpeningTagIndex - Math.min(startOfOpeningTagIndex, startIndent) return [ previousContent.slice(0, endOfOpeningTagIndex + closingTag.length), '\n', - newContent, + newContent.replace('\n', `\n${' '.repeat(nbSpaces)}`), '\n', previousContent.slice(startOfClosingTagIndex), ].join('') diff --git a/src/init/prompt.js b/src/init/prompt.js index 87446a54..c67fd8c3 100644 --- a/src/init/prompt.js +++ b/src/init/prompt.js @@ -35,7 +35,7 @@ const questions = [ name: 'repoHost', message: "Where is the repository hosted? Hit Enter if it's on GitHub or GitLab", - default: function(answers) { + default: function (answers) { if (answers.repoType === 'github') { return 'https://github.com' } else if (answers.repoType === 'gitlab') { @@ -58,10 +58,10 @@ const questions = [ type: 'input', name: 'badgeFile', message: 'In which file should the badge be shown?', - when: function(answers) { + when: function (answers) { return answers.needBadge }, - default: function(answers) { + default: function (answers) { return answers.contributorFile }, }, @@ -84,14 +84,17 @@ const questions = [ name: 'commitConvention', message: 'What commit convention would you want it to use?', choices: Object.values(conventions), - default: 'none', + default: 'angular', + }, + { + type: 'confirm', + name: 'linkToUsage', + message: 'Do you want to add a footer with link to usage?', + default: true, }, ] -const uniqueFiles = _.flow( - _.compact, - _.uniq, -) +const uniqueFiles = _.flow(_.compact, _.uniq) module.exports = function prompt() { return git @@ -116,6 +119,7 @@ module.exports = function prompt() { commitConvention: answers.commitConvention, contributors: [], contributorsPerLine: 7, + linkToUsage: answers.linkToUsage, }, contributorFile: answers.contributorFile, badgeFile: answers.badgeFile, diff --git a/src/repo/github.js b/src/repo/github.js index be671404..15261e63 100644 --- a/src/repo/github.js +++ b/src/repo/github.js @@ -45,7 +45,7 @@ function getNextLink(link) { return null } - return nextLink.split(';')[0].slice(1, -1) + return nextLink.split(';')[0].trim().slice(1, -1) } function getContributorsPage(githubUrl, optionalPrivateToken) { diff --git a/src/util/__tests__/url.js b/src/util/__tests__/url.js index 50ff6d4d..359775e9 100644 --- a/src/util/__tests__/url.js +++ b/src/util/__tests__/url.js @@ -1,49 +1,57 @@ -import url from '../url'; +import url from '../url' test(`Result of protocol validation should be true`, () => { - expect(url.isHttpProtocol('http:')).toBe(true) - expect(url.isHttpProtocol('https:')).toBe(true) + expect(url.isHttpProtocol('http:')).toBe(true) + expect(url.isHttpProtocol('https:')).toBe(true) }) test(`Result of protocol validation should be false`, () => { - expect(url.isHttpProtocol('ftp:')).toBe(false) + expect(url.isHttpProtocol('ftp:')).toBe(false) }) test(`Result of url validation should be true`, () => { - expect(url.isValidHttpUrl('https://api.github.com/users/octocat')).toBe(true) + expect(url.isValidHttpUrl('https://api.github.com/users/octocat')).toBe(true) }) test(`Result of url validation should be false when url uses wrong protocol`, () => { - expect(url.isValidHttpUrl('git://git@github.com:all-contributors/all-contributors-cli.git')).toBe(false) + expect( + url.isValidHttpUrl( + 'git://git@github.com:all-contributors/all-contributors-cli.git', + ), + ).toBe(false) }) test(`Result of url validation should be false when input isn't url`, () => { - expect(url.isValidHttpUrl('github-octocat')).toBe(false) + expect(url.isValidHttpUrl('github-octocat')).toBe(false) }) test(`Result of parsed url should be equal`, () => { - const input = 'https://api.github.com/users/octocat' - const expected = 'https://api.github.com/users/octocat' - expect(url.parseHttpUrl(input)).toBe(expected) + const input = 'https://api.github.com/users/octocat' + const expected = 'https://api.github.com/users/octocat' + expect(url.parseHttpUrl(input)).toBe(expected) }) test(`Result of parsed url without protocol should be equal`, () => { - const input = 'example.com' - const expected = 'http://example.com/' - expect(url.parseHttpUrl(input)).toBe(expected) + const input = 'example.com' + const expected = 'http://example.com/' + expect(url.parseHttpUrl(input)).toBe(expected) }) test(`Throw an error when parsed input isn't a string`, () => { - const input = 123 - expect(url.parseHttpUrl.bind(null, input)).toThrowError('input must be a string') + const input = 123 + expect(url.parseHttpUrl.bind(null, input)).toThrowError( + 'input must be a string', + ) }) test(`Throw an error when parsed url has wrong protocol`, () => { - const input = 'ftp://domain.xyz' - expect(url.parseHttpUrl.bind(null, input)).toThrowError('Provided URL has an invalid protocol') + const input = 'ftp://domain.xyz' + expect(url.parseHttpUrl.bind(null, input)).toThrowError( + 'Provided URL has an invalid protocol', + ) }) test(`Throw an error when parsed input isn't a URL`, () => { - const input = 'some string' - expect(url.parseHttpUrl.bind(null, input)).toThrowError('Invalid URL: http://some string') + const input = 'some string' + expect(url.parseHttpUrl.bind(null, input)).toThrowError('Invalid URL') }) diff --git a/src/util/config-file.js b/src/util/config-file.js index 912d95fb..fdcb154d 100644 --- a/src/util/config-file.js +++ b/src/util/config-file.js @@ -10,7 +10,7 @@ function readConfig(configPath) { config.repoType = 'github' } if (!('commitConvention' in config)) { - config.commitConvention = 'none' + config.commitConvention = 'angular' } if (changed) { //Updates the file with fixes @@ -20,9 +20,7 @@ function readConfig(configPath) { } catch (error) { if (error instanceof SyntaxError) { throw new SyntaxError( - `Configuration file has malformed JSON: ${configPath}. Error:: ${ - error.message - }`, + `Configuration file has malformed JSON: ${configPath}. Error:: ${error.message}`, ) } if (error.code === 'ENOENT') { diff --git a/src/util/contribution-types.js b/src/util/contribution-types.js index 98073263..9d0a3c50 100644 --- a/src/util/contribution-types.js +++ b/src/util/contribution-types.js @@ -1,7 +1,7 @@ const _ = require('lodash/fp') const repo = require('../repo') -const defaultTypes = function(repoType) { +const defaultTypes = function (repoType) { return { a11y: { symbol: '️️️️♿️', @@ -136,9 +136,13 @@ const defaultTypes = function(repoType) { symbol: 'πŸ“Ή', description: 'Videos', }, + promotion: { + symbol: 'πŸ“£', + description: 'Promotion', + }, } } -module.exports = function(options) { +module.exports = function (options) { return _.assign(defaultTypes(options.repoType), options.types) }