Skip to content

Commit 7257ebb

Browse files
Respect trailing newline at the end of the file (#27)
Co-authored-by: Sindre Sorhus <[email protected]>
1 parent 5b66b0e commit 7257ebb

File tree

2 files changed

+40
-16
lines changed

2 files changed

+40
-16
lines changed

index.js

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ const isPlainObj = require('is-plain-obj');
1010

1111
const readFile = promisify(fs.readFile);
1212

13+
const hasTrailingNewline = file => /\n$/.test(file);
14+
1315
const init = (fn, filePath, data, options) => {
1416
if (!filePath) {
1517
throw new TypeError('Expected a filepath');
@@ -37,40 +39,48 @@ const init = (fn, filePath, data, options) => {
3739

3840
const main = async (filePath, data, options) => {
3941
let {indent} = options;
42+
let trailingNewline = '\n';
43+
try {
44+
const file = await readFile(filePath, 'utf8');
45+
if (!hasTrailingNewline(file)) {
46+
trailingNewline = '';
47+
}
4048

41-
if (options.detectIndent) {
42-
try {
43-
const file = await readFile(filePath, 'utf8');
49+
if (options.detectIndent) {
4450
indent = detectIndent(file).indent;
45-
} catch (error) {
46-
if (error.code !== 'ENOENT') {
47-
throw error;
48-
}
51+
}
52+
} catch (error) {
53+
if (error.code !== 'ENOENT') {
54+
throw error;
4955
}
5056
}
5157

5258
const json = JSON.stringify(data, options.replacer, indent);
5359

54-
return writeFileAtomic(filePath, `${json}\n`, {mode: options.mode});
60+
return writeFileAtomic(filePath, `${json}${trailingNewline}`, {mode: options.mode});
5561
};
5662

5763
const mainSync = (filePath, data, options) => {
5864
let {indent} = options;
65+
let trailingNewline = '\n';
66+
try {
67+
const file = fs.readFileSync(filePath, 'utf8');
68+
if (!hasTrailingNewline(file)) {
69+
trailingNewline = '';
70+
}
5971

60-
if (options.detectIndent) {
61-
try {
62-
const file = fs.readFileSync(filePath, 'utf8');
72+
if (options.detectIndent) {
6373
indent = detectIndent(file).indent;
64-
} catch (error) {
65-
if (error.code !== 'ENOENT') {
66-
throw error;
67-
}
74+
}
75+
} catch (error) {
76+
if (error.code !== 'ENOENT') {
77+
throw error;
6878
}
6979
}
7080

7181
const json = JSON.stringify(data, options.replacer, indent);
7282

73-
return writeFileAtomic.sync(filePath, `${json}\n`, {mode: options.mode});
83+
return writeFileAtomic.sync(filePath, `${json}${trailingNewline}`, {mode: options.mode});
7484
};
7585

7686
module.exports = async (filePath, data, options) => {

test.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,17 @@ test('sync - `replacer` option', t => {
6161
writeJsonFile.sync(tempFile, {foo: true, bar: true}, {replacer: ['foo']});
6262
t.is(fs.readFileSync(tempFile, 'utf8'), '{\n\t"foo": true\n}\n');
6363
});
64+
65+
test('async - respect trailing newline at the end of the file', async t => {
66+
const tempFile = tempy.file();
67+
fs.writeFileSync(tempFile, JSON.stringify({foo: true}));
68+
await writeJsonFile(tempFile, {bar: true});
69+
t.is(fs.readFileSync(tempFile, 'utf8'), '{\n\t"bar": true\n}');
70+
});
71+
72+
test('sync - respect trailing newline at the end of the file', t => {
73+
const tempFile = tempy.file();
74+
fs.writeFileSync(tempFile, JSON.stringify({foo: true}));
75+
writeJsonFile.sync(tempFile, {bar: true});
76+
t.is(fs.readFileSync(tempFile, 'utf8'), '{\n\t"bar": true\n}');
77+
});

0 commit comments

Comments
 (0)