Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@trivago/prettier-plugin-sort-imports

Package Overview
Dependencies
Maintainers
2
Versions
40
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@trivago/prettier-plugin-sort-imports - npm Package Compare versions

Comparing version 4.3.0 to 5.0.0

.yarnrc.yml

10

CHANGELOG.md

@@ -5,5 +5,15 @@ ## Changelog

---
### v5.0.0
#### New features
- Type imports [#153](https://github.com/trivago/prettier-plugin-sort-imports/pull/153) by [Xenfo](https://github.com/broofa)
- Svelte support [#310](https://github.com/trivago/prettier-plugin-sort-imports/pull/310) by [canarddemagret](https://github.com/canarddemagret)
- Side effect import support [#320](https://github.com/trivago/prettier-plugin-sort-imports/pull/320) by [blutorange](https://github.com/blutorange) and [vladislavarsenev](https://github.com/vladislavarsenev)
- Fixed dollar sign group replace in Vue [#283](https://github.com/trivago/prettier-plugin-sort-imports/pull/283) by [adamDilger](https://github.com/adamDilger)
- Support `importOrderImportAttributesKeyword` [#273](https://github.com/trivago/prettier-plugin-sort-imports/pull/273) by [chentsulin](https://github.com/chentsulin)
### v4.3.0
#### New features
- added support for sort-imports-ignore [#237](https://github.com/trivago/prettier-plugin-sort-imports/pull/237) by [stephdotnet](https://github.com/stephdotnet)
- Upgrade node in CI to current and lts versions [#264](https://github.com/trivago/prettier-plugin-sort-imports/pull/264) by [harryzcy](https://github.com/harryzcy)

@@ -10,0 +20,0 @@ ### v4.2.1

6

lib/src/constants.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.newLineNode = exports.THIRD_PARTY_MODULES_SPECIAL_WORD = exports.sortImportsIgnoredComment = exports.newLineCharacters = exports.jsx = exports.typescript = exports.flow = void 0;
exports.newLineNode = exports.TYPES_SPECIAL_WORD = exports.THIRD_PARTY_TYPES_SPECIAL_WORD = exports.THIRD_PARTY_MODULES_SPECIAL_WORD = exports.chunkSideOtherNode = exports.chunkSideEffectNode = exports.sortImportsIgnoredComment = exports.newLineCharacters = exports.jsx = exports.typescript = exports.flow = void 0;
var types_1 = require("@babel/types");

@@ -10,2 +10,4 @@ exports.flow = 'flow';

exports.sortImportsIgnoredComment = 'sort-imports-ignore';
exports.chunkSideEffectNode = 'side-effect-node';
exports.chunkSideOtherNode = 'other-node';
/*

@@ -16,3 +18,5 @@ * Used to mark the position between RegExps,

exports.THIRD_PARTY_MODULES_SPECIAL_WORD = '<THIRD_PARTY_MODULES>';
exports.THIRD_PARTY_TYPES_SPECIAL_WORD = '<THIRD_PARTY_TS_TYPES>';
exports.TYPES_SPECIAL_WORD = '<TS_TYPES>';
var PRETTIER_PLUGIN_SORT_IMPORTS_NEW_LINE = 'PRETTIER_PLUGIN_SORT_IMPORTS_NEW_LINE';
exports.newLineNode = (0, types_1.expressionStatement)((0, types_1.stringLiteral)(PRETTIER_PLUGIN_SORT_IMPORTS_NEW_LINE));

31

lib/src/index.js

@@ -14,8 +14,10 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
var parser_babel_1 = require("prettier/parser-babel");
var parser_flow_1 = require("prettier/parser-flow");
var parser_html_1 = require("prettier/parser-html");
var parser_typescript_1 = require("prettier/parser-typescript");
var babel_1 = require("prettier/plugins/babel");
var flow_1 = require("prettier/plugins/flow");
var html_1 = require("prettier/plugins/html");
var typescript_1 = require("prettier/plugins/typescript");
var default_processor_1 = require("./preprocessors/default-processor");
var svelte_preprocessor_1 = require("./preprocessors/svelte-preprocessor");
var vue_preprocessor_1 = require("./preprocessors/vue-preprocessor");
var svelteParsers = require('prettier-plugin-svelte').parsers;
var options = {

@@ -62,11 +64,24 @@ importOrder: {

},
importOrderSideEffects: {
type: 'boolean',
category: 'Global',
default: true,
description: 'Should side effects be sorted?',
},
importOrderImportAttributesKeyword: {
type: 'string',
category: 'Global',
default: 'with',
description: 'Provide a keyword for import attributes',
}
};
module.exports = {
parsers: {
babel: __assign(__assign({}, parser_babel_1.parsers.babel), { preprocess: default_processor_1.defaultPreprocessor }),
flow: __assign(__assign({}, parser_flow_1.parsers.flow), { preprocess: default_processor_1.defaultPreprocessor }),
typescript: __assign(__assign({}, parser_typescript_1.parsers.typescript), { preprocess: default_processor_1.defaultPreprocessor }),
vue: __assign(__assign({}, parser_html_1.parsers.vue), { preprocess: vue_preprocessor_1.vuePreprocessor }),
babel: __assign(__assign({}, babel_1.parsers.babel), { preprocess: default_processor_1.defaultPreprocessor }),
flow: __assign(__assign({}, flow_1.parsers.flow), { preprocess: default_processor_1.defaultPreprocessor }),
typescript: __assign(__assign({}, typescript_1.parsers.typescript), { preprocess: default_processor_1.defaultPreprocessor }),
vue: __assign(__assign({}, html_1.parsers.vue), { preprocess: vue_preprocessor_1.vuePreprocessor }),
svelte: __assign(__assign({}, svelteParsers.svelte), { preprocess: svelte_preprocessor_1.sveltePreprocessor }),
},
options: options,
};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.defaultPreprocessor = void 0;
exports.defaultPreprocessor = defaultPreprocessor;
var preprocessor_1 = require("./preprocessor");
function defaultPreprocessor(code, options) {
var _a;
if ((_a = options.filepath) === null || _a === void 0 ? void 0 : _a.endsWith('.vue'))
return code;
for (var _i = 0, _b = ['svelte', 'vue']; _i < _b.length; _i++) {
var extension = _b[_i];
if ((_a = options.filepath) === null || _a === void 0 ? void 0 : _a.endsWith(".".concat(extension)))
return code;
}
return (0, preprocessor_1.preprocessor)(code, options);
}
exports.defaultPreprocessor = defaultPreprocessor;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.preprocessor = void 0;
exports.preprocessor = preprocessor;
var parser_1 = require("@babel/parser");

@@ -11,3 +11,3 @@ var extract_ast_nodes_1 = require("../utils/extract-ast-nodes");

function preprocessor(code, options) {
var importOrderParserPlugins = options.importOrderParserPlugins, importOrder = options.importOrder, importOrderCaseInsensitive = options.importOrderCaseInsensitive, importOrderSeparation = options.importOrderSeparation, importOrderGroupNamespaceSpecifiers = options.importOrderGroupNamespaceSpecifiers, importOrderSortSpecifiers = options.importOrderSortSpecifiers;
var importOrderParserPlugins = options.importOrderParserPlugins, importOrder = options.importOrder, importOrderCaseInsensitive = options.importOrderCaseInsensitive, importOrderSeparation = options.importOrderSeparation, importOrderGroupNamespaceSpecifiers = options.importOrderGroupNamespaceSpecifiers, importOrderSortSpecifiers = options.importOrderSortSpecifiers, importOrderSideEffects = options.importOrderSideEffects, importOrderImportAttributesKeyword = options.importOrderImportAttributesKeyword;
var parserOptions = {

@@ -31,5 +31,7 @@ sourceType: 'module',

importOrderSortSpecifiers: importOrderSortSpecifiers,
importOrderSideEffects: importOrderSideEffects,
});
return (0, get_code_from_ast_1.getCodeFromAst)(allImports, directives, code, interpreter);
return (0, get_code_from_ast_1.getCodeFromAst)(allImports, directives, code, interpreter, {
importOrderImportAttributesKeyword: importOrderImportAttributesKeyword,
});
}
exports.preprocessor = preprocessor;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.vuePreprocessor = void 0;
exports.vuePreprocessor = vuePreprocessor;
var preprocessor_1 = require("./preprocessor");

@@ -9,8 +9,20 @@ function vuePreprocessor(code, options) {

var descriptor = parse(code).descriptor;
var content = (_b = ((_a = descriptor.script) !== null && _a !== void 0 ? _a : descriptor.scriptSetup)) === null || _b === void 0 ? void 0 : _b.content;
if (!content) {
var scriptContent = (_a = descriptor.script) === null || _a === void 0 ? void 0 : _a.content;
var scriptSetupContent = (_b = descriptor.scriptSetup) === null || _b === void 0 ? void 0 : _b.content;
if (!scriptContent && !scriptSetupContent) {
return code;
}
return code.replace(content, "\n".concat((0, preprocessor_1.preprocessor)(content, options), "\n"));
var transformedCode = code;
var replacer = function (content) {
// we pass the second argument as a function to avoid issues with the replacement string
// if string contained special groups (like $&, $`, $', $n, $<n>, etc.) this would produce invalid results
return transformedCode.replace(content, function () { return "\n".concat((0, preprocessor_1.preprocessor)(content, options), "\n"); });
};
if (scriptContent) {
transformedCode = replacer(scriptContent);
}
if (scriptSetupContent) {
transformedCode = replacer(scriptSetupContent);
}
return transformedCode;
}
exports.vuePreprocessor = vuePreprocessor;

@@ -14,2 +14,3 @@ "use strict";

importOrderSortSpecifiers: false,
importOrderSideEffects: true,
});

@@ -16,0 +17,0 @@ };

"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });

@@ -10,27 +46,48 @@ var core_1 = require("@babel/core");

var get_sorted_nodes_1 = require("../get-sorted-nodes");
test('it sorts imports correctly', function () {
var code = "// first comment\n// second comment\nimport z from 'z';\nimport c from 'c';\nimport g from 'g';\nimport t from 't';\nimport k from 'k';\nimport a from 'a';\n";
var importNodes = (0, get_import_nodes_1.getImportNodes)(code);
var sortedNodes = (0, get_sorted_nodes_1.getSortedNodes)(importNodes, {
importOrder: [],
importOrderCaseInsensitive: false,
importOrderSeparation: false,
importOrderGroupNamespaceSpecifiers: false,
importOrderSortSpecifiers: false,
test('it sorts imports correctly', function () { return __awaiter(void 0, void 0, void 0, function () {
var code, importNodes, sortedNodes, formatted, _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
code = "// first comment\n// second comment\nimport z from 'z';\nimport c from 'c';\nimport g from 'g';\nimport t from 't';\nimport k from 'k';\nimport a from 'a';\n";
importNodes = (0, get_import_nodes_1.getImportNodes)(code);
sortedNodes = (0, get_sorted_nodes_1.getSortedNodes)(importNodes, {
importOrder: [],
importOrderCaseInsensitive: false,
importOrderSeparation: false,
importOrderGroupNamespaceSpecifiers: false,
importOrderSortSpecifiers: false,
importOrderSideEffects: true,
});
formatted = (0, get_code_from_ast_1.getCodeFromAst)(sortedNodes, [], code, null);
_a = expect;
return [4 /*yield*/, (0, prettier_1.format)(formatted, { parser: 'babel' })];
case 1:
_a.apply(void 0, [_b.sent()]).toEqual("// first comment\n// second comment\nimport a from \"a\";\nimport c from \"c\";\nimport g from \"g\";\nimport k from \"k\";\nimport t from \"t\";\nimport z from \"z\";\n");
return [2 /*return*/];
}
});
var formatted = (0, get_code_from_ast_1.getCodeFromAst)(sortedNodes, [], code, null);
expect((0, prettier_1.format)(formatted, { parser: 'babel' })).toEqual("// first comment\n// second comment\nimport a from \"a\";\nimport c from \"c\";\nimport g from \"g\";\nimport k from \"k\";\nimport t from \"t\";\nimport z from \"z\";\n");
});
test('it renders directives correctly', function () {
var code = "\n \"use client\";\n// first comment\nimport b from 'b';\nimport a from 'a';";
var parserOptions = {
sourceType: 'module',
plugins: (0, get_experimental_parser_plugins_1.getExperimentalParserPlugins)([]),
};
var ast = (0, core_1.parse)(code, parserOptions);
if (!ast)
throw new Error('ast is null');
var _a = (0, extract_ast_nodes_1.extractASTNodes)(ast), directives = _a.directives, importNodes = _a.importNodes;
var formatted = (0, get_code_from_ast_1.getCodeFromAst)(importNodes, directives, code, null);
expect((0, prettier_1.format)(formatted, { parser: 'babel' })).toEqual("\"use client\";\n\n// first comment\nimport b from \"b\";\nimport a from \"a\";\n");
});
}); });
test('it renders directives correctly', function () { return __awaiter(void 0, void 0, void 0, function () {
var code, parserOptions, ast, _a, directives, importNodes, formatted, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
code = "\n \"use client\";\n// first comment\nimport b from 'b';\nimport a from 'a';";
parserOptions = {
sourceType: 'module',
plugins: (0, get_experimental_parser_plugins_1.getExperimentalParserPlugins)([]),
};
ast = (0, core_1.parse)(code, parserOptions);
if (!ast)
throw new Error('ast is null');
_a = (0, extract_ast_nodes_1.extractASTNodes)(ast), directives = _a.directives, importNodes = _a.importNodes;
formatted = (0, get_code_from_ast_1.getCodeFromAst)(importNodes, directives, code, null);
_b = expect;
return [4 /*yield*/, (0, prettier_1.format)(formatted, { parser: 'babel' })];
case 1:
_b.apply(void 0, [_c.sent()]).toEqual("\"use client\";\n\n// first comment\nimport b from \"b\";\nimport a from \"a\";\n");
return [2 /*return*/];
}
});
}); });

