@putout/printer 18.3.4 → 18.3.6

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,17 @@
1
+ 2026.03.10, v18.3.6
2
+
3
+ feature:
4
+ - a3281ef @putout/printer: ObjectExpression: isMultiline
5
+ - da64dc7 @putout/printer: ObjectExpression: isCommaAfterProperty
6
+ - 69ff480 @putout/printer: ObjectExpression: hasTrailingComment
7
+ - 50f7e07 @putout/printer: ObjectExpression: isIndentBeforeClosingCurlyBrace
8
+
9
+ 2026.03.10, v18.3.5
10
+
11
+ feature:
12
+ - 8a3ffb9 @putout/printer: ObjectExpression: isIndentBeforeProperty
13
+ - 3d450fc @putout/printer: ObjectExpression: indent
14
+
1
15
  2026.03.10, v18.3.4
2
16
 
3
17
  feature:
@@ -0,0 +1,24 @@
1
+ import {createTypeChecker} from '#type-checker';
2
+ import {
3
+ isMultilineOption,
4
+ isTrailingCommaOption,
5
+ } from '../array-expression/is.js';
6
+
7
+ const isCouple = (a) => a > 1;
8
+ const isLastProperty = ({node, parentPath}) => node === parentPath.node.properties.at(-1);
9
+
10
+ const isCoupleOrManyLines = createTypeChecker([
11
+ ['+: parentPath.node.properties.length ->', isCouple],
12
+ ['+', isMultilineOption],
13
+ ]);
14
+
15
+ const isLastOrTrailingComma = createTypeChecker([
16
+ ['+: -> !', isLastProperty],
17
+ ['+', isTrailingCommaOption],
18
+ ]);
19
+
20
+ export const isCommaAfterProperty = createTypeChecker([
21
+ ['-: -> !SpreadElement'],
22
+ ['-: -> !', isCoupleOrManyLines],
23
+ ['+', isLastOrTrailingComma],
24
+ ]);
@@ -4,18 +4,21 @@ import {
4
4
  isCoupleLines,
5
5
  isForOf,
6
6
  isIf,
7
- noTrailingComment,
8
7
  isNewlineBetweenSiblings,
9
- noLeadingComment,
10
8
  hasLeadingComment,
11
- exists,
12
9
  isInsideCall,
13
10
  isInsideBody,
14
11
  isInsideExpression,
12
+ callWithNext,
13
+ hasTrailingComment,
15
14
  } from '#is';
16
15
  import {parseComments} from '../../comment/comment.js';
17
16
  import {isInsideTuple} from './is-inside-tuple.js';
18
17
  import {isLooksLikeChain} from '../member-expression/is-looks-like-chain.js';
18
+ import {isCommaAfterProperty} from './comma.js';
19
+ import {isMultilineOption} from '../array-expression/is.js';
20
+
21
+ const hasNextLeadingComment = callWithNext(hasLeadingComment);
19
22
 
