prettier-plugin-sort 0.2.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +98 -258
- package/README.zh.md +92 -257
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1753 -636
- package/dist/options.d.ts +13 -16
- package/dist/parser-ast.d.ts +78 -0
- package/dist/sort-exports.d.ts +6 -9
- package/dist/sort-imports.d.ts +8 -2
- package/dist/sort-package.d.ts +6 -2
- package/dist/sort-typescript.d.ts +6 -0
- package/dist/utils/package-rules.d.ts +12 -0
- package/dist/utils/source-text.d.ts +9 -0
- package/package.json +13 -10
- package/dist/order-package.d.ts +0 -10
- package/dist/utils.d.ts +0 -8
package/dist/index.js
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
import
|
|
3
|
-
import
|
|
2
|
+
import acornPlugin from "prettier/plugins/acorn";
|
|
3
|
+
import babelPlugin from "prettier/plugins/babel";
|
|
4
|
+
import flowPlugin from "prettier/plugins/flow";
|
|
5
|
+
import meriyahPlugin from "prettier/plugins/meriyah";
|
|
6
|
+
import typescriptPlugin from "prettier/plugins/typescript";
|
|
4
7
|
|
|
5
8
|
// src/options.ts
|
|
6
9
|
var DEFAULT_SORT_OPTIONS = {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
packageJsonOrderExcludeKeys: []
|
|
10
|
+
esmImportSort: true,
|
|
11
|
+
esmImportGroups: ["builtin", "external", "parent", "sibling", "index"],
|
|
12
|
+
esmImportSeparation: true,
|
|
13
|
+
esmImportTypeStyle: "separate",
|
|
14
|
+
esmImportMerge: true,
|
|
15
|
+
esmExportSpecifierSort: true,
|
|
16
|
+
packageSort: true
|
|
15
17
|
};
|
|
16
18
|
var VALID_IMPORT_GROUPS = new Set([
|
|
17
19
|
"builtin",
|
|
@@ -21,502 +23,251 @@ var VALID_IMPORT_GROUPS = new Set([
|
|
|
21
23
|
"sibling",
|
|
22
24
|
"index"
|
|
23
25
|
]);
|
|
24
|
-
var
|
|
26
|
+
var VALID_TYPE_IMPORT_STYLES = new Set([
|
|
25
27
|
"separate",
|
|
26
28
|
"inline-first",
|
|
27
29
|
"inline-last",
|
|
28
30
|
"mixed"
|
|
29
31
|
]);
|
|
30
|
-
var isValidImportGroup = (
|
|
31
|
-
var
|
|
32
|
-
function
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
32
|
+
var isValidImportGroup = (candidateValue) => typeof candidateValue === "string" && VALID_IMPORT_GROUPS.has(candidateValue);
|
|
33
|
+
var isValidTypeImportStyle = (candidateValue) => typeof candidateValue === "string" && VALID_TYPE_IMPORT_STYLES.has(candidateValue);
|
|
34
|
+
function resolveBooleanSortOption(prettierOptions, optionName) {
|
|
35
|
+
const configuredValue = prettierOptions[optionName];
|
|
36
|
+
if (typeof configuredValue === "boolean") {
|
|
37
|
+
return configuredValue;
|
|
38
|
+
}
|
|
39
|
+
return DEFAULT_SORT_OPTIONS[optionName];
|
|
40
|
+
}
|
|
41
|
+
function resolveSortOptions(prettierOptions) {
|
|
42
|
+
const configuredImportGroups = Array.isArray(prettierOptions.esmImportGroups) ? [...new Set(prettierOptions.esmImportGroups.filter(isValidImportGroup))] : [];
|
|
43
|
+
const remainingDefaultImportGroups = DEFAULT_SORT_OPTIONS.esmImportGroups.filter((importGroup) => !configuredImportGroups.includes(importGroup));
|
|
44
|
+
const resolvedImportGroups = configuredImportGroups.length > 0 ? [...configuredImportGroups, ...remainingDefaultImportGroups] : [...DEFAULT_SORT_OPTIONS.esmImportGroups];
|
|
45
|
+
const resolvedTypeImportStyle = isValidTypeImportStyle(prettierOptions.esmImportTypeStyle) ? prettierOptions.esmImportTypeStyle : DEFAULT_SORT_OPTIONS.esmImportTypeStyle;
|
|
40
46
|
return {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
packageJsonOrderExcludeKeys: excludeKeys
|
|
47
|
+
esmImportSort: resolveBooleanSortOption(prettierOptions, "esmImportSort"),
|
|
48
|
+
esmImportGroups: resolvedImportGroups,
|
|
49
|
+
esmImportSeparation: resolveBooleanSortOption(prettierOptions, "esmImportSeparation"),
|
|
50
|
+
esmImportTypeStyle: resolvedTypeImportStyle,
|
|
51
|
+
esmImportMerge: resolveBooleanSortOption(prettierOptions, "esmImportMerge"),
|
|
52
|
+
esmExportSpecifierSort: resolveBooleanSortOption(prettierOptions, "esmExportSpecifierSort"),
|
|
53
|
+
packageSort: resolveBooleanSortOption(prettierOptions, "packageSort")
|
|
49
54
|
};
|
|
50
55
|
}
|
|
51
56
|
var options = {
|
|
52
|
-
|
|
57
|
+
esmImportSort: {
|
|
53
58
|
type: "boolean",
|
|
54
|
-
default: DEFAULT_SORT_OPTIONS.
|
|
55
|
-
category: "
|
|
56
|
-
description: "Sort
|
|
59
|
+
default: DEFAULT_SORT_OPTIONS.esmImportSort,
|
|
60
|
+
category: "ES Module Imports",
|
|
61
|
+
description: "Sort top-level ES module import declarations and named specifiers."
|
|
57
62
|
},
|
|
58
|
-
|
|
63
|
+
esmImportGroups: {
|
|
59
64
|
type: "string",
|
|
60
65
|
array: true,
|
|
61
|
-
default: [{ value: [...DEFAULT_SORT_OPTIONS.
|
|
62
|
-
category: "
|
|
63
|
-
description: '
|
|
66
|
+
default: [{ value: [...DEFAULT_SORT_OPTIONS.esmImportGroups] }],
|
|
67
|
+
category: "ES Module Imports",
|
|
68
|
+
description: 'Set import group order. Valid groups: "builtin", "external", "internal", "parent", "sibling", and "index". Unlisted groups sort after listed groups.'
|
|
64
69
|
},
|
|
65
|
-
|
|
70
|
+
esmImportSeparation: {
|
|
66
71
|
type: "boolean",
|
|
67
|
-
default: DEFAULT_SORT_OPTIONS.
|
|
68
|
-
category: "
|
|
69
|
-
description: "
|
|
72
|
+
default: DEFAULT_SORT_OPTIONS.esmImportSeparation,
|
|
73
|
+
category: "ES Module Imports",
|
|
74
|
+
description: "Add blank lines between import groups and around side-effect import boundaries."
|
|
70
75
|
},
|
|
71
|
-
|
|
76
|
+
esmImportTypeStyle: {
|
|
72
77
|
type: "choice",
|
|
73
|
-
default: DEFAULT_SORT_OPTIONS.
|
|
74
|
-
category: "
|
|
75
|
-
description: "
|
|
78
|
+
default: DEFAULT_SORT_OPTIONS.esmImportTypeStyle,
|
|
79
|
+
category: "ES Module Imports",
|
|
80
|
+
description: "Format named type imports as separate declarations or inline specifiers without changing runtime module requests.",
|
|
76
81
|
choices: [
|
|
77
82
|
{
|
|
78
83
|
value: "separate",
|
|
79
|
-
description: "
|
|
84
|
+
description: "Use a separate import type declaration."
|
|
80
85
|
},
|
|
81
86
|
{
|
|
82
87
|
value: "inline-first",
|
|
83
|
-
description: "
|
|
88
|
+
description: "Place inline type specifiers before value specifiers."
|
|
84
89
|
},
|
|
85
90
|
{
|
|
86
91
|
value: "inline-last",
|
|
87
|
-
description: "
|
|
92
|
+
description: "Place inline type specifiers after value specifiers."
|
|
88
93
|
},
|
|
89
94
|
{
|
|
90
95
|
value: "mixed",
|
|
91
|
-
description: "
|
|
96
|
+
description: "Use inline type specifiers and sort all specifiers together."
|
|
92
97
|
}
|
|
93
98
|
]
|
|
94
99
|
},
|
|
95
|
-
|
|
100
|
+
esmImportMerge: {
|
|
96
101
|
type: "boolean",
|
|
97
|
-
default: DEFAULT_SORT_OPTIONS.
|
|
98
|
-
category: "
|
|
99
|
-
description: "Merge
|
|
102
|
+
default: DEFAULT_SORT_OPTIONS.esmImportMerge,
|
|
103
|
+
category: "ES Module Imports",
|
|
104
|
+
description: "Merge compatible import declarations from the same module."
|
|
100
105
|
},
|
|
101
|
-
|
|
106
|
+
esmExportSpecifierSort: {
|
|
102
107
|
type: "boolean",
|
|
103
|
-
default: DEFAULT_SORT_OPTIONS.
|
|
104
|
-
category: "
|
|
105
|
-
description: "Sort named
|
|
108
|
+
default: DEFAULT_SORT_OPTIONS.esmExportSpecifierSort,
|
|
109
|
+
category: "ES Module Exports",
|
|
110
|
+
description: "Sort named export specifiers without reordering export declarations."
|
|
106
111
|
},
|
|
107
|
-
|
|
112
|
+
packageSort: {
|
|
108
113
|
type: "boolean",
|
|
109
|
-
default: DEFAULT_SORT_OPTIONS.
|
|
110
|
-
category: "
|
|
111
|
-
description: "Sort
|
|
112
|
-
},
|
|
113
|
-
packageJsonOrderExcludeKeys: {
|
|
114
|
-
type: "string",
|
|
115
|
-
array: true,
|
|
116
|
-
default: [{ value: [...DEFAULT_SORT_OPTIONS.packageJsonOrderExcludeKeys] }],
|
|
117
|
-
category: "SortPackageJson",
|
|
118
|
-
description: "Top-level `package.json` keys to leave untouched (no key reordering or array sorting). Takes priority over `packageJsonOrder`."
|
|
114
|
+
default: DEFAULT_SORT_OPTIONS.packageSort,
|
|
115
|
+
category: "package.json",
|
|
116
|
+
description: "Sort package.json fields using the sort-package-json community convention."
|
|
119
117
|
}
|
|
120
118
|
};
|
|
121
119
|
|
|
122
|
-
// src/
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
let current = "";
|
|
126
|
-
let depth = 0;
|
|
127
|
-
for (const char of input) {
|
|
128
|
-
if (char === "{" || char === "(" || char === "[") {
|
|
129
|
-
depth++;
|
|
130
|
-
} else if (char === "}" || char === ")" || char === "]") {
|
|
131
|
-
depth--;
|
|
132
|
-
}
|
|
133
|
-
if (char === separator && depth === 0) {
|
|
134
|
-
segments.push(current);
|
|
135
|
-
current = "";
|
|
136
|
-
continue;
|
|
137
|
-
}
|
|
138
|
-
current += char;
|
|
139
|
-
}
|
|
140
|
-
if (current.length > 0) {
|
|
141
|
-
segments.push(current);
|
|
142
|
-
}
|
|
143
|
-
return segments.map((segment) => segment.trim()).filter((segment) => segment.length > 0);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// src/sort-exports.ts
|
|
147
|
-
function sortExports(text, rawOptions) {
|
|
148
|
-
const options2 = resolveSortOptions(rawOptions);
|
|
149
|
-
if (!options2.exportOrder) {
|
|
150
|
-
return text;
|
|
151
|
-
}
|
|
152
|
-
return text.replace(/export(\s+type)?\s*\{([^}]*)\}/g, (match, typeKeyword, inner) => {
|
|
153
|
-
const members = splitTopLevel(inner, ",");
|
|
154
|
-
if (members.length <= 1) {
|
|
155
|
-
return match;
|
|
156
|
-
}
|
|
157
|
-
const sorted = [...members].sort((a, b) => stripTypePrefix(a).localeCompare(stripTypePrefix(b), "en", {
|
|
158
|
-
sensitivity: "base"
|
|
159
|
-
}));
|
|
160
|
-
const unchanged = sorted.every((member, index) => member === members[index]);
|
|
161
|
-
if (unchanged) {
|
|
162
|
-
return match;
|
|
163
|
-
}
|
|
164
|
-
const prefix = typeKeyword ? `export${typeKeyword}` : "export";
|
|
165
|
-
return `${prefix} { ${sorted.join(", ")} }`;
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
function stripTypePrefix(member) {
|
|
169
|
-
return member.replace(/^type\s+/, "");
|
|
170
|
-
}
|
|
120
|
+
// src/sort-package.ts
|
|
121
|
+
import findMinimumSemanticVersion from "semver/ranges/min-version.js";
|
|
122
|
+
import getValidSemanticVersionRange from "semver/ranges/valid.js";
|
|
171
123
|
|
|
172
|
-
// src/
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
function detectGroup(source) {
|
|
177
|
-
if (source === "bun" || source.startsWith("bun:") || source.startsWith("node:")) {
|
|
178
|
-
return "builtin";
|
|
179
|
-
}
|
|
180
|
-
const slashIndex = source.indexOf("/");
|
|
181
|
-
const head = slashIndex === -1 ? source : source.slice(0, slashIndex);
|
|
182
|
-
if (head && NODE_BUILTINS.has(head)) {
|
|
183
|
-
return "builtin";
|
|
184
|
-
}
|
|
185
|
-
if (source === "." || source === "./" || INDEX_PATTERN.test(source)) {
|
|
186
|
-
return "index";
|
|
187
|
-
}
|
|
188
|
-
if (source.startsWith("../") || source === "..") {
|
|
189
|
-
return "parent";
|
|
190
|
-
}
|
|
191
|
-
if (source.startsWith("./")) {
|
|
192
|
-
return "sibling";
|
|
124
|
+
// src/parser-ast.ts
|
|
125
|
+
function getAstNodeTextRange(node) {
|
|
126
|
+
if (!node) {
|
|
127
|
+
return null;
|
|
193
128
|
}
|
|
194
|
-
|
|
195
|
-
|
|
129
|
+
const [start = NaN, end = NaN] = node.range ?? [node.start, node.end];
|
|
130
|
+
const isOffsetRangeValid = [start, end].every(Number.isSafeInteger) && start >= 0 && end >= start;
|
|
131
|
+
if (!isOffsetRangeValid) {
|
|
132
|
+
return null;
|
|
196
133
|
}
|
|
197
|
-
return
|
|
134
|
+
return { start, end };
|
|
198
135
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
});
|
|
136
|
+
function getSortedAstCommentsWithTextRanges(comments) {
|
|
137
|
+
return comments.flatMap((comment) => {
|
|
138
|
+
const textRange = getAstNodeTextRange(comment);
|
|
139
|
+
return textRange ? [{ comment, textRange }] : [];
|
|
140
|
+
}).sort((left, right) => left.textRange.start - right.textRange.start || left.textRange.end - right.textRange.end);
|
|
205
141
|
}
|
|
206
|
-
function
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
sideEffect: true,
|
|
215
|
-
defaultSpec: null,
|
|
216
|
-
namespaceSpec: null,
|
|
217
|
-
members: null,
|
|
218
|
-
attributes: sideEffect[3] ?? null,
|
|
219
|
-
leadingComments
|
|
220
|
-
};
|
|
221
|
-
}
|
|
222
|
-
const match = /^import\s+(type\s+)?([\s\S]+?)\s*from\s*(['"])([^'"]+)\3(?:\s+with\s*(\{[^}]*\}))?\s*;?$/.exec(trimmed);
|
|
223
|
-
if (!match) {
|
|
224
|
-
return null;
|
|
225
|
-
}
|
|
226
|
-
const typeClause = Boolean(match[1]);
|
|
227
|
-
const clause = (match[2] ?? "").trim();
|
|
228
|
-
const source = match[4] ?? "";
|
|
229
|
-
const attributes = match[5] ?? null;
|
|
230
|
-
let defaultSpec = null;
|
|
231
|
-
let namespaceSpec = null;
|
|
232
|
-
let members = null;
|
|
233
|
-
for (const part of splitTopLevel(clause, ",")) {
|
|
234
|
-
if (part.startsWith("{")) {
|
|
235
|
-
const inner = part.slice(1, part.lastIndexOf("}")).trim();
|
|
236
|
-
members = inner ? splitMembers(inner) : [];
|
|
237
|
-
} else if (part.startsWith("*")) {
|
|
238
|
-
namespaceSpec = part;
|
|
142
|
+
function findCommentIndexAtOrAfter(sortedComments, sourceIndex) {
|
|
143
|
+
let searchStartIndex = 0;
|
|
144
|
+
let searchEndIndex = sortedComments.length;
|
|
145
|
+
while (searchStartIndex < searchEndIndex) {
|
|
146
|
+
const middleIndex = Math.floor((searchStartIndex + searchEndIndex) / 2);
|
|
147
|
+
const middleCommentStart = sortedComments[middleIndex].textRange.start;
|
|
148
|
+
if (middleCommentStart < sourceIndex) {
|
|
149
|
+
searchStartIndex = middleIndex + 1;
|
|
239
150
|
} else {
|
|
240
|
-
|
|
151
|
+
searchEndIndex = middleIndex;
|
|
241
152
|
}
|
|
242
153
|
}
|
|
243
|
-
return
|
|
244
|
-
source,
|
|
245
|
-
typeClause,
|
|
246
|
-
sideEffect: false,
|
|
247
|
-
defaultSpec,
|
|
248
|
-
namespaceSpec,
|
|
249
|
-
members,
|
|
250
|
-
attributes,
|
|
251
|
-
leadingComments
|
|
252
|
-
};
|
|
154
|
+
return searchStartIndex;
|
|
253
155
|
}
|
|
254
|
-
function
|
|
255
|
-
|
|
256
|
-
const first = firstRe.exec(text);
|
|
257
|
-
if (!first) {
|
|
156
|
+
function getAstNodeName(node) {
|
|
157
|
+
if (!node) {
|
|
258
158
|
return null;
|
|
259
159
|
}
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
const statements = [];
|
|
263
|
-
const skipRe = /(?:[ \t]*(?:\/\/[^\n]*|\/\*[\s\S]*?\*\/)?[ \t]*\n)*/y;
|
|
264
|
-
const importRe = /[ \t]*(import\b(?![.(])[\s\S]*?(?:from\s*(['"])[^'"]+\2|(['"])[^'"]+\3)(?:\s+with\s*\{[^}]*\})?\s*;?)/y;
|
|
265
|
-
let cursor = start;
|
|
266
|
-
while (cursor < text.length) {
|
|
267
|
-
skipRe.lastIndex = cursor;
|
|
268
|
-
const skipMatch = skipRe.exec(text);
|
|
269
|
-
const skipped = skipMatch ? skipMatch[0] : "";
|
|
270
|
-
const afterSkip = cursor + skipped.length;
|
|
271
|
-
importRe.lastIndex = afterSkip;
|
|
272
|
-
const importMatch = importRe.exec(text);
|
|
273
|
-
if (!importMatch) {
|
|
274
|
-
break;
|
|
275
|
-
}
|
|
276
|
-
const normalised = skipped.endsWith(`
|
|
277
|
-
`) ? skipped.slice(0, -1) : skipped;
|
|
278
|
-
const commentLines = normalised.length > 0 ? normalised.split(`
|
|
279
|
-
`) : [];
|
|
280
|
-
const leadingLines = [];
|
|
281
|
-
for (let i = commentLines.length - 1;i >= 0; i--) {
|
|
282
|
-
const line = commentLines[i];
|
|
283
|
-
if (line.trim() === "") {
|
|
284
|
-
break;
|
|
285
|
-
}
|
|
286
|
-
leadingLines.unshift(line);
|
|
287
|
-
}
|
|
288
|
-
const leadingComments = leadingLines.length > 0 ? leadingLines.join(`
|
|
289
|
-
`) + `
|
|
290
|
-
` : "";
|
|
291
|
-
const statement = importMatch[1];
|
|
292
|
-
if (!statement) {
|
|
293
|
-
break;
|
|
294
|
-
}
|
|
295
|
-
statements.push({ raw: statement.trim(), leadingComments });
|
|
296
|
-
cursor = afterSkip + importMatch[0].length;
|
|
160
|
+
if (typeof node.name === "string") {
|
|
161
|
+
return node.name;
|
|
297
162
|
}
|
|
298
|
-
|
|
299
|
-
|
|
163
|
+
switch (typeof node.value) {
|
|
164
|
+
case "string":
|
|
165
|
+
case "number":
|
|
166
|
+
case "boolean":
|
|
167
|
+
return String(node.value);
|
|
168
|
+
default:
|
|
169
|
+
return null;
|
|
300
170
|
}
|
|
301
|
-
return { start, end: cursor, statements };
|
|
302
171
|
}
|
|
303
|
-
function
|
|
304
|
-
return
|
|
172
|
+
function getAstCommentText(comment) {
|
|
173
|
+
return typeof comment.value === "string" ? comment.value : null;
|
|
305
174
|
}
|
|
306
|
-
function
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
parts.push(importDecl.defaultSpec);
|
|
175
|
+
function getProgramStatements(parserAst) {
|
|
176
|
+
if (Array.isArray(parserAst.body)) {
|
|
177
|
+
return parserAst.body;
|
|
310
178
|
}
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
if (importDecl.members) {
|
|
315
|
-
parts.push(`{ ${renderMembers(importDecl.members)} }`);
|
|
179
|
+
const programNode = parserAst.program;
|
|
180
|
+
if (!programNode || !Array.isArray(programNode.body)) {
|
|
181
|
+
return [];
|
|
316
182
|
}
|
|
317
|
-
return
|
|
183
|
+
return programNode.body;
|
|
318
184
|
}
|
|
319
|
-
function
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
const body = importDecl.sideEffect ? `import ${source}${suffix};` : importDecl.typeClause ? `import type ${renderSpecifiers(importDecl)} from ${source}${suffix};` : `import ${renderSpecifiers(importDecl)} from ${source}${suffix};`;
|
|
323
|
-
return importDecl.leadingComments + body;
|
|
324
|
-
}
|
|
325
|
-
function sortMembersAlpha(members) {
|
|
326
|
-
return [...members].sort((a, b) => a.name.localeCompare(b.name, "en", { sensitivity: "base" }));
|
|
327
|
-
}
|
|
328
|
-
function normalizeTypeClause(importDecl) {
|
|
329
|
-
if (!importDecl.typeClause || importDecl.members === null) {
|
|
330
|
-
return importDecl;
|
|
185
|
+
function getProgramComments(parserAst) {
|
|
186
|
+
if (Array.isArray(parserAst.comments)) {
|
|
187
|
+
return parserAst.comments;
|
|
331
188
|
}
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
189
|
+
const programNode = parserAst.program;
|
|
190
|
+
if (!programNode || !Array.isArray(programNode.comments)) {
|
|
191
|
+
return [];
|
|
192
|
+
}
|
|
193
|
+
return programNode.comments;
|
|
337
194
|
}
|
|
338
|
-
function
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
for (
|
|
342
|
-
const
|
|
343
|
-
if (
|
|
344
|
-
|
|
345
|
-
continue;
|
|
195
|
+
function isSourceRangeWhitespaceOrComments(sourceText, sourceRange, sortedComments) {
|
|
196
|
+
let sourceIndex = sourceRange.start;
|
|
197
|
+
let commentIndex = Math.max(findCommentIndexAtOrAfter(sortedComments, sourceRange.start) - 1, 0);
|
|
198
|
+
for (;commentIndex < sortedComments.length; commentIndex++) {
|
|
199
|
+
const parserComment = sortedComments[commentIndex];
|
|
200
|
+
if (!parserComment || parserComment.textRange.start >= sourceRange.end) {
|
|
201
|
+
break;
|
|
346
202
|
}
|
|
347
|
-
|
|
348
|
-
const existingIndex = indexByKey.get(mergeKey);
|
|
349
|
-
if (existingIndex === undefined) {
|
|
350
|
-
indexByKey.set(mergeKey, result.length);
|
|
351
|
-
result.push(importDecl);
|
|
203
|
+
if (parserComment.textRange.end <= sourceIndex) {
|
|
352
204
|
continue;
|
|
353
205
|
}
|
|
354
|
-
const
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
typeClause: false,
|
|
358
|
-
sideEffect: false,
|
|
359
|
-
defaultSpec: existing.defaultSpec ?? importDecl.defaultSpec,
|
|
360
|
-
namespaceSpec: existing.namespaceSpec ?? importDecl.namespaceSpec,
|
|
361
|
-
members: existing.members === null && importDecl.members === null ? null : [...existing.members ?? [], ...importDecl.members ?? []],
|
|
362
|
-
attributes: existing.attributes,
|
|
363
|
-
leadingComments: existing.leadingComments
|
|
364
|
-
};
|
|
365
|
-
}
|
|
366
|
-
return result;
|
|
367
|
-
}
|
|
368
|
-
function applyTypeImports(importDecl, style) {
|
|
369
|
-
if (importDecl.sideEffect || !importDecl.members) {
|
|
370
|
-
return [importDecl];
|
|
371
|
-
}
|
|
372
|
-
if (style === "separate") {
|
|
373
|
-
if (importDecl.typeClause) {
|
|
374
|
-
return [importDecl];
|
|
375
|
-
}
|
|
376
|
-
const typeMembers2 = importDecl.members.filter((member) => member.isType);
|
|
377
|
-
const valueMembers2 = importDecl.members.filter((member) => !member.isType);
|
|
378
|
-
const output = [];
|
|
379
|
-
if (typeMembers2.length > 0) {
|
|
380
|
-
output.push({
|
|
381
|
-
source: importDecl.source,
|
|
382
|
-
typeClause: true,
|
|
383
|
-
sideEffect: false,
|
|
384
|
-
defaultSpec: null,
|
|
385
|
-
namespaceSpec: null,
|
|
386
|
-
members: sortMembersAlpha(typeMembers2.map((member) => ({ ...member, isType: false }))),
|
|
387
|
-
attributes: importDecl.attributes,
|
|
388
|
-
leadingComments: importDecl.leadingComments
|
|
389
|
-
});
|
|
390
|
-
}
|
|
391
|
-
const hasValueBody = valueMembers2.length > 0 || importDecl.defaultSpec !== null || importDecl.namespaceSpec !== null;
|
|
392
|
-
if (hasValueBody) {
|
|
393
|
-
output.push({
|
|
394
|
-
...importDecl,
|
|
395
|
-
members: valueMembers2.length > 0 ? sortMembersAlpha(valueMembers2) : null,
|
|
396
|
-
leadingComments: typeMembers2.length > 0 ? "" : importDecl.leadingComments
|
|
397
|
-
});
|
|
206
|
+
const commentStart = Math.max(parserComment.textRange.start, sourceRange.start);
|
|
207
|
+
if (sourceText.slice(sourceIndex, commentStart).trim() !== "") {
|
|
208
|
+
return false;
|
|
398
209
|
}
|
|
399
|
-
|
|
400
|
-
}
|
|
401
|
-
const inlineBase = importDecl.typeClause ? {
|
|
402
|
-
...importDecl,
|
|
403
|
-
typeClause: false,
|
|
404
|
-
members: importDecl.members.map((member) => ({
|
|
405
|
-
...member,
|
|
406
|
-
isType: true
|
|
407
|
-
}))
|
|
408
|
-
} : { ...importDecl, members: importDecl.members };
|
|
409
|
-
if (style === "mixed") {
|
|
410
|
-
return [{ ...inlineBase, members: sortMembersAlpha(inlineBase.members) }];
|
|
411
|
-
}
|
|
412
|
-
const typeMembers = inlineBase.members.filter((member) => member.isType);
|
|
413
|
-
const valueMembers = inlineBase.members.filter((member) => !member.isType);
|
|
414
|
-
const sortedTypes = sortMembersAlpha(typeMembers);
|
|
415
|
-
const sortedValues = sortMembersAlpha(valueMembers);
|
|
416
|
-
const ordered = style === "inline-first" ? [...sortedTypes, ...sortedValues] : [...sortedValues, ...sortedTypes];
|
|
417
|
-
return [{ ...inlineBase, members: ordered }];
|
|
418
|
-
}
|
|
419
|
-
function sortSegment(imports, options2, groupIndex, fallback) {
|
|
420
|
-
if (imports.length === 0) {
|
|
421
|
-
return [];
|
|
210
|
+
sourceIndex = Math.min(parserComment.textRange.end, sourceRange.end);
|
|
422
211
|
}
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
decorated.sort((a, b) => {
|
|
432
|
-
const groupOrderA = groupIndex.get(a.group) ?? fallback;
|
|
433
|
-
const groupOrderB = groupIndex.get(b.group) ?? fallback;
|
|
434
|
-
if (groupOrderA !== groupOrderB) {
|
|
435
|
-
return groupOrderA - groupOrderB;
|
|
212
|
+
return sourceText.slice(sourceIndex, sourceRange.end).trim() === "";
|
|
213
|
+
}
|
|
214
|
+
function isPrettierIgnored(sourceText, statementRange, sortedComments) {
|
|
215
|
+
let leadingCommentsStart = statementRange.start;
|
|
216
|
+
for (let commentIndex = findCommentIndexAtOrAfter(sortedComments, statementRange.start) - 1;commentIndex >= 0; commentIndex--) {
|
|
217
|
+
const parserComment = sortedComments[commentIndex];
|
|
218
|
+
if (!parserComment || parserComment.textRange.end > statementRange.start) {
|
|
219
|
+
continue;
|
|
436
220
|
}
|
|
437
|
-
const
|
|
438
|
-
const
|
|
439
|
-
if (
|
|
440
|
-
|
|
221
|
+
const { comment, textRange } = parserComment;
|
|
222
|
+
const followingText = sourceText.slice(textRange.end, leadingCommentsStart);
|
|
223
|
+
if (followingText.trim() !== "") {
|
|
224
|
+
break;
|
|
441
225
|
}
|
|
442
|
-
if (
|
|
443
|
-
|
|
226
|
+
if (followingText.includes(`
|
|
227
|
+
`)) {
|
|
228
|
+
const commentLineStart = sourceText.lastIndexOf(`
|
|
229
|
+
`, textRange.start - 1) + 1;
|
|
230
|
+
const isCommentLinePrefixEmpty = isSourceRangeWhitespaceOrComments(sourceText, { start: commentLineStart, end: textRange.start }, sortedComments);
|
|
231
|
+
if (!isCommentLinePrefixEmpty) {
|
|
232
|
+
break;
|
|
233
|
+
}
|
|
444
234
|
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
for (const item of decorated) {
|
|
450
|
-
if (options2.importOrderSeparation && previousGroup !== null && item.group !== previousGroup) {
|
|
451
|
-
lines.push("");
|
|
235
|
+
const commentText = getAstCommentText(comment);
|
|
236
|
+
const isPrettierIgnoreComment = commentText?.trim() === "prettier-ignore";
|
|
237
|
+
if (isPrettierIgnoreComment) {
|
|
238
|
+
return true;
|
|
452
239
|
}
|
|
453
|
-
|
|
454
|
-
previousGroup = item.group;
|
|
455
|
-
}
|
|
456
|
-
return lines;
|
|
457
|
-
}
|
|
458
|
-
function sortImports(text, rawOptions) {
|
|
459
|
-
const options2 = resolveSortOptions(rawOptions);
|
|
460
|
-
if (!options2.importOrder) {
|
|
461
|
-
return text;
|
|
462
|
-
}
|
|
463
|
-
const block = extractImportBlock(text);
|
|
464
|
-
if (!block || block.statements.length === 0) {
|
|
465
|
-
return text;
|
|
240
|
+
leadingCommentsStart = textRange.start;
|
|
466
241
|
}
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
group,
|
|
473
|
-
index
|
|
474
|
-
]));
|
|
475
|
-
const fallback = options2.importOrderGroups.length;
|
|
476
|
-
const chunks = [];
|
|
477
|
-
let currentSegment = [];
|
|
478
|
-
for (const importDecl of parsed) {
|
|
479
|
-
if (importDecl.sideEffect) {
|
|
480
|
-
if (currentSegment.length > 0) {
|
|
481
|
-
chunks.push({ kind: "segment", imports: currentSegment });
|
|
482
|
-
currentSegment = [];
|
|
483
|
-
}
|
|
484
|
-
chunks.push({ kind: "side-effect", importDecl });
|
|
485
|
-
} else {
|
|
486
|
-
currentSegment.push(importDecl);
|
|
242
|
+
let trailingCommentsEnd = statementRange.end;
|
|
243
|
+
for (let commentIndex = findCommentIndexAtOrAfter(sortedComments, statementRange.end);commentIndex < sortedComments.length; commentIndex++) {
|
|
244
|
+
const parserComment = sortedComments[commentIndex];
|
|
245
|
+
if (!parserComment) {
|
|
246
|
+
break;
|
|
487
247
|
}
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
let previousKind = null;
|
|
494
|
-
for (const chunk of chunks) {
|
|
495
|
-
if (previousKind !== null && previousKind !== chunk.kind && options2.importOrderSeparation) {
|
|
496
|
-
allLines.push("");
|
|
248
|
+
const { comment, textRange } = parserComment;
|
|
249
|
+
const textBeforeComment = sourceText.slice(trailingCommentsEnd, textRange.start);
|
|
250
|
+
if (textBeforeComment.includes(`
|
|
251
|
+
`) || textBeforeComment.trim() !== "") {
|
|
252
|
+
break;
|
|
497
253
|
}
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
254
|
+
const commentLineEnd = sourceText.indexOf(`
|
|
255
|
+
`, textRange.end);
|
|
256
|
+
const isCommentLastOnLine = isSourceRangeWhitespaceOrComments(sourceText, {
|
|
257
|
+
start: textRange.end,
|
|
258
|
+
end: commentLineEnd < 0 ? sourceText.length : commentLineEnd
|
|
259
|
+
}, sortedComments);
|
|
260
|
+
const commentText = getAstCommentText(comment);
|
|
261
|
+
if (isCommentLastOnLine && commentText?.trim() === "prettier-ignore") {
|
|
262
|
+
return true;
|
|
502
263
|
}
|
|
503
|
-
|
|
264
|
+
trailingCommentsEnd = textRange.end;
|
|
504
265
|
}
|
|
505
|
-
|
|
506
|
-
`);
|
|
507
|
-
const trailing = text.slice(block.end);
|
|
508
|
-
const nonBlankIndex = trailing.search(/\S/);
|
|
509
|
-
const suffix = nonBlankIndex >= 0 ? `
|
|
510
|
-
|
|
511
|
-
` + trailing.slice(nonBlankIndex) : trailing;
|
|
512
|
-
return text.slice(0, block.start) + replacement + suffix;
|
|
266
|
+
return false;
|
|
513
267
|
}
|
|
514
268
|
|
|
515
|
-
// src/
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
// src/order-package.ts
|
|
519
|
-
var PACKAGE_JSON_TOP_LEVEL_ORDER = [
|
|
269
|
+
// src/utils/package-rules.ts
|
|
270
|
+
var PACKAGE_JSON_FIELD_ORDER = [
|
|
520
271
|
"$schema",
|
|
521
272
|
"name",
|
|
522
273
|
"displayName",
|
|
@@ -565,6 +316,7 @@ var PACKAGE_JSON_TOP_LEVEL_ORDER = [
|
|
|
565
316
|
"binary",
|
|
566
317
|
"scripts",
|
|
567
318
|
"betterScripts",
|
|
319
|
+
"wireit",
|
|
568
320
|
"l10n",
|
|
569
321
|
"contributes",
|
|
570
322
|
"activationEvents",
|
|
@@ -628,263 +380,1628 @@ var PACKAGE_JSON_TOP_LEVEL_ORDER = [
|
|
|
628
380
|
"markdown",
|
|
629
381
|
"pnpm"
|
|
630
382
|
];
|
|
631
|
-
var
|
|
383
|
+
var DIRECTORY_FIELD_ORDER = [
|
|
384
|
+
"lib",
|
|
385
|
+
"bin",
|
|
386
|
+
"man",
|
|
387
|
+
"doc",
|
|
388
|
+
"example",
|
|
389
|
+
"test"
|
|
390
|
+
];
|
|
391
|
+
var ESLINT_CONFIG_FIELD_ORDER = [
|
|
392
|
+
"files",
|
|
393
|
+
"excludedFiles",
|
|
394
|
+
"env",
|
|
395
|
+
"parser",
|
|
396
|
+
"parserOptions",
|
|
397
|
+
"settings",
|
|
398
|
+
"plugins",
|
|
399
|
+
"extends",
|
|
400
|
+
"rules",
|
|
401
|
+
"overrides",
|
|
402
|
+
"globals",
|
|
403
|
+
"processor",
|
|
404
|
+
"noInlineConfig",
|
|
405
|
+
"reportUnusedDisableDirectives"
|
|
406
|
+
];
|
|
407
|
+
var GIT_HOOK_ORDER = [
|
|
408
|
+
"applypatch-msg",
|
|
409
|
+
"pre-applypatch",
|
|
410
|
+
"post-applypatch",
|
|
411
|
+
"pre-commit",
|
|
412
|
+
"pre-merge-commit",
|
|
413
|
+
"prepare-commit-msg",
|
|
414
|
+
"commit-msg",
|
|
415
|
+
"post-commit",
|
|
416
|
+
"pre-rebase",
|
|
417
|
+
"post-checkout",
|
|
418
|
+
"post-merge",
|
|
419
|
+
"pre-push",
|
|
420
|
+
"pre-receive",
|
|
421
|
+
"update",
|
|
422
|
+
"proc-receive",
|
|
423
|
+
"post-receive",
|
|
424
|
+
"post-update",
|
|
425
|
+
"reference-transaction",
|
|
426
|
+
"push-to-checkout",
|
|
427
|
+
"pre-auto-gc",
|
|
428
|
+
"post-rewrite",
|
|
429
|
+
"sendemail-validate",
|
|
430
|
+
"fsmonitor-watchman",
|
|
431
|
+
"p4-changelist",
|
|
432
|
+
"p4-prepare-changelist",
|
|
433
|
+
"p4-post-changelist",
|
|
434
|
+
"p4-pre-submit",
|
|
435
|
+
"post-index-change"
|
|
436
|
+
];
|
|
437
|
+
var NPM_LIFECYCLE_SCRIPT_NAMES = new Set([
|
|
438
|
+
"install",
|
|
439
|
+
"pack",
|
|
440
|
+
"prepare",
|
|
441
|
+
"publish",
|
|
442
|
+
"restart",
|
|
443
|
+
"shrinkwrap",
|
|
444
|
+
"start",
|
|
445
|
+
"stop",
|
|
446
|
+
"test",
|
|
447
|
+
"uninstall",
|
|
448
|
+
"version"
|
|
449
|
+
]);
|
|
450
|
+
var PNPM_CONFIG_FIELD_ORDER = [
|
|
451
|
+
"peerDependencyRules",
|
|
452
|
+
"neverBuiltDependencies",
|
|
453
|
+
"onlyBuiltDependencies",
|
|
454
|
+
"onlyBuiltDependenciesFile",
|
|
455
|
+
"allowedDeprecatedVersions",
|
|
456
|
+
"allowNonAppliedPatches",
|
|
457
|
+
"updateConfig",
|
|
458
|
+
"auditConfig",
|
|
459
|
+
"requiredScripts",
|
|
460
|
+
"supportedArchitectures",
|
|
461
|
+
"overrides",
|
|
462
|
+
"patchedDependencies",
|
|
463
|
+
"packageExtensions"
|
|
464
|
+
];
|
|
465
|
+
var WIREIT_SCRIPT_FIELD_ORDER = [
|
|
466
|
+
"command",
|
|
632
467
|
"dependencies",
|
|
633
|
-
"
|
|
634
|
-
"
|
|
635
|
-
"optionalDependencies",
|
|
636
|
-
"resolutions",
|
|
637
|
-
"overrides"
|
|
468
|
+
"files",
|
|
469
|
+
"output"
|
|
638
470
|
];
|
|
639
471
|
|
|
640
472
|
// src/sort-package.ts
|
|
641
|
-
|
|
642
|
-
|
|
473
|
+
class JsonSourceLiteral {
|
|
474
|
+
value;
|
|
475
|
+
sourceText;
|
|
476
|
+
constructor(value, sourceText) {
|
|
477
|
+
this.value = value;
|
|
478
|
+
this.sourceText = sourceText;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
var SEQUENTIAL_SCRIPT_PATTERN = /(?<=^|[\s&;<>|(])(?:run-s|npm-run-all2? .*(?:--sequential|--serial|-s))(?=$|[\s&;<>|)])/;
|
|
482
|
+
function compareText(leftText, rightText) {
|
|
483
|
+
if (leftText === rightText) {
|
|
484
|
+
return 0;
|
|
485
|
+
}
|
|
486
|
+
return leftText < rightText ? -1 : 1;
|
|
487
|
+
}
|
|
488
|
+
function isJsonObject(value) {
|
|
489
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) && !(value instanceof JsonSourceLiteral);
|
|
490
|
+
}
|
|
491
|
+
function getJsonPathKey(jsonPath) {
|
|
492
|
+
return JSON.stringify(jsonPath);
|
|
493
|
+
}
|
|
494
|
+
function getJsonString(jsonValue) {
|
|
495
|
+
if (typeof jsonValue === "string") {
|
|
496
|
+
return jsonValue;
|
|
497
|
+
}
|
|
498
|
+
if (jsonValue instanceof JsonSourceLiteral && typeof jsonValue.value === "string") {
|
|
499
|
+
return jsonValue.value;
|
|
500
|
+
}
|
|
501
|
+
return null;
|
|
502
|
+
}
|
|
503
|
+
function isJsonStringValue(jsonValue) {
|
|
504
|
+
return getJsonString(jsonValue) !== null;
|
|
505
|
+
}
|
|
506
|
+
function isParserJsonAstNode(value) {
|
|
507
|
+
return typeof value === "object" && value !== null && "type" in value && typeof value.type === "string";
|
|
508
|
+
}
|
|
509
|
+
function preserveJsonSourceLiterals(jsonValue, parserJsonNode, sourceText, fieldNameSourceTexts, jsonPath = []) {
|
|
510
|
+
if (parserJsonNode.type === "JsonRoot") {
|
|
511
|
+
const rootNode = parserJsonNode.node;
|
|
512
|
+
if (!isParserJsonAstNode(rootNode)) {
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
return preserveJsonSourceLiterals(jsonValue, rootNode, sourceText, fieldNameSourceTexts, jsonPath);
|
|
516
|
+
}
|
|
517
|
+
const isStringLiteral = parserJsonNode.type === "StringLiteral";
|
|
518
|
+
const isNumberLiteral = parserJsonNode.type === "NumericLiteral";
|
|
519
|
+
const isNegativeNumberLiteral = parserJsonNode.type === "UnaryExpression" && parserJsonNode.operator === "-" && parserJsonNode.argument?.type === "NumericLiteral";
|
|
520
|
+
if (isStringLiteral || isNumberLiteral || isNegativeNumberLiteral) {
|
|
521
|
+
const literalRange = getAstNodeTextRange(parserJsonNode);
|
|
522
|
+
const isLiteralValueValid = isStringLiteral && typeof jsonValue === "string" || !isStringLiteral && typeof jsonValue === "number";
|
|
523
|
+
if (!literalRange || !isLiteralValueValid) {
|
|
524
|
+
return;
|
|
525
|
+
}
|
|
526
|
+
return new JsonSourceLiteral(jsonValue, sourceText.slice(literalRange.start, literalRange.end));
|
|
527
|
+
}
|
|
528
|
+
if (parserJsonNode.type === "ObjectExpression") {
|
|
529
|
+
if (!isJsonObject(jsonValue) || !Array.isArray(parserJsonNode.properties)) {
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
const jsonObject = { ...jsonValue };
|
|
533
|
+
const propertyNames = new Set;
|
|
534
|
+
for (const propertyNode of parserJsonNode.properties) {
|
|
535
|
+
const propertyName = getAstNodeName(propertyNode.key);
|
|
536
|
+
const propertyNameRange = getAstNodeTextRange(propertyNode.key);
|
|
537
|
+
const propertyValueNode = propertyNode.value;
|
|
538
|
+
if (propertyNode.type !== "ObjectProperty" || propertyName === null || !propertyNameRange || propertyNames.has(propertyName) || !Object.hasOwn(jsonValue, propertyName) || !isParserJsonAstNode(propertyValueNode)) {
|
|
539
|
+
return;
|
|
540
|
+
}
|
|
541
|
+
propertyNames.add(propertyName);
|
|
542
|
+
const propertyPath = [...jsonPath, propertyName];
|
|
543
|
+
const propertyValue = preserveJsonSourceLiterals(jsonValue[propertyName], propertyValueNode, sourceText, fieldNameSourceTexts, propertyPath);
|
|
544
|
+
if (propertyValue === undefined) {
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
547
|
+
fieldNameSourceTexts.set(getJsonPathKey(propertyPath), sourceText.slice(propertyNameRange.start, propertyNameRange.end));
|
|
548
|
+
jsonObject[propertyName] = propertyValue;
|
|
549
|
+
}
|
|
550
|
+
return jsonObject;
|
|
551
|
+
}
|
|
552
|
+
if (parserJsonNode.type === "ArrayExpression") {
|
|
553
|
+
if (!Array.isArray(jsonValue) || !Array.isArray(parserJsonNode.elements) || jsonValue.length !== parserJsonNode.elements.length) {
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
const jsonArray = [];
|
|
557
|
+
for (const [
|
|
558
|
+
elementIndex,
|
|
559
|
+
elementNode
|
|
560
|
+
] of parserJsonNode.elements.entries()) {
|
|
561
|
+
if (!elementNode) {
|
|
562
|
+
return;
|
|
563
|
+
}
|
|
564
|
+
const elementValue = preserveJsonSourceLiterals(jsonValue[elementIndex], elementNode, sourceText, fieldNameSourceTexts, [...jsonPath, elementIndex]);
|
|
565
|
+
if (elementValue === undefined) {
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
jsonArray.push(elementValue);
|
|
569
|
+
}
|
|
570
|
+
return jsonArray;
|
|
571
|
+
}
|
|
572
|
+
return jsonValue;
|
|
573
|
+
}
|
|
574
|
+
function serializeJsonValue(jsonValue, fieldNameSourceTexts, jsonPath = []) {
|
|
575
|
+
if (jsonValue instanceof JsonSourceLiteral) {
|
|
576
|
+
return jsonValue.sourceText;
|
|
577
|
+
}
|
|
578
|
+
if (typeof jsonValue === "number" || typeof jsonValue === "string") {
|
|
579
|
+
return null;
|
|
580
|
+
}
|
|
581
|
+
if (Array.isArray(jsonValue)) {
|
|
582
|
+
const serializedValues = [];
|
|
583
|
+
for (const [arrayIndex, arrayValue] of jsonValue.entries()) {
|
|
584
|
+
const serializedValue = serializeJsonValue(arrayValue, fieldNameSourceTexts, [...jsonPath, arrayIndex]);
|
|
585
|
+
if (serializedValue === null) {
|
|
586
|
+
return null;
|
|
587
|
+
}
|
|
588
|
+
serializedValues.push(serializedValue);
|
|
589
|
+
}
|
|
590
|
+
return `[${serializedValues.join(",")}]`;
|
|
591
|
+
}
|
|
592
|
+
if (isJsonObject(jsonValue)) {
|
|
593
|
+
const serializedFields = [];
|
|
594
|
+
for (const [fieldName, fieldValue] of Object.entries(jsonValue)) {
|
|
595
|
+
const fieldPath = [...jsonPath, fieldName];
|
|
596
|
+
const fieldNameSourceText = fieldNameSourceTexts.get(getJsonPathKey(fieldPath));
|
|
597
|
+
const serializedValue = serializeJsonValue(fieldValue, fieldNameSourceTexts, fieldPath);
|
|
598
|
+
if (!fieldNameSourceText || serializedValue === null) {
|
|
599
|
+
return null;
|
|
600
|
+
}
|
|
601
|
+
serializedFields.push(`${fieldNameSourceText}:${serializedValue}`);
|
|
602
|
+
}
|
|
603
|
+
return `{${serializedFields.join(",")}}`;
|
|
604
|
+
}
|
|
605
|
+
return JSON.stringify(jsonValue);
|
|
643
606
|
}
|
|
644
607
|
function isStringArray(value) {
|
|
645
|
-
return Array.isArray(value) && value.every(
|
|
646
|
-
}
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
const
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
if (orderIndex.has(key)) {
|
|
654
|
-
known.push(entry);
|
|
655
|
-
} else {
|
|
656
|
-
rest.push(entry);
|
|
608
|
+
return Array.isArray(value) && value.every(isJsonStringValue);
|
|
609
|
+
}
|
|
610
|
+
function deduplicateStringValues(stringValues) {
|
|
611
|
+
const uniqueStringValues = new Map;
|
|
612
|
+
for (const stringValue of stringValues) {
|
|
613
|
+
const text = getJsonString(stringValue);
|
|
614
|
+
if (!uniqueStringValues.has(text)) {
|
|
615
|
+
uniqueStringValues.set(text, stringValue);
|
|
657
616
|
}
|
|
658
617
|
}
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
618
|
+
return [...uniqueStringValues.values()];
|
|
619
|
+
}
|
|
620
|
+
function sortJsonObject(jsonObject, compareKeys = compareText) {
|
|
621
|
+
return Object.fromEntries(Object.entries(jsonObject).sort(([leftKey], [rightKey]) => compareKeys(leftKey, rightKey)));
|
|
622
|
+
}
|
|
623
|
+
function sortJsonObjectByKeyOrder(jsonObject, keyOrder) {
|
|
624
|
+
const keyOrderIndexes = new Map(keyOrder.map((key, index) => [key, index]));
|
|
625
|
+
return sortJsonObject(jsonObject, (leftKey, rightKey) => {
|
|
626
|
+
const leftIndex = keyOrderIndexes.get(leftKey);
|
|
627
|
+
const rightIndex = keyOrderIndexes.get(rightKey);
|
|
628
|
+
const isLeftKeyKnown = leftIndex !== undefined;
|
|
629
|
+
const isRightKeyKnown = rightIndex !== undefined;
|
|
630
|
+
if (isLeftKeyKnown && isRightKeyKnown) {
|
|
631
|
+
return leftIndex - rightIndex;
|
|
632
|
+
}
|
|
633
|
+
if (isLeftKeyKnown) {
|
|
634
|
+
return -1;
|
|
635
|
+
}
|
|
636
|
+
if (isRightKeyKnown) {
|
|
637
|
+
return 1;
|
|
638
|
+
}
|
|
639
|
+
return compareText(leftKey, rightKey);
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
function sortJsonObjectRecursively(jsonObject, sortObject = sortJsonObject) {
|
|
643
|
+
const sortedNestedValues = Object.fromEntries(Object.entries(jsonObject).map(([key, value]) => [
|
|
644
|
+
key,
|
|
645
|
+
isJsonObject(value) ? sortJsonObjectRecursively(value, sortObject) : value
|
|
646
|
+
]));
|
|
647
|
+
return sortObject(sortedNestedValues);
|
|
648
|
+
}
|
|
649
|
+
function sortJsonObjectValue(fieldValue, sortObject) {
|
|
650
|
+
return isJsonObject(fieldValue) ? sortObject(fieldValue) : fieldValue;
|
|
651
|
+
}
|
|
652
|
+
function sortJsonObjectValueAlphabetically(fieldValue) {
|
|
653
|
+
return sortJsonObjectValue(fieldValue, sortJsonObject);
|
|
654
|
+
}
|
|
655
|
+
function sortJsonObjectValueRecursively(fieldValue) {
|
|
656
|
+
return sortJsonObjectValue(fieldValue, sortJsonObjectRecursively);
|
|
662
657
|
}
|
|
663
|
-
function
|
|
664
|
-
|
|
665
|
-
|
|
658
|
+
function sortJsonObjectValueByKeyOrder(fieldValue, keyOrder) {
|
|
659
|
+
return sortJsonObjectValue(fieldValue, (jsonObject) => sortJsonObjectByKeyOrder(jsonObject, keyOrder));
|
|
660
|
+
}
|
|
661
|
+
function sortUniqueStringArrayValue(fieldValue) {
|
|
662
|
+
if (!isStringArray(fieldValue)) {
|
|
663
|
+
return fieldValue;
|
|
666
664
|
}
|
|
667
|
-
return
|
|
665
|
+
return deduplicateStringValues(fieldValue).sort((leftValue, rightValue) => compareText(getJsonString(leftValue), getJsonString(rightValue)));
|
|
668
666
|
}
|
|
669
|
-
function
|
|
670
|
-
return
|
|
667
|
+
function deduplicateStringArrayValue(fieldValue) {
|
|
668
|
+
return isStringArray(fieldValue) ? deduplicateStringValues(fieldValue) : fieldValue;
|
|
671
669
|
}
|
|
672
|
-
function
|
|
673
|
-
return [
|
|
670
|
+
function sortPersonValue(fieldValue) {
|
|
671
|
+
return sortJsonObjectValueByKeyOrder(fieldValue, ["name", "email", "url"]);
|
|
674
672
|
}
|
|
675
|
-
function
|
|
676
|
-
if (!
|
|
677
|
-
return
|
|
673
|
+
function sortPeopleArrayValue(fieldValue) {
|
|
674
|
+
if (!Array.isArray(fieldValue)) {
|
|
675
|
+
return fieldValue;
|
|
678
676
|
}
|
|
679
|
-
return
|
|
677
|
+
return fieldValue.map((person) => sortPersonValue(person));
|
|
680
678
|
}
|
|
681
|
-
function
|
|
682
|
-
const
|
|
683
|
-
return
|
|
679
|
+
function sortPackageJsonFields(packageJson) {
|
|
680
|
+
const fieldOrderIndexes = new Map(PACKAGE_JSON_FIELD_ORDER.map((fieldName, index) => [fieldName, index]));
|
|
681
|
+
return sortJsonObject(packageJson, (leftFieldName, rightFieldName) => {
|
|
682
|
+
const leftIndex = fieldOrderIndexes.get(leftFieldName);
|
|
683
|
+
const rightIndex = fieldOrderIndexes.get(rightFieldName);
|
|
684
|
+
const isLeftFieldKnown = leftIndex !== undefined;
|
|
685
|
+
const isRightFieldKnown = rightIndex !== undefined;
|
|
686
|
+
if (isLeftFieldKnown && isRightFieldKnown) {
|
|
687
|
+
return leftIndex - rightIndex;
|
|
688
|
+
}
|
|
689
|
+
if (isLeftFieldKnown) {
|
|
690
|
+
return -1;
|
|
691
|
+
}
|
|
692
|
+
if (isRightFieldKnown) {
|
|
693
|
+
return 1;
|
|
694
|
+
}
|
|
695
|
+
const isLeftFieldPrivate = leftFieldName.startsWith("_");
|
|
696
|
+
const isRightFieldPrivate = rightFieldName.startsWith("_");
|
|
697
|
+
if (isLeftFieldPrivate !== isRightFieldPrivate) {
|
|
698
|
+
return isLeftFieldPrivate ? 1 : -1;
|
|
699
|
+
}
|
|
700
|
+
return compareText(leftFieldName, rightFieldName);
|
|
701
|
+
});
|
|
684
702
|
}
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
function hasSequentialScript(packageObject) {
|
|
700
|
-
const devDependencies = packageObject["devDependencies"];
|
|
701
|
-
if (!isPlainObject(devDependencies) || !Object.hasOwn(devDependencies, "npm-run-all") && !Object.hasOwn(devDependencies, "npm-run-all2")) {
|
|
703
|
+
function isNpmDependencyOrderPreferred(packageJson) {
|
|
704
|
+
const packageManager = getJsonString(packageJson.packageManager);
|
|
705
|
+
if (packageManager !== null) {
|
|
706
|
+
return packageManager.startsWith("npm@");
|
|
707
|
+
}
|
|
708
|
+
const devEngines = packageJson.devEngines;
|
|
709
|
+
if (isJsonObject(devEngines)) {
|
|
710
|
+
const devPackageManager = devEngines.packageManager;
|
|
711
|
+
const devPackageManagerName = isJsonObject(devPackageManager) ? getJsonString(devPackageManager.name) : null;
|
|
712
|
+
if (devPackageManagerName !== null) {
|
|
713
|
+
return devPackageManagerName === "npm";
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
if (isJsonObject(packageJson.pnpm)) {
|
|
702
717
|
return false;
|
|
703
718
|
}
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
719
|
+
return true;
|
|
720
|
+
}
|
|
721
|
+
function sortDependencyObject(dependencyObject, packageJson) {
|
|
722
|
+
if (!isNpmDependencyOrderPreferred(packageJson)) {
|
|
723
|
+
return sortJsonObject(dependencyObject);
|
|
724
|
+
}
|
|
725
|
+
return sortJsonObject(dependencyObject, (leftName, rightName) => leftName.localeCompare(rightName, "en"));
|
|
726
|
+
}
|
|
727
|
+
function sortDependencyValue(fieldValue, packageJson) {
|
|
728
|
+
return sortJsonObjectValue(fieldValue, (dependencyObject) => sortDependencyObject(dependencyObject, packageJson));
|
|
729
|
+
}
|
|
730
|
+
function sortWorkspacesValue(fieldValue, packageJson) {
|
|
731
|
+
if (!isJsonObject(fieldValue)) {
|
|
732
|
+
return fieldValue;
|
|
733
|
+
}
|
|
734
|
+
const sortedWorkspaces = sortJsonObjectByKeyOrder(fieldValue, [
|
|
735
|
+
"packages",
|
|
736
|
+
"catalog"
|
|
737
|
+
]);
|
|
738
|
+
const workspacePackages = sortedWorkspaces.packages;
|
|
739
|
+
if (workspacePackages !== undefined) {
|
|
740
|
+
sortedWorkspaces.packages = sortUniqueStringArrayValue(workspacePackages);
|
|
741
|
+
}
|
|
742
|
+
if (isJsonObject(sortedWorkspaces.catalog)) {
|
|
743
|
+
sortedWorkspaces.catalog = sortDependencyObject(sortedWorkspaces.catalog, packageJson);
|
|
744
|
+
}
|
|
745
|
+
return sortedWorkspaces;
|
|
746
|
+
}
|
|
747
|
+
function sortEslintRules(rules) {
|
|
748
|
+
return sortJsonObject(rules, (leftRuleName, rightRuleName) => {
|
|
749
|
+
const leftPluginDepth = leftRuleName.split("/").length;
|
|
750
|
+
const rightPluginDepth = rightRuleName.split("/").length;
|
|
751
|
+
return leftPluginDepth - rightPluginDepth || leftRuleName.localeCompare(rightRuleName);
|
|
707
752
|
});
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
const
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
753
|
+
}
|
|
754
|
+
function sortEslintConfigObject(eslintConfig) {
|
|
755
|
+
const sortedConfig = sortJsonObjectByKeyOrder(eslintConfig, ESLINT_CONFIG_FIELD_ORDER);
|
|
756
|
+
for (const fieldName of ["env", "globals", "parserOptions", "settings"]) {
|
|
757
|
+
if (isJsonObject(sortedConfig[fieldName])) {
|
|
758
|
+
sortedConfig[fieldName] = sortJsonObject(sortedConfig[fieldName]);
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
if (isJsonObject(sortedConfig.rules)) {
|
|
762
|
+
sortedConfig.rules = sortEslintRules(sortedConfig.rules);
|
|
763
|
+
}
|
|
764
|
+
if (Array.isArray(sortedConfig.overrides)) {
|
|
765
|
+
sortedConfig.overrides = sortedConfig.overrides.map((override) => isJsonObject(override) ? sortEslintConfigObject(override) : override);
|
|
766
|
+
}
|
|
767
|
+
return sortedConfig;
|
|
768
|
+
}
|
|
769
|
+
function sortEslintConfigValue(fieldValue) {
|
|
770
|
+
return sortJsonObjectValue(fieldValue, sortEslintConfigObject);
|
|
771
|
+
}
|
|
772
|
+
function sortPrettierConfigObject(prettierConfig) {
|
|
773
|
+
const keyOrder = Object.keys(prettierConfig).filter((key) => key !== "overrides").sort(compareText);
|
|
774
|
+
if (Object.hasOwn(prettierConfig, "overrides")) {
|
|
775
|
+
keyOrder.push("overrides");
|
|
776
|
+
}
|
|
777
|
+
const sortedConfig = sortJsonObjectByKeyOrder(prettierConfig, keyOrder);
|
|
778
|
+
if (Array.isArray(sortedConfig.overrides)) {
|
|
779
|
+
sortedConfig.overrides = sortedConfig.overrides.map((override) => {
|
|
780
|
+
if (!isJsonObject(override)) {
|
|
781
|
+
return override;
|
|
721
782
|
}
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
if (!group) {
|
|
726
|
-
group = [];
|
|
727
|
-
groupMap.set(key, group);
|
|
783
|
+
const sortedOverride = sortJsonObject(override);
|
|
784
|
+
if (isJsonObject(sortedOverride.options)) {
|
|
785
|
+
sortedOverride.options = sortJsonObject(sortedOverride.options);
|
|
728
786
|
}
|
|
729
|
-
|
|
730
|
-
}
|
|
787
|
+
return sortedOverride;
|
|
788
|
+
});
|
|
789
|
+
}
|
|
790
|
+
return sortedConfig;
|
|
791
|
+
}
|
|
792
|
+
function sortPrettierConfigValue(fieldValue) {
|
|
793
|
+
return sortJsonObjectValue(fieldValue, sortPrettierConfigObject);
|
|
794
|
+
}
|
|
795
|
+
function sortWireitScriptObject(scriptConfig) {
|
|
796
|
+
const sortedConfig = sortJsonObjectByKeyOrder(scriptConfig, WIREIT_SCRIPT_FIELD_ORDER);
|
|
797
|
+
if (Array.isArray(sortedConfig.dependencies)) {
|
|
798
|
+
sortedConfig.dependencies = sortedConfig.dependencies.map((dependency) => sortJsonObjectValueByKeyOrder(dependency, ["script", "cascade"]));
|
|
799
|
+
}
|
|
800
|
+
if (isJsonObject(sortedConfig.env)) {
|
|
801
|
+
sortedConfig.env = sortJsonObject(Object.fromEntries(Object.entries(sortedConfig.env).map(([name, value]) => [
|
|
802
|
+
name,
|
|
803
|
+
sortJsonObjectValueByKeyOrder(value, ["external", "default"])
|
|
804
|
+
])));
|
|
731
805
|
}
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
806
|
+
if (isJsonObject(sortedConfig.service)) {
|
|
807
|
+
sortedConfig.service = sortJsonObjectByKeyOrder(sortedConfig.service, [
|
|
808
|
+
"readyWhen"
|
|
809
|
+
]);
|
|
810
|
+
if (isJsonObject(sortedConfig.service.readyWhen)) {
|
|
811
|
+
sortedConfig.service.readyWhen = sortJsonObject(sortedConfig.service.readyWhen);
|
|
738
812
|
}
|
|
739
|
-
|
|
813
|
+
}
|
|
814
|
+
return sortedConfig;
|
|
815
|
+
}
|
|
816
|
+
function sortWireitValue(fieldValue) {
|
|
817
|
+
if (!isJsonObject(fieldValue)) {
|
|
818
|
+
return fieldValue;
|
|
819
|
+
}
|
|
820
|
+
return sortJsonObject(Object.fromEntries(Object.entries(fieldValue).map(([scriptName, scriptConfig]) => [
|
|
821
|
+
scriptName,
|
|
822
|
+
sortJsonObjectValue(scriptConfig, sortWireitScriptObject)
|
|
823
|
+
])));
|
|
824
|
+
}
|
|
825
|
+
function hasSequentialScript(packageJson) {
|
|
826
|
+
const devDependencies = packageJson.devDependencies;
|
|
827
|
+
if (!isJsonObject(devDependencies)) {
|
|
828
|
+
return false;
|
|
829
|
+
}
|
|
830
|
+
const isSequentialRunnerInstalled = Object.hasOwn(devDependencies, "npm-run-all") || Object.hasOwn(devDependencies, "npm-run-all2");
|
|
831
|
+
if (!isSequentialRunnerInstalled) {
|
|
832
|
+
return false;
|
|
833
|
+
}
|
|
834
|
+
return ["scripts", "betterScripts"].some((fieldName) => {
|
|
835
|
+
const scripts = packageJson[fieldName];
|
|
836
|
+
return isJsonObject(scripts) && Object.values(scripts).some((script) => {
|
|
837
|
+
const scriptText = getJsonString(script);
|
|
838
|
+
return scriptText !== null && scriptText.includes("*") && SEQUENTIAL_SCRIPT_PATTERN.test(scriptText);
|
|
839
|
+
});
|
|
740
840
|
});
|
|
741
841
|
}
|
|
742
|
-
function
|
|
743
|
-
const
|
|
744
|
-
const
|
|
745
|
-
|
|
746
|
-
const
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
842
|
+
function sortScriptNames(scriptNames, namespacePrefix = "") {
|
|
843
|
+
const scriptGroups = new Map;
|
|
844
|
+
for (const scriptName of scriptNames) {
|
|
845
|
+
const unprefixedScriptName = namespacePrefix ? scriptName.slice(namespacePrefix.length + 1) : scriptName;
|
|
846
|
+
const namespaceSeparatorIndex = unprefixedScriptName.indexOf(":");
|
|
847
|
+
const scriptGroupName = namespaceSeparatorIndex > 0 ? scriptName.slice(0, (namespacePrefix ? namespacePrefix.length + 1 : 0) + namespaceSeparatorIndex) : scriptName;
|
|
848
|
+
const groupedScriptNames = scriptGroups.get(scriptGroupName) ?? [];
|
|
849
|
+
groupedScriptNames.push(scriptName);
|
|
850
|
+
scriptGroups.set(scriptGroupName, groupedScriptNames);
|
|
851
|
+
}
|
|
852
|
+
return [...scriptGroups.keys()].sort(compareText).flatMap((scriptGroupName) => {
|
|
853
|
+
const groupedScriptNames = scriptGroups.get(scriptGroupName);
|
|
854
|
+
const isNestedGroup = groupedScriptNames.length > 1 && groupedScriptNames.some((scriptName) => scriptName !== scriptGroupName && scriptName.startsWith(`${scriptGroupName}:`));
|
|
855
|
+
if (!isNestedGroup) {
|
|
856
|
+
return groupedScriptNames.sort(compareText);
|
|
750
857
|
}
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
let sortedNames;
|
|
754
|
-
if (hasSequentialScript(packageObject)) {
|
|
755
|
-
sortedNames = [...new Set(normalized)];
|
|
756
|
-
} else {
|
|
757
|
-
sortedNames = sortScriptNames(normalized);
|
|
758
|
-
}
|
|
759
|
-
const orderedNames = sortedNames.flatMap((key) => prefixable.has(key) ? [`pre${key}`, key, `post${key}`] : [key]);
|
|
760
|
-
return Object.fromEntries(orderedNames.filter((name) => Object.hasOwn(scripts, name)).map((name) => [name, scripts[name]]));
|
|
761
|
-
}
|
|
762
|
-
function sortExportsField(exports) {
|
|
763
|
-
const keys = Object.keys(exports);
|
|
764
|
-
const paths = keys.filter((key) => key.startsWith(".")).sort();
|
|
765
|
-
const conditions = keys.filter((key) => !key.startsWith(".")).sort();
|
|
766
|
-
const defaultIndex = conditions.indexOf("default");
|
|
767
|
-
if (defaultIndex >= 0) {
|
|
768
|
-
conditions.splice(defaultIndex, 1);
|
|
769
|
-
conditions.push("default");
|
|
770
|
-
}
|
|
771
|
-
const orderedKeys = [...paths, ...conditions];
|
|
772
|
-
return Object.fromEntries(orderedKeys.map((key) => {
|
|
773
|
-
const value = exports[key];
|
|
858
|
+
const directScriptNames = groupedScriptNames.filter((scriptName) => scriptName === scriptGroupName || !scriptName.startsWith(`${scriptGroupName}:`)).sort(compareText);
|
|
859
|
+
const nestedScriptNames = groupedScriptNames.filter((scriptName) => scriptName.startsWith(`${scriptGroupName}:`));
|
|
774
860
|
return [
|
|
775
|
-
|
|
776
|
-
|
|
861
|
+
...directScriptNames,
|
|
862
|
+
...sortScriptNames(nestedScriptNames, scriptGroupName)
|
|
777
863
|
];
|
|
778
|
-
})
|
|
864
|
+
});
|
|
779
865
|
}
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
866
|
+
function sortScriptsValue(fieldValue, packageJson) {
|
|
867
|
+
if (!isJsonObject(fieldValue)) {
|
|
868
|
+
return fieldValue;
|
|
869
|
+
}
|
|
870
|
+
const scriptNames = Object.keys(fieldValue);
|
|
871
|
+
const baseScriptNames = new Set;
|
|
872
|
+
const normalizedScriptNames = scriptNames.map((scriptName) => {
|
|
873
|
+
const baseScriptName = scriptName.replace(/^(?:pre|post)/, "");
|
|
874
|
+
const isLifecycleScript = NPM_LIFECYCLE_SCRIPT_NAMES.has(baseScriptName);
|
|
875
|
+
const isBaseScriptPresent = scriptNames.includes(baseScriptName);
|
|
876
|
+
if (isLifecycleScript || isBaseScriptPresent) {
|
|
877
|
+
baseScriptNames.add(baseScriptName);
|
|
878
|
+
return baseScriptName;
|
|
879
|
+
}
|
|
880
|
+
return scriptName;
|
|
881
|
+
});
|
|
882
|
+
const orderedBaseScriptNames = hasSequentialScript(packageJson) ? [...new Set(normalizedScriptNames)] : sortScriptNames(normalizedScriptNames);
|
|
883
|
+
const orderedScriptNames = orderedBaseScriptNames.flatMap((baseScriptName) => baseScriptNames.has(baseScriptName) ? [`pre${baseScriptName}`, baseScriptName, `post${baseScriptName}`] : [baseScriptName]);
|
|
884
|
+
return Object.fromEntries(orderedScriptNames.filter((scriptName) => Object.hasOwn(fieldValue, scriptName)).map((scriptName) => [scriptName, fieldValue[scriptName]]));
|
|
794
885
|
}
|
|
795
|
-
function
|
|
796
|
-
if (!
|
|
797
|
-
return
|
|
886
|
+
function sortExportsValue(fieldValue) {
|
|
887
|
+
if (!isJsonObject(fieldValue)) {
|
|
888
|
+
return fieldValue;
|
|
798
889
|
}
|
|
799
|
-
const
|
|
800
|
-
const
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
} catch {
|
|
805
|
-
return text;
|
|
890
|
+
const exportKeys = Object.keys(fieldValue);
|
|
891
|
+
const exportPathKeys = exportKeys.filter((key) => key.startsWith("."));
|
|
892
|
+
const exportConditionKeys = exportKeys.filter((key) => !key.startsWith(".") && key !== "default");
|
|
893
|
+
if (Object.hasOwn(fieldValue, "default")) {
|
|
894
|
+
exportConditionKeys.push("default");
|
|
806
895
|
}
|
|
807
|
-
|
|
808
|
-
|
|
896
|
+
return Object.fromEntries([...exportPathKeys, ...exportConditionKeys].map((exportKey) => [exportKey, sortExportsValue(fieldValue[exportKey])]));
|
|
897
|
+
}
|
|
898
|
+
function sortDevEnginesValue(fieldValue) {
|
|
899
|
+
if (!isJsonObject(fieldValue) || !isJsonObject(fieldValue.packageManager)) {
|
|
900
|
+
return fieldValue;
|
|
809
901
|
}
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
902
|
+
return {
|
|
903
|
+
...fieldValue,
|
|
904
|
+
packageManager: sortJsonObjectByKeyOrder(fieldValue.packageManager, [
|
|
905
|
+
"name",
|
|
906
|
+
"version",
|
|
907
|
+
"onFail"
|
|
908
|
+
])
|
|
909
|
+
};
|
|
910
|
+
}
|
|
911
|
+
function getDependencyName(dependencyIdentifier) {
|
|
912
|
+
const versionSeparatorIndex = dependencyIdentifier.indexOf("@", dependencyIdentifier.startsWith("@") ? 1 : 0);
|
|
913
|
+
return versionSeparatorIndex < 0 ? dependencyIdentifier : dependencyIdentifier.slice(0, versionSeparatorIndex);
|
|
914
|
+
}
|
|
915
|
+
function getPackageVersionSeparatorIndex(packageSelector) {
|
|
916
|
+
return packageSelector.indexOf("@", packageSelector.startsWith("@") ? 1 : 0);
|
|
917
|
+
}
|
|
918
|
+
function isCompletePackageSelector(packageSelector) {
|
|
919
|
+
const versionSeparatorIndex = getPackageVersionSeparatorIndex(packageSelector);
|
|
920
|
+
if (versionSeparatorIndex < 0) {
|
|
921
|
+
return packageSelector !== "";
|
|
816
922
|
}
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
if (exportsValue !== undefined && isPlainObject(exportsValue) && !exclude.has("exports")) {
|
|
827
|
-
result["exports"] = sortExportsField(exportsValue);
|
|
923
|
+
const name = packageSelector.slice(0, versionSeparatorIndex);
|
|
924
|
+
const versionRange = packageSelector.slice(versionSeparatorIndex + 1);
|
|
925
|
+
return name !== "" && versionRange.trim() !== "" && !versionRange.trimEnd().endsWith("||") && getValidSemanticVersionRange(versionRange) !== null;
|
|
926
|
+
}
|
|
927
|
+
function findPnpmDependencySeparator(packageSelector) {
|
|
928
|
+
for (let separatorIndex = packageSelector.indexOf(">");separatorIndex >= 0; separatorIndex = packageSelector.indexOf(">", separatorIndex + 1)) {
|
|
929
|
+
const isSemverComparator = packageSelector[separatorIndex - 1]?.trim() === "";
|
|
930
|
+
if (isSemverComparator) {
|
|
931
|
+
continue;
|
|
828
932
|
}
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
if (!isStringArray(value)) {
|
|
834
|
-
continue;
|
|
835
|
-
}
|
|
836
|
-
if (NO_SORT_ARRAY_FIELDS.has(key)) {
|
|
837
|
-
continue;
|
|
838
|
-
}
|
|
839
|
-
if (UNIQUE_ONLY_FIELDS.has(key)) {
|
|
840
|
-
result[key] = uniqueStringArray(value);
|
|
841
|
-
continue;
|
|
842
|
-
}
|
|
843
|
-
if (UNIQUE_AND_SORT_FIELDS.has(key)) {
|
|
844
|
-
result[key] = sortStringArrayAlpha(uniqueStringArray(value));
|
|
845
|
-
continue;
|
|
846
|
-
}
|
|
847
|
-
result[key] = sortStringArrayAlpha(value);
|
|
933
|
+
const parentSelector = packageSelector.slice(0, separatorIndex);
|
|
934
|
+
const dependencySelector = packageSelector.slice(separatorIndex + 1);
|
|
935
|
+
if (dependencySelector.trim() !== "" && isCompletePackageSelector(parentSelector)) {
|
|
936
|
+
return separatorIndex;
|
|
848
937
|
}
|
|
849
938
|
}
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
939
|
+
return -1;
|
|
940
|
+
}
|
|
941
|
+
function parsePackageSelector(packageSelector) {
|
|
942
|
+
const dependencySeparatorIndex = findPnpmDependencySeparator(packageSelector);
|
|
943
|
+
const nameAndVersion = dependencySeparatorIndex < 0 ? packageSelector : packageSelector.slice(0, dependencySeparatorIndex);
|
|
944
|
+
const versionSeparatorIndex = getPackageVersionSeparatorIndex(nameAndVersion);
|
|
945
|
+
if (versionSeparatorIndex < 0) {
|
|
946
|
+
return { name: nameAndVersion, versionRange: null };
|
|
947
|
+
}
|
|
948
|
+
return {
|
|
949
|
+
name: nameAndVersion.slice(0, versionSeparatorIndex),
|
|
950
|
+
versionRange: nameAndVersion.slice(versionSeparatorIndex + 1) || null
|
|
951
|
+
};
|
|
952
|
+
}
|
|
953
|
+
function getMinimumSemanticVersion(versionRange) {
|
|
954
|
+
try {
|
|
955
|
+
return findMinimumSemanticVersion(versionRange);
|
|
956
|
+
} catch {
|
|
957
|
+
return null;
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
function comparePnpmOverrideSelectors(leftSelector, rightSelector) {
|
|
961
|
+
const leftPackage = parsePackageSelector(leftSelector);
|
|
962
|
+
const rightPackage = parsePackageSelector(rightSelector);
|
|
963
|
+
if (leftPackage.name !== rightPackage.name) {
|
|
964
|
+
return leftPackage.name.localeCompare(rightPackage.name, "en");
|
|
965
|
+
}
|
|
966
|
+
if (!leftPackage.versionRange && !rightPackage.versionRange) {
|
|
967
|
+
return 0;
|
|
968
|
+
}
|
|
969
|
+
if (!leftPackage.versionRange) {
|
|
970
|
+
return -1;
|
|
971
|
+
}
|
|
972
|
+
if (!rightPackage.versionRange) {
|
|
973
|
+
return 1;
|
|
974
|
+
}
|
|
975
|
+
const leftVersion = getMinimumSemanticVersion(leftPackage.versionRange);
|
|
976
|
+
const rightVersion = getMinimumSemanticVersion(rightPackage.versionRange);
|
|
977
|
+
if (!leftVersion && !rightVersion) {
|
|
978
|
+
return compareText(leftPackage.versionRange, rightPackage.versionRange);
|
|
979
|
+
}
|
|
980
|
+
if (!leftVersion) {
|
|
981
|
+
return 1;
|
|
982
|
+
}
|
|
983
|
+
if (!rightVersion) {
|
|
984
|
+
return -1;
|
|
985
|
+
}
|
|
986
|
+
return leftVersion.compare(rightVersion);
|
|
987
|
+
}
|
|
988
|
+
function sortDependencyMetadataValue(fieldValue) {
|
|
989
|
+
return sortJsonObjectValue(fieldValue, (dependencyMetadata) => {
|
|
990
|
+
const compareDependencyIdentifiers = (leftIdentifier, rightIdentifier) => compareText(getDependencyName(leftIdentifier), getDependencyName(rightIdentifier));
|
|
991
|
+
return sortJsonObjectRecursively(dependencyMetadata, (jsonObject) => sortJsonObject(jsonObject, compareDependencyIdentifiers));
|
|
992
|
+
});
|
|
993
|
+
}
|
|
994
|
+
function sortPnpmConfigValue(fieldValue) {
|
|
995
|
+
return sortJsonObjectValue(fieldValue, (pnpmConfig) => {
|
|
996
|
+
const sortedPnpmConfig = sortJsonObjectRecursively(pnpmConfig, (jsonObject) => sortJsonObjectByKeyOrder(jsonObject, PNPM_CONFIG_FIELD_ORDER));
|
|
997
|
+
if (!isJsonObject(sortedPnpmConfig.overrides)) {
|
|
998
|
+
return sortedPnpmConfig;
|
|
999
|
+
}
|
|
1000
|
+
return {
|
|
1001
|
+
...sortedPnpmConfig,
|
|
1002
|
+
overrides: sortJsonObject(sortedPnpmConfig.overrides, comparePnpmOverrideSelectors)
|
|
1003
|
+
};
|
|
1004
|
+
});
|
|
1005
|
+
}
|
|
1006
|
+
var PACKAGE_JSON_FIELD_SORTERS = {
|
|
1007
|
+
categories: deduplicateStringArrayValue,
|
|
1008
|
+
keywords: deduplicateStringArrayValue,
|
|
1009
|
+
bugs: (fieldValue) => sortJsonObjectValueByKeyOrder(fieldValue, ["url", "email"]),
|
|
1010
|
+
repository: (fieldValue) => sortJsonObjectValueByKeyOrder(fieldValue, ["type", "url"]),
|
|
1011
|
+
funding: (fieldValue) => sortJsonObjectValueByKeyOrder(fieldValue, ["type", "url"]),
|
|
1012
|
+
license: (fieldValue) => sortJsonObjectValueByKeyOrder(fieldValue, ["type", "url"]),
|
|
1013
|
+
author: sortPersonValue,
|
|
1014
|
+
maintainers: sortPeopleArrayValue,
|
|
1015
|
+
contributors: sortPeopleArrayValue,
|
|
1016
|
+
exports: sortExportsValue,
|
|
1017
|
+
bin: sortJsonObjectValueAlphabetically,
|
|
1018
|
+
directories: (fieldValue) => sortJsonObjectValueByKeyOrder(fieldValue, DIRECTORY_FIELD_ORDER),
|
|
1019
|
+
files: deduplicateStringArrayValue,
|
|
1020
|
+
workspaces: sortWorkspacesValue,
|
|
1021
|
+
binary: (fieldValue) => sortJsonObjectValueByKeyOrder(fieldValue, [
|
|
1022
|
+
"module_name",
|
|
1023
|
+
"module_path",
|
|
1024
|
+
"remote_path",
|
|
1025
|
+
"package_name",
|
|
1026
|
+
"host"
|
|
1027
|
+
]),
|
|
1028
|
+
scripts: sortScriptsValue,
|
|
1029
|
+
betterScripts: sortScriptsValue,
|
|
1030
|
+
wireit: sortWireitValue,
|
|
1031
|
+
contributes: sortJsonObjectValueAlphabetically,
|
|
1032
|
+
activationEvents: deduplicateStringArrayValue,
|
|
1033
|
+
husky: (fieldValue) => {
|
|
1034
|
+
if (!isJsonObject(fieldValue) || !isJsonObject(fieldValue.hooks)) {
|
|
1035
|
+
return fieldValue;
|
|
1036
|
+
}
|
|
1037
|
+
return {
|
|
1038
|
+
...fieldValue,
|
|
1039
|
+
hooks: sortJsonObjectByKeyOrder(fieldValue.hooks, GIT_HOOK_ORDER)
|
|
1040
|
+
};
|
|
1041
|
+
},
|
|
1042
|
+
"simple-git-hooks": (fieldValue) => sortJsonObjectValueByKeyOrder(fieldValue, GIT_HOOK_ORDER),
|
|
1043
|
+
commitlint: sortJsonObjectValueAlphabetically,
|
|
1044
|
+
config: sortJsonObjectValueAlphabetically,
|
|
1045
|
+
nodemonConfig: sortJsonObjectValueAlphabetically,
|
|
1046
|
+
browserify: sortJsonObjectValueAlphabetically,
|
|
1047
|
+
babel: sortJsonObjectValueAlphabetically,
|
|
1048
|
+
xo: sortJsonObjectValueAlphabetically,
|
|
1049
|
+
prettier: sortPrettierConfigValue,
|
|
1050
|
+
eslintConfig: sortEslintConfigValue,
|
|
1051
|
+
npmpkgjsonlint: sortJsonObjectValueAlphabetically,
|
|
1052
|
+
npmPackageJsonLintConfig: sortJsonObjectValueAlphabetically,
|
|
1053
|
+
npmpackagejsonlint: sortJsonObjectValueAlphabetically,
|
|
1054
|
+
release: sortJsonObjectValueAlphabetically,
|
|
1055
|
+
remarkConfig: sortJsonObjectValueAlphabetically,
|
|
1056
|
+
ava: sortJsonObjectValueAlphabetically,
|
|
1057
|
+
jest: sortJsonObjectValueAlphabetically,
|
|
1058
|
+
"jest-junit": sortJsonObjectValueAlphabetically,
|
|
1059
|
+
"jest-stare": sortJsonObjectValueAlphabetically,
|
|
1060
|
+
mocha: sortJsonObjectValueAlphabetically,
|
|
1061
|
+
nyc: sortJsonObjectValueAlphabetically,
|
|
1062
|
+
c8: sortJsonObjectValueAlphabetically,
|
|
1063
|
+
tap: sortJsonObjectValueAlphabetically,
|
|
1064
|
+
oclif: sortJsonObjectValueRecursively,
|
|
1065
|
+
resolutions: sortJsonObjectValueAlphabetically,
|
|
1066
|
+
overrides: sortDependencyValue,
|
|
1067
|
+
dependencies: sortDependencyValue,
|
|
1068
|
+
devDependencies: sortDependencyValue,
|
|
1069
|
+
dependenciesMeta: sortDependencyMetadataValue,
|
|
1070
|
+
peerDependencies: sortDependencyValue,
|
|
1071
|
+
peerDependenciesMeta: sortJsonObjectValueRecursively,
|
|
1072
|
+
optionalDependencies: sortDependencyValue,
|
|
1073
|
+
bundledDependencies: sortUniqueStringArrayValue,
|
|
1074
|
+
bundleDependencies: sortUniqueStringArrayValue,
|
|
1075
|
+
extensionPack: sortUniqueStringArrayValue,
|
|
1076
|
+
extensionDependencies: sortUniqueStringArrayValue,
|
|
1077
|
+
engines: sortJsonObjectValueAlphabetically,
|
|
1078
|
+
engineStrict: sortJsonObjectValueAlphabetically,
|
|
1079
|
+
devEngines: sortDevEnginesValue,
|
|
1080
|
+
volta: (fieldValue) => sortJsonObjectValueByKeyOrder(fieldValue, ["node", "npm", "yarn"]),
|
|
1081
|
+
preferGlobal: sortJsonObjectValueAlphabetically,
|
|
1082
|
+
publishConfig: sortJsonObjectValueAlphabetically,
|
|
1083
|
+
badges: (fieldValue) => {
|
|
1084
|
+
if (!Array.isArray(fieldValue)) {
|
|
1085
|
+
return fieldValue;
|
|
1086
|
+
}
|
|
1087
|
+
return fieldValue.map((badge) => sortJsonObjectValueByKeyOrder(badge, ["description", "url", "href"]));
|
|
1088
|
+
},
|
|
1089
|
+
galleryBanner: sortJsonObjectValueAlphabetically,
|
|
1090
|
+
pnpm: sortPnpmConfigValue
|
|
1091
|
+
};
|
|
1092
|
+
function sortPackageJsonObject(packageJson) {
|
|
1093
|
+
const sortedPackageJsonFields = sortPackageJsonFields(packageJson);
|
|
1094
|
+
return Object.fromEntries(Object.entries(sortedPackageJsonFields).map(([fieldName, fieldValue]) => {
|
|
1095
|
+
const fieldSorter = Object.hasOwn(PACKAGE_JSON_FIELD_SORTERS, fieldName) ? PACKAGE_JSON_FIELD_SORTERS[fieldName] : undefined;
|
|
1096
|
+
return [
|
|
1097
|
+
fieldName,
|
|
1098
|
+
fieldSorter ? fieldSorter(fieldValue, packageJson) : fieldValue
|
|
1099
|
+
];
|
|
1100
|
+
}));
|
|
1101
|
+
}
|
|
1102
|
+
function isPackageJsonFile(filePath) {
|
|
1103
|
+
return filePath?.split(/[\\/]/).at(-1) === "package.json";
|
|
1104
|
+
}
|
|
1105
|
+
async function preprocessPackageJson(sourceText, prettierOptions, parser) {
|
|
1106
|
+
if (!isPackageJsonFile(prettierOptions.filepath) || !resolveSortOptions(prettierOptions).packageSort) {
|
|
1107
|
+
return sourceText;
|
|
1108
|
+
}
|
|
1109
|
+
try {
|
|
1110
|
+
const parsedPackageJson = JSON.parse(sourceText);
|
|
1111
|
+
if (!isJsonObject(parsedPackageJson)) {
|
|
1112
|
+
return sourceText;
|
|
1113
|
+
}
|
|
1114
|
+
const parserJsonAst = await parser.parse(sourceText, prettierOptions);
|
|
1115
|
+
if (!isParserJsonAstNode(parserJsonAst)) {
|
|
1116
|
+
return sourceText;
|
|
1117
|
+
}
|
|
1118
|
+
const fieldNameSourceTexts = new Map;
|
|
1119
|
+
const packageJsonWithSourceLiterals = preserveJsonSourceLiterals(parsedPackageJson, parserJsonAst, sourceText, fieldNameSourceTexts);
|
|
1120
|
+
if (!isJsonObject(packageJsonWithSourceLiterals)) {
|
|
1121
|
+
return sourceText;
|
|
1122
|
+
}
|
|
1123
|
+
return serializeJsonValue(sortPackageJsonObject(packageJsonWithSourceLiterals), fieldNameSourceTexts) ?? sourceText;
|
|
1124
|
+
} catch {
|
|
1125
|
+
return sourceText;
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
// src/sort-exports.ts
|
|
1130
|
+
function buildExportSortingEdits(sourceText, programStatements, sortedComments) {
|
|
1131
|
+
const sortingEdits = [];
|
|
1132
|
+
for (const exportDeclarationNode of programStatements) {
|
|
1133
|
+
if (exportDeclarationNode.type !== "ExportNamedDeclaration" || exportDeclarationNode.declaration) {
|
|
1134
|
+
continue;
|
|
1135
|
+
}
|
|
1136
|
+
const declarationRange = getAstNodeTextRange(exportDeclarationNode);
|
|
1137
|
+
const specifierNodes = exportDeclarationNode.specifiers;
|
|
1138
|
+
if (!declarationRange || !specifierNodes || specifierNodes.length <= 1 || isPrettierIgnored(sourceText, declarationRange, sortedComments) || specifierNodes.some((specifierNode) => specifierNode.type !== "ExportSpecifier")) {
|
|
1139
|
+
continue;
|
|
1140
|
+
}
|
|
1141
|
+
const firstSpecifierRange = getAstNodeTextRange(specifierNodes[0]);
|
|
1142
|
+
const lastSpecifierRange = getAstNodeTextRange(specifierNodes.at(-1));
|
|
1143
|
+
if (!firstSpecifierRange || !lastSpecifierRange) {
|
|
1144
|
+
continue;
|
|
1145
|
+
}
|
|
1146
|
+
const openingBraceIndex = sourceText.lastIndexOf("{", firstSpecifierRange.start);
|
|
1147
|
+
const closingBraceIndex = sourceText.indexOf("}", lastSpecifierRange.end);
|
|
1148
|
+
if (openingBraceIndex < declarationRange.start || closingBraceIndex < lastSpecifierRange.end || closingBraceIndex >= declarationRange.end) {
|
|
1149
|
+
continue;
|
|
1150
|
+
}
|
|
1151
|
+
const firstInternalCommentIndex = findCommentIndexAtOrAfter(sortedComments, openingBraceIndex + 1);
|
|
1152
|
+
const firstInternalComment = sortedComments[firstInternalCommentIndex];
|
|
1153
|
+
const isInternalCommentPresent = firstInternalComment !== undefined && firstInternalComment.textRange.start < closingBraceIndex;
|
|
1154
|
+
if (isInternalCommentPresent) {
|
|
1155
|
+
continue;
|
|
1156
|
+
}
|
|
1157
|
+
let isEverySpecifierValid = true;
|
|
1158
|
+
const sortableSpecifiers = [];
|
|
1159
|
+
for (const [originalIndex, specifierNode] of specifierNodes.entries()) {
|
|
1160
|
+
const specifierRange = getAstNodeTextRange(specifierNode);
|
|
1161
|
+
const exportedName = getAstNodeName(specifierNode.exported);
|
|
1162
|
+
const localName = getAstNodeName(specifierNode.local);
|
|
1163
|
+
const sortName = exportedName ?? localName;
|
|
1164
|
+
if (!specifierRange || !sortName) {
|
|
1165
|
+
isEverySpecifierValid = false;
|
|
1166
|
+
break;
|
|
1167
|
+
}
|
|
1168
|
+
sortableSpecifiers.push({
|
|
1169
|
+
originalIndex,
|
|
1170
|
+
sortName,
|
|
1171
|
+
specifierText: sourceText.slice(specifierRange.start, specifierRange.end)
|
|
1172
|
+
});
|
|
1173
|
+
}
|
|
1174
|
+
if (!isEverySpecifierValid) {
|
|
1175
|
+
continue;
|
|
1176
|
+
}
|
|
1177
|
+
const sortedSpecifiers = [...sortableSpecifiers].sort((left, right) => left.sortName.localeCompare(right.sortName, "en", {
|
|
1178
|
+
sensitivity: "base"
|
|
1179
|
+
}) || left.originalIndex - right.originalIndex);
|
|
1180
|
+
const isSpecifierOrderUnchanged = sortedSpecifiers.every((specifier, sortedIndex) => specifier.originalIndex === sortedIndex);
|
|
1181
|
+
if (isSpecifierOrderUnchanged) {
|
|
1182
|
+
continue;
|
|
1183
|
+
}
|
|
1184
|
+
sortingEdits.push({
|
|
1185
|
+
start: openingBraceIndex,
|
|
1186
|
+
end: closingBraceIndex + 1,
|
|
1187
|
+
replacementText: `{ ${sortedSpecifiers.map((specifier) => specifier.specifierText).join(", ")} }`
|
|
1188
|
+
});
|
|
1189
|
+
}
|
|
1190
|
+
return sortingEdits;
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
// src/utils/source-text.ts
|
|
1194
|
+
function applySourceTextEdits(sourceText, sourceTextEdits) {
|
|
1195
|
+
if (sourceTextEdits.length === 0) {
|
|
1196
|
+
return sourceText;
|
|
1197
|
+
}
|
|
1198
|
+
let previousEditEnd = 0;
|
|
1199
|
+
const ascendingEdits = [...sourceTextEdits].sort((left, right) => left.start - right.start || left.end - right.end);
|
|
1200
|
+
for (const sourceTextEdit of ascendingEdits) {
|
|
1201
|
+
const { start, end } = sourceTextEdit;
|
|
1202
|
+
const isSourceTextEditValid = [start, end].every(Number.isSafeInteger) && start >= previousEditEnd && end >= start && end <= sourceText.length;
|
|
1203
|
+
if (!isSourceTextEditValid) {
|
|
1204
|
+
return null;
|
|
1205
|
+
}
|
|
1206
|
+
previousEditEnd = end;
|
|
1207
|
+
}
|
|
1208
|
+
let editedText = sourceText;
|
|
1209
|
+
for (const sourceTextEdit of ascendingEdits.reverse()) {
|
|
1210
|
+
editedText = editedText.slice(0, sourceTextEdit.start) + sourceTextEdit.replacementText + editedText.slice(sourceTextEdit.end);
|
|
1211
|
+
}
|
|
1212
|
+
return editedText;
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
// src/sort-imports.ts
|
|
1216
|
+
var INDEX_MODULE_PATTERN = /^\.\/index(?:\.[^/]+)*$/;
|
|
1217
|
+
var PRETTIER_FILE_PRAGMA_DIRECTIVES = ["@format", "@prettier"];
|
|
1218
|
+
var ESLINT_RANGE_DIRECTIVES = ["eslint-disable", "eslint-enable"];
|
|
1219
|
+
var ESLINT_GLOBAL_DIRECTIVES = ["global", "globals"];
|
|
1220
|
+
function getCommentDirectiveArguments(commentLine, directive) {
|
|
1221
|
+
if (!commentLine.startsWith(directive)) {
|
|
1222
|
+
return null;
|
|
1223
|
+
}
|
|
1224
|
+
const directiveArguments = commentLine.slice(directive.length);
|
|
1225
|
+
if (directiveArguments === "") {
|
|
1226
|
+
return "";
|
|
1227
|
+
}
|
|
1228
|
+
if (directiveArguments[0]?.trim() !== "") {
|
|
1229
|
+
return null;
|
|
1230
|
+
}
|
|
1231
|
+
return directiveArguments.trimStart();
|
|
1232
|
+
}
|
|
1233
|
+
function hasCommentDirective(commentLine, directives) {
|
|
1234
|
+
return directives.some((directive) => getCommentDirectiveArguments(commentLine, directive) !== null);
|
|
1235
|
+
}
|
|
1236
|
+
function isEslintRuleConfiguration(commentLine) {
|
|
1237
|
+
const ruleConfiguration = getCommentDirectiveArguments(commentLine, "eslint");
|
|
1238
|
+
if (!ruleConfiguration) {
|
|
1239
|
+
return false;
|
|
1240
|
+
}
|
|
1241
|
+
const separatorIndex = ruleConfiguration.indexOf(":");
|
|
1242
|
+
if (separatorIndex < 1) {
|
|
1243
|
+
return false;
|
|
1244
|
+
}
|
|
1245
|
+
const ruleName = ruleConfiguration.slice(0, separatorIndex).trimEnd();
|
|
1246
|
+
return ruleName.length > 0 && [...ruleName].every((character) => character.trim() !== "");
|
|
1247
|
+
}
|
|
1248
|
+
function isFixedEslintComment(comment, isBlockComment) {
|
|
1249
|
+
if (!isBlockComment) {
|
|
1250
|
+
return false;
|
|
1251
|
+
}
|
|
1252
|
+
const commentText = getAstCommentText(comment)?.trim();
|
|
1253
|
+
if (!commentText) {
|
|
1254
|
+
return false;
|
|
1255
|
+
}
|
|
1256
|
+
return hasCommentDirective(commentText, ESLINT_RANGE_DIRECTIVES) || isEslintRuleConfiguration(commentText) || hasCommentDirective(commentText, ESLINT_GLOBAL_DIRECTIVES);
|
|
1257
|
+
}
|
|
1258
|
+
function isEslintNextLineComment(comment) {
|
|
1259
|
+
const commentText = getAstCommentText(comment)?.trim();
|
|
1260
|
+
if (!commentText) {
|
|
1261
|
+
return false;
|
|
1262
|
+
}
|
|
1263
|
+
return getCommentDirectiveArguments(commentText, "eslint-disable-next-line") !== null;
|
|
1264
|
+
}
|
|
1265
|
+
function isFixedEslintParserComment(sourceText, parserComment) {
|
|
1266
|
+
const { comment, textRange } = parserComment;
|
|
1267
|
+
const sourceCommentText = sourceText.slice(textRange.start, textRange.end);
|
|
1268
|
+
return isFixedEslintComment(comment, sourceCommentText.startsWith("/*"));
|
|
1269
|
+
}
|
|
1270
|
+
function isPositionSensitiveEslintComment(sourceText, parserComment) {
|
|
1271
|
+
return isEslintNextLineComment(parserComment.comment) || isFixedEslintParserComment(sourceText, parserComment);
|
|
1272
|
+
}
|
|
1273
|
+
function getCommentLines(comment) {
|
|
1274
|
+
const commentText = getAstCommentText(comment);
|
|
1275
|
+
if (commentText === null) {
|
|
1276
|
+
return [];
|
|
1277
|
+
}
|
|
1278
|
+
return commentText.split(/\r?\n/).map((commentLine) => commentLine.replace(/^\s*\*+\s*/, ""));
|
|
1279
|
+
}
|
|
1280
|
+
function isFixedFileComment(sourceText, comment, commentRange, prettierFilePragmaComment) {
|
|
1281
|
+
const sourceCommentText = sourceText.slice(commentRange.start, commentRange.end);
|
|
1282
|
+
if (sourceCommentText.startsWith("#!")) {
|
|
1283
|
+
return true;
|
|
1284
|
+
}
|
|
1285
|
+
if (comment === prettierFilePragmaComment) {
|
|
1286
|
+
return true;
|
|
1287
|
+
}
|
|
1288
|
+
const isBlockComment = sourceCommentText.startsWith("/*");
|
|
1289
|
+
return isFixedEslintComment(comment, isBlockComment);
|
|
1290
|
+
}
|
|
1291
|
+
function getPrettierFilePragmaComment(sortedComments, isPrettierFilePragmaPresent) {
|
|
1292
|
+
if (!isPrettierFilePragmaPresent) {
|
|
1293
|
+
return null;
|
|
1294
|
+
}
|
|
1295
|
+
return sortedComments.find(({ comment }) => getCommentLines(comment).some((commentLine) => hasCommentDirective(commentLine.trim(), PRETTIER_FILE_PRAGMA_DIRECTIVES)))?.comment ?? null;
|
|
1296
|
+
}
|
|
1297
|
+
function classifyImportGroup(moduleSpecifier) {
|
|
1298
|
+
if (moduleSpecifier === "bun" || moduleSpecifier.startsWith("bun:") || moduleSpecifier.startsWith("node:")) {
|
|
1299
|
+
return "builtin";
|
|
1300
|
+
}
|
|
1301
|
+
if (moduleSpecifier === "." || moduleSpecifier === "./" || INDEX_MODULE_PATTERN.test(moduleSpecifier)) {
|
|
1302
|
+
return "index";
|
|
1303
|
+
}
|
|
1304
|
+
if (moduleSpecifier === ".." || moduleSpecifier.startsWith("../")) {
|
|
1305
|
+
return "parent";
|
|
1306
|
+
}
|
|
1307
|
+
if (moduleSpecifier.startsWith("./")) {
|
|
1308
|
+
return "sibling";
|
|
1309
|
+
}
|
|
1310
|
+
if (moduleSpecifier.startsWith("/") || moduleSpecifier.startsWith("~") || moduleSpecifier.startsWith("@/") || moduleSpecifier.startsWith("#")) {
|
|
1311
|
+
return "internal";
|
|
1312
|
+
}
|
|
1313
|
+
return "external";
|
|
1314
|
+
}
|
|
1315
|
+
function findLeadingCommentsStart(sourceText, statementStart, sortedComments, prettierFilePragmaComment) {
|
|
1316
|
+
let attachedTextStart = statementStart;
|
|
1317
|
+
for (let commentIndex = findCommentIndexAtOrAfter(sortedComments, statementStart) - 1;commentIndex >= 0; commentIndex--) {
|
|
1318
|
+
const parserComment = sortedComments[commentIndex];
|
|
1319
|
+
if (!parserComment || parserComment.textRange.end > statementStart) {
|
|
1320
|
+
continue;
|
|
1321
|
+
}
|
|
1322
|
+
const { comment, textRange } = parserComment;
|
|
1323
|
+
if (isFixedFileComment(sourceText, comment, textRange, prettierFilePragmaComment)) {
|
|
1324
|
+
break;
|
|
1325
|
+
}
|
|
1326
|
+
const textBetweenCommentAndImport = sourceText.slice(textRange.end, attachedTextStart);
|
|
1327
|
+
const lineBreakCount = textBetweenCommentAndImport.match(/\n/g)?.length ?? 0;
|
|
1328
|
+
const isEslintNextLineCommentAttached = attachedTextStart === statementStart && isEslintNextLineComment(comment) && textBetweenCommentAndImport.trim() === "" && lineBreakCount === 1;
|
|
1329
|
+
if (isEslintNextLineCommentAttached) {
|
|
1330
|
+
attachedTextStart = textRange.start;
|
|
1331
|
+
continue;
|
|
1332
|
+
}
|
|
1333
|
+
const commentLineStart = sourceText.lastIndexOf(`
|
|
1334
|
+
`, textRange.start - 1) + 1;
|
|
1335
|
+
if (sourceText.slice(commentLineStart, textRange.start).trim() !== "") {
|
|
1336
|
+
break;
|
|
1337
|
+
}
|
|
1338
|
+
if (textBetweenCommentAndImport.trim() !== "" || lineBreakCount >= 2) {
|
|
1339
|
+
break;
|
|
1340
|
+
}
|
|
1341
|
+
attachedTextStart = textRange.start;
|
|
1342
|
+
}
|
|
1343
|
+
while (attachedTextStart > 0 && /[ \t]/.test(sourceText[attachedTextStart - 1])) {
|
|
1344
|
+
attachedTextStart--;
|
|
1345
|
+
}
|
|
1346
|
+
return attachedTextStart;
|
|
1347
|
+
}
|
|
1348
|
+
function getRangeEndIncludingLineBreak(sourceText, sourceIndex) {
|
|
1349
|
+
if (sourceText[sourceIndex] === "\r" && sourceText[sourceIndex + 1] === `
|
|
1350
|
+
`) {
|
|
1351
|
+
return sourceIndex + 2;
|
|
1352
|
+
}
|
|
1353
|
+
if (sourceText[sourceIndex] === `
|
|
1354
|
+
`) {
|
|
1355
|
+
return sourceIndex + 1;
|
|
1356
|
+
}
|
|
1357
|
+
return sourceIndex;
|
|
1358
|
+
}
|
|
1359
|
+
function getTrailingComments(sourceText, statementEnd, sortedComments) {
|
|
1360
|
+
let trailingCommentsEnd = statementEnd;
|
|
1361
|
+
let isImportSortingBoundary = false;
|
|
1362
|
+
const firstTrailingCommentIndex = findCommentIndexAtOrAfter(sortedComments, statementEnd);
|
|
1363
|
+
for (let commentIndex = firstTrailingCommentIndex;commentIndex < sortedComments.length; commentIndex++) {
|
|
1364
|
+
const trailingComment = sortedComments[commentIndex];
|
|
1365
|
+
if (!trailingComment) {
|
|
1366
|
+
break;
|
|
1367
|
+
}
|
|
1368
|
+
const { textRange } = trailingComment;
|
|
1369
|
+
const textBeforeComment = sourceText.slice(trailingCommentsEnd, textRange.start);
|
|
1370
|
+
if (textBeforeComment.includes(`
|
|
1371
|
+
`) || textBeforeComment.trim() !== "") {
|
|
1372
|
+
break;
|
|
1373
|
+
}
|
|
1374
|
+
const commentLineEnd = sourceText.indexOf(`
|
|
1375
|
+
`, textRange.end);
|
|
1376
|
+
if (!isSourceRangeWhitespaceOrComments(sourceText, {
|
|
1377
|
+
start: textRange.end,
|
|
1378
|
+
end: commentLineEnd < 0 ? sourceText.length : commentLineEnd
|
|
1379
|
+
}, sortedComments)) {
|
|
1380
|
+
break;
|
|
1381
|
+
}
|
|
1382
|
+
if (isFixedEslintParserComment(sourceText, trailingComment)) {
|
|
1383
|
+
isImportSortingBoundary = true;
|
|
1384
|
+
break;
|
|
1385
|
+
}
|
|
1386
|
+
if (isEslintNextLineComment(trailingComment.comment)) {
|
|
1387
|
+
break;
|
|
1388
|
+
}
|
|
1389
|
+
trailingCommentsEnd = textRange.end;
|
|
1390
|
+
}
|
|
1391
|
+
return {
|
|
1392
|
+
commentsText: sourceText.slice(statementEnd, trailingCommentsEnd),
|
|
1393
|
+
rangeEnd: trailingCommentsEnd,
|
|
1394
|
+
isImportSortingBoundary
|
|
1395
|
+
};
|
|
1396
|
+
}
|
|
1397
|
+
function parseImportAttributes(sourceText, importDeclarationNode) {
|
|
1398
|
+
const declarationRange = getAstNodeTextRange(importDeclarationNode);
|
|
1399
|
+
const moduleSpecifierRange = getAstNodeTextRange(importDeclarationNode.source);
|
|
1400
|
+
if (!declarationRange || !moduleSpecifierRange) {
|
|
1401
|
+
return { attributesText: null, isValid: false };
|
|
1402
|
+
}
|
|
1403
|
+
const importAttributesText = sourceText.slice(moduleSpecifierRange.end, declarationRange.end).replace(/;\s*$/, "").trim();
|
|
1404
|
+
if (importAttributesText === "") {
|
|
1405
|
+
return { attributesText: null, isValid: true };
|
|
1406
|
+
}
|
|
1407
|
+
return {
|
|
1408
|
+
attributesText: importAttributesText,
|
|
1409
|
+
isValid: /^(?:with|assert)\s*\{[\s\S]*\}$/.test(importAttributesText)
|
|
1410
|
+
};
|
|
1411
|
+
}
|
|
1412
|
+
function parseImportDeclaration(importDeclarationMetadata, sourceText) {
|
|
1413
|
+
const {
|
|
1414
|
+
importDeclarationNode,
|
|
1415
|
+
declarationRange,
|
|
1416
|
+
leadingCommentsText,
|
|
1417
|
+
trailingCommentsText,
|
|
1418
|
+
hasInternalComments
|
|
1419
|
+
} = importDeclarationMetadata;
|
|
1420
|
+
const moduleSpecifierNode = importDeclarationNode.source;
|
|
1421
|
+
const moduleSpecifierRange = getAstNodeTextRange(moduleSpecifierNode);
|
|
1422
|
+
const moduleSpecifier = getAstNodeName(moduleSpecifierNode);
|
|
1423
|
+
if (!moduleSpecifierRange || moduleSpecifier === null) {
|
|
1424
|
+
return null;
|
|
1425
|
+
}
|
|
1426
|
+
let importKind = "value";
|
|
1427
|
+
const declarationText = sourceText.slice(declarationRange.start, declarationRange.end);
|
|
1428
|
+
if (typeof importDeclarationNode.importKind === "string") {
|
|
1429
|
+
importKind = importDeclarationNode.importKind;
|
|
1430
|
+
}
|
|
1431
|
+
let specifierNodes = [];
|
|
1432
|
+
const isTypeOnly = importKind === "type";
|
|
1433
|
+
if (Array.isArray(importDeclarationNode.specifiers)) {
|
|
1434
|
+
specifierNodes = importDeclarationNode.specifiers;
|
|
1435
|
+
}
|
|
1436
|
+
let importPhase = null;
|
|
1437
|
+
const isSideEffectOnly = specifierNodes.length === 0 && importKind === "value";
|
|
1438
|
+
const parsedImportAttributes = parseImportAttributes(sourceText, importDeclarationNode);
|
|
1439
|
+
if (typeof importDeclarationNode.phase === "string") {
|
|
1440
|
+
importPhase = importDeclarationNode.phase;
|
|
1441
|
+
}
|
|
1442
|
+
let defaultBinding = null;
|
|
1443
|
+
let namespaceBinding = null;
|
|
1444
|
+
let isEverySpecifierSupported = true;
|
|
1445
|
+
const namedSpecifiers = [];
|
|
1446
|
+
for (const specifierNode of specifierNodes) {
|
|
1447
|
+
if (specifierNode.type === "ImportDefaultSpecifier") {
|
|
1448
|
+
defaultBinding = getAstNodeName(specifierNode.local);
|
|
1449
|
+
isEverySpecifierSupported &&= defaultBinding !== null;
|
|
1450
|
+
continue;
|
|
1451
|
+
}
|
|
1452
|
+
if (specifierNode.type === "ImportNamespaceSpecifier") {
|
|
1453
|
+
namespaceBinding = getAstNodeName(specifierNode.local);
|
|
1454
|
+
isEverySpecifierSupported &&= namespaceBinding !== null;
|
|
1455
|
+
continue;
|
|
1456
|
+
}
|
|
1457
|
+
if (specifierNode.type !== "ImportSpecifier") {
|
|
1458
|
+
isEverySpecifierSupported = false;
|
|
1459
|
+
continue;
|
|
1460
|
+
}
|
|
1461
|
+
let specifierKind = "value";
|
|
1462
|
+
const importedNode = specifierNode.imported;
|
|
1463
|
+
const importedNameRange = getAstNodeTextRange(importedNode);
|
|
1464
|
+
const importedName = getAstNodeName(importedNode);
|
|
1465
|
+
const localName = getAstNodeName(specifierNode.local);
|
|
1466
|
+
if (typeof specifierNode.importKind === "string") {
|
|
1467
|
+
specifierKind = specifierNode.importKind;
|
|
1468
|
+
}
|
|
1469
|
+
if (!importedNameRange || importedName === null || localName === null || specifierKind !== "value" && specifierKind !== "type") {
|
|
1470
|
+
isEverySpecifierSupported = false;
|
|
1471
|
+
continue;
|
|
1472
|
+
}
|
|
1473
|
+
namedSpecifiers.push({
|
|
1474
|
+
importedName,
|
|
1475
|
+
importedNameText: sourceText.slice(importedNameRange.start, importedNameRange.end),
|
|
1476
|
+
localName,
|
|
1477
|
+
isTypeOnly: specifierKind === "type"
|
|
1478
|
+
});
|
|
1479
|
+
}
|
|
1480
|
+
let parsedNamedSpecifiers = null;
|
|
1481
|
+
const isTypeClauseRewriteUnsupported = isTypeOnly && (defaultBinding !== null || namespaceBinding !== null);
|
|
1482
|
+
const isVerbatimRenderingRequired = specifierNodes.length === 0 || hasInternalComments || importPhase !== null || importKind !== "value" && importKind !== "type" || !isEverySpecifierSupported || !parsedImportAttributes.isValid || isTypeClauseRewriteUnsupported || isTypeOnly && parsedImportAttributes.attributesText !== null;
|
|
1483
|
+
if (namedSpecifiers.length > 0) {
|
|
1484
|
+
parsedNamedSpecifiers = namedSpecifiers;
|
|
1485
|
+
}
|
|
1486
|
+
let verbatimDeclaration = null;
|
|
1487
|
+
if (isVerbatimRenderingRequired) {
|
|
1488
|
+
verbatimDeclaration = declarationText;
|
|
1489
|
+
}
|
|
1490
|
+
return {
|
|
1491
|
+
moduleSpecifier,
|
|
1492
|
+
moduleSpecifierText: sourceText.slice(moduleSpecifierRange.start, moduleSpecifierRange.end),
|
|
1493
|
+
isTypeOnly,
|
|
1494
|
+
isSideEffectOnly,
|
|
1495
|
+
defaultBinding,
|
|
1496
|
+
namespaceBinding,
|
|
1497
|
+
namedSpecifiers: parsedNamedSpecifiers,
|
|
1498
|
+
importAttributes: parsedImportAttributes.attributesText,
|
|
1499
|
+
verbatimDeclaration,
|
|
1500
|
+
leadingCommentsText,
|
|
1501
|
+
trailingCommentsText,
|
|
1502
|
+
isMergeBoundary: leadingCommentsText.trim() !== "" || trailingCommentsText !== "" || hasInternalComments
|
|
1503
|
+
};
|
|
1504
|
+
}
|
|
1505
|
+
function renderNamedImportSpecifiers(namedSpecifiers) {
|
|
1506
|
+
return namedSpecifiers.map((importSpecifier) => {
|
|
1507
|
+
let renderedSpecifier = importSpecifier.importedNameText;
|
|
1508
|
+
const isAliasRequired = importSpecifier.importedNameText !== importSpecifier.importedName || importSpecifier.importedName !== importSpecifier.localName;
|
|
1509
|
+
if (isAliasRequired) {
|
|
1510
|
+
renderedSpecifier = `${importSpecifier.importedNameText} as ${importSpecifier.localName}`;
|
|
1511
|
+
}
|
|
1512
|
+
if (importSpecifier.isTypeOnly) {
|
|
1513
|
+
return `type ${renderedSpecifier}`;
|
|
1514
|
+
}
|
|
1515
|
+
return renderedSpecifier;
|
|
1516
|
+
}).join(", ");
|
|
1517
|
+
}
|
|
1518
|
+
function renderImportBindings(importDeclaration) {
|
|
1519
|
+
const renderedBindings = [];
|
|
1520
|
+
if (importDeclaration.defaultBinding) {
|
|
1521
|
+
renderedBindings.push(importDeclaration.defaultBinding);
|
|
1522
|
+
}
|
|
1523
|
+
if (importDeclaration.namespaceBinding) {
|
|
1524
|
+
renderedBindings.push(`* as ${importDeclaration.namespaceBinding}`);
|
|
1525
|
+
}
|
|
1526
|
+
if (importDeclaration.namedSpecifiers) {
|
|
1527
|
+
renderedBindings.push(`{ ${renderNamedImportSpecifiers(importDeclaration.namedSpecifiers)} }`);
|
|
1528
|
+
}
|
|
1529
|
+
return renderedBindings.join(", ");
|
|
1530
|
+
}
|
|
1531
|
+
function renderImportDeclaration(importDeclaration) {
|
|
1532
|
+
if (importDeclaration.verbatimDeclaration !== null) {
|
|
1533
|
+
return importDeclaration.leadingCommentsText + importDeclaration.verbatimDeclaration + importDeclaration.trailingCommentsText;
|
|
1534
|
+
}
|
|
1535
|
+
let attributesSuffix = "";
|
|
1536
|
+
if (importDeclaration.importAttributes) {
|
|
1537
|
+
attributesSuffix = ` ${importDeclaration.importAttributes}`;
|
|
1538
|
+
}
|
|
1539
|
+
let declarationText = `import ${renderImportBindings(importDeclaration)} from ${importDeclaration.moduleSpecifierText}${attributesSuffix};`;
|
|
1540
|
+
if (importDeclaration.isTypeOnly) {
|
|
1541
|
+
declarationText = `import type ${renderImportBindings(importDeclaration)} from ${importDeclaration.moduleSpecifierText}${attributesSuffix};`;
|
|
1542
|
+
}
|
|
1543
|
+
return importDeclaration.leadingCommentsText + declarationText + importDeclaration.trailingCommentsText;
|
|
1544
|
+
}
|
|
1545
|
+
function sortNamedImportSpecifiers(namedSpecifiers) {
|
|
1546
|
+
return [...namedSpecifiers].sort((left, right) => left.localName.localeCompare(right.localName, "en", {
|
|
1547
|
+
sensitivity: "base"
|
|
1548
|
+
}));
|
|
1549
|
+
}
|
|
1550
|
+
function getLocalBindingNames(importDeclaration) {
|
|
1551
|
+
const localBindingNames = [];
|
|
1552
|
+
if (importDeclaration.defaultBinding) {
|
|
1553
|
+
localBindingNames.push(importDeclaration.defaultBinding);
|
|
1554
|
+
}
|
|
1555
|
+
if (importDeclaration.namespaceBinding) {
|
|
1556
|
+
localBindingNames.push(importDeclaration.namespaceBinding);
|
|
1557
|
+
}
|
|
1558
|
+
if (importDeclaration.namedSpecifiers) {
|
|
1559
|
+
localBindingNames.push(...importDeclaration.namedSpecifiers.map((importSpecifier) => importSpecifier.localName));
|
|
1560
|
+
}
|
|
1561
|
+
return localBindingNames;
|
|
1562
|
+
}
|
|
1563
|
+
function getImportRequestKey(importDeclaration) {
|
|
1564
|
+
return `${importDeclaration.moduleSpecifier}\x00${importDeclaration.importAttributes ?? ""}`;
|
|
1565
|
+
}
|
|
1566
|
+
function isImportDeclarationMergeSafe(targetImportDeclaration, candidateImportDeclaration, bindingCounts) {
|
|
1567
|
+
if (targetImportDeclaration.verbatimDeclaration !== null || candidateImportDeclaration.verbatimDeclaration !== null || targetImportDeclaration.isSideEffectOnly || candidateImportDeclaration.isSideEffectOnly || targetImportDeclaration.moduleSpecifier !== candidateImportDeclaration.moduleSpecifier || targetImportDeclaration.importAttributes !== candidateImportDeclaration.importAttributes || targetImportDeclaration.isMergeBoundary || candidateImportDeclaration.isMergeBoundary) {
|
|
1568
|
+
return false;
|
|
1569
|
+
}
|
|
1570
|
+
if (bindingCounts.defaultBindingCount > 1 && (targetImportDeclaration.defaultBinding !== null || candidateImportDeclaration.defaultBinding !== null) || bindingCounts.namespaceBindingCount > 1 && (targetImportDeclaration.namespaceBinding !== null || candidateImportDeclaration.namespaceBinding !== null) || targetImportDeclaration.defaultBinding !== null && candidateImportDeclaration.defaultBinding !== null || targetImportDeclaration.namespaceBinding !== null && candidateImportDeclaration.namespaceBinding !== null) {
|
|
1571
|
+
return false;
|
|
1572
|
+
}
|
|
1573
|
+
const isAnyNamedSpecifierPresent = (targetImportDeclaration.namedSpecifiers?.length ?? 0) > 0 || (candidateImportDeclaration.namedSpecifiers?.length ?? 0) > 0;
|
|
1574
|
+
if (isAnyNamedSpecifierPresent && (targetImportDeclaration.namespaceBinding !== null || candidateImportDeclaration.namespaceBinding !== null)) {
|
|
1575
|
+
return false;
|
|
1576
|
+
}
|
|
1577
|
+
const usedLocalNames = new Set(getLocalBindingNames(targetImportDeclaration));
|
|
1578
|
+
return getLocalBindingNames(candidateImportDeclaration).every((localName) => !usedLocalNames.has(localName));
|
|
1579
|
+
}
|
|
1580
|
+
function mergeImportDeclarations(targetImportDeclaration, candidateImportDeclaration) {
|
|
1581
|
+
let namedSpecifiers = null;
|
|
1582
|
+
const isTypeOnly = targetImportDeclaration.isTypeOnly && candidateImportDeclaration.isTypeOnly;
|
|
1583
|
+
const mergedNamedSpecifiers = [
|
|
1584
|
+
...getNamedSpecifiersForMerge(targetImportDeclaration, isTypeOnly),
|
|
1585
|
+
...getNamedSpecifiersForMerge(candidateImportDeclaration, isTypeOnly)
|
|
1586
|
+
];
|
|
1587
|
+
if (mergedNamedSpecifiers.length > 0) {
|
|
1588
|
+
namedSpecifiers = mergedNamedSpecifiers;
|
|
1589
|
+
}
|
|
1590
|
+
return {
|
|
1591
|
+
moduleSpecifier: targetImportDeclaration.moduleSpecifier,
|
|
1592
|
+
moduleSpecifierText: targetImportDeclaration.moduleSpecifierText,
|
|
1593
|
+
isTypeOnly,
|
|
1594
|
+
isSideEffectOnly: false,
|
|
1595
|
+
defaultBinding: targetImportDeclaration.defaultBinding ?? candidateImportDeclaration.defaultBinding,
|
|
1596
|
+
namespaceBinding: targetImportDeclaration.namespaceBinding ?? candidateImportDeclaration.namespaceBinding,
|
|
1597
|
+
namedSpecifiers,
|
|
1598
|
+
importAttributes: targetImportDeclaration.importAttributes,
|
|
1599
|
+
verbatimDeclaration: null,
|
|
1600
|
+
leadingCommentsText: targetImportDeclaration.leadingCommentsText,
|
|
1601
|
+
trailingCommentsText: "",
|
|
1602
|
+
isMergeBoundary: false
|
|
1603
|
+
};
|
|
1604
|
+
}
|
|
1605
|
+
function getNamedSpecifiersForMerge(importDeclaration, isMergedTypeOnly) {
|
|
1606
|
+
return (importDeclaration.namedSpecifiers ?? []).map((importSpecifier) => ({
|
|
1607
|
+
...importSpecifier,
|
|
1608
|
+
isTypeOnly: !isMergedTypeOnly && (importDeclaration.isTypeOnly || importSpecifier.isTypeOnly)
|
|
1609
|
+
}));
|
|
1610
|
+
}
|
|
1611
|
+
function mergeCompatibleImports(importDeclarations) {
|
|
1612
|
+
const bindingCountsByImportDeclaration = new Map;
|
|
1613
|
+
const currentBindingCountsByRequest = new Map;
|
|
1614
|
+
const minimumMergeTargetIndexByRequest = new Map;
|
|
1615
|
+
for (const importDeclaration of importDeclarations) {
|
|
1616
|
+
const importRequestKey = getImportRequestKey(importDeclaration);
|
|
1617
|
+
if (importDeclaration.isMergeBoundary) {
|
|
1618
|
+
currentBindingCountsByRequest.delete(importRequestKey);
|
|
1619
|
+
continue;
|
|
1620
|
+
}
|
|
1621
|
+
if (importDeclaration.verbatimDeclaration !== null || importDeclaration.isSideEffectOnly) {
|
|
1622
|
+
continue;
|
|
1623
|
+
}
|
|
1624
|
+
const bindingCounts = currentBindingCountsByRequest.get(importRequestKey) ?? {
|
|
1625
|
+
defaultBindingCount: 0,
|
|
1626
|
+
namespaceBindingCount: 0
|
|
1627
|
+
};
|
|
1628
|
+
if (importDeclaration.defaultBinding !== null) {
|
|
1629
|
+
bindingCounts.defaultBindingCount++;
|
|
1630
|
+
}
|
|
1631
|
+
if (importDeclaration.namespaceBinding !== null) {
|
|
1632
|
+
bindingCounts.namespaceBindingCount++;
|
|
1633
|
+
}
|
|
1634
|
+
currentBindingCountsByRequest.set(importRequestKey, bindingCounts);
|
|
1635
|
+
bindingCountsByImportDeclaration.set(importDeclaration, bindingCounts);
|
|
1636
|
+
}
|
|
1637
|
+
const mergedImportDeclarations = [];
|
|
1638
|
+
for (const importDeclaration of importDeclarations) {
|
|
1639
|
+
const importRequestKey = getImportRequestKey(importDeclaration);
|
|
1640
|
+
const bindingCounts = bindingCountsByImportDeclaration.get(importDeclaration) ?? {
|
|
1641
|
+
defaultBindingCount: 0,
|
|
1642
|
+
namespaceBindingCount: 0
|
|
1643
|
+
};
|
|
1644
|
+
const minimumMergeTargetIndex = minimumMergeTargetIndexByRequest.get(importRequestKey) ?? 0;
|
|
1645
|
+
const mergeTargetIndex = mergedImportDeclarations.findIndex((existingImportDeclaration, existingImportIndex) => existingImportIndex >= minimumMergeTargetIndex && isImportDeclarationMergeSafe(existingImportDeclaration, importDeclaration, bindingCounts));
|
|
1646
|
+
if (mergeTargetIndex < 0) {
|
|
1647
|
+
mergedImportDeclarations.push(importDeclaration);
|
|
1648
|
+
} else {
|
|
1649
|
+
mergedImportDeclarations[mergeTargetIndex] = mergeImportDeclarations(mergedImportDeclarations[mergeTargetIndex], importDeclaration);
|
|
1650
|
+
}
|
|
1651
|
+
if (importDeclaration.isMergeBoundary) {
|
|
1652
|
+
minimumMergeTargetIndexByRequest.set(importRequestKey, mergedImportDeclarations.length);
|
|
1653
|
+
}
|
|
1654
|
+
}
|
|
1655
|
+
return mergedImportDeclarations;
|
|
1656
|
+
}
|
|
1657
|
+
function applyTypeImportStyle(importDeclaration, typeImportStyle) {
|
|
1658
|
+
if (importDeclaration.verbatimDeclaration !== null || !importDeclaration.namedSpecifiers) {
|
|
1659
|
+
return [importDeclaration];
|
|
1660
|
+
}
|
|
1661
|
+
const namedSpecifiers = importDeclaration.namedSpecifiers;
|
|
1662
|
+
if (importDeclaration.isTypeOnly) {
|
|
1663
|
+
return [
|
|
1664
|
+
{
|
|
1665
|
+
...importDeclaration,
|
|
1666
|
+
namedSpecifiers: sortNamedImportSpecifiers(namedSpecifiers)
|
|
1667
|
+
}
|
|
1668
|
+
];
|
|
1669
|
+
}
|
|
1670
|
+
if (typeImportStyle === "separate") {
|
|
1671
|
+
const typeSpecifiers2 = namedSpecifiers.filter((importSpecifier) => importSpecifier.isTypeOnly);
|
|
1672
|
+
const valueSpecifiers2 = namedSpecifiers.filter((importSpecifier) => !importSpecifier.isTypeOnly);
|
|
1673
|
+
const hasValueBinding = valueSpecifiers2.length > 0 || importDeclaration.defaultBinding !== null || importDeclaration.namespaceBinding !== null;
|
|
1674
|
+
if (typeSpecifiers2.length > 0 && (!hasValueBinding || importDeclaration.importAttributes !== null || importDeclaration.leadingCommentsText.trim() !== "" || importDeclaration.trailingCommentsText !== "")) {
|
|
1675
|
+
return [
|
|
1676
|
+
{
|
|
1677
|
+
...importDeclaration,
|
|
1678
|
+
namedSpecifiers: sortNamedImportSpecifiers(namedSpecifiers)
|
|
1679
|
+
}
|
|
1680
|
+
];
|
|
1681
|
+
}
|
|
1682
|
+
const styledImportDeclarations = [];
|
|
1683
|
+
if (typeSpecifiers2.length > 0) {
|
|
1684
|
+
styledImportDeclarations.push({
|
|
1685
|
+
...importDeclaration,
|
|
1686
|
+
isTypeOnly: true,
|
|
1687
|
+
defaultBinding: null,
|
|
1688
|
+
namespaceBinding: null,
|
|
1689
|
+
namedSpecifiers: sortNamedImportSpecifiers(typeSpecifiers2.map((importSpecifier) => ({
|
|
1690
|
+
...importSpecifier,
|
|
1691
|
+
isTypeOnly: false
|
|
1692
|
+
})))
|
|
1693
|
+
});
|
|
1694
|
+
}
|
|
1695
|
+
if (valueSpecifiers2.length > 0 || importDeclaration.defaultBinding !== null || importDeclaration.namespaceBinding !== null) {
|
|
1696
|
+
let namedValueSpecifiers = null;
|
|
1697
|
+
if (valueSpecifiers2.length > 0) {
|
|
1698
|
+
namedValueSpecifiers = sortNamedImportSpecifiers(valueSpecifiers2);
|
|
1699
|
+
}
|
|
1700
|
+
let leadingCommentsText = importDeclaration.leadingCommentsText;
|
|
1701
|
+
if (typeSpecifiers2.length > 0) {
|
|
1702
|
+
leadingCommentsText = "";
|
|
1703
|
+
}
|
|
1704
|
+
styledImportDeclarations.push({
|
|
1705
|
+
...importDeclaration,
|
|
1706
|
+
namedSpecifiers: namedValueSpecifiers,
|
|
1707
|
+
leadingCommentsText
|
|
1708
|
+
});
|
|
1709
|
+
}
|
|
1710
|
+
return styledImportDeclarations;
|
|
1711
|
+
}
|
|
1712
|
+
if (typeImportStyle === "mixed") {
|
|
1713
|
+
return [
|
|
1714
|
+
{
|
|
1715
|
+
...importDeclaration,
|
|
1716
|
+
namedSpecifiers: sortNamedImportSpecifiers(namedSpecifiers)
|
|
1717
|
+
}
|
|
1718
|
+
];
|
|
1719
|
+
}
|
|
1720
|
+
const typeSpecifiers = sortNamedImportSpecifiers(namedSpecifiers.filter((importSpecifier) => importSpecifier.isTypeOnly));
|
|
1721
|
+
const valueSpecifiers = sortNamedImportSpecifiers(namedSpecifiers.filter((importSpecifier) => !importSpecifier.isTypeOnly));
|
|
1722
|
+
let orderedSpecifiers = [...valueSpecifiers, ...typeSpecifiers];
|
|
1723
|
+
if (typeImportStyle === "inline-first") {
|
|
1724
|
+
orderedSpecifiers = [...typeSpecifiers, ...valueSpecifiers];
|
|
1725
|
+
}
|
|
1726
|
+
return [{ ...importDeclaration, namedSpecifiers: orderedSpecifiers }];
|
|
1727
|
+
}
|
|
1728
|
+
function getImportBindingShapeRank(importDeclaration) {
|
|
1729
|
+
if (importDeclaration.defaultBinding !== null) {
|
|
1730
|
+
return 0;
|
|
1731
|
+
}
|
|
1732
|
+
if (importDeclaration.namespaceBinding !== null) {
|
|
1733
|
+
return 1;
|
|
1734
|
+
}
|
|
1735
|
+
return 2;
|
|
1736
|
+
}
|
|
1737
|
+
function sortImportSegment(importDeclarations, sortOptions, importGroupOrder) {
|
|
1738
|
+
let mergedImportDeclarations = [...importDeclarations];
|
|
1739
|
+
if (sortOptions.esmImportMerge) {
|
|
1740
|
+
mergedImportDeclarations = mergeCompatibleImports(importDeclarations);
|
|
1741
|
+
}
|
|
1742
|
+
const styledImportDeclarations = mergedImportDeclarations.flatMap((importDeclaration) => applyTypeImportStyle(importDeclaration, sortOptions.esmImportTypeStyle));
|
|
1743
|
+
const unlistedGroupRank = sortOptions.esmImportGroups.length;
|
|
1744
|
+
const rankedImportDeclarations = styledImportDeclarations.map((importDeclaration, originalIndex) => ({
|
|
1745
|
+
importDeclaration,
|
|
1746
|
+
importGroup: classifyImportGroup(importDeclaration.moduleSpecifier),
|
|
1747
|
+
originalIndex
|
|
1748
|
+
}));
|
|
1749
|
+
rankedImportDeclarations.sort((left, right) => {
|
|
1750
|
+
const groupRankDifference = (importGroupOrder.get(left.importGroup) ?? unlistedGroupRank) - (importGroupOrder.get(right.importGroup) ?? unlistedGroupRank);
|
|
1751
|
+
if (groupRankDifference !== 0) {
|
|
1752
|
+
return groupRankDifference;
|
|
1753
|
+
}
|
|
1754
|
+
const moduleSpecifierDifference = left.importDeclaration.moduleSpecifier.localeCompare(right.importDeclaration.moduleSpecifier, "en", { sensitivity: "base" });
|
|
1755
|
+
if (moduleSpecifierDifference !== 0) {
|
|
1756
|
+
return moduleSpecifierDifference;
|
|
1757
|
+
}
|
|
1758
|
+
if (left.importDeclaration.isTypeOnly !== right.importDeclaration.isTypeOnly) {
|
|
1759
|
+
if (left.importDeclaration.isTypeOnly) {
|
|
1760
|
+
return -1;
|
|
1761
|
+
}
|
|
1762
|
+
return 1;
|
|
1763
|
+
}
|
|
1764
|
+
return getImportBindingShapeRank(left.importDeclaration) - getImportBindingShapeRank(right.importDeclaration) || left.originalIndex - right.originalIndex;
|
|
1765
|
+
});
|
|
1766
|
+
let previousImportGroup = null;
|
|
1767
|
+
const renderedImportLines = [];
|
|
1768
|
+
for (const { importDeclaration, importGroup } of rankedImportDeclarations) {
|
|
1769
|
+
if (sortOptions.esmImportSeparation && previousImportGroup !== null && importGroup !== previousImportGroup) {
|
|
1770
|
+
renderedImportLines.push("");
|
|
1771
|
+
}
|
|
1772
|
+
renderedImportLines.push(renderImportDeclaration(importDeclaration));
|
|
1773
|
+
previousImportGroup = importGroup;
|
|
1774
|
+
}
|
|
1775
|
+
return renderedImportLines;
|
|
1776
|
+
}
|
|
1777
|
+
function renderSortedImportLines(importDeclarations, sortOptions) {
|
|
1778
|
+
let currentSortableImportDeclarations = [];
|
|
1779
|
+
const importGroupOrder = new Map(sortOptions.esmImportGroups.map((importGroup, groupIndex) => [
|
|
1780
|
+
importGroup,
|
|
1781
|
+
groupIndex
|
|
1782
|
+
]));
|
|
1783
|
+
const importDeclarationChunks = [];
|
|
1784
|
+
for (const importDeclaration of importDeclarations) {
|
|
1785
|
+
if (!importDeclaration.isSideEffectOnly) {
|
|
1786
|
+
currentSortableImportDeclarations.push(importDeclaration);
|
|
1787
|
+
continue;
|
|
1788
|
+
}
|
|
1789
|
+
if (currentSortableImportDeclarations.length > 0) {
|
|
1790
|
+
importDeclarationChunks.push({
|
|
1791
|
+
kind: "sortable",
|
|
1792
|
+
importDeclarations: currentSortableImportDeclarations
|
|
1793
|
+
});
|
|
1794
|
+
currentSortableImportDeclarations = [];
|
|
1795
|
+
}
|
|
1796
|
+
importDeclarationChunks.push({ kind: "side-effect", importDeclaration });
|
|
1797
|
+
}
|
|
1798
|
+
if (currentSortableImportDeclarations.length > 0) {
|
|
1799
|
+
importDeclarationChunks.push({
|
|
1800
|
+
kind: "sortable",
|
|
1801
|
+
importDeclarations: currentSortableImportDeclarations
|
|
1802
|
+
});
|
|
1803
|
+
}
|
|
1804
|
+
let previousChunkKind = null;
|
|
1805
|
+
const renderedImportLines = [];
|
|
1806
|
+
for (const importChunk of importDeclarationChunks) {
|
|
1807
|
+
if (sortOptions.esmImportSeparation && previousChunkKind !== null && previousChunkKind !== importChunk.kind) {
|
|
1808
|
+
renderedImportLines.push("");
|
|
1809
|
+
}
|
|
1810
|
+
if (importChunk.kind === "sortable") {
|
|
1811
|
+
renderedImportLines.push(...sortImportSegment(importChunk.importDeclarations, sortOptions, importGroupOrder));
|
|
1812
|
+
} else {
|
|
1813
|
+
renderedImportLines.push(renderImportDeclaration(importChunk.importDeclaration));
|
|
1814
|
+
}
|
|
1815
|
+
previousChunkKind = importChunk.kind;
|
|
1816
|
+
}
|
|
1817
|
+
return renderedImportLines;
|
|
1818
|
+
}
|
|
1819
|
+
function isCommentPresentWithinRange(sortedComments, start, end) {
|
|
1820
|
+
const firstCommentIndex = findCommentIndexAtOrAfter(sortedComments, start);
|
|
1821
|
+
const firstComment = sortedComments[firstCommentIndex];
|
|
1822
|
+
return firstComment !== undefined && firstComment.textRange.end <= end;
|
|
1823
|
+
}
|
|
1824
|
+
function hasPositionSensitiveEslintCommentWithinRange(sourceText, sortedComments, start, end) {
|
|
1825
|
+
for (let commentIndex = findCommentIndexAtOrAfter(sortedComments, start);commentIndex < sortedComments.length; commentIndex++) {
|
|
1826
|
+
const parserComment = sortedComments[commentIndex];
|
|
1827
|
+
if (!parserComment || parserComment.textRange.start >= end) {
|
|
1828
|
+
return false;
|
|
1829
|
+
}
|
|
1830
|
+
if (parserComment.textRange.end <= end && isPositionSensitiveEslintComment(sourceText, parserComment)) {
|
|
1831
|
+
return true;
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
return false;
|
|
1835
|
+
}
|
|
1836
|
+
function buildImportSegmentEdits(sourceText, importEntries, sortOptions, lineEnding, isBlankLineRequired) {
|
|
1837
|
+
const [firstImportEntry] = importEntries;
|
|
1838
|
+
if (!firstImportEntry) {
|
|
1839
|
+
return null;
|
|
1840
|
+
}
|
|
1841
|
+
let trailingLineBreaks = lineEnding;
|
|
1842
|
+
const replacementText = renderSortedImportLines(importEntries.map((importEntry) => importEntry.parsedImportDeclaration), sortOptions).join(lineEnding);
|
|
1843
|
+
const removalEdits = importEntries.slice(1).map((importEntry) => ({
|
|
1844
|
+
start: importEntry.start,
|
|
1845
|
+
end: importEntry.end,
|
|
1846
|
+
replacementText: ""
|
|
1847
|
+
}));
|
|
1848
|
+
if (isBlankLineRequired) {
|
|
1849
|
+
const textWithoutLaterImports = applySourceTextEdits(sourceText, removalEdits);
|
|
1850
|
+
if (textWithoutLaterImports === null) {
|
|
1851
|
+
return null;
|
|
1852
|
+
}
|
|
1853
|
+
const isFollowingContentPresent = textWithoutLaterImports.slice(firstImportEntry.end).trim() !== "";
|
|
1854
|
+
if (isFollowingContentPresent) {
|
|
1855
|
+
trailingLineBreaks += lineEnding;
|
|
1856
|
+
}
|
|
1857
|
+
}
|
|
1858
|
+
return [
|
|
1859
|
+
{
|
|
1860
|
+
start: firstImportEntry.start,
|
|
1861
|
+
end: firstImportEntry.end,
|
|
1862
|
+
replacementText: replacementText + trailingLineBreaks
|
|
1863
|
+
},
|
|
1864
|
+
...removalEdits
|
|
1865
|
+
];
|
|
1866
|
+
}
|
|
1867
|
+
function buildImportSortingEdits(sourceText, programStatements, sortedComments, sortOptions, isPrettierFilePragmaPresent) {
|
|
1868
|
+
const importDeclarationNodes = programStatements.filter((statement) => statement.type === "ImportDeclaration");
|
|
1869
|
+
if (importDeclarationNodes.length === 0) {
|
|
1870
|
+
return [];
|
|
1871
|
+
}
|
|
1872
|
+
const prettierFilePragmaComment = getPrettierFilePragmaComment(sortedComments, isPrettierFilePragmaPresent);
|
|
1873
|
+
if (isPrettierFilePragmaPresent && !prettierFilePragmaComment) {
|
|
1874
|
+
return [];
|
|
1875
|
+
}
|
|
1876
|
+
let currentSortableSegment = [];
|
|
1877
|
+
const sortableSegments = [];
|
|
1878
|
+
for (const importDeclarationNode of importDeclarationNodes) {
|
|
1879
|
+
const declarationRange = getAstNodeTextRange(importDeclarationNode);
|
|
1880
|
+
if (!declarationRange) {
|
|
1881
|
+
return [];
|
|
1882
|
+
}
|
|
1883
|
+
if (hasPositionSensitiveEslintCommentWithinRange(sourceText, sortedComments, declarationRange.start, declarationRange.end)) {
|
|
1884
|
+
return [];
|
|
1885
|
+
}
|
|
1886
|
+
const isImportIgnoredByPrettier = isPrettierIgnored(sourceText, declarationRange, sortedComments);
|
|
1887
|
+
const leadingCommentsStart = findLeadingCommentsStart(sourceText, declarationRange.start, sortedComments, prettierFilePragmaComment);
|
|
1888
|
+
const trailingComments = getTrailingComments(sourceText, declarationRange.end, sortedComments);
|
|
1889
|
+
if (isImportIgnoredByPrettier || trailingComments.isImportSortingBoundary) {
|
|
1890
|
+
if (currentSortableSegment.length > 0) {
|
|
1891
|
+
sortableSegments.push(currentSortableSegment);
|
|
1892
|
+
currentSortableSegment = [];
|
|
1893
|
+
}
|
|
1894
|
+
continue;
|
|
1895
|
+
}
|
|
1896
|
+
const parsedImportDeclaration = parseImportDeclaration({
|
|
1897
|
+
importDeclarationNode,
|
|
1898
|
+
declarationRange,
|
|
1899
|
+
leadingCommentsText: sourceText.slice(leadingCommentsStart, declarationRange.start),
|
|
1900
|
+
trailingCommentsText: trailingComments.commentsText,
|
|
1901
|
+
hasInternalComments: isCommentPresentWithinRange(sortedComments, declarationRange.start, declarationRange.end)
|
|
1902
|
+
}, sourceText);
|
|
1903
|
+
if (parsedImportDeclaration === null) {
|
|
1904
|
+
return [];
|
|
1905
|
+
}
|
|
1906
|
+
const parsedImportEntry = {
|
|
1907
|
+
importDeclarationNode,
|
|
1908
|
+
start: leadingCommentsStart,
|
|
1909
|
+
end: getRangeEndIncludingLineBreak(sourceText, trailingComments.rangeEnd),
|
|
1910
|
+
parsedImportDeclaration
|
|
1911
|
+
};
|
|
1912
|
+
const previousImportEntry = currentSortableSegment.at(-1);
|
|
1913
|
+
if (previousImportEntry && isCommentPresentWithinRange(sortedComments, previousImportEntry.end, parsedImportEntry.start)) {
|
|
1914
|
+
sortableSegments.push(currentSortableSegment);
|
|
1915
|
+
currentSortableSegment = [];
|
|
1916
|
+
}
|
|
1917
|
+
currentSortableSegment.push(parsedImportEntry);
|
|
1918
|
+
}
|
|
1919
|
+
if (currentSortableSegment.length > 0) {
|
|
1920
|
+
sortableSegments.push(currentSortableSegment);
|
|
1921
|
+
}
|
|
1922
|
+
let lineEnding = `
|
|
1923
|
+
`;
|
|
1924
|
+
if (sourceText.includes(`\r
|
|
1925
|
+
`)) {
|
|
1926
|
+
lineEnding = `\r
|
|
1927
|
+
`;
|
|
1928
|
+
}
|
|
1929
|
+
const sortingEdits = [];
|
|
1930
|
+
const lastImportDeclarationNode = importDeclarationNodes.at(-1);
|
|
1931
|
+
for (const sortableSegment of sortableSegments) {
|
|
1932
|
+
const isLastImportSegment = sortableSegment.at(-1)?.importDeclarationNode === lastImportDeclarationNode;
|
|
1933
|
+
const importSegmentEdits = buildImportSegmentEdits(sourceText, sortableSegment, sortOptions, lineEnding, isLastImportSegment);
|
|
1934
|
+
if (importSegmentEdits === null) {
|
|
1935
|
+
return [];
|
|
1936
|
+
}
|
|
1937
|
+
sortingEdits.push(...importSegmentEdits);
|
|
1938
|
+
}
|
|
1939
|
+
return sortingEdits;
|
|
1940
|
+
}
|
|
1941
|
+
|
|
1942
|
+
// src/sort-typescript.ts
|
|
1943
|
+
async function sortTypeScript(sourceText, prettierOptions, parser) {
|
|
1944
|
+
const sortOptions = resolveSortOptions(prettierOptions);
|
|
1945
|
+
if (!sortOptions.esmImportSort && !sortOptions.esmExportSpecifierSort) {
|
|
1946
|
+
return sourceText;
|
|
1947
|
+
}
|
|
1948
|
+
let parserAst;
|
|
1949
|
+
try {
|
|
1950
|
+
parserAst = await parser.parse(sourceText, prettierOptions);
|
|
1951
|
+
} catch {
|
|
1952
|
+
return sourceText;
|
|
1953
|
+
}
|
|
1954
|
+
const programStatements = getProgramStatements(parserAst);
|
|
1955
|
+
const sortedComments = getSortedAstCommentsWithTextRanges(getProgramComments(parserAst));
|
|
1956
|
+
const sortingEdits = [];
|
|
1957
|
+
if (sortOptions.esmImportSort) {
|
|
1958
|
+
const isPrettierFilePragmaPresent = parser.hasPragma?.(sourceText) ?? false;
|
|
1959
|
+
sortingEdits.push(...buildImportSortingEdits(sourceText, programStatements, sortedComments, sortOptions, isPrettierFilePragmaPresent));
|
|
1960
|
+
}
|
|
1961
|
+
if (sortOptions.esmExportSpecifierSort) {
|
|
1962
|
+
sortingEdits.push(...buildExportSortingEdits(sourceText, programStatements, sortedComments));
|
|
1963
|
+
}
|
|
1964
|
+
const sortedText = applySourceTextEdits(sourceText, sortingEdits);
|
|
1965
|
+
if (sortedText === null || sortedText === sourceText) {
|
|
1966
|
+
return sourceText;
|
|
1967
|
+
}
|
|
1968
|
+
try {
|
|
1969
|
+
await parser.parse(sortedText, prettierOptions);
|
|
1970
|
+
return sortedText;
|
|
1971
|
+
} catch {
|
|
1972
|
+
return sourceText;
|
|
859
1973
|
}
|
|
860
|
-
return newline === `\r
|
|
861
|
-
` ? output.replace(/\n/g, `\r
|
|
862
|
-
`) : output;
|
|
863
1974
|
}
|
|
864
1975
|
|
|
865
1976
|
// src/index.ts
|
|
866
|
-
function
|
|
1977
|
+
function wrapParserPreprocess(parser, preprocessTransform) {
|
|
867
1978
|
return {
|
|
868
1979
|
...parser,
|
|
869
|
-
async preprocess(
|
|
870
|
-
let
|
|
871
|
-
|
|
872
|
-
|
|
1980
|
+
async preprocess(sourceText, prettierOptions) {
|
|
1981
|
+
let transformedText = sourceText;
|
|
1982
|
+
if (parser.preprocess) {
|
|
1983
|
+
transformedText = await parser.preprocess(sourceText, prettierOptions);
|
|
873
1984
|
}
|
|
874
|
-
return
|
|
1985
|
+
return preprocessTransform(transformedText, prettierOptions, parser);
|
|
875
1986
|
}
|
|
876
1987
|
};
|
|
877
1988
|
}
|
|
878
|
-
var
|
|
1989
|
+
var sortPlugin = {
|
|
879
1990
|
options,
|
|
880
1991
|
parsers: {
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
"
|
|
1992
|
+
acorn: wrapParserPreprocess(acornPlugin.parsers.acorn, sortTypeScript),
|
|
1993
|
+
babel: wrapParserPreprocess(babelPlugin.parsers.babel, sortTypeScript),
|
|
1994
|
+
"babel-flow": wrapParserPreprocess(babelPlugin.parsers["babel-flow"], sortTypeScript),
|
|
1995
|
+
"babel-ts": wrapParserPreprocess(babelPlugin.parsers["babel-ts"], sortTypeScript),
|
|
1996
|
+
espree: wrapParserPreprocess(acornPlugin.parsers.espree, sortTypeScript),
|
|
1997
|
+
flow: wrapParserPreprocess(flowPlugin.parsers.flow, sortTypeScript),
|
|
1998
|
+
json: wrapParserPreprocess(babelPlugin.parsers.json, preprocessPackageJson),
|
|
1999
|
+
"json-stringify": wrapParserPreprocess(babelPlugin.parsers["json-stringify"], preprocessPackageJson),
|
|
2000
|
+
meriyah: wrapParserPreprocess(meriyahPlugin.parsers.meriyah, sortTypeScript),
|
|
2001
|
+
typescript: wrapParserPreprocess(typescriptPlugin.parsers.typescript, sortTypeScript)
|
|
885
2002
|
}
|
|
886
2003
|
};
|
|
887
|
-
var src_default =
|
|
2004
|
+
var src_default = sortPlugin;
|
|
888
2005
|
export {
|
|
889
2006
|
options,
|
|
890
2007
|
src_default as default
|