diff --git a/src/index.ts b/src/index.ts index 88cd5f3..ce0527f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -98,7 +98,7 @@ export const modifyJsonFile: ModifyJsonFileGenericFunction = async (path, modify removeJsonc = false, } = options try { - let { json, indent } = await loadJsonFile(path, { encoding, tabSize, removeJsonc }) + let { json, indent, hasFinalNewline } = await loadJsonFile(path, { encoding, tabSize, removeJsonc }) if (typeof modifyProperties === 'function') { // TODO why arg is never json = await (modifyProperties as any)(json) @@ -120,7 +120,10 @@ export const modifyJsonFile: ModifyJsonFileGenericFunction = async (path, modify } } - await fs.promises.writeFile(path, JSON.stringify(json, undefined, indent)) + // TODO don't use this fix + let string = JSON.stringify(json, undefined, indent) + if (hasFinalNewline) string += '\n' + await fs.promises.writeFile(path, string) } catch (err) { if (throws) throw err } diff --git a/src/loadJsonFile.ts b/src/loadJsonFile.ts index 6181bd3..c950bf4 100644 --- a/src/loadJsonFile.ts +++ b/src/loadJsonFile.ts @@ -19,5 +19,6 @@ export const loadJsonFile = async (filePath: string, { encoding, tabSize, remove return { json: parseJson(contents, filePath) as JsonRoot, indent: tabSize === 'preserve' ? detectIndent(contents).indent : tabSize === 'hard' ? '\t' : tabSize === null ? undefined : ' '.repeat(tabSize), + hasFinalNewline: contents.split('\n').slice(-1)[0]! === '', } } diff --git a/tests/index.test.ts b/tests/index.test.ts index 8127d5b..81cd3cc 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -190,6 +190,47 @@ test("Don't throw error if option is provided on missing property in input", asy ) }) +test('Preserves empty newline', async () => { + expect.assertions(1) + prepare({ + data: ` +{ + "author": "eldar", + "bin": "src/bin.ts", + "dependencies": { + "fdir": ">=2", + "type-fest": "*" + } +} +`, + json: false, + writeCallback(data) { + expect(data).toMatchInlineSnapshot(` +"{ + \\"author\\": \\"eldar\\", + \\"bin\\": \\"build/bin.js\\", + \\"dependencies\\": { + \\"fdir\\": \\">=2\\", + \\"type-fest\\": \\"*\\" + }, + \\"somethingWeird\\": \\"new-item\\" +} +" +`) + }, + }) + await modifyJsonFile( + '', + { + bin: 'build/bin.js', + somethingWeird: () => 'new-item', + }, + { + ifPropertyIsMissingForSetter: 'pass', + }, + ) +}) + test('loader removes comments and trailing commas', async () => { const { json } = await loadJsonFile(join(__dirname, './tsconfig.fixture.json'), { encoding: 'utf-8', removeJsonc: true, tabSize: 'preserve' }) expect(json).toMatchInlineSnapshot(`