20
23
  const notLastArgInsideCall = (path) => {
21
24
  const {parentPath} = path;
@@ -34,11 +37,9 @@ const hasValue = (path) => path.node.properties[0].value;
34
37
 
35
38
  const {
36
39
  isMemberExpression,
37
- isLogicalExpression,
40
+ isSpreadElement,
38
41
  } = types;
39
42
 
40
- const isLogicalArgument = (path) => isLogicalExpression(path.node.argument);
41
-
42
43
  const isParens = createTypeChecker([isInsideBody, isInsideExpression]);
43
44
 
44
45
  const getCallee = (fn) => (a) => fn(a.get('callee'));
@@ -61,7 +62,7 @@ const isInsideTupleLike = createTypeChecker([
61
62
  ['+: parentPath.parentPath.node.elements.0 -> StringLiteral'],
62
63
  ]);
63
64
 
64
- export const isManyLines = createTypeChecker([
65
+ export const isMultiline = createTypeChecker([
65
66
  ['-', hasNoProperties],
66
67
  ['-: parentPath -> ForOfStatement'],
67
68
  ['+: node.properties.0 -> SpreadElement'],
@@ -72,6 +73,11 @@ export const isManyLines = createTypeChecker([
72
73
  ['+', hasValue],
73
74
  ]);
74
75
 
76
+ const isIndentBeforeProperty = createTypeChecker([
77
+ ['-: -> !', isMultilineOption],
78
+ ['+: -> !', hasLeadingComment],
79
+ ]);
80
+
75
81
  export const ObjectExpression = (path, printer, semantics) => {
76
82
  const {trailingComma} = semantics;
77
83
  const {
@@ -87,55 +93,49 @@ export const ObjectExpression = (path, printer, semantics) => {
87
93
  const properties = path.get('properties');
88
94
  const {length} = properties;
89
95
  const parens = isParens(path);
90
- const manyLines = isManyLines(path);
96
+ const multiline = isMultiline(path);
91
97
 
92
98
  maybe.print(parens, '(');
93
99
  print('{');
94
100
  parseComments(path, printer, semantics);
95
- maybe.print.newline(manyLines);
96
-
97
- const n = properties.length - 1;
101
+ maybe.print.newline(multiline);
98
102
 
99
103
  const memberCallee = isMemberExpressionCallee(path);
100
104
  maybe.indent.inc(memberCallee);
101
105
 
102
- for (const [index, property] of properties.entries()) {
103
- if (property.isSpreadElement()) {
104
- const logical = isLogicalArgument(property);
105
-
106
- if (noLeadingComment(property))
107
- maybe.indent(length > 1 || logical || manyLines);
108
-
109
- print(property);
110
-
111
- if (noTrailingComment(property) && (length > 1 || manyLines)) {
112
- maybe.print(index !== n || trailingComma, ',');
113
- print.newline();
114
- }
115
-
116
- continue;
117
- }
106
+ for (const property of properties) {
107
+ const couple = length > 1;
108
+
109
+ if (isIndentBeforeProperty(property, {multiline}))
110
+ indent();
118
111
 
119
- maybe.indent(manyLines && noLeadingComment(property));
120
112
  print(property);
121
113
 
122
114
  if (property.isObjectMethod())
123
115
  continue;
124
116
 
125
- if (noTrailingComment(property) && !hasNextLeadingComment(property)) {
126
- maybe.print.newline(manyLines);
127
- maybe.print.linebreak(isNewlineBetweenSiblings(property));
128
- }
117
+ if (hasTrailingComment(property))
118
+ continue;
119
+
120
+ maybe.print(isCommaAfterProperty(property, {
121
+ multiline,
122
+ trailingComma,
123
+ }), ',');
124
+
125
+ if (!isSpreadElement(property) && !hasNextLeadingComment(property) && multiline || property.isSpreadElement() && (couple || multiline))
126
+ print.newline();
127
+
128
+ if (!isSpreadElement(property) && !hasNextLeadingComment(property) && isNewlineBetweenSiblings(property))
129
+ print.linebreak();
129
130
  }
130
131
 
131
- if (!insideNestedArrayCall) {
132
- indent.dec();
133
- maybe.indent(manyLines);
134
- } else if (isInsideTupleLike(path)) {
135
- indent.dec();
132
+ indent.dec();
133
+
134
+ if (isIndentBeforeClosingCurlyBrace(path, {multiline}))
136
135
  indent();
136
+
137
+ if (insideNestedArrayCall)
137
138
  indent.inc();
138
- }
139
139
 
140
140
  print('}');
141
141
  maybe.print(parens, ')');
@@ -143,11 +143,8 @@ export const ObjectExpression = (path, printer, semantics) => {
143
143
  maybe.indent.dec(memberCallee);
144
144
  };
145
145
 
146
- const hasNextLeadingComment = (path) => {
147
- const next = path.getNextSibling();
148
-
149
- if (!exists(next))
150
- return false;
151
-
152
- return hasLeadingComment(next);
153
- };
146
+ const isIndentBeforeClosingCurlyBrace = createTypeChecker([
147
+ ['+', isInsideTupleLike],
148
+ ['-: -> !', isMultilineOption],
149
+ ['+: -> !', isInsideNestedArrayCall],
150
+ ]);
@@ -1,5 +1,5 @@
1
1
  import {isConcatenation} from '../binary-expression/concatenate.js';
2
- import {isManyLines} from './object-expression.js';
2
+ import {isMultiline} from './object-expression.js';
3
3
  import {printKey} from './print-key.js';
4
4
 
5
5
  export const ObjectProperty = (path, printer, semantics) => {
@@ -14,7 +14,7 @@ export const ObjectProperty = (path, printer, semantics) => {
14
14
  const value = path.get('value');
15
15
  const properties = path.parentPath.get('properties');
16
16
  const isLast = path === properties.at(-1);
17
- const manyLines = isManyLines(path.parentPath);
17
+ const multiline = isMultiline(path.parentPath);
18
18
 
19
19
  printKey(path, printer);
20
20
 
@@ -24,7 +24,7 @@ export const ObjectProperty = (path, printer, semantics) => {
24
24
  traverse(value);
25
25
  }
26
26
 
27
- if (manyLines) {
27
+ if (multiline) {
28
28
  maybe.write(!isLast || trailingComma, ',');
29
29
  return;
30
30
  }
@@ -209,4 +209,3 @@ export const hasTrailingComment = (path) => {
209
209
  export const hasLeadingComment = (path) => path.node?.leadingComments?.length;
210
210
 
211
211
  export const noTrailingComment = (path) => !path.node.trailingComments?.length;
212
- export const noLeadingComment = (path) => !path.node.leadingComments?.length;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@putout/printer",
3
- "version": "18.3.4",
3
+ "version": "18.3.6",
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",