@@ -8,2 +8,3 @@ "use strict";

var code = "// first comment\n// second comment\nimport z from 'z';\nimport c, { cD } from 'c';\nimport g from 'g';\nimport { tC, tA, tB } from 't';\nimport k, { kE, kB } from 'k';\nimport * as a from 'a';\nimport * as x from 'x';\nimport BY from 'BY';\nimport Ba from 'Ba';\nimport XY from 'XY';\nimport Xa from 'Xa';\n";
var typeCode = "// first comment\n// second comment\nimport type sm from 'sm';\nimport type xl from './xl';\nimport l from './l';\nimport z from 'z';\nimport c, { cD } from 'c';\nimport g from 'g';\nimport { tC, tA, tB } from 't';\nimport k, { kE, kB } from 'k';\nimport * as a from 'a';\nimport * as x from 'x';\nimport BY from 'BY';\nimport Ba from 'Ba';\nimport XY from 'XY';\nimport Xa from 'Xa';\n";
test('it returns all sorted nodes', function () {

@@ -17,2 +18,3 @@ var result = (0, get_import_nodes_1.getImportNodes)(code);

importOrderSortSpecifiers: false,
importOrderSideEffects: true,
});

@@ -58,2 +60,3 @@ expect((0, get_sorted_nodes_names_1.getSortedNodesNames)(sorted)).toEqual([

importOrderSortSpecifiers: false,
importOrderSideEffects: true,
});

