Skip to content

Commit fbaf9d9

Browse files
committed
feat!: make author prompt even when already specified
BREAKING CHANGE: The author prompt will now be shown even if an author is already specified in the existing package.json. If the user leaves the prompt blank, the author field will be omitted from the resulting package.json instead of being set to an empty string.
1 parent cddad4f commit fbaf9d9

10 files changed

Lines changed: 106 additions & 16 deletions

lib/default-input.js

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -204,15 +204,31 @@ if (!package.keywords) {
204204
})
205205
}
206206

207-
if (!package.author) {
207+
let author
208+
if (package.author) {
209+
if (typeof package.author === 'string') {
210+
author = package.author
211+
} else {
212+
const authorName = package.author.name
213+
const authorEmail = package.author.email || package.author.mail
214+
const authorUrl = package.author.url || package.author.web
215+
author = `${authorName}${authorEmail ? ` <${authorEmail}>` : ''}${authorUrl ? ` (${authorUrl})` : ''}`
216+
}
217+
} else {
208218
const authorName = getConfig('author.name')
209-
exports.author = authorName
210-
? {
211-
name: authorName,
212-
email: getConfig('author.email'),
213-
url: getConfig('author.url'),
214-
}
215-
: yes ? '' : prompt('author')
219+
if (authorName) {
220+
const authorEmail = getConfig('author.email')
221+
const authorUrl = getConfig('author.url')
222+
author = `${authorName}${authorEmail ? ` <${authorEmail}>` : ''}${authorUrl ? ` (${authorUrl})` : ''}`
223+
}
224+
}
225+
226+
if (yes) {
227+
if (author) {
228+
exports.author = author
229+
}
230+
} else {
231+
exports.author = prompt('author', author || undefined)
216232
}
217233

218234
const configLicense = getConfig('license')

lib/init-package-json.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,11 @@ async function init (dir,
105105
delete pkg.content.license
106106
}
107107

108+
// if no author was explicitly provided, don't include one
109+
if (!pzData.author) {
110+
delete pkg.content.author
111+
}
112+
108113
// readJson filters out empty descriptions, but init-package-json
109114
// traditionally leaves them alone
110115
if (!pkg.content.description) {

test/author.js

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
const t = require('tap')
2+
const { setup, child, isChild } = require('./fixtures/setup')
3+
4+
if (isChild()) {
5+
return child()
6+
}
7+
8+
t.test('author from config used as default', async (t) => {
9+
const { data } = await setup(t, __filename, {
10+
inputs: {
11+
name: 'the-name',
12+
author: [
13+
[/author: \(npmbot <n@p\.m> \(http:\/\/npm\.im\)\) $/, ''],
14+
],
15+
},
16+
config: {
17+
'init-author-name': 'npmbot',
18+
'init-author-email': 'n@p.m',
19+
'init-author-url': 'http://npm.im',
20+
},
21+
})
22+
23+
t.equal(data.author, 'npmbot <n@p.m> (http://npm.im)', 'uses config author as default')
24+
})
25+
26+
t.test('author from config in yes mode', async (t) => {
27+
const { data } = await setup(t, __filename, {
28+
config: {
29+
yes: 'yes',
30+
'init-author-name': 'npmbot',
31+
'init-author-email': 'n@p.m',
32+
'init-author-url': 'http://npm.im',
33+
},
34+
})
35+
36+
t.equal(data.author, 'npmbot <n@p.m> (http://npm.im)', 'uses config author in yes mode')
37+
})
38+
39+
t.test('author omitted when left blank', async (t) => {
40+
const { data } = await setup(t, __filename, {
41+
inputs: {
42+
name: 'the-name',
43+
author: [
44+
[/author: $/, ''],
45+
],
46+
},
47+
})
48+
49+
t.equal(data.author, undefined, 'author is omitted when left blank')
50+
})
51+
52+
t.test('author preserved from existing package.json', async (t) => {
53+
const { data } = await setup(t, __filename, {
54+
testdir: {
55+
'package.json': JSON.stringify({
56+
name: 'existing-package',
57+
version: '1.0.0',
58+
author: 'Existing Author <exist@example.com>',
59+
}),
60+
},
61+
config: { yes: 'yes' },
62+
})
63+
64+
t.equal(data.author, 'Existing Author <exist@example.com>', 'preserves existing author')
65+
})
66+
67+
t.test('author name only from config', async (t) => {
68+
const { data } = await setup(t, __filename, {
69+
config: {
70+
yes: 'yes',
71+
'init-author-name': 'npmbot',
72+
},
73+
})
74+
75+
t.equal(data.author, 'npmbot', 'uses author name only when no email/url configured')
76+
})

test/dependencies.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ t.test('existing dependencies', async (t) => {
2828
version: '1.0.0',
2929
type: 'commonjs',
3030
description: '',
31-
author: '',
3231
scripts: { test: 'echo "Error: no test specified" && exit 1' },
3332
main: 'index.js',
3433
keywords: [],

test/license.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ t.test('license', async (t) => {
2222
description: '',
2323
scripts: { test: 'echo "Error: no test specified" && exit 1' },
2424
license: 'Apache-2.0',
25-
author: '',
2625
main: 'index.js',
2726
}
2827
t.has(data, wanted)

test/name-spaces.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ t.test('single space', async t => {
2020
version: '1.0.0',
2121
description: '',
2222
scripts: { test: 'echo "Error: no test specified" && exit 1' },
23-
author: '',
2423
main: 'index.js',
2524
}
2625
t.has(data, wanted)
@@ -41,7 +40,6 @@ t.test('multiple spaces', async t => {
4140
version: '1.0.0',
4241
description: '',
4342
scripts: { test: 'echo "Error: no test specified" && exit 1' },
44-
author: '',
4543
main: 'index.js',
4644
}
4745
t.has(data, wanted)

test/name-uppercase.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ t.test('uppercase', async (t) => {
2020
version: '1.0.0',
2121
description: '',
2222
scripts: { test: 'echo "Error: no test specified" && exit 1' },
23-
author: '',
2423
main: 'index.js',
2524
}
2625
t.has(data, EXPECT)

test/repository.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ t.test('license', async (t) => {
1515
version: '1.0.0',
1616
description: '',
1717
scripts: { test: 'echo "Error: no test specified" && exit 1' },
18-
author: '',
1918
repository: {
2019
type: 'git',
2120
url: 'git+https://github.com/npm/cli.git',

test/scope-in-config.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ t.test('--yes with scope', async (t) => {
1010
name: '@scoped/tap-testdir-scope-in-config---yes-with-scope',
1111
version: '1.0.0',
1212
description: '',
13-
author: '',
1413
scripts: { test: 'echo "Error: no test specified" && exit 1' },
1514
main: 'index.js',
1615
keywords: [],

test/yes-defaults.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ t.test('--yes defaults', async (t) => {
1010
name: 'tap-testdir-yes-defaults---yes-defaults',
1111
version: '1.0.0',
1212
description: '',
13-
author: '',
1413
scripts: { test: 'echo "Error: no test specified" && exit 1' },
1514
main: 'index.js',
1615
keywords: [],
@@ -21,5 +20,6 @@ t.test('--yes defaults', async (t) => {
2120
})
2221

2322
t.has(data, EXPECT, 'used the default data')
23+
t.equal(data.author, undefined, 'author is omitted by default')
2424
t.equal(data.license, undefined, 'license is omitted by default')
2525
})

0 commit comments

Comments
 (0)