@putout/printer 18.7.0 → 18.7.2

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.03.15, v18.7.2
2
+
3
+ feature:
4
+ - 03c11aa @putout/printer: ReturnStatements: maybeSpaceAfterKeyword: simplify
5
+ - 2a0d633 @putout/printer: ReturnStatement: isJSXWithComment
6
+ - 3ee3a68 @putout/printer: ReturnStatement: afterIf
7
+
8
+ 2026.03.14, v18.7.1
9
+
10
+ feature:
11
+ - 5003310 @putout/printer: ReturnStatement: simplify
12
+
1
13
  2026.03.14, v18.7.0
2
14
 
3
15
  feature:
@@ -35,6 +35,7 @@ export const maybeInsideReturnWithCommentStart = (path, {print, indent}) => {
35
35
  const {leadingComments} = path.node;
36
36
 
37
37
  print.breakline();
38
+
38
39
  for (const {type, value} of leadingComments) {
39
40
  if (type === 'CommentLine')
40
41
  print(`//${value}`);
@@ -51,8 +51,6 @@ export const isNextTry = (path) => {
51
51
  return isTryStatement(path.getNextSibling());
52
52
  };
53
53
 
54
- export const isPrevTry = (path) => isTryStatement(path.getPrevSibling());
55
-
56
54
  export const isPrev = (path) => {
57
55
  const next = path.getPrevSibling();
58
56
  return next.node;
@@ -62,10 +60,6 @@ export const isNextParent = (path) => isNext(path.parentPath);
62
60
  export const isLast = (path) => isInsideProgram(path) && !isNext(path);
63
61
 
64
62
  export const isFirst = (path) => path.node === path.parentPath.node.body?.[0];
65
- export const isPrevBody = (path) => path
66
- .getPrevSibling()
67
- .isBlockStatement();
68
-
69
63
  export const isParentLast = (path) => isLast(path.parentPath);
70
64
 
71
65
  export function isCoupleLines(path) {
@@ -0,0 +1,17 @@
1
+ import {
2
+ isLast,
3
+ noTrailingComment,
4
+ } from '#is';
5
+ import {createTypeChecker} from '#type-checker';
6
+
7
+ const isInsideIfWithElse = createTypeChecker([
8
+ ['-: parentPath -> !IfStatement'],
9
+ ['+: parentPath.node.alternate', Boolean],
10
+ ]);
11
+
12
+ export const afterIf = createTypeChecker([
13
+ ['+', isInsideIfWithElse],
14
+ ['-', isLast],
15
+ ['-: parentPath', isLast],
16
+ ['+', noTrailingComment],
17
+ ]);
@@ -0,0 +1,18 @@
1
+ import {types} from '@putout/babel';
2
+ import {callWithPrev} from '#is';
3
+ import {hasPrevNewline} from '#mark';
4
+ import {createTypeChecker} from '#type-checker';
5
+
6
+ const {
7
+ isTryStatement,
8
+ isBlockStatement,
9
+ } = types;
10
+
11
+ const isBodyLength = ({parentPath}) => parentPath.node?.body?.length > 2;
12
+
13
+ export const beforeIf = createTypeChecker([
14
+ ['+', callWithPrev(isTryStatement)],
15
+ ['-: ->', hasPrevNewline],
16
+ ['+: ->', isBodyLength],
17
+ ['+: ->', callWithPrev(isBlockStatement)],
18
+ ]);
@@ -1,3 +1,9 @@
1
+ import {createTypeChecker} from '#type-checker';
2
+
3
+ const isSequenceOption = (a, {roundBraces}) => roundBraces.sequence;
4
+ const isArrowOption = (a, {roundBraces}) => roundBraces.arrow;
5
+ const isNot = (a) => a === '!';
6
+
1
7
  export const maybeSpaceAfterKeyword = (path, {print}, semantics) => {
2
8
  const {roundBraces} = semantics;
3
9
  const {node} = path;
@@ -5,22 +11,35 @@ export const maybeSpaceAfterKeyword = (path, {print}, semantics) => {
5
11
  if (!node)
6
12
  return;
7
13
 
8
- const {type} = node;
9
-
10
- if (type === 'SequenceExpression' && roundBraces.sequence)
11
- return print.space();
12
-
13
- if (type === 'StringLiteral' || type === 'TemplateLiteral')
14
- return print.space();
15
-
16
- if (type === 'ArrayExpression' || type === 'ObjectExpression')
17
- return print.space();
18
-
19
- if (type === 'UnaryExpression' && node.operator === '!')
20
- return print.space();
21
-
22
- if (type === 'ArrowFunctionExpression' && roundBraces.arrow)
23
- return print.space();
14
+ if (isOptionalSpace(path, {roundBraces})) {
15
+ print.space();
16
+ return;
17
+ }
24
18
 
25
19
  print(' ');
26
20
  };
21
+
22
+ const isSequenceWithOption = createTypeChecker([
23
+ ['-: -> !SequenceExpression'],
24
+ ['+', isSequenceOption],
25
+ ]);
26
+
27
+ const isArrowWithOption = createTypeChecker([
28
+ ['-: -> !ArrowFunctionExpression'],
29
+ ['+', isArrowOption],
30
+ ]);
31
+
32
+ const isUnaryNot = createTypeChecker([
33
+ ['-: -> !UnaryExpression'],
34
+ ['+: node.operator', isNot],
35
+ ]);
36
+
37
+ const isOptionalSpace = createTypeChecker([
38
+ ['+: -> StringLiteral'],
39
+ ['+: -> TemplateLiteral'],
40
+ ['+: -> ArrayExpression'],
41
+ ['+: -> ObjectExpression'],
42
+ ['+', isUnaryNot],
43
+ ['+', isSequenceWithOption],
44
+ ['+', isArrowWithOption],
45
+ ]);
@@ -1,26 +1,11 @@
1
- import {types} from '@putout/babel';
2
- import {hasPrevNewline} from '#mark';
3
- import {
4
- isInsideLabel,
5
- isPrevBody,
6
- noTrailingComment,
7
- isLast,
8
- isPrevTry,
9
- } from '#is';
1
+ import {isInsideLabel} from '#is';
2
+ import {createTypeChecker} from '#type-checker';
10
3
  import {maybeSpaceAfterKeyword} from './maybe-space-after-keyword.js';
11
-
12
- const {isJSXElement} = types;
13
- const isBodyLength = ({parentPath}) => parentPath.node?.body?.length > 2;
14
-
15
- const isInsideIfWithElse = ({parentPath}) => parentPath.isIfStatement() && parentPath.node.alternate;
4
+ import {beforeIf} from './before-if.js';
5
+ import {afterIf} from './after-if.js';
16
6
 
17
7
  export const ReturnStatement = {
18
- beforeIf(path) {
19
- if (isPrevTry(path))
20
- return true;
21
-
22
- return !hasPrevNewline(path) && isBodyLength(path) || isPrevBody(path);
23
- },
8
+ beforeIf,
24
9
  before(path, {print}) {
25
10
  print.linebreak();
26
11
  },
@@ -46,30 +31,13 @@ export const ReturnStatement = {
46
31
  print('__argument');
47
32
  print(';');
48
33
  },
49
- afterIf: (path) => {
50
- if (isInsideIfWithElse(path))
51
- return true;
52
-
53
- if (isLast(path))
54
- return false;
55
-
56
- if (isLast(path.parentPath))
57
- return false;
58
-
59
- return noTrailingComment(path);
60
- },
34
+ afterIf,
61
35
  after(path, {print}) {
62
36
  print.newline();
63
37
  },
64
38
  };
65
39
 
66
- function isJSXWithComment(path) {
67
- const arg = path.node.argument;
68
-
69
- if (!arg)
70
- return;
71
-
72
- const {leadingComments} = arg;
73
-
74
- return isJSXElement(arg) && leadingComments?.length;
75
- }
40
+ const isJSXWithComment = createTypeChecker([
41
+ ['-: node.argument -> !JSXElement'],
42
+ ['+: node.argument.leadingComments ->', Boolean],
43
+ ]);
@@ -14,13 +14,13 @@ export const createTypeChecker = (typeNames, overrides = {}) => {
14
14
  } = overrides;
15
15
 
16
16
  const tuples = parseTypeNames(typeNames);
17
- const checkers = new Set();
17
+ const checkers = [];
18
18
  const results = new Set();
19
19
 
20
20
  for (const [operation, typeName] of tuples) {
21
21
  const [result, selector, not] = parseOperation(operation);
22
22
  results.add(result);
23
- checkers.add({
23
+ checkers.push({
24
24
  result,
25
25
  selector,
26
26
  not,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@putout/printer",
3
- "version": "18.7.0",
3
+ "version": "18.7.2",
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",