@@ -99,2 +102,3 @@ expect((0, get_sorted_nodes_names_1.getSortedNodesNames)(sorted)).toEqual([

importOrderSortSpecifiers: false,
importOrderSideEffects: true,
});

@@ -140,2 +144,3 @@ expect((0, get_sorted_nodes_names_1.getSortedNodesNames)(sorted)).toEqual([

importOrderSortSpecifiers: false,
importOrderSideEffects: true,
});

@@ -181,2 +186,3 @@ expect((0, get_sorted_nodes_names_1.getSortedNodesNames)(sorted)).toEqual([

importOrderSortSpecifiers: true,
importOrderSideEffects: true,
});

@@ -222,2 +228,3 @@ expect((0, get_sorted_nodes_names_1.getSortedNodesNames)(sorted)).toEqual([

importOrderSortSpecifiers: true,
importOrderSideEffects: true,
});

@@ -263,2 +270,3 @@ expect((0, get_sorted_nodes_names_1.getSortedNodesNames)(sorted)).toEqual([

importOrderSortSpecifiers: false,
importOrderSideEffects: true,
});

@@ -287,2 +295,3 @@ expect((0, get_sorted_nodes_names_1.getSortedNodesNames)(sorted)).toEqual([

importOrderSortSpecifiers: false,
importOrderSideEffects: true,
});

