@putout/printer 18.2.11 → 18.3.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,19 @@
1
+ 2026.03.08, v18.3.0
2
+
3
+ feature:
4
+ - 31aa6f8 @putout/printer: ArrayExpression: isIndentBeforeElement
5
+ - e21a6cd @putout/printer: ArrayExpression: simplify
6
+ - 00b646d @putout/printer: ArrayExpression: maybePrintSpace
7
+ - 56e83f6 @putout/printer: ArrayExpression: maybePrintCommaWithSpace
8
+ - 9be2086 @putout/printer: ArrayExpression: afterIf: simplify
9
+ - 2ccc185 @putout/printer: ArrayExpression: isCommaBeforeClosingSquareBrace
10
+ - 35e1a1a @putout/printer: ArrayExpression: neesComma
11
+
12
+ 2026.03.08, v18.2.12
13
+
14
+ feature:
15
+ - 284d9a7 @putout/printer: ArrayExpression: isNewlineAfterComma: simplify
16
+
1
17
  2026.03.08, v18.2.11
2
18
 
3
19
  feature:
@@ -7,7 +23,7 @@ feature:
7
23
  2026.03.08, v18.2.10
8
24
 
9
25
  feature:
10
- - 7a73310 @putout/printer: ArrayExpresison: maybeSecondIndent
26
+ - 7a73310 @putout/printer: ArrayExpresison: maybeAdditionalIndent
11
27
  - cfcf1ce @putout/printer: ArrayExpression: isSecondIndent
12
28
  - 0acb26a @putout/printer: ArrayExpression: isSecondIndent
13
29
 
@@ -0,0 +1,16 @@
1
+ import {
2
+ isCoupleLines,
3
+ isIdentifierAndIdentifier,
4
+ isStringAndIdentifier,
5
+ } from '#is';
6
+ import {createTypeChecker} from '#type-checker';
7
+ import {isInsideOneElementArray} from './before-if.js';
8
+
9
+ export const afterIf = createTypeChecker([
10
+ ['-: parentPath -> !ArrayExpression'],
11
+ ['-: parentPath ->', isCoupleLines],
12
+ ['+', isIdentifierAndIdentifier],
13
+ ['-: -> !', isStringAndIdentifier],
14
+ ['+', isInsideOneElementArray],
15
+ ]);
16
+
@@ -1,46 +1,23 @@
1
1
  import {types} from '@putout/babel';
2
2
  import {createTypeChecker} from '#type-checker';
3
+ import {callWithNext, callWithPrev} from '#is';
3
4
  import {
4
- isCoupleLines,
5
- isStringAndIdentifier,
6
- isIdentifierAndIdentifier,
7
- isSimpleAndNotEmptyObject,
8
- callWithNext,
9
- callWithPrev,
10
- } from '#is';
11
- import {
12
- isCurrentNewLine,
5
+ isIndentBeforeElement,
13
6
  isMultiLine,
14
- isNewlineAfterComma,
15
7
  } from './newline.js';
16
- import {isObjectAfterSimple} from './is-object-after-simple.js';
17
8
  import {
18
9
  isNeedIndent,
19
- maybeSecondIndent,
10
+ maybeAdditionalIndent,
20
11
  } from './indent.js';
12
+ import {beforeIf} from './before-if.js';
13
+ import {afterIf} from './after-if.js';
21
14
  import {
22
- beforeIf,
23
- isInsideOneElementArray,
24
- } from './before-if.js';
25
-
26
- const {
27
- isObjectExpression,
28
- isSpreadElement,
29
- isIdentifier,
30
- isCallExpression,
31
- } = types;
32
-
33
- const isSimpleBetweenObjects = createTypeChecker([
34
- ['+', callWithNext(isObjectExpression)],
35
- ['-', isSpreadElement],
36
- ['-', isIdentifier],
37
- ['+: -> !', isCallExpression],
38
- ]);
15
+ isCommaBeforeClosingSquareBrace,
16
+ isNewlineAfterComma,
17
+ isSpaceAfterComa,
18
+ } from './comma.js';
39
19
 
40
- const isSpaceAfterComa = createTypeChecker([
41
- ['+', callWithNext(isSimpleBetweenObjects)],
42
- ['+: -> !ObjectExpression'],
43
- ]);
20
+ const {isObjectExpression} = types;
44
21
 
