@putout/printer 17.0.8 → 17.2.0

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/ChangeLog CHANGED
@@ -1,3 +1,15 @@
1
+ 2026.02.11, v17.2.0
2
+
3
+ feature:
4
+ - 7cb116c @putout/printer: ArrayExpression: ObjectExpression, after StringLiteral/TemplateLiteral: indent
5
+ - 7a5f660 @putout/printer: eslint v10.0.0
6
+
7
+ 2026.02.01, v17.1.0
8
+
9
+ feature:
10
+ - df72e84 @putout/printer: ObjectPattern: split to couple files
11
+ - 3dba268 @putout/printer: ObjectPattern: couple assigns
12
+
1
13
  2026.01.28, v17.0.8
2
14
 
3
15
  feature:
@@ -4,10 +4,25 @@ import {isIndented} from '#is';
4
4
  const {
5
5
  isStringLiteral,
6
6
  isArrayExpression,
7
+ isObjectExpression,
8
+ isTemplateLiteral,
7
9
  } = types;
8
10
 
9
11
  export const isInsideArray = (path) => path.parentPath.isArrayExpression();
10
12
 
13
+ const isObjectAfterString = ([first, second]) => {
14
+ if (!first || !second)
15
+ return false;
16
+
17
+ if (!isObjectExpression(second))
18
+ return false;
19
+
20
+ if (isStringLiteral(first))
21
+ return true;
22
+
23
+ return isTemplateLiteral(first);
24
+ };
25
+
11
26
  export const isArrayIndented = (path) => {
12
27
  const elements = path.get('elements');
13
28
 
@@ -16,6 +31,9 @@ export const isArrayIndented = (path) => {
16
31
 
17
32
  const [first] = elements;
18
33
 
34
+ if (isObjectAfterString(elements))
35
+ return false;
36
+
19
37
  return !isTwoLongStrings(elements) || !isInsideArray(path) && isIndented(first);
20
38
  };
21
39
 
@@ -0,0 +1,51 @@
1
+ import {types} from '@putout/babel';
2
+
3
+ const {
4
+ isAssignmentPattern,
5
+ isObjectPattern,
6
+ isVariableDeclaration,
7
+ isObjectExpression,
8
+ } = types;
9
+
10
+ export function hasObjectPattern(properties) {
11
+ for (const property of properties) {
12
+ if (isObjectPattern(property.node.value))
13
+ return true;
14
+ }
15
+
16
+ return false;
17
+ }
18
+
19
+ export function hasAssign(properties) {
20
+ for (const prop of properties) {
21
+ const {value} = prop.node;
22
+
23
+ if (isAssignmentPattern(value))
24
+ return true;
25
+ }
26
+
27
+ return false;
28
+ }
29
+
30
+ export function hasAssignObject(path, maxPropertiesLengthInOneLine) {
31
+ const {parentPath} = path;
32
+
33
+ if (isVariableDeclaration(parentPath.parentPath)) {
34
+ const {declarations} = parentPath.parentPath.node;
35
+
36
+ if (declarations.length > 1)
37
+ return false;
38
+ }
39
+
40
+ const properties = path.get('properties');
41
+ const n = properties.length;
42
+
43
+ for (const prop of properties) {
44
+ const {value} = prop.node;
45
+
46
+ if (isAssignmentPattern(value) && isObjectExpression(value.right))
47
+ return n > 1 || maxPropertiesLengthInOneLine <= value.left;
48
+ }
49
+
50
+ return false;
51
+ }
@@ -0,0 +1,74 @@
1
+ import {types} from '@putout/babel';
2
+ import {isCoupleLines, exists} from '#is';
3
+ import {hasAssign} from './has.js';
4
+
5
+ const {
6
+ isObjectExpression,
7
+ isAssignmentPattern,
8
+ isForOfStatement,
9
+ isFunction,
10
+ isVariableDeclarator,
11
+ isObjectProperty,
12
+ } = types;
13
+
14
+ export const isInsideFn = (path) => {
15
+ if (isFunction(path.parentPath))
16
+ return true;
17
+
18
+ return isFunction(path.parentPath.parentPath);
19
+ };
20
+
21
+ export function isIndent(path) {
22
+ return !path.parentPath.isArrayPattern();
23
+ }
24
+
25
+ export const isCoupleProperties = ({path, valuePath, property}) => {
26
+ if (!isCoupleLines(valuePath))
27
+ return false;
28
+
29
+ if (exists(property.getPrevSibling()))
30
+ return false;
31
+
32
+ const properties = path.get('properties');
33
+ const {parentPath} = path;
34
+
35
+ if (isVariableDeclarator(parentPath) && !hasAssign(properties))
36
+ return false;
37
+
38
+ return !isObjectProperty(parentPath);
39
+ };
40
+
41
+ export function isInsideForOf({parentPath}) {
42
+ return isForOfStatement(parentPath.parentPath.parentPath);
43
+ }
44
+
45
+ export function isPrevAssign(path) {
46
+ const prev = path.getPrevSibling();
47
+
48
+ return isAssignmentPattern(prev.node.value);
49
+ }
50
+
51
+ export function isPrevAssignObject(path) {
52
+ const prev = path.getPrevSibling();
53
+
54
+ if (!isAssignmentPattern(prev.node.value))
55
+ return false;
56
+
57
+ const {right} = prev.node.value;
58
+
59
+ return isObjectExpression(right);
60
+ }
61
+
62
+ export function isNextAssignObject(path) {
63
+ const next = path.getNextSibling();
64
+
65
+ if (!next.node)
66
+ return false;
67
+
68
+ if (!isAssignmentPattern(next.node.value))
69
+ return false;
70
+
71
+ const {right} = next.node.value;
72
+
73
+ return isObjectExpression(right);
74
+ }
@@ -1,91 +1,28 @@
1
1
  import {types} from '@putout/babel';
2
- import {
3
- isForOf,
4
- isCoupleLines,
5
- exists,
6
- } from '#is';
7
2
  import {wrongShorthand} from './wrong-shorthand.js';
8
- import {moreThenMaxPropertiesInOneLine} from './more-then-max-properties-in-one-line.js';
9
3
  import {maybeTypeAnnotation} from '../../maybe/maybe-type-annotation.js';
10
- import {moreThenMaxPropertiesLengthInOneLine} from './more-then-max-properties-length-in-one-line.js';
11
4
  import {printKey} from '../object-expression/print-key.js';
12
5
  import {
13
6
  calculateAssigns,
14
7
  isLongAssignPattern,
15
8
  } from './calculate-long-assign-pattern.js';
16
9
  import {printLeadingComments} from './comments.js';
10
+ import {shouldAddNewline} from './should-add-new-line.js';
11
+ import {
12
+ hasAssignObject,
13
+ hasObjectPattern,
14
+ } from './has.js';
15
+ import {
16
+ isCoupleProperties,
17
+ isIndent,
18
+ isInsideFn,
19
+ isInsideForOf,
20
+ isNextAssignObject,
21
+ isPrevAssign,
22
+ isPrevAssignObject,
23
+ } from './is.js';
17
24
 
18
- const {
19
- isObjectExpression,
20
- isIdentifier,
21
- isAssignmentPattern,
22
- isVariableDeclarator,
23
- isFunction,
24
- isObjectPattern,
25
- isForOfStatement,
26
- isVariableDeclaration,
27
- } = types;
28
-
29
- const isInsideFn = (path) => {
30
- if (isFunction(path.parentPath))
31
- return true;
32
-
33
- return isFunction(path.parentPath.parentPath);
34
- };
35
-
36
- function isIndent(path) {
37
- return !path.parentPath.isArrayPattern();
38
- }
39
-
40
- const isCoupleProperties = ({path, valuePath, property}) => {
41
- if (!isCoupleLines(valuePath))
42
- return false;
43
-
44
- if (exists(property.getPrevSibling()))
45
- return false;
46
-
47
- const properties = path.get('properties');
48
-
49
- if (path.parentPath.isVariableDeclarator() && !hasAssign(properties))
50
- return false;
51
-
52
- return !path.parentPath.isObjectProperty();
53
- };
54
-
55
- function isInsideForOf({parentPath}) {
56
- return isForOfStatement(parentPath.parentPath.parentPath);
57
- }
58
-
59
- function isPrevAssign(path) {
60
- const prev = path.getPrevSibling();
61
-
62
- return isAssignmentPattern(prev.node.value);
63
- }
64
-
65
- function isPrevAssignObject(path) {
66
- const prev = path.getPrevSibling();
67
-
68
- if (!isAssignmentPattern(prev.node.value))
69
- return false;
70
-
71
- const {right} = prev.node.value;
72
-
73
- return isObjectExpression(right);
74
- }
75
-
76
- function isNextAssignObject(path) {
77
- const next = path.getNextSibling();
78
-
79
- if (!next.node)
80
- return false;
81
-
82
- if (!isAssignmentPattern(next.node.value))
83
- return false;
84
-
85
- const {right} = next.node.value;
86
-
87
- return isObjectExpression(right);
88
- }
25
+ const {isObjectExpression} = types;
89
26
 
90
27
  export const ObjectPattern = {
91
28
  print: maybeTypeAnnotation((path, printer, semantics) => {
@@ -142,6 +79,7 @@ export const ObjectPattern = {
142
79
  });
143
80
 
144
81
  maybe.indent((prevAssignObject || is) && notInsideFn);
82
+
145
83
  maybe.print.breakline(couple && !isLongAssignPattern(property, semantics));
146
84
 
147
85
  if (!isAssign && nextAssignObject)
@@ -199,134 +137,3 @@ export const ObjectPattern = {
199
137
  print('}');
200
138
  }),
201
139
  };
202
-
203
- function checkLength(properties) {
204
- for (const prop of properties) {
205
- const {value} = prop.node;
206
-
207
- if (!isIdentifier(value))
208
- continue;
209
-
210
- if (value.name.length > 4)
211
- return true;
212
- }
213
-
214
- return false;
215
- }
216
-
217
- function hasAssign(properties) {
218
- for (const prop of properties) {
219
- const {value} = prop.node;
220
-
221
- if (isAssignmentPattern(value))
222
- return true;
223
- }
224
-
225
- return false;
226
- }
227
-
228
- function hasComputed(properties) {
229
- for (const prop of properties) {
230
- const {computed} = prop.node;
231
-
232
- if (computed)
233
- return true;
234
- }
235
-
236
- return false;
237
- }
238
-
239
- function hasAssignObject(path, maxPropertiesLengthInOneLine) {
240
- const {parentPath} = path;
241
-
242
- if (isVariableDeclaration(parentPath.parentPath)) {
243
- const {declarations} = parentPath.parentPath.node;
244
-
245
- if (declarations.length > 1)
246
- return false;
247
- }
248
-
249
- const properties = path.get('properties');
250
- const n = properties.length;
251
-
252
- for (const prop of properties) {
253
- const {value} = prop.node;
254
-
255
- if (isAssignmentPattern(value) && isObjectExpression(value.right))
256
- return n > 1 || maxPropertiesLengthInOneLine <= value.left;
257
- }
258
-
259
- return false;
260
- }
261
-
262
- function hasObjectPattern(properties) {
263
- for (const property of properties) {
264
- if (isObjectPattern(property.node.value))
265
- return true;
266
- }
267
-
268
- return false;
269
- }
270
-
271
- const ONE_LINE = false;
272
- const COUPLE_LINES = true;
273
-
274
- function hasPropertyLeadingComment(properties) {
275
- for (const property of properties) {
276
- if (property.node.leadingComments)
277
- return true;
278
- }
279
-
280
- return false;
281
- }
282
-
283
- function shouldAddNewline(path, semantics) {
284
- const {parentPath} = path;
285
- const properties = path.get('properties');
286
- const n = properties.length - 1;
287
-
288
- if (hasPropertyLeadingComment(properties))
289
- return true;
290
-
291
- const {
292
- maxPropertiesInOneLine,
293
- maxPropertiesLengthInOneLine,
294
- } = semantics;
295
-
296
- const moreLength = moreThenMaxPropertiesLengthInOneLine(path, {
297
- maxPropertiesLengthInOneLine,
298
- });
299
-
300
- const moreCount = moreThenMaxPropertiesInOneLine(path, {
301
- maxPropertiesInOneLine,
302
- });
303
-
304
- if (hasComputed(properties))
305
- return COUPLE_LINES;
306
-
307
- const fnParam = isFunctionParam(path);
308
-
309
- if (hasObjectPattern(properties))
310
- return COUPLE_LINES;
311
-
312
- if (moreCount && !moreLength && isVariableDeclarator(path.parentPath))
313
- return ONE_LINE;
314
-
315
- if (!fnParam && n && !isForOf(path) && checkLength(properties))
316
- return COUPLE_LINES;
317
-
318
- if (!fnParam && hasAssign(properties))
319
- return COUPLE_LINES;
320
-
321
- return parentPath.isObjectProperty();
322
- }
323
-
324
- function isFunctionParam({parentPath}) {
325
- if (parentPath.isFunction())
326
- return true;
327
-
328
- if (!parentPath.isAssignmentPattern())
329
- return false;
330
-
331
- return parentPath.parentPath.isFunction();
332
- }
@@ -0,0 +1,123 @@
1
+ import {types} from '@putout/babel';
2
+ import {isForOf} from '#is';
3
+ import {moreThenMaxPropertiesInOneLine} from './more-then-max-properties-in-one-line.js';
4
+ import {moreThenMaxPropertiesLengthInOneLine} from './more-then-max-properties-length-in-one-line.js';
5
+ import {
6
+ hasAssign,
7
+ hasObjectPattern,
8
+ } from './has.js';
9
+
10
+ const {
11
+ isIdentifier,
12
+ isAssignmentPattern,
13
+ isVariableDeclarator,
14
+ isObjectProperty,
15
+ } = types;
16
+
17
+ const ONE_LINE = false;
18
+ const COUPLE_LINES = true;
19
+
20
+ function hasPropertyLeadingComment(properties) {
21
+ for (const property of properties) {
22
+ if (property.node.leadingComments)
23
+ return true;
24
+ }
25
+
26
+ return false;
27
+ }
28
+
29
+ function isFunctionParam({parentPath}) {
30
+ if (parentPath.isFunction())
31
+ return true;
32
+
33
+ if (!parentPath.isAssignmentPattern())
34
+ return false;
35
+
36
+ return parentPath.parentPath.isFunction();
37
+ }
38
+
39
+ export function shouldAddNewline(path, semantics) {
40
+ const {parentPath} = path;
41
+ const properties = path.get('properties');
42
+ const n = properties.length - 1;
43
+
44
+ if (isCoupleAssigns(path))
45
+ return COUPLE_LINES;
46
+
47
+ if (hasPropertyLeadingComment(properties))
48
+ return COUPLE_LINES;
49
+
50
+ const {
51
+ maxPropertiesInOneLine,
52
+ maxPropertiesLengthInOneLine,
53
+ } = semantics;
54
+
55
+ const moreLength = moreThenMaxPropertiesLengthInOneLine(path, {
56
+ maxPropertiesLengthInOneLine,
57
+ });
58
+
59
+ const moreCount = moreThenMaxPropertiesInOneLine(path, {
60
+ maxPropertiesInOneLine,
61
+ });
62
+
63
+ if (hasComputed(properties))
64
+ return COUPLE_LINES;
65
+
66
+ const fnParam = isFunctionParam(path);
67
+
68
+ if (hasObjectPattern(properties))
69
+ return COUPLE_LINES;
70
+
71
+ if (moreCount && !moreLength && isVariableDeclarator(path.parentPath))
72
+ return ONE_LINE;
73
+
74
+ if (!fnParam && n && !isForOf(path) && checkLength(properties))
75
+ return COUPLE_LINES;
76
+
77
+ if (!fnParam && hasAssign(properties))
78
+ return COUPLE_LINES;
79
+
80
+ return parentPath.isObjectProperty();
81
+ }
82
+
83
+ function isCoupleAssigns(path) {
84
+ if (isFunctionParam(path))
85
+ return false;
86
+
87
+ let assignsCount = 0;
88
+
89
+ for (const property of path.node.properties) {
90
+ if (!isObjectProperty(property))
91
+ continue;
92
+
93
+ if (isAssignmentPattern(property.value))
94
+ ++assignsCount;
95
+ }
96
+
97
+ return assignsCount > 1;
98
+ }
99
+
100
+ function checkLength(properties) {
101
+ for (const prop of properties) {
102
+ const {value} = prop.node;
103
+
104
+ if (!isIdentifier(value))
105
+ continue;
106
+
107
+ if (value.name.length > 4)
108
+ return true;
109
+ }
110
+
111
+ return false;
112
+ }
113
+
114
+ function hasComputed(properties) {
115
+ for (const prop of properties) {
116
+ const {computed} = prop.node;
117
+
118
+ if (computed)
119
+ return true;
120
+ }
121
+
122
+ return false;
123
+ }
@@ -32,18 +32,18 @@ const maybeEscape = (value, {escapeDoubleQuote, escapeSingleQuote}) => {
32
32
  };
33
33
 
34
34
  const escape = (list, {slash, quote}) => {
35
- const res = [];
35
+ const result = [];
36
36
 
37
37
  for (const [index, char] of list.entries()) {
38
38
  const prev = list[index - 1];
39
39
 
40
40
  if (char === quote && prev !== slash) {
41
- res.push(`${slash}${char}`);
41
+ result.push(`${slash}${char}`);
42
42
  continue;
43
43
  }
44
44
 
45
- res.push(char);
45
+ result.push(char);
46
46
  }
47
47
 
48
- return res.join('');
48
+ return result.join('');
49
49
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@putout/printer",
3
- "version": "17.0.8",
3
+ "version": "17.2.0",
4
4
  "type": "module",
5
5
  "author": "coderaiser <mnemonic.enemy@gmail.com> (https://github.com/coderaiser)",
6
6
  "description": "Simplest possible opinionated Babel AST printer for 🐊Putout",
@@ -72,7 +72,7 @@
72
72
  "c8": "^10.1.2",
73
73
  "check-dts": "^0.9.0",
74
74
  "escover": "^5.0.0",
75
- "eslint": "^9.0.0",
75
+ "eslint": "^10.0.0",
76
76
  "eslint-plugin-putout": "^30.0.0",
77
77
  "estree-to-babel": "^12.0.0",
78
78
  "goldstein": "^7.0.0",