@putout/printer 18.8.1 → 18.8.3

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.20, v18.8.3
2
+
3
+ feature:
4
+ - 527b8425 @putout/printer: ObjectPattern: shouldAddNewline: simplify
5
+ - 0332d176 @putout/printer: ObjectPattern: isFunctionParam
6
+ - 3eadc072 @putout/printer: ObjectPattern: isLessThenMaxPropertiesInOneLine
7
+ - 63c73f94 @putout/printer: ObjectPattern: hasAssignObject: simplify
8
+
9
+ 2026.03.19, v18.8.2
10
+
11
+ feature:
12
+ - 62e8f395 @putout/printer: ObjectPattern: isIndentAfterNewline
13
+ - 03b337f7 @putout/printer: ObjectPattern: isNewlineAfterComma: simplify
14
+
1
15
  2026.03.19, v18.8.1
2
16
 
3
17
  feature:
@@ -59,7 +59,8 @@ export const printLeadingComments = (path, printer, semantics, {currentTraverse}
59
59
  export const printTrailingComments = (path, printer, semantics, {currentTraverse}) => {
60
60
  const {print} = printer;
61
61
  const {
62
- trailingComments = []} = path.node;
62
+ trailingComments = [],
63
+ } = path.node;
63
64
 
64
65
  const {
65
66
  printTrailingCommentLine,
@@ -39,9 +39,10 @@ export const isCommaAfterProperty = createTypeChecker([
39
39
  ]);
40
40
 
41
41
  export const isNewlineAfterComma = createTypeChecker([
42
+ ['+', hasOptionIs],
43
+ ['+', isPrevAssignObject],
42
44
  ['+', isCoupleOption],
45
+ ['+', isNextAssignObject],
43
46
  ['-: key -> -'],
44
- ['-', isPrevAssign],
45
- ['-: parentPath', isInsideForOf],
46
47
  ['+: node.value.right -> ObjectExpression'],
47
48
  ]);
@@ -3,23 +3,20 @@ import {types} from '@putout/babel';
3
3
  const {
4
4
  isAssignmentPattern,
5
5
  isObjectPattern,
6
- isVariableDeclaration,
7
6
  isObjectExpression,
8
7
  } = types;
9
8
 
10
- export function hasObjectPattern(properties) {
11
- for (const property of properties) {
12
- if (isObjectPattern(property.node.value))
9
+ export function hasObjectPattern(path) {
10
+ for (const {value} of path.node.properties) {
11
+ if (isObjectPattern(value))
13
12
  return true;
14
13
  }
15
14
 
16
15
  return false;
17
16
  }
18
17
 
19
- export function hasAssign(properties) {
20
- for (const prop of properties) {
21
- const {value} = prop.node;
22
-
18
+ export function hasAssign(path) {
19
+ for (const {value} of path.node.properties) {
23
20
  if (isAssignmentPattern(value))
24
21
  return true;
25
22
  }
@@ -28,15 +25,6 @@ export function hasAssign(properties) {
28
25
  }
29
26
 
30
27
  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
28
  const properties = path.get('properties');
41
29
  const n = properties.length;
42
30
 
@@ -2,6 +2,7 @@ import {createTypeChecker} from '#type-checker';
2
2
  import {
3
3
  hasOptionIs,
4
4
  isInsideFn,
5
+ isNextAssignObject,
5
6
  isPrevAssignObject,
6
7
  } from './is.js';
7
8
 
@@ -10,3 +11,8 @@ export const isIndentBeforeProperty = createTypeChecker([
10
11
  ['+', isPrevAssignObject],
11
12
  ['+', hasOptionIs],
12
13
  ]);
14
+
15
+ export const isIndentAfterNewline = createTypeChecker([
16
+ ['-: node.value -> AssignmentPattern'],
17
+ ['+', isNextAssignObject],
18
+ ]);
@@ -0,0 +1,7 @@
1
+ import {createTypeChecker} from '#type-checker';
2
+
3
+ const getMaxPropertiesInOneLine = (a, {maxPropertiesInOneLine}) => maxPropertiesInOneLine;
4
+
5
+ export const isLessThenMaxPropertiesInOneLine = createTypeChecker([
6
+ ['+: node.properties.length', '<=', getMaxPropertiesInOneLine],
7
+ ]);
@@ -9,13 +9,10 @@ function getLength(left, right) {
9
9
  if (isIdentifier(left) && isIdentifier(right))
10
10
  return left.name.length + right.name.length;
11
11
 
12
- if (isIdentifier(left))
13
- return left.name.length;
14
-
15
- return 0;
12
+ return left.name.length;
16
13
  }
17
14
 
18
- export const moreThenMaxPropertiesLengthInOneLine = (path, {maxPropertiesLengthInOneLine}) => {
15
+ export const isMoreThenMaxPropertiesLengthInOneLine = (path, {maxPropertiesLengthInOneLine}) => {
19
16
  const {properties} = path.node;
20
17
 
21
18
  for (const {key, value} of properties) {
@@ -34,10 +34,9 @@ export const isCoupleProperties = ({path, valuePath, property}) => {
34
34
  if (exists(property.getPrevSibling()))
35
35
  return false;
36
36
 
37
- const properties = path.get('properties');
38
37
  const {parentPath} = path;
39
38
 
40
- if (isVariableDeclarator(parentPath) && !hasAssign(properties))
39
+ if (isVariableDeclarator(parentPath) && !hasAssign(path))
41
40
  return false;
42
41
 
43
42
  return !isObjectProperty(parentPath);
@@ -12,13 +12,14 @@ import {
12
12
  isCommaAfterProperty,
13
13
  isNewlineAfterComma,
14
14
  } from './comma.js';
15
- import {isIndentBeforeProperty} from './indent.js';
15
+ import {
16
+ isIndentBeforeProperty,
17
+ isIndentAfterNewline,
18
+ } from './indent.js';
16
19
  import {
17
20
  isCoupleProperties,
18
21
  isIndent,
19
22
  isInsideFn,
20
- isNextAssignObject,
21
- isPrevAssignObject,
22
23
  } from './is.js';
23
24
 
24
25
  export const ObjectPattern = {
@@ -46,14 +47,12 @@ export const ObjectPattern = {
46
47
  maxPropertiesLengthInOneLine,
47
48
  });
48
49
 
49
- const hasObject = n && hasObjectPattern(properties);
50
+ const hasObject = n && hasObjectPattern(path);
50
51
  const notInsideFn = !isInsideFn(path);
51
52
 
52
53
  maybe.print.newline(is && notInsideFn);
53
54
 
54
55
  for (const [i, property] of properties.entries()) {
55
- const prevAssignObject = i && isPrevAssignObject(property);
56
-
57
56
  if (isIndentBeforeProperty(property, {is}))
58
57
  indent();
59
58
 
@@ -65,8 +64,6 @@ export const ObjectPattern = {
65
64
  continue;
66
65
  }
67
66
 
68
- const nextAssignObject = isNextAssignObject(property);
69
-
70
67
  const valuePath = property.get('value');
71
68
  const keyPath = property.get('key');
72
69
  const isAssign = valuePath.isAssignmentPattern();
@@ -97,22 +94,16 @@ export const ObjectPattern = {
97
94
  if (isCommaAfterProperty(property, {is, couple}))
98
95
  print(',');
99
96
 
100
- if (isNewlineAfterComma(property, {couple})) {
101
- print.newline();
102
- continue;
103
- }
104
-
105
- if (!isAssign && nextAssignObject && notInsideFn) {
106
- print.breakline();
107
- continue;
108
- }
109
-
110
- if (is || hasObject || prevAssignObject && notInsideFn) {
97
+ if (isNewlineAfterComma(property, {is, couple})) {
111
98
  print.newline();
99
+
100
+ if (isIndentAfterNewline(property))
101
+ indent();
102
+
112
103
  continue;
113
104
  }
114
105
 
115
- if (i < n && !(isAssign && couple))
106
+ if (i < n)
116
107
  print.space();
117
108
  }
118
109
 
@@ -1,84 +1,66 @@
1
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';
2
+ import {callWithParent, isForOf} from '#is';
3
+ import {createTypeChecker} from '#type-checker';
4
+ import {isLessThenMaxPropertiesInOneLine} from './is-less-then-max-properties-in-one-line.js';
5
+ import {isMoreThenMaxPropertiesLengthInOneLine} from './is-more-then-max-properties-length-in-one-line.js';
5
6
  import {
6
7
  hasAssign,
7
8
  hasObjectPattern,
8
9
  } from './has.js';
9
10
 
11
+ const isMoreCountLessLength = createTypeChecker([
12
+ ['-: -> !', isLessThenMaxPropertiesInOneLine],
13
+ ['-', isMoreThenMaxPropertiesLengthInOneLine],
14
+ ['+: parentPath -> VariableDeclarator'],
15
+ ]);
16
+
10
17
  const {
11
18
  isIdentifier,
12
19
  isAssignmentPattern,
13
- isVariableDeclarator,
14
20
  isObjectProperty,
21
+ isFunction,
15
22
  } = types;
16
23
 
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)
24
+ function hasPropertyLeadingComment(path) {
25
+ for (const property of path.node.properties) {
26
+ if (property.leadingComments)
23
27
  return true;
24
28
  }
25
29
 
26
30
  return false;
27
31
  }
28
32
 
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
- }
33
+ const cutOptions = (fn) => (a) => fn(a);
34
+ const isFunctionLike = cutOptions(isFunction);
38
35
 
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
- }
36
+ const isFunctionParam = callWithParent(createTypeChecker([
37
+ ['+', isFunctionLike],
38
+ ['-: -> !AssignmentPattern'],
39
+ ['+: parentPath', isFunctionLike],
40
+ ]));
41
+
42
+ const isOneOfIdentifiersHasMoreLength = createTypeChecker([
43
+ ['-', isFunctionParam],
44
+ ['-', isForOf],
45
+ ['-: node.properties.length', '=', 1],
46
+ ['+', checkLength],
47
+ ]);
48
+
49
+ const hasAssignNotFunctionParam = createTypeChecker([
50
+ ['-', isFunctionParam],
51
+ ['+', hasAssign],
52
+ ]);
53
+
54
+ export const shouldAddNewline = createTypeChecker([
55
+ ['+', isCoupleAssigns],
56
+ ['+', hasPropertyLeadingComment],
57
+ ['+', hasComputed],
58
+ ['+', hasObjectPattern],
59
+ ['-', isMoreCountLessLength],
60
+ ['+', hasAssignNotFunctionParam],
61
+ ['+', isOneOfIdentifiersHasMoreLength],
62
+ ['+: parentPath -> ObjectProperty'],
63
+ ]);
82
64
 
83
65
  function isCoupleAssigns(path) {
84
66
  if (isFunctionParam(path))
@@ -97,13 +79,16 @@ function isCoupleAssigns(path) {
97
79
  return assignsCount > 1;
98
80
  }
99
81
 
100
- function checkLength(properties) {
101
- for (const prop of properties) {
102
- const {value} = prop.node;
103
-
104
- if (!isIdentifier(value))
105
- continue;
106
-
82
+ const getValue = (a) => a.value;
83
+
84
+ function checkLength(path) {
85
+ const identifiers = path
86
+ .node
87
+ .properties
88
+ .map(getValue)
89
+ .filter(isIdentifier);
90
+
91
+ for (const value of identifiers) {
107
92
  if (value.name.length > 4)
108
93
  return true;
109
94
  }
@@ -111,10 +96,8 @@ function checkLength(properties) {
111
96
  return false;
112
97
  }
113
98
 
114
- function hasComputed(properties) {
115
- for (const prop of properties) {
116
- const {computed} = prop.node;
117
-
99
+ function hasComputed(path) {
100
+ for (const {computed} of path.node.properties) {
118
101
  if (computed)
119
102
  return true;
120
103
  }
@@ -1,5 +1,6 @@
1
1
  import {createTuple} from './create-tuple.js';
2
2
 
3
+ const isFn = (a) => typeof a === 'function';
3
4
  const isString = (a) => typeof a === 'string';
4
5
  const {isArray} = Array;
5
6
 
@@ -46,11 +47,18 @@ export function parseTypeNames(typeNames) {
46
47
  return tuples;
47
48
  }
48
49
 
49
- const equal = (a) => (b) => b === a;
50
- const more = (a) => (b) => b > a;
51
- const less = (a) => (b) => b < a;
52
- const moreOrEqual = (a) => (b) => b >= a;
53
- const lessOrEqual = (a) => (b) => b <= a;
50
+ const createValueParser = (fn) => (a) => (b, ...c) => {
51
+ if (isFn(a))
52
+ return fn(a(b, ...c), b);
53
+
54
+ return fn(a, b);
55
+ };
56
+
57
+ const equal = createValueParser((a, b) => b === a);
58
+ const more = createValueParser((a, b) => b > a);
59
+ const less = createValueParser((a, b) => b < a);
60
+ const moreOrEqual = createValueParser((a, b) => b >= a);
61
+ const lessOrEqual = createValueParser((a, b) => b <= a);
54
62
 
55
63
  const CMP = {
56
64
  '=': equal,
@@ -63,7 +71,6 @@ const CMP = {
63
71
  function parseComparison(typeName) {
64
72
  if (typeName.length === 3) {
65
73
  const [result, comparison, value] = typeName;
66
-
67
74
  return [result, CMP[comparison](value)];
68
75
  }
69
76
 
@@ -42,7 +42,13 @@ export const report = (coverage) => {
42
42
  };
43
43
 
44
44
  const setLine = (name, index) => {
45
- const [at, uri, line, column] = name.split(':');
45
+ const [
46
+ at,
47
+ uri,
48
+ line,
49
+ column,
50
+ ] = name.split(':');
51
+
46
52
  const newLine = Number(line) + index + 1;
47
53
 
48
54
  return [
@@ -71,12 +77,15 @@ function createRawCode(currentType) {
71
77
  if (isFn(currentType))
72
78
  return currentType.name;
73
79
 
74
- const [operator, fn] = currentType;
80
+ const [operator, fn, value] = currentType;
75
81
 
76
- if (fn) {
82
+ if (isFn(fn)) {
77
83
  const name = fn.name || fn;
78
84
  return `['${operator}', ${name}]`;
79
85
  }
80
86
 
87
+ if (isString(fn))
88
+ return `['${operator}', '${fn}', ${value}]`;
89
+
81
90
  return operator;
82
91
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@putout/printer",
3
- "version": "18.8.1",
3
+ "version": "18.8.3",
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,10 +0,0 @@
1
- export const moreThenMaxPropertiesInOneLine = (path, {maxPropertiesInOneLine}) => {
2
- const {parentPath} = path;
3
-
4
- if (parentPath.isObjectProperty())
5
- return false;
6
-
7
- const n = path.node.properties.length;
8
-
9
- return maxPropertiesInOneLine >= n;
10
- };