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/dist/index.js CHANGED
@@ -1,17 +1,19 @@
1
1
  // src/index.ts
2
- import { parsers as babelParsers } from "prettier/plugins/babel";
3
- import { parsers as typescriptParsers } from "prettier/plugins/typescript";
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
- importOrder: true,
8
- importOrderGroups: ["builtin", "external", "parent", "sibling", "index"],
9
- importOrderSeparation: true,
10
- importOrderTypeImports: "separate",
11
- importOrderMergeDuplicates: true,
12
- exportOrder: true,
13
- packageJsonOrder: true,
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 VALID_TYPE_STYLES = new Set([
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 = (value) => typeof value === "string" && VALID_IMPORT_GROUPS.has(value);
31
- var isValidTypeStyle = (value) => typeof value === "string" && VALID_TYPE_STYLES.has(value);
32
- function resolveBoolean(rawOptions, key) {
33
- const raw = rawOptions[key];
34
- return typeof raw === "boolean" ? raw : DEFAULT_SORT_OPTIONS[key];
35
- }
36
- function resolveSortOptions(rawOptions) {
37
- const groups = Array.isArray(rawOptions.importOrderGroups) ? rawOptions.importOrderGroups.filter(isValidImportGroup) : [];
38
- const excludeKeys = Array.isArray(rawOptions.packageJsonOrderExcludeKeys) ? rawOptions.packageJsonOrderExcludeKeys.filter((key) => typeof key === "string") : [];
39
- const importOrderTypeImports = isValidTypeStyle(rawOptions.importOrderTypeImports) ? rawOptions.importOrderTypeImports : DEFAULT_SORT_OPTIONS.importOrderTypeImports;
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
- importOrder: resolveBoolean(rawOptions, "importOrder"),
42
- importOrderGroups: groups.length > 0 ? groups : [...DEFAULT_SORT_OPTIONS.importOrderGroups],
43
- importOrderSeparation: resolveBoolean(rawOptions, "importOrderSeparation"),
44
- importOrderTypeImports,
45
- importOrderMergeDuplicates: resolveBoolean(rawOptions, "importOrderMergeDuplicates"),
46
- exportOrder: resolveBoolean(rawOptions, "exportOrder"),
47
- packageJsonOrder: resolveBoolean(rawOptions, "packageJsonOrder"),
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
- importOrder: {
57
+ esmImportSort: {
53
58
  type: "boolean",
54
- default: DEFAULT_SORT_OPTIONS.importOrder,
55
- category: "SortImports",
56
- description: "Sort `import` declarations in JS/TS files."
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
- importOrderGroups: {
63
+ esmImportGroups: {
59
64
  type: "string",
60
65
  array: true,
61
- default: [{ value: [...DEFAULT_SORT_OPTIONS.importOrderGroups] }],
62
- category: "SortImports",
63
- description: 'Ordered list of import groups. Valid values: "builtin", "external", "internal", "parent", "sibling", "index". Each group is sorted alphabetically; unknown groups are ignored.'
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
- importOrderSeparation: {
70
+ esmImportSeparation: {
66
71
  type: "boolean",
67
- default: DEFAULT_SORT_OPTIONS.importOrderSeparation,
68
- category: "SortImports",
69
- description: "Insert a blank line between adjacent import groups."
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
- importOrderTypeImports: {
76
+ esmImportTypeStyle: {
72
77
  type: "choice",
73
- default: DEFAULT_SORT_OPTIONS.importOrderTypeImports,
74
- category: "SortImports",
75
- description: "How to place `type` imports relative to value imports.",
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: "Keep `import type { … }` as its own statement."
84
+ description: "Use a separate import type declaration."
80
85
  },
81
86
  {
82
87
  value: "inline-first",
83
- description: "Inline inside braces, type specifiers before value specifiers."
88
+ description: "Place inline type specifiers before value specifiers."
84
89
  },
85
90
  {
86
91
  value: "inline-last",
87
- description: "Inline inside braces, type specifiers after value specifiers."
92
+ description: "Place inline type specifiers after value specifiers."
88
93
  },
89
94
  {
90
95
  value: "mixed",
91
- description: "Inline inside braces, alphabetical without distinguishing type from value."
96
+ description: "Use inline type specifiers and sort all specifiers together."
92
97
  }
93
98
  ]
94
99
  },
95
- importOrderMergeDuplicates: {
100
+ esmImportMerge: {
96
101
  type: "boolean",
97
- default: DEFAULT_SORT_OPTIONS.importOrderMergeDuplicates,
98
- category: "SortImports",
99
- description: "Merge multiple `import` statements from the same source into one. Side-effect imports are never merged."
102
+ default: DEFAULT_SORT_OPTIONS.esmImportMerge,
103
+ category: "ES Module Imports",
104
+ description: "Merge compatible import declarations from the same module."
100
105
  },
101
- exportOrder: {
106
+ esmExportSpecifierSort: {
102
107
  type: "boolean",
103
- default: DEFAULT_SORT_OPTIONS.exportOrder,
104
- category: "SortExports",
105
- description: "Sort named specifiers inside `export { }` alphabetically. Does not reorder export statements."
108
+ default: DEFAULT_SORT_OPTIONS.esmExportSpecifierSort,
109
+ category: "ES Module Exports",
110
+ description: "Sort named export specifiers without reordering export declarations."
106
111
  },
107
- packageJsonOrder: {
112
+ packageSort: {
108
113
  type: "boolean",
109
- default: DEFAULT_SORT_OPTIONS.packageJsonOrder,
110
- category: "SortPackageJson",
111
- description: "Sort top-level keys and string-array values inside `package.json`. Dependency maps are always alphabetised regardless of this option."
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/utils.ts
123
- function splitTopLevel(input, separator) {
124
- const segments = [];
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/sort-imports.ts
173
- import { builtinModules } from "node:module";
174
- var NODE_BUILTINS = new Set(builtinModules);
175
- var INDEX_PATTERN = /^\.\/index(\.[a-z]+)?$/;
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
- if (source.startsWith("/") || source.startsWith("~") || source.startsWith("@/")) {
195
- return "internal";
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 "external";
134
+ return { start, end };
198
135
  }
199
- var TYPE_PREFIX = /^type\s+(.+)$/;
200
- function splitMembers(inner) {
201
- return splitTopLevel(inner, ",").map((part) => {
202
- const match = TYPE_PREFIX.exec(part);
203
- return match ? { name: match[1].trim(), isType: true } : { name: part, isType: false };
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 parseImport(statement) {
207
- const trimmed = statement.raw.trim();
208
- const leadingComments = statement.leadingComments;
209
- const sideEffect = /^import\s*(['"])([^'"]+)\1(?:\s+with\s*(\{[^}]*\}))?\s*;?$/.exec(trimmed);
210
- if (sideEffect) {
211
- return {
212
- source: sideEffect[2] ?? "",
213
- typeClause: false,
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
- defaultSpec = part;
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 extractImportBlock(text) {
255
- const firstRe = /(?:^|\n)(?:[ \t]*(?:\/\/[^\n]*|\/\*[\s\S]*?\*\/)[ \t]*\n)*[ \t]*import\b(?![.(])/;
256
- const first = firstRe.exec(text);
257
- if (!first) {
156
+ function getAstNodeName(node) {
157
+ if (!node) {
258
158
  return null;
259
159
  }
260
- const start = first.index + (text[first.index] === `
261
- ` ? 1 : 0);
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
- if (statements.length === 0) {
299
- return null;
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 renderMembers(members) {
304
- return members.map((member) => member.isType ? `type ${member.name}` : member.name).join(", ");
172
+ function getAstCommentText(comment) {
173
+ return typeof comment.value === "string" ? comment.value : null;
305
174
  }
306
- function renderSpecifiers(importDecl) {
307
- const parts = [];
308
- if (importDecl.defaultSpec) {
309
- parts.push(importDecl.defaultSpec);
175
+ function getProgramStatements(parserAst) {
176
+ if (Array.isArray(parserAst.body)) {
177
+ return parserAst.body;
310
178
  }
311
- if (importDecl.namespaceSpec) {
312
- parts.push(importDecl.namespaceSpec);
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 parts.join(", ");
183
+ return programNode.body;
318
184
  }
319
- function renderImport(importDecl) {
320
- const suffix = importDecl.attributes ? ` with ${importDecl.attributes}` : "";
321
- const source = `'${importDecl.source}'`;
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
- return {
333
- ...importDecl,
334
- typeClause: false,
335
- members: importDecl.members.map((member) => ({ ...member, isType: true }))
336
- };
189
+ const programNode = parserAst.program;
190
+ if (!programNode || !Array.isArray(programNode.comments)) {
191
+ return [];
192
+ }
193
+ return programNode.comments;
337
194
  }
338
- function mergeImportsFromSameSource(imports) {
339
- const indexByKey = new Map;
340
- const result = [];
341
- for (const rawImport of imports) {
342
- const importDecl = normalizeTypeClause(rawImport);
343
- if (importDecl.sideEffect || importDecl.typeClause) {
344
- result.push(importDecl);
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
- const mergeKey = `${importDecl.source}\x00${importDecl.attributes ?? ""}`;
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 existing = result[existingIndex];
355
- result[existingIndex] = {
356
- source: existing.source,
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
- return output.length > 0 ? output : [importDecl];
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
- const style = options2.importOrderTypeImports;
424
- const deduplicated = options2.importOrderMergeDuplicates ? mergeImportsFromSameSource(imports) : imports;
425
- const rewritten = deduplicated.flatMap((importDecl) => applyTypeImports(importDecl, style));
426
- const decorated = rewritten.map((importDecl, index) => ({
427
- importDecl,
428
- group: detectGroup(importDecl.source),
429
- originalIndex: index
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 sourceA = a.importDecl.source.toLowerCase();
438
- const sourceB = b.importDecl.source.toLowerCase();
439
- if (sourceA !== sourceB) {
440
- return sourceA < sourceB ? -1 : 1;
221
+ const { comment, textRange } = parserComment;
222
+ const followingText = sourceText.slice(textRange.end, leadingCommentsStart);
223
+ if (followingText.trim() !== "") {
224
+ break;
441
225
  }
442
- if (a.importDecl.typeClause !== b.importDecl.typeClause) {
443
- return a.importDecl.typeClause ? -1 : 1;
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
- return a.originalIndex - b.originalIndex;
446
- });
447
- const lines = [];
448
- let previousGroup = null;
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
- lines.push(renderImport(item.importDecl));
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
- const parsed = block.statements.map((rawStatement) => parseImport(rawStatement)).filter((importDecl) => importDecl !== null);
468
- if (parsed.length === 0) {
469
- return text;
470
- }
471
- const groupIndex = new Map(options2.importOrderGroups.map((group, index) => [
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
- if (currentSegment.length > 0) {
490
- chunks.push({ kind: "segment", imports: currentSegment });
491
- }
492
- const allLines = [];
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
- if (chunk.kind === "segment") {
499
- allLines.push(...sortSegment(chunk.imports, options2, groupIndex, fallback));
500
- } else {
501
- allLines.push(renderImport(chunk.importDecl));
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
- previousKind = chunk.kind;
264
+ trailingCommentsEnd = textRange.end;
504
265
  }
505
- const replacement = allLines.join(`
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/sort-package.ts
516
- import path from "node:path";
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 DEPENDENCY_FIELDS = [
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
- "devDependencies",
634
- "peerDependencies",
635
- "optionalDependencies",
636
- "resolutions",
637
- "overrides"
468
+ "files",
469
+ "output"
638
470
  ];
639
471
 
640
472
  // src/sort-package.ts
641
- function isPlainObject(value) {
642
- return typeof value === "object" && value !== null && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype;
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((item) => typeof item === "string");
646
- }
647
- var TOP_LEVEL_ORDER_INDEX = new Map(PACKAGE_JSON_TOP_LEVEL_ORDER.map((key, index) => [key, index]));
648
- function sortObjectKeysByOrder(record, orderIndex) {
649
- const known = [];
650
- const rest = [];
651
- for (const entry of Object.entries(record)) {
652
- const [key] = entry;
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
- known.sort(([a], [b]) => (orderIndex.get(a) ?? 0) - (orderIndex.get(b) ?? 0));
660
- rest.sort(([a], [b]) => a.localeCompare(b, "en"));
661
- return Object.fromEntries([...known, ...rest]);
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 sortObjectKeysAlpha(value) {
664
- if (!isPlainObject(value)) {
665
- return value;
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 Object.fromEntries(Object.entries(value).sort(([a], [b]) => a.localeCompare(b, "en")));
665
+ return deduplicateStringValues(fieldValue).sort((leftValue, rightValue) => compareText(getJsonString(leftValue), getJsonString(rightValue)));
668
666
  }
669
- function sortStringArrayAlpha(value) {
670
- return [...value].sort((a, b) => a.localeCompare(b, "en"));
667
+ function deduplicateStringArrayValue(fieldValue) {
668
+ return isStringArray(fieldValue) ? deduplicateStringValues(fieldValue) : fieldValue;
671
669
  }
672
- function uniqueStringArray(value) {
673
- return [...new Set(value)];
670
+ function sortPersonValue(fieldValue) {
671
+ return sortJsonObjectValueByKeyOrder(fieldValue, ["name", "email", "url"]);
674
672
  }
675
- function isPackageJson(filepath) {
676
- if (!filepath) {
677
- return false;
673
+ function sortPeopleArrayValue(fieldValue) {
674
+ if (!Array.isArray(fieldValue)) {
675
+ return fieldValue;
678
676
  }
679
- return path.basename(filepath) === "package.json";
677
+ return fieldValue.map((person) => sortPersonValue(person));
680
678
  }
681
- function detectIndent(source) {
682
- const match = /\n([ \t]+)\S/.exec(source);
683
- return match ? match[1] ?? " " : " ";
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
- var DEFAULT_NPM_SCRIPTS = new Set([
686
- "install",
687
- "pack",
688
- "prepare",
689
- "publish",
690
- "restart",
691
- "shrinkwrap",
692
- "start",
693
- "stop",
694
- "test",
695
- "uninstall",
696
- "version"
697
- ]);
698
- var RUN_S_PATTERN = /(?<=^|[\s&;<>|(])(?:run-s|npm-run-all2? .*(?:--sequential|--serial|-s))(?=$|[\s&;<>|)])/;
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
- const scriptCommands = ["scripts", "betterScripts"].flatMap((field) => {
705
- const scriptsObject = packageObject[field];
706
- return isPlainObject(scriptsObject) ? Object.values(scriptsObject) : [];
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
- return scriptCommands.some((script) => typeof script === "string" && script.includes("*") && RUN_S_PATTERN.test(script));
709
- }
710
- function sortScriptNames(keys, prefix = "") {
711
- const groupMap = new Map;
712
- for (const key of keys) {
713
- const rest = prefix ? key.slice(prefix.length + 1) : key;
714
- const colonIndex = rest.indexOf(":");
715
- if (colonIndex > 0) {
716
- const base = key.slice(0, (prefix ? prefix.length + 1 : 0) + colonIndex);
717
- let group = groupMap.get(base);
718
- if (!group) {
719
- group = [];
720
- groupMap.set(base, group);
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
- group.push(key);
723
- } else {
724
- let group = groupMap.get(key);
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
- group.push(key);
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
- return [...groupMap.keys()].sort((a, b) => a.localeCompare(b, "en")).flatMap((groupKey) => {
733
- const children = groupMap.get(groupKey);
734
- if (children.length > 1 && children.some((key) => key !== groupKey && key.startsWith(groupKey + ":"))) {
735
- const direct = children.filter((key) => key === groupKey || !key.startsWith(groupKey + ":")).sort((a, b) => a.localeCompare(b, "en"));
736
- const nested = children.filter((key) => key.startsWith(groupKey + ":"));
737
- return [...direct, ...sortScriptNames(nested, groupKey)];
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
- return children.sort((a, b) => a.localeCompare(b, "en"));
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 sortScripts(scripts, packageObject) {
743
- const names = Object.keys(scripts);
744
- const prefixable = new Set;
745
- const normalized = names.map((name) => {
746
- const base = name.replace(/^(?:pre|post)/, "");
747
- if (DEFAULT_NPM_SCRIPTS.has(base) || names.includes(base)) {
748
- prefixable.add(base);
749
- return base;
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
- return name;
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
- key,
776
- isPlainObject(value) ? sortExportsField(value) : value
861
+ ...directScriptNames,
862
+ ...sortScriptNames(nestedScriptNames, scriptGroupName)
777
863
  ];
778
- }));
864
+ });
779
865
  }
780
- var UNIQUE_ONLY_FIELDS = new Set(["keywords", "files", "activationEvents"]);
781
- var UNIQUE_AND_SORT_FIELDS = new Set([
782
- "bundledDependencies",
783
- "bundleDependencies",
784
- "extensionPack",
785
- "extensionDependencies"
786
- ]);
787
- var NO_SORT_ARRAY_FIELDS = new Set(["workspaces"]);
788
- function detectNewline(source) {
789
- const crlfIndex = source.indexOf(`\r
790
- `);
791
- return crlfIndex >= 0 ? `\r
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 sortPackageJson(text, rawOptions) {
796
- if (!isPackageJson(rawOptions.filepath)) {
797
- return text;
886
+ function sortExportsValue(fieldValue) {
887
+ if (!isJsonObject(fieldValue)) {
888
+ return fieldValue;
798
889
  }
799
- const options2 = resolveSortOptions(rawOptions);
800
- const exclude = new Set(options2.packageJsonOrderExcludeKeys);
801
- let parsed;
802
- try {
803
- parsed = JSON.parse(text);
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
- if (!isPlainObject(parsed)) {
808
- return text;
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
- let result = parsed;
811
- for (const field of DEPENDENCY_FIELDS) {
812
- const dependencyMap = result[field];
813
- if (dependencyMap !== undefined && !exclude.has(field)) {
814
- result[field] = sortObjectKeysAlpha(dependencyMap);
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
- if (options2.packageJsonOrder) {
818
- result = sortObjectKeysByOrder(result, TOP_LEVEL_ORDER_INDEX);
819
- for (const field of ["scripts", "betterScripts"]) {
820
- const scriptsValue = result[field];
821
- if (scriptsValue !== undefined && isPlainObject(scriptsValue) && !exclude.has(field)) {
822
- result[field] = sortScripts(scriptsValue, result);
823
- }
824
- }
825
- const exportsValue = result["exports"];
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
- for (const [key, value] of Object.entries(result)) {
830
- if (exclude.has(key)) {
831
- continue;
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
- const indent = detectIndent(text);
851
- const newline = detectNewline(text);
852
- const output = JSON.stringify(result, null, indent);
853
- if (text.endsWith(newline)) {
854
- return newline === `\r
855
- ` ? output.replace(/\n/g, `\r
856
- `) + `\r
857
- ` : output + `
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 wrap(parser, ...transforms) {
1977
+ function wrapParserPreprocess(parser, preprocessTransform) {
867
1978
  return {
868
1979
  ...parser,
869
- async preprocess(text, parserOptions) {
870
- let source = parser.preprocess ? await parser.preprocess(text, parserOptions) : text;
871
- for (const transform of transforms) {
872
- source = transform(source, parserOptions);
1980
+ async preprocess(sourceText, prettierOptions) {
1981
+ let transformedText = sourceText;
1982
+ if (parser.preprocess) {
1983
+ transformedText = await parser.preprocess(sourceText, prettierOptions);
873
1984
  }
874
- return source;
1985
+ return preprocessTransform(transformedText, prettierOptions, parser);
875
1986
  }
876
1987
  };
877
1988
  }
878
- var plugin = {
1989
+ var sortPlugin = {
879
1990
  options,
880
1991
  parsers: {
881
- babel: wrap(babelParsers.babel, sortImports, sortExports),
882
- "babel-ts": wrap(babelParsers["babel-ts"], sortImports, sortExports),
883
- typescript: wrap(typescriptParsers.typescript, sortImports, sortExports),
884
- "json-stringify": wrap(babelParsers["json-stringify"], sortPackageJson)
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 = plugin;
2004
+ var src_default = sortPlugin;
888
2005
  export {
889
2006
  options,
890
2007
  src_default as default