45
22
  export const ArrayExpression = {
46
23
  beforeIf,
@@ -48,7 +25,11 @@ export const ArrayExpression = {
48
25
  print.breakline();
49
26
  },
50
27
  print(path, printer, semantics) {
51
- const {print, maybe} = printer;
28
+ const {
29
+ print,
30
+ maybe,
31
+ indent,
32
+ } = printer;
52
33
 
53
34
  const {
54
35
  maxElementsInOneLine,
@@ -56,73 +37,58 @@ export const ArrayExpression = {
56
37
  maxElementLengthInOneLine,
57
38
  } = semantics;
58
39
 
59
- const elements = path.get('elements');
60
-
61
- print('[');
62
-
63
40
  const needIndent = isNeedIndent(path);
64
-
65
- maybe.indent.inc(needIndent);
66
-
67
- const needsNewline = isMultiLine(path, {
41
+ const multiline = isMultiLine(path, {
68
42
  maxElementsInOneLine,
69
43
  maxElementLengthInOneLine,
70
44
  });
71
45
 
72
- const n = elements.length - 1;
46
+ const elements = path.get('elements');
73
47
 
74
- if (needsNewline)
75
- print.newline();
48
+ print('[');
49
+ maybe.indent.inc(needIndent);
50
+ maybe.print.newline(multiline);
51
+
52
+ const n = elements.length - 1;
76
53
 
77
54
  for (const [index, element] of elements.entries()) {
78
- const is = needsNewline && isCurrentNewLine(element);
55
+ const isLast = index === n;
56
+ const needsIndentBeforeElement = isIndentBeforeElement(element, {multiline});
57
+ const needsComma = needsIndentBeforeElement && trailingComma || !isLast;
79
58
 
80
- if (isSimpleAfterObject(element))
59
+ if (isNewlineBeforeElement(element))
81
60
  print.newline();
82
61
 
83
- maybe.indent(is);
62
+ if (needsIndentBeforeElement)
63
+ indent();
64
+
84
65
  print(element);
85
66
 
86
- if (index < n || trailingComma)
87
- maybe.print(is, ',');
67
+ if (needsComma)
68
+ print(',');
88
69
 
89
- if (is && isNewlineAfterComma(element))
70
+ if (isNewlineAfterComma(element, {multiline})) {
90
71
  print.newline();
91
-
92
- maybe.print.space(is && isObjectAfterSimple(element));
93
-
94
- if (!is && index < n) {
95
- print(',');
96
- maybe.print.space(isSpaceAfterComa(element));
72
+ continue;
97
73
  }
74
+
75
+ if (isSpaceAfterComa(element, {isLast}))
76
+ print.space();
98
77
  }
99
78
 
100
79
  maybe.indent.dec(needIndent);
101
- maybeSecondIndent(path, printer, semantics, {
102
- needsNewline,
80
+ maybeAdditionalIndent(path, printer, semantics, {
81
+ multiline,
103
82
  });
104
83
 
105
- if (isSimpleAndNotEmptyObject(path) && !isSpreadElement(elements.at(-1)) && !isCallExpression(elements.at(-1))) {
84
+ if (isCommaBeforeClosingSquareBrace(path)) {
106
85
  print(',');
107
86
  print.breakline();
108
87
  }
109
88
 
110
89
  print(']');
111
90
  },
112
- afterIf(path) {
113
- const {parentPath} = path;
114
-
115
- if (!parentPath.isArrayExpression())
116
- return false;
117
-
118
- if (isCoupleLines(parentPath))
119
- return false;
120
-
121
- if (isStringAndIdentifier(path) && isInsideOneElementArray(path))
122
- return true;
123
-
124
- return isIdentifierAndIdentifier(path);
125
- },
91
+ afterIf,
126
92
  after(path, {print, indent}) {
127
93
  indent.dec();
128
94
  print.breakline();
@@ -136,8 +102,9 @@ const isSimple = createTypeChecker([
136
102
  '+: -> !CallExpression',
137
103
  ]);
138
104
 
139
- const isSimpleAfterObject = createTypeChecker([
105
+ const isNewlineBeforeElement = createTypeChecker([
140
106
  ['-', isSimple],
141
107
  ['-', callWithNext(isObjectExpression)],
142
108
  ['+', callWithPrev(isObjectExpression)],
143
109
  ]);
110
+
@@ -0,0 +1,44 @@
1
+ import {types} from '@putout/babel';
2
+ import {createTypeChecker} from '#type-checker';
3
+ import {
4
+ callWithNext,
5
+ isSimpleAndNotEmptyObject,
6
+ } from '#is';
7
+ import {
8
+ isLastOption,
9
+ isMultilineOption,
10
+ } from './is.js';
11
+
12
+ const {
13
+ isSpreadElement,
14
+ isCallExpression,
15
+ isObjectExpression,
16
+ isIdentifier,
17
+ } = types;
18
+
19
+ const callWithLastElement = (fn) => (a) => fn(a.at(-1));
20
+
21
+ export const isCommaBeforeClosingSquareBrace = createTypeChecker([
22
+ ['-: -> !', isSimpleAndNotEmptyObject],
23
+ ['-: node.elements', callWithLastElement(isSpreadElement)],
24
+ ['+: node.elements -> !', callWithLastElement(isCallExpression)],
25
+ ]);
26
+
27
+ export const isNewlineAfterComma = createTypeChecker([
28
+ ['-: -> !', isMultilineOption],
29
+ ['-', callWithNext(isObjectExpression)],
30
+ ['+: -> !ObjectExpression'],
31
+ ]);
32
+
33
+ const isSimpleBetweenObjects = createTypeChecker([
34
+ ['+', callWithNext(isObjectExpression)],
35
+ ['-', isSpreadElement],
36
+ ['-', isIdentifier],
37
+ ['+: -> !', isCallExpression],
38
+ ]);
39
+
40
+ export const isSpaceAfterComa = createTypeChecker([
41
+ ['-', isLastOption],
42
+ ['+', callWithNext(isSimpleBetweenObjects)],
43
+ ['+: -> !ObjectExpression'],
44
+ ]);
@@ -5,6 +5,10 @@ import {
5
5
  isInsideCall,
6
6
  isStringAndArray,
7
7
  } from '#is';
8
+ import {
9
+ isMultilineOption,
10
+ isNeedsToHideIndentOption,
11
+ } from './is.js';
8
12
 
9
13
  const isTwoLongStrings = (path) => {
10
14
  const [a, b] = path.node.elements;
@@ -104,23 +108,20 @@ export const isHideIndent = createTypeChecker([
104
108
 
105
109
  const isLastElementObjectExpression = ({node}) => isObjectExpression(node.elements.at(-1));
106
110
 
107
- const isNeedsNewlineOption = (a, {needsNewline}) => needsNewline;
108
- const isNeedsToHideIndentOption = (a, {needsToHideIndent}) => needsToHideIndent;
109
-
110
111
  export const isSecondIndent = createTypeChecker([
111
- ['-: -> !', isNeedsNewlineOption],
112
+ ['-: -> !', isMultilineOption],
112
113
  ['+', isNeedsToHideIndentOption],
113
114
  ['-: ->', isArrayInsideArray],
114
115
  ['+: -> !', isLastElementObjectExpression],
115
116
  ]);
116
117
 
117
- export function maybeSecondIndent(path, printer, semantics, options) {
118
+ export function maybeAdditionalIndent(path, printer, semantics, options) {
118
119
  const {maybe, indent} = printer;
119
- const {needsNewline} = options;
120
+ const {multiline} = options;
120
121
  const needsToHideIndent = isHideIndent(path);
121
122
 
122
123
  const needsToMakeSecondIndent = isSecondIndent(path, {
123
- needsNewline,
124
+ multiline,
124
125
  needsToHideIndent,
125
126
  });
126
127
 
@@ -0,0 +1,4 @@
1
+ export const isMultilineOption = (a, {multiline}) => multiline;
2
+ export const isNeedsToHideIndentOption = (a, {needsToHideIndent}) => needsToHideIndent;
3
+ export const isLastOption = (a, {isLast}) => isLast;
4
+
@@ -11,9 +11,9 @@ import {
11
11
  isSimpleAndNotEmptyObject,
12
12
  isInsideCall,
13
13
  isInsideArray,
14
- isNextObject,
15
14
  } from '#is';
16
15
  import {isIncreaseIndent} from './indent.js';
16
+ import {isMultilineOption} from './is.js';
17
17
 
18
18
  const isParentProperty = (path) => path.find(isObjectProperty);
19
19
 
@@ -306,12 +306,9 @@ function isNumbers(elements) {
306
306
  return false;
307
307
  }
308
308
 
309
- export const isCurrentNewLine = createTypeChecker([
310
- '+: -> SpreadElement',
311
- '+: -> !ObjectExpression',
309
+ export const isIndentBeforeElement = createTypeChecker([
310
+ ['-: -> !', isMultilineOption],
311
+ ['+: -> SpreadElement'],
312
+ ['+: -> !ObjectExpression'],
312
313
  ]);
313
314
 
314
- export const isNewlineAfterComma = createTypeChecker([
315
- ['-', isNextObject],
316
- ['+: -> !', isObjectExpression],
317
- ]);
@@ -61,10 +61,6 @@ export const isPrev = (path) => {
61
61
  export const isNextParent = (path) => isNext(path.parentPath);
62
62
  export const isLast = (path) => isInsideProgram(path) && !isNext(path);
63
63
 
64
- export const isNextObject = (a) => a
65
- .getNextSibling()
66
- .isObjectExpression();
67
-
68
64
  export const isFirst = (path) => path.node === path.parentPath.node.body?.[0];
69
65
  export const isPrevBody = (path) => path
70
66
  .getPrevSibling()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@putout/printer",
3
- "version": "18.2.11",
3
+ "version": "18.3.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",
@@ -1,18 +0,0 @@
1
- import {isNextObject} from '#is';
2
- import {createTypeChecker} from '#type-checker';
3
-
4
- const SIMPLE_TYPES = [
5
- 'ArrayExpression',
6
- 'ObjectExpression',
7
- 'SpreadElement',
8
- 'CallExpression',
9
- 'Identifier',
10
- 'NewExpression',
11
- ];
12
-
13
- const isSimpleType = ({type}) => SIMPLE_TYPES.includes(type);
14
-
15
- export const isObjectAfterSimple = createTypeChecker([
16
- ['-: -> !', isNextObject],
17
- ['+', isSimpleType],
18
- ]);