Skip to content
This repository has been archived by the owner on Apr 17, 2023. It is now read-only.

Commit

Permalink
feat(useLocalPrettier): Prefer local prettier over bundled
Browse files Browse the repository at this point in the history
To make prettier-atom work nicer in projects with prettier installed,
it will now prefer the local version of the prettier package over the
bundled dependency, to give output consistent with package scripts and
CLI prettier. If no local prettier can be found, we fallback to the
bundled package.
  • Loading branch information
charypar committed Apr 10, 2017
1 parent 57534b1 commit 98e2ea9
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 2 deletions.
22 changes: 21 additions & 1 deletion dist/executePrettier.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ var _require2 = require('./helpers'),
getPrettierOptions = _require2.getPrettierOptions,
getPrettierEslintOptions = _require2.getPrettierEslintOptions,
getCurrentFilePath = _require2.getCurrentFilePath,
getLocalPrettierPath = _require2.getLocalPrettierPath,
shouldDisplayErrors = _require2.shouldDisplayErrors,
shouldUseEslint = _require2.shouldUseEslint,
runLinter = _require2.runLinter;
Expand All @@ -31,6 +32,17 @@ var handleError = function handleError(error) {
return false;
};

// charypar: This is currently the best way to use local prettier instance.
// Using the CLI introduces a noticeable delay and there is currently no
// way to use prettier as a long-running process for formatting files as needed
//
// See https://github.com/prettier/prettier/issues/918
//
// $FlowFixMe when possible, don't use dynamic require
var getLocalPrettier = function getLocalPrettier(path) {
return require(path);
}; // eslint-disable-line

var executePrettier = function executePrettier(editor, text) {
try {
if (shouldUseEslint()) {
Expand All @@ -41,7 +53,15 @@ var executePrettier = function executePrettier(editor, text) {
}));
});
}
return prettier.format(text, getPrettierOptions(editor));

var prettierOptions = getPrettierOptions(editor);
var localPrettier = getLocalPrettierPath(getCurrentFilePath(editor));

if (!localPrettier) {
return prettier.format(text, prettierOptions);
}

return getLocalPrettier(localPrettier).format(text, prettierOptions);
} catch (error) {
return handleError(error);
}
Expand Down
11 changes: 11 additions & 0 deletions dist/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,16 @@ var getNearestEslintignorePath = function getNearestEslintignorePath(filePath) {
return findCached(getDirFromFilePath(filePath), '.eslintignore');
};

var getLocalPrettierPath = function getLocalPrettierPath(filePath) {
if (!filePath) return null;

var indexPath = path.join('node_modules', 'prettier', 'index.js');
var dirPath = getDirFromFilePath(filePath);
if (!dirPath) return null;

return findCached(dirPath, indexPath);
};

var getFilePathRelativeToEslintignore = function getFilePathRelativeToEslintignore(filePath) {
var nearestEslintignorePath = getNearestEslintignorePath(filePath);

Expand Down Expand Up @@ -168,6 +178,7 @@ module.exports = {
getPrettierOption: getPrettierOption,
getPrettierEslintOption: getPrettierEslintOption,
getCurrentFilePath: getCurrentFilePath,
getLocalPrettierPath: getLocalPrettierPath,
isInScope: isInScope,
isCurrentScopeEmbeddedScope: isCurrentScopeEmbeddedScope,
isFilePathEslintignored: isFilePathEslintignored,
Expand Down
20 changes: 19 additions & 1 deletion src/executePrettier.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const {
getPrettierOptions,
getPrettierEslintOptions,
getCurrentFilePath,
getLocalPrettierPath,
shouldDisplayErrors,
shouldUseEslint,
runLinter,
Expand All @@ -27,6 +28,15 @@ const handleError = (error) => {
return false;
};

// charypar: This is currently the best way to use local prettier instance.
// Using the CLI introduces a noticeable delay and there is currently no
// way to use prettier as a long-running process for formatting files as needed
//
// See https://github.com/prettier/prettier/issues/918
//
// $FlowFixMe when possible, don't use dynamic require
const getLocalPrettier = path => require(path); // eslint-disable-line

const executePrettier = (editor, text) => {
try {
if (shouldUseEslint()) {
Expand All @@ -37,7 +47,15 @@ const executePrettier = (editor, text) => {
filePath: getCurrentFilePath(editor),
}));
}
return prettier.format(text, getPrettierOptions(editor));

const prettierOptions = getPrettierOptions(editor);
const localPrettier = getLocalPrettierPath(getCurrentFilePath(editor));

if (!localPrettier) {
return prettier.format(text, prettierOptions);
}

return getLocalPrettier(localPrettier).format(text, prettierOptions);
} catch (error) {
return handleError(error);
}
Expand Down
13 changes: 13 additions & 0 deletions src/executePrettier.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// @flow
const path = require('path');
const prettier = require('prettier');
const prettierEslint = require('prettier-eslint');

Expand Down Expand Up @@ -95,6 +96,18 @@ describe('executePrettierOnBufferRange()', () => {
});
});

describe('when there is a local prettier', () => {
test('transforms using local prettier', () => {
const mockPrettierPath = path.join(__dirname, '..', 'tests', 'fixtures', 'prettier.js');
// $FlowFixMe
helpers.getLocalPrettierPath.mockImplementation(() => mockPrettierPath);

executePrettierOnBufferRange(editor, bufferRangeFixture);

expect(editor.setTextInBufferRange).toHaveBeenCalledWith(bufferRangeFixture, 'mock formatted text');
});
});

describe('when prettier throws an error', () => {
beforeEach(() => {
prettier.format.mockImplementation(() => {
Expand Down
11 changes: 11 additions & 0 deletions src/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ const getDirFromFilePath = (filePath: FilePath): FilePath => path.parse(filePath
const getNearestEslintignorePath = (filePath: FilePath): ?FilePath =>
findCached(getDirFromFilePath(filePath), '.eslintignore');

const getLocalPrettierPath = (filePath: ?FilePath): ?FilePath => {
if (!filePath) return null;

const indexPath = path.join('node_modules', 'prettier', 'index.js');
const dirPath = getDirFromFilePath(filePath);
if (!dirPath) return null;

return findCached(dirPath, indexPath);
};

const getFilePathRelativeToEslintignore = (filePath: FilePath): ?FilePath => {
const nearestEslintignorePath = getNearestEslintignorePath(filePath);

Expand Down Expand Up @@ -122,6 +132,7 @@ module.exports = {
getPrettierOption,
getPrettierEslintOption,
getCurrentFilePath,
getLocalPrettierPath,
isInScope,
isCurrentScopeEmbeddedScope,
isFilePathEslintignored,
Expand Down
38 changes: 38 additions & 0 deletions src/helpers.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const {
getPrettierOption,
getPrettierEslintOption,
getCurrentFilePath,
getLocalPrettierPath,
isInScope,
isFilePathEslintignored,
isFilePathExcluded,
Expand Down Expand Up @@ -96,6 +97,43 @@ describe('getCurrentFilePath', () => {
});
});

describe('getLocalPrettierPath', () => {
test('is null if no prettier package can be found', () => {
atomLinter.findCached.mockImplementation(() => undefined);
const filePath = path.join(__dirname, 'sourceFile.js');

const actual = getLocalPrettierPath(filePath);
const expected = undefined;

expect(actual).toEqual(expected);
});

test('is prettier instance if one could be found', () => {
const prettierLib = path.join(__dirname, '..', 'node_modules', 'prettier', 'index.js');

atomLinter.findCached.mockImplementation(() => prettierLib);
const filePath = path.join(__dirname, '..', 'tests', 'fixtures', 'sourceFile.js');

const actual = getLocalPrettierPath(filePath);
const expected = prettierLib;

expect(actual).toBe(expected);
});

test('looks for prettier entry file', () => {
const prettierLib = path.join(__dirname, '..', 'node_modules', 'prettier', 'index.js');

atomLinter.findCached.mockImplementation(() => prettierLib);
const filePath = path.join(__dirname, '..', 'tests', 'fixtures', 'sourceFile.js');

getLocalPrettierPath(filePath);
const expectedDir = path.join(__dirname, '..', 'tests', 'fixtures');
const expectedLib = path.join('node_modules', 'prettier', 'index.js');

expect(atomLinter.findCached).toHaveBeenCalledWith(expectedDir, expectedLib);
});
});

describe('isInScope', () => {
test("returns true if the editor's current scope is listed among the config's scopes", () => {
const mockGet = jest.fn(() => ['source.js.jsx', 'text.html.vue']);
Expand Down
6 changes: 6 additions & 0 deletions tests/fixtures/prettier.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

module.exports = {
format() {
return 'mock formatted text';
},
};

0 comments on commit 98e2ea9

Please sign in to comment.