Skip to content

Commit

Permalink
fix: preserve trailing whitespace in manifest
Browse files Browse the repository at this point in the history
  • Loading branch information
antongolub committed Aug 4, 2020
1 parent 8ac9f2e commit 06426ec
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 23 deletions.
7 changes: 4 additions & 3 deletions lib/createInlinePluginCreator.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
const { writeFileSync } = require("fs");
const debug = require("debug")("msr:inlinePlugin");
const getCommitsFiltered = require("./getCommitsFiltered");
const { getManifest, getIndent } = require("./getManifest");
const getManifest = require("./getManifest");
const hasChangedDeep = require("./hasChangedDeep");
const recognizeFormat = require("./recognizeFormat");
const { get } = require("lodash");

/**
Expand Down Expand Up @@ -32,7 +33,7 @@ function createInlinePluginCreator(packages, multiContext, synchronizer, flags)
const updateManifestDeps = (pkg, path) => {
// Get and parse manifest file contents.
const manifest = getManifest(path);
const indent = getIndent(path);
const { indent, trailingWhitespace } = recognizeFormat(manifest.__contents__);
const updateDependency = (scope, name, version) => {
if (get(manifest, `${scope}.${name}`)) {
manifest[scope][name] = version;
Expand All @@ -56,7 +57,7 @@ function createInlinePluginCreator(packages, multiContext, synchronizer, flags)
});

// Write package.json back out.
writeFileSync(path, JSON.stringify(manifest, null, indent));
writeFileSync(path, JSON.stringify(manifest, null, indent) + trailingWhitespace);
};

/**
Expand Down
23 changes: 5 additions & 18 deletions lib/getManifest.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ function readManifest(path) {
try {
stat = lstatSync(path);
} catch (_) {
// istanbul ignore next (hard to test — happens if no read acccess etc).
// istanbul ignore next (hard to test — happens if no read access etc).
throw new ReferenceError(`package.json cannot be read: "${path}"`);
}

Expand All @@ -33,22 +33,6 @@ function readManifest(path) {
}
}

/**
* Extract the current indent sequence from file.
*
* @param {string} path The path to the package.json manifest file.
* @returns {string} indent symbols
*
* @internal
*/
function getIndent(path) {
// Read the file.
const contents = readManifest(path);
const match = /\n([^"]+)/.exec(contents);

return match ? match[1] : 2;
}

/**
* Get the parsed contents of a package.json manifest file.
*
Expand Down Expand Up @@ -87,9 +71,12 @@ function getManifest(path) {
checkDeps("peerDependencies");
checkDeps("optionalDependencies");

// NOTE non-enumerable prop is skipped by JSON.stringify
Object.defineProperty(manifest, "__contents__", { enumerable: false, value: contents });

// Return contents.
return manifest;
}

// Exports.
module.exports = { getManifest, getIndent };
module.exports = getManifest;
2 changes: 1 addition & 1 deletion lib/getWorkspacesYarn.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const glob = require("bash-glob");
const { getManifest } = require("./getManifest");
const getManifest = require("./getManifest");
const { checker } = require("./blork");

/**
Expand Down
2 changes: 1 addition & 1 deletion lib/multiSemanticRelease.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const getLogger = require("./getLogger");
const getSynchronizer = require("./getSynchronizer");
const getConfig = require("./getConfig");
const getConfigSemantic = require("./getConfigSemantic");
const { getManifest } = require("./getManifest");
const getManifest = require("./getManifest");
const cleanPath = require("./cleanPath");
const RescopedStream = require("./RescopedStream");
const createInlinePluginCreator = require("./createInlinePluginCreator");
Expand Down
25 changes: 25 additions & 0 deletions lib/recognizeFormat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* Information about the format of a file.
* @typedef FileFormat
* @property {string|number} indent Indentation characters
* @property {string} trailingWhitespace Trailing whitespace at the end of the file
*/

/**
* Detects the indentation and trailing whitespace of a file.
*
* @param {string} contents contents of the file
* @returns {FileFormat} Formatting of the file
*/
function recognizeFormat(contents) {
const indentMatch = /\n([^"]+)/.exec(contents);
const trailingWhitespaceMatch = /}(\s*)$/.exec(contents);

return {
indent: indentMatch ? indentMatch[1] : 2,
trailingWhitespace: trailingWhitespaceMatch ? trailingWhitespaceMatch[1] : "",
};
}

// Exports.
module.exports = recognizeFormat;
24 changes: 24 additions & 0 deletions test/lib/recognizeFormat.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/** @typedef {import('@types/jest')} */
const recognizeFormat = require("../../lib/recognizeFormat");

// Tests.
describe("recognizeFormat()", () => {
describe("Indentation", () => {
test("Normal indentation", () =>
expect(
recognizeFormat(`{
"a": "b",
"c": {
"d": "e"
}
}`).indent
).toBe("\t"));
test("No indentation", () => expect(recognizeFormat('{"a": "b"}').indent).toBe(2));
});

describe("Trailing whitespace", () => {
test("No trailing whitespace", () => expect(recognizeFormat('{"a": "b"}').trailingWhitespace).toBe(""));
test("Newline", () => expect(recognizeFormat('{"a": "b"}\n').trailingWhitespace).toBe("\n"));
test("Multiple newlines", () => expect(recognizeFormat('{"a": "b"}\n\n').trailingWhitespace).toBe("\n\n"));
});
});

0 comments on commit 06426ec

Please sign in to comment.