@@ -303,1 +312,50 @@ expect((0, get_sorted_nodes_names_1.getSortedNodesNames)(sorted)).toEqual([

});
test('it returns all sorted nodes with types', function () {
var result = (0, get_import_nodes_1.getImportNodes)(typeCode, {
plugins: ['typescript'],
});
var sorted = (0, get_sorted_nodes_1.getSortedNodes)(result, {
importOrder: ['<THIRD_PARTY_TS_TYPES>', '^[./]', '<TS_TYPES>^[./]'],
importOrderCaseInsensitive: false,
importOrderSeparation: false,
importOrderGroupNamespaceSpecifiers: false,
importOrderSortSpecifiers: false,
importOrderSideEffects: true,
});
expect((0, get_sorted_nodes_names_1.getSortedNodesNames)(sorted)).toEqual([
'BY',
'Ba',
'XY',
'Xa',
'a',
'c',
'g',
'k',
't',
'x',
'z',
'sm',
'./l',
'./xl',
]);
expect(sorted
.filter(function (node) { return node.type === 'ImportDeclaration'; })
.map(function (importDeclaration) {
return (0, get_sorted_nodes_modules_names_1.getSortedNodesModulesNames)(importDeclaration.specifiers);
})).toEqual([
['BY'],
['Ba'],
['XY'],
['Xa'],
['a'],
['c', 'cD'],
['g'],
['k', 'kE', 'kB'],
['tC', 'tA', 'tB'],
['x'],
['z'],
['sm'],
['l'],
['xl'],
]);
});
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {

@@ -18,16 +54,28 @@ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {

var code = "// first comment\n// second comment\nimport z from 'z';\nimport c from 'c';\nimport g from 'g';\nimport t from 't';\nimport k from 'k';\n// import a from 'a';\n // import a from 'a';\nimport a from 'a';\n";
test('it should remove nodes from the original code', function () {
var importNodes = (0, get_import_nodes_1.getImportNodes)(code);
var sortedNodes = (0, get_sorted_nodes_1.getSortedNodes)(importNodes, {
importOrder: [],
importOrderCaseInsensitive: false,
importOrderSeparation: false,
importOrderGroupNamespaceSpecifiers: false,
importOrderSortSpecifiers: false,
test('it should remove nodes from the original code', function () { return __awaiter(void 0, void 0, void 0, function () {
var importNodes, sortedNodes, allCommentsFromImports, commentAndImportsToRemoveFromCode, codeWithoutImportDeclarations, result;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
importNodes = (0, get_import_nodes_1.getImportNodes)(code);
sortedNodes = (0, get_sorted_nodes_1.getSortedNodes)(importNodes, {
importOrder: [],
importOrderCaseInsensitive: false,
importOrderSeparation: false,
importOrderGroupNamespaceSpecifiers: false,
importOrderSortSpecifiers: false,
importOrderSideEffects: true,
});
allCommentsFromImports = (0, get_all_comments_from_nodes_1.getAllCommentsFromNodes)(sortedNodes);
commentAndImportsToRemoveFromCode = __spreadArray(__spreadArray([], sortedNodes, true), allCommentsFromImports, true);
codeWithoutImportDeclarations = (0, remove_nodes_from_original_code_1.removeNodesFromOriginalCode)(code, commentAndImportsToRemoveFromCode);
return [4 /*yield*/, (0, prettier_1.format)(codeWithoutImportDeclarations, {
parser: 'babel',
})];
case 1:
result = _a.sent();
expect(result).toEqual('');
return [2 /*return*/];
}
});
var allCommentsFromImports = (0, get_all_comments_from_nodes_1.getAllCommentsFromNodes)(sortedNodes);
var commentAndImportsToRemoveFromCode = __spreadArray(__spreadArray([], sortedNodes, true), allCommentsFromImports, true);
var codeWithoutImportDeclarations = (0, remove_nodes_from_original_code_1.removeNodesFromOriginalCode)(code, commentAndImportsToRemoveFromCode);
var result = (0, prettier_1.format)(codeWithoutImportDeclarations, { parser: 'babel' });
expect(result).toEqual('');
});
}); });

@@ -6,5 +6,4 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.extractASTNodes = void 0;
exports.extractASTNodes = extractASTNodes;
var traverse_1 = __importDefault(require("@babel/traverse"));
var types_1 = require("@babel/types");
function extractASTNodes(ast) {

@@ -28,3 +27,3 @@ var importNodes = [];

var tsModuleParent = path.findParent(function (p) {
return (0, types_1.isTSModuleDeclaration)(p);
return p.isTSModuleDeclaration();
});

@@ -38,2 +37,1 @@ if (!tsModuleParent) {

}
exports.extractASTNodes = extractASTNodes;

@@ -26,3 +26,3 @@ "use strict";

*/
var getCodeFromAst = function (nodes, directives, originalCode, interpreter) {
var getCodeFromAst = function (nodes, directives, originalCode, interpreter, options) {
var allCommentsFromImports = (0, get_all_comments_from_nodes_1.getAllCommentsFromNodes)(nodes);

@@ -37,3 +37,2 @@ var nodesToRemoveFromCode = __spreadArray(__spreadArray(__spreadArray(__spreadArray([], directives, true), nodes, true), allCommentsFromImports, true), (interpreter ? [interpreter] : []), true);

interpreter: interpreter,
sourceFile: '',
leadingComments: [],

@@ -45,9 +44,11 @@ innerComments: [],

loc: {
start: { line: 0, column: 0 },
end: { line: 0, column: 0 },
filename: '',
identifierName: '',
start: { line: 0, column: 0, index: 0 },
end: { line: 0, column: 0, index: 0 },
},
});
var code = (0, generator_1.default)(newAST).code;
var code = (0, generator_1.default)(newAST, { importAttributesKeyword: options === null || options === void 0 ? void 0 : options.importOrderImportAttributesKeyword }).code;
return (code.replace(/"PRETTIER_PLUGIN_SORT_IMPORTS_NEW_LINE";/gi, constants_1.newLineCharacters) + codeWithoutImportsAndInterpreter.trim());
};
exports.getCodeFromAst = getCodeFromAst;

@@ -13,6 +13,13 @@ "use strict";

group: group,
regExp: new RegExp(group),
regExp: group.startsWith(constants_1.TYPES_SPECIAL_WORD)
? new RegExp(group.replace(constants_1.TYPES_SPECIAL_WORD, ''))
: new RegExp(group),
}); });
for (var _i = 0, groupWithRegExp_1 = groupWithRegExp; _i < groupWithRegExp_1.length; _i++) {
var _a = groupWithRegExp_1[_i], group = _a.group, regExp = _a.regExp;
if ((group.startsWith(constants_1.TYPES_SPECIAL_WORD) &&
node.importKind !== 'type') ||
(!group.startsWith(constants_1.TYPES_SPECIAL_WORD) &&
node.importKind === 'type'))
continue;
var matched = node.source.value.match(regExp) !== null;

@@ -22,4 +29,7 @@ if (matched)

}
return constants_1.THIRD_PARTY_MODULES_SPECIAL_WORD;
return node.importKind === 'type' &&
importOrder.find(function (group) { return group === constants_1.THIRD_PARTY_TYPES_SPECIAL_WORD; })
? constants_1.THIRD_PARTY_TYPES_SPECIAL_WORD
: constants_1.THIRD_PARTY_MODULES_SPECIAL_WORD;
};
exports.getImportNodesMatchedGroup = getImportNodesMatchedGroup;

@@ -20,3 +20,2 @@ "use strict";

var traverse_1 = __importDefault(require("@babel/traverse"));
var types_1 = require("@babel/types");
var getImportNodes = function (code, options) {

@@ -28,3 +27,3 @@ var importNodes = [];

var tsModuleParent = path.findParent(function (p) {
return (0, types_1.isTSModuleDeclaration)(p);
return p.isTSModuleDeclaration();
});

@@ -31,0 +30,0 @@ if (!tsModuleParent) {

"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getSortedNodes = void 0;
var types_1 = require("@babel/types");
var lodash_1 = require("lodash");
var constants_1 = require("../constants");
var natural_sort_1 = require("../natural-sort");
var get_import_nodes_matched_group_1 = require("./get-import-nodes-matched-group");
var get_sorted_import_specifiers_1 = require("./get-sorted-import-specifiers");
var get_sorted_nodes_group_1 = require("./get-sorted-nodes-group");
var adjust_comments_on_sorted_nodes_1 = require("./adjust-comments-on-sorted-nodes");
var get_sorted_nodes_by_import_order_1 = require("./get-sorted-nodes-by-import-order");
/**
* This function returns all the nodes which are in the importOrder array.
* The plugin considered these import nodes as local import declarations.
* @param nodes all import nodes
* @param options
* This function returns the given nodes, sorted in the order as indicated by
* the importOrder array. The plugin considers these import nodes as local
* import declarations
*
* In addition, this method preserves the relative order of side effect imports
* and non side effect imports. A side effect import is an ImportDeclaration
* without any import specifiers. It does this by splitting the import nodes at
* each side effect node, then sorting only the non side effect import nodes
* between the side effect nodes according to the given options.
* @param nodes All import nodes that should be sorted.
* @param options Options to influence the behavior of the sorting algorithm.
*/
var getSortedNodes = function (nodes, options) {
natural_sort_1.naturalSort.insensitive = options.importOrderCaseInsensitive;
var importOrder = options.importOrder;
var importOrderSeparation = options.importOrderSeparation, importOrderSortSpecifiers = options.importOrderSortSpecifiers, importOrderGroupNamespaceSpecifiers = options.importOrderGroupNamespaceSpecifiers;
var originalNodes = nodes.map(lodash_1.clone);
var importOrderSeparation = options.importOrderSeparation, importOrderSideEffects = options.importOrderSideEffects;
// Split nodes at each boundary between a side-effect node and a
// non-side-effect node, keeping both types of nodes together.
var splitBySideEffectNodes = nodes.reduce(function (chunks, node) {
var isChunkEffectNode = node.specifiers.length === 0 &&
importOrderSideEffects === false;
var type = isChunkEffectNode
? constants_1.chunkSideEffectNode
: constants_1.chunkSideOtherNode;
var last = chunks[chunks.length - 1];
if (last === undefined || last.type !== type) {
chunks.push({ type: type, nodes: [node] });
}
else {
last.nodes.push(node);
}
return chunks;
}, []);
var finalNodes = [];
if (!importOrder.includes(constants_1.THIRD_PARTY_MODULES_SPECIAL_WORD)) {
importOrder = __spreadArray([constants_1.THIRD_PARTY_MODULES_SPECIAL_WORD], importOrder, true);
}
var importOrderGroups = importOrder.reduce(function (groups, regexp) {
var _a;
return (__assign(__assign({}, groups), (_a = {}, _a[regexp] = [], _a)));
}, {});
var importOrderWithOutThirdPartyPlaceholder = importOrder.filter(function (group) { return group !== constants_1.THIRD_PARTY_MODULES_SPECIAL_WORD; });
for (var _i = 0, originalNodes_1 = originalNodes; _i < originalNodes_1.length; _i++) {
var node = originalNodes_1[_i];
var matchedGroup = (0, get_import_nodes_matched_group_1.getImportNodesMatchedGroup)(node, importOrderWithOutThirdPartyPlaceholder);
importOrderGroups[matchedGroup].push(node);
}
for (var _a = 0, importOrder_1 = importOrder; _a < importOrder_1.length; _a++) {
var group = importOrder_1[_a];
var groupNodes = importOrderGroups[group];
if (groupNodes.length === 0)
continue;
var sortedInsideGroup = (0, get_sorted_nodes_group_1.getSortedNodesGroup)(groupNodes, {
importOrderGroupNamespaceSpecifiers: importOrderGroupNamespaceSpecifiers,
});
// Sort the import specifiers
if (importOrderSortSpecifiers) {
sortedInsideGroup.forEach(function (node) {
return (0, get_sorted_import_specifiers_1.getSortedImportSpecifiers)(node);
});
// Sort each chunk of side-effect and non-side-effect nodes, and insert new
// lines according the importOrderSeparation option.
for (var _i = 0, splitBySideEffectNodes_1 = splitBySideEffectNodes; _i < splitBySideEffectNodes_1.length; _i++) {
var chunk = splitBySideEffectNodes_1[_i];
if (chunk.type === constants_1.chunkSideEffectNode) {
// do not sort side effect nodes
finalNodes.push.apply(finalNodes, chunk.nodes);
}
finalNodes.push.apply(finalNodes, sortedInsideGroup);
else {
// sort non-side effect nodes
var sorted = (0, get_sorted_nodes_by_import_order_1.getSortedNodesByImportOrder)(chunk.nodes, options);
finalNodes.push.apply(finalNodes, sorted);
}
if (importOrderSeparation) {

@@ -76,21 +58,8 @@ finalNodes.push(constants_1.newLineNode);

if (finalNodes.length > 0 && !importOrderSeparation) {
// a newline after all imports
finalNodes.push(constants_1.newLineNode);
}
// maintain a copy of the nodes to extract comments from
var finalNodesClone = finalNodes.map(lodash_1.clone);
var firstNodesComments = nodes[0].leadingComments;
// Remove all comments from sorted nodes
finalNodes.forEach(types_1.removeComments);
// insert comments other than the first comments
finalNodes.forEach(function (node, index) {
if ((0, lodash_1.isEqual)(nodes[0].loc, node.loc))
return;
(0, types_1.addComments)(node, 'leading', finalNodesClone[index].leadingComments || []);
});
if (firstNodesComments) {
(0, types_1.addComments)(finalNodes[0], 'leading', firstNodesComments);
}
// Adjust the comments on the sorted nodes to match the original comments
(0, adjust_comments_on_sorted_nodes_1.adjustCommentsOnSortedNodes)(nodes, finalNodes);
return finalNodes;
};
exports.getSortedNodes = getSortedNodes;

@@ -8,3 +8,4 @@ "use strict";

return (0, get_all_comments_from_nodes_1.getAllCommentsFromNodes)(nodes).some(function (comment) {
return comment.loc.start.line === 1 &&
return comment.loc &&
comment.loc.start.line === 1 &&
comment.value.includes(constants_1.sortImportsIgnoredComment);

@@ -11,0 +12,0 @@ });

{
"name": "@trivago/prettier-plugin-sort-imports",
"version": "4.3.0",
"version": "5.0.0",
"description": "A prettier plugins to sort imports in provided RegEx order",

@@ -17,5 +17,6 @@ "main": "lib/src/index.js",

"example": "prettier --config ./examples/.prettierrc --plugin lib/src/index.js",
"test": "jest -i",
"test": "yarn node --experimental-vm-modules $(yarn bin jest)",
"type-check": "tsc --noEmit",
"prepublishOnly": "npm run compile && npm run test"
"prepublishOnly": "npm run compile && npm run test",
"postinstall": "patch-package"
},

@@ -37,6 +38,6 @@ "keywords": [

"dependencies": {
"@babel/generator": "7.17.7",
"@babel/parser": "^7.20.5",
"@babel/traverse": "7.23.2",
"@babel/types": "7.17.0",
"@babel/generator": "7.26.2",
"@babel/parser": "7.26.2",
"@babel/traverse": "7.25.9",
"@babel/types": "7.26.0",
"javascript-natural-sort": "0.7.1",

@@ -46,22 +47,40 @@ "lodash": "^4.17.21"

"devDependencies": {
"@babel/core": "^7.20.7",
"@types/chai": "4.2.15",
"@types/jest": "26.0.20",
"@types/lodash": "4.14.168",
"@types/node": "20.8.6",
"@vue/compiler-sfc": "^3.2.41",
"jest": "26.6.3",
"prettier": "2.8",
"ts-jest": "26.5.3",
"typescript": "4.9.4"
"@babel/core": "^7.26.0",
"@types/chai": "5.0.1",
"@types/jest": "29.5.14",
"@types/lodash": "4.17.13",
"@types/node": "22.9.1",
"@vue/compiler-sfc": "^3.5.13",
"jest": "29.7.0",
"patch-package": "^8.0.0",
"postinstall-postinstall": "^2.1.0",
"prettier": "3.3.3",
"prettier-plugin-svelte": "3.3.1",
"svelte": "^4.2.19",
"ts-jest": "29.2.5",
"typescript": "5.6.3"
},
"peerDependencies": {
"@vue/compiler-sfc": "3.x",
"prettier": "2.x - 3.x"
"prettier": "2.x - 3.x",
"prettier-plugin-svelte": "3.x",
"svelte": "4.x"
},
"engines": {
"node": ">18.12"
},
"peerDependenciesMeta": {
"@vue/compiler-sfc": {
"optional": true
},
"prettier-plugin-svelte": {
"optional": true
},
"svelte": {
"optional": true
}
},
"resolutions": {
"@types/babel__generator": "7.6.8"
}
}

@@ -89,3 +89,3 @@ # Prettier plugin sort imports

**Note: There may be an issue with some package managers, such as `pnpm`. You can solve it by providing additional configuration option in prettier config file.
**Note: There may be an issue with some package managers, such as `pnpm` or when using `prettier` v3.x. You can solve it by providing additional configuration option in prettier config file.

@@ -202,2 +202,60 @@ ```js

### `importOrderSideEffects`
**type**: `boolean`
**default value**: `true`
By default, the plugin sorts [side effect imports](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#import_a_module_for_its_side_effects_only) like any other imports in the file. If you need to keep side effect imports in the same place but sort all other imports around them, set this option to false.
Example:
Initial file:
```js
import z from 'z'
import a from 'a'
import 'side-effect-lib'
import c from 'c'
import b from 'b'
```
When sorted:
```js
import a from 'a'
import z from 'z'
import 'side-effect-lib'
import b from 'b'
import c from 'c'
```
### Ignoring import ordering
In some cases it's desired to ignore import ordering, specifically if you require to instantiate a common service or polyfill in your application logic before all the other imports. The plugin supports the `// sort-imports-ignore` comment, which will exclude the file from ordering the imports.
```javascript
// sort-imports-ignore
import './polyfills';
import foo from 'foo'
```
#### `importOrderImportAttributesKeyword`
**type**: `'assert' | 'with' | 'with-legacy'`
The import attributes/assertions syntax:
- `with`: `import "..." with { type: "json" }`
- `assert`: `import "..." assert { type: "json" }`
- `with-legacy`: `import "..." with type: "json"`.
```json
"importOrderImportAttributesKeyword": 'with'
```
_Default behavior:_ When not specified, @babel/generator will try to match the style in the input code based on the AST shape.
### How does import sort work ?

@@ -225,5 +283,6 @@

| React | ✅ Everything | - |
| Solid | ✅ Everything | - |
| Angular | ✅ Everything | Supported through `importOrderParserPlugins` API |
| Vue | ✅ Everything | `@vue/compiler-sfc` is required |
| Svelte | ⚠️ Soon to be supported. | Any contribution is welcome. |
| Svelte | ✅ Everything | `prettier-plugin-svelte` is required |

@@ -230,0 +289,0 @@ ### Used by

@@ -95,4 +95,17 @@ import { ParserPlugin } from '@babel/parser';

importOrderParserPlugins?: ImportOrderParserPlugin[];
/**
* The import attributes/assertions syntax to use. "with" for import "..." with { type: "json" },
* "assert" for import "..." assert { type: "json" }, and "with-legacy" for import "..." with type: "json".
*
* ```
* "importOrderImportAttributesKeyword": 'with',
* ```
*
* _Default behavior:_ When not specified, @babel/generator will try to match the style in the input code based on the AST shape.
*/
importOrderImportAttributesKeyword?: 'assert' | 'with' | 'with-legacy';
}
export type PrettierConfig = PluginConfig & Config;
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc