@putout/printer 1.12.0 → 1.13.1

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.
Files changed (31) hide show
  1. package/ChangeLog +10 -0
  2. package/README.md +6 -1
  3. package/lib/tokenize/expressions/array-expression.js +56 -10
  4. package/lib/tokenize/expressions/array-pattern.js +0 -5
  5. package/lib/tokenize/expressions/assignment-expression.js +0 -1
  6. package/lib/tokenize/expressions/assignment-pattern.js +0 -1
  7. package/lib/tokenize/expressions/binary-expression.js +0 -1
  8. package/lib/tokenize/expressions/call-expression.js +0 -2
  9. package/lib/tokenize/expressions/class-declaration.js +10 -1
  10. package/lib/tokenize/expressions/conditional-expression.js +0 -1
  11. package/lib/tokenize/expressions/functions.js +0 -2
  12. package/lib/tokenize/expressions/member-expressions.js +0 -2
  13. package/lib/tokenize/expressions/new-expression.js +1 -1
  14. package/lib/tokenize/expressions/object-expression.js +3 -0
  15. package/lib/tokenize/expressions/object-pattern.js +2 -2
  16. package/lib/tokenize/expressions/sequence-expression.js +0 -1
  17. package/lib/tokenize/expressions/spread-element.js +0 -1
  18. package/lib/tokenize/expressions/unary-expressions.js +9 -4
  19. package/lib/tokenize/literals/template-literal.js +1 -1
  20. package/lib/tokenize/mark.js +0 -1
  21. package/lib/tokenize/statements/block-statement.js +0 -1
  22. package/lib/tokenize/statements/debugger-statement.js +0 -1
  23. package/lib/tokenize/statements/export-declarations.js +0 -1
  24. package/lib/tokenize/statements/for-of-statement.js +0 -1
  25. package/lib/tokenize/statements/import-declarations.js +1 -0
  26. package/lib/tokenize/statements/switch-statement.js +0 -2
  27. package/lib/tokenize/statements/try-statements.js +1 -2
  28. package/lib/tokenize/tokenize.js +7 -4
  29. package/lib/tokenize/typescript/index.js +24 -0
  30. package/lib/types.js +0 -1
  31. package/package.json +1 -1
package/ChangeLog CHANGED
@@ -1,3 +1,13 @@
1
+ 2023.03.29, v1.13.1
2
+
3
+ feature:
4
+ - d320519 @putout/printer: improve support of nested objects
5
+
6
+ 2023.03.29, v1.13.0
7
+
8
+ feature:
9
+ - 37cca9d @putout/printer: add support of TypeScript
10
+
1
11
  2023.03.29, v1.12.0
2
12
 
3
13
  feature:
package/README.md CHANGED
@@ -20,9 +20,11 @@ npm i @putout/printer
20
20
  ```js
21
21
  const {print} = require('@putout/printer');
22
22
  const {parse} = require('@babel/parser');
23
-
24
23
  const ast = parse('const a = (b, c) => {const d = 5; return a;}');
24
+
25
25
  print(ast);
26
+
27
+ // returns
26
28
  // returns
27
29
  `
28
30
  const a = (b, c) => {
@@ -30,6 +32,7 @@ const a = (b, c) => {
30
32
  return a;
31
33
  };
32
34
  `;
35
+
33
36
  ```
34
37
 
35
38
  ## Overrides
@@ -59,8 +62,10 @@ print(ast, {
59
62
  },
60
63
  });
61
64
 
65
+ // returns
62
66
  // returns
63
67
  'const {a /* [hello world] */= 5} = b;\n';
68
+
64
69
  ```
65
70
 
66
71
  ## License
@@ -1,32 +1,58 @@
1
1
  'use strict';
2
2
 
3
+ const {round} = Math;
4
+
3
5
  const {isObjectProperty} = require('@babel/types');
4
6
  const {isCoupleLines} = require('../is');
5
- const {entries} = Object;
6
7
  const isForOf = ({parentPath}) => parentPath.isForOfStatement();
7
8
  const SECOND = 1;
8
9
 
9
- module.exports.ArrayExpression = (path, {print, maybe}) => {
10
+ const isStringAndArray = ([a, b]) => a?.isStringLiteral() && b?.isArrayExpression();
11
+ const isTwoLongStrings = ([a, b]) => {
12
+ const LONG_STRING = 20;
13
+
14
+ if (!a?.isStringLiteral() || !b?.isStringLiteral())
15
+ return false;
16
+
17
+ if (a.node.value.length > LONG_STRING)
18
+ return true;
19
+
20
+ return false;
21
+ };
22
+
23
+ module.exports.ArrayExpression = (path, {print, maybe, indent}) => {
10
24
  const elements = path.get('elements');
11
- const elementIsObject = isElementObject(path);
25
+ const shouldIncreaseIndent = isIncreaseIndent(path);
12
26
 
13
27
  print('[');
14
- maybe.indent.inc(!elementIsObject);
15
28
 
16
- const isNewLine = !elementIsObject && isNewLineBefore(path, {elements});
29
+ if (!isTwoLongStrings(elements) && !shouldIncreaseIndent) {
30
+ indent.inc();
31
+ }
32
+
33
+ const isNewLine = isNewlineBetweenElements(path, {elements});
17
34
  const n = elements.length - 1;
18
35
 
19
36
  maybe.print(isNewLine && elements.length, '\n');
20
37
 
21
- for (const [index, element] of entries(elements)) {
38
+ for (const [index, element] of elements.entries()) {
22
39
  maybe.indent(isNewLine);
23
40
  print(element);
24
41
  maybe.print(isNewLine, ',\n');
25
42
  maybe.print(!isNewLine && index < n, ', ');
26
43
  }
27
44
 
28
- maybe.indent.dec(!elementIsObject);
29
- maybe.indent(elements.length && isNewLine);
45
+ if (!isTwoLongStrings(elements))
46
+ maybe.indent.dec(!shouldIncreaseIndent);
47
+
48
+ if (path.parentPath.isArrayExpression() && isStringAndArray(path.parentPath.get('elements'))) {
49
+ indent.dec();
50
+ maybe.indent(elements.length && isNewLine);
51
+ indent.inc();
52
+ } else {
53
+ maybe.indent(elements.length && isNewLine);
54
+ }
55
+
30
56
  print(']');
31
57
  };
32
58
 
@@ -55,7 +81,7 @@ function isParentProperty(path) {
55
81
  return path.find(isObjectProperty);
56
82
  }
57
83
 
58
- function isElementObject(path) {
84
+ function isIncreaseIndent(path) {
59
85
  const elements = path.get('elements');
60
86
 
61
87
  if (!elements.length)
@@ -84,9 +110,29 @@ function tooLong(path) {
84
110
  return false;
85
111
  }
86
112
 
87
- function isNewLineBefore(path, {elements}) {
113
+ function isNewlineBetweenElements(path, {elements}) {
114
+ if (isIncreaseIndent(path))
115
+ return false;
116
+
117
+ if (isTwoStringsDifferentLength(elements))
118
+ return false;
119
+
120
+ if (isStringAndArray(elements))
121
+ return false;
122
+
88
123
  if (tooLong(path) || isCoupleLines(path) || !isNumbers(elements) && !isForOf(path) && isLastArg(path) && !isParentProperty(path))
89
124
  return true;
90
125
 
91
126
  return false;
92
127
  }
128
+
129
+ function isTwoStringsDifferentLength([a, b]) {
130
+ if (!a?.isStringLiteral() || !b?.isStringLiteral())
131
+ return false;
132
+
133
+ const aLength = a.node.value.length;
134
+ const bLength = b.node.value.length;
135
+
136
+ return round(bLength / aLength) > 2;
137
+ }
138
+
@@ -17,17 +17,12 @@ module.exports.ArrayPattern = (path, {indent, maybe, print}) => {
17
17
 
18
18
  for (const [index, element] of entries(elements)) {
19
19
  maybe.indent(isNewLine);
20
-
21
20
  print(element);
22
-
23
21
  maybe.print(isNewLine, ',\n');
24
22
  maybe.print(!isNewLine && index < n, ', ');
25
23
  }
26
24
 
27
25
  indent.dec();
28
-
29
26
  maybe.indent(elements.length && isNewLine);
30
-
31
27
  print(']');
32
28
  };
33
-
@@ -2,7 +2,6 @@
2
2
 
3
3
  module.exports.AssignmentExpression = (path, {print}) => {
4
4
  const {operator} = path.node;
5
-
6
5
  print('__left');
7
6
  print(' ');
8
7
  print(operator);
@@ -7,4 +7,3 @@ module.exports.AssignmentPattern = (path, {print, maybe}) => {
7
7
  print(' = ');
8
8
  print('__right');
9
9
  };
10
-
@@ -10,4 +10,3 @@ function BinaryExpression(path, {print}) {
10
10
  print.space();
11
11
  print('__right');
12
12
  }
13
-
@@ -16,7 +16,6 @@ const CallExpression = {
16
16
  },
17
17
  print(path, {indent, print, maybe}) {
18
18
  const isParentCall = toLong(path) && path.parentPath.isCallExpression();
19
-
20
19
  print('__callee');
21
20
 
22
21
  if (path.node.optional)
@@ -56,7 +55,6 @@ const CallExpression = {
56
55
  };
57
56
 
58
57
  module.exports.OptionalCallExpression = CallExpression;
59
-
60
58
  module.exports.CallExpression = CallExpression;
61
59
 
62
60
  function isNewLineBefore({parentPath}) {
@@ -1,10 +1,20 @@
1
1
  'use strict';
2
2
 
3
3
  const {entries} = Object;
4
+
4
5
  module.exports.ClassDeclaration = (path, {maybe, print, indent}) => {
5
6
  indent();
6
7
  print('class ');
7
8
  print('__id');
9
+ print('__typeParameters');
10
+
11
+ const {node} = path;
12
+
13
+ if (node.implements) {
14
+ print(' implements ');
15
+ path.get('implements').forEach(print);
16
+ }
17
+
8
18
  print(' {\n');
9
19
  indent.inc();
10
20
 
@@ -20,4 +30,3 @@ module.exports.ClassDeclaration = (path, {maybe, print, indent}) => {
20
30
  indent.dec();
21
31
  print('}');
22
32
  };
23
-
@@ -11,4 +11,3 @@ module.exports.ConditionalExpression = (path, {print}) => {
11
11
  print.space();
12
12
  print('__alternate');
13
13
  };
14
-
@@ -1,7 +1,6 @@
1
1
  'use strict';
2
2
 
3
3
  const {hasPrevNewline} = require('../mark');
4
-
5
4
  const isFirst = (path) => !path.getPrevSibling().node;
6
5
 
7
6
  module.exports.FunctionExpression = (path, {print, maybe}) => {
@@ -51,7 +50,6 @@ function ArrowFunctionExpression(path, {print, maybe}) {
51
50
  print(') => ');
52
51
  print('__body');
53
52
  }
54
-
55
53
  module.exports.ObjectMethod = (path, {print}) => {
56
54
  print('__key');
57
55
  print('(');
@@ -2,7 +2,6 @@
2
2
 
3
3
  module.exports.MemberExpression = (path, {print}) => {
4
4
  const {computed} = path.node;
5
-
6
5
  print('__object');
7
6
 
8
7
  if (computed) {
@@ -22,4 +21,3 @@ module.exports.OptionalMemberExpression = (path, {print}) => {
22
21
  print('?.');
23
22
  print('__property');
24
23
  };
25
-
@@ -6,6 +6,7 @@ module.exports.NewExpression = (path, {indent, print, maybe}) => {
6
6
  print('__callee');
7
7
 
8
8
  const args = path.get('arguments');
9
+
9
10
  print('(');
10
11
 
11
12
  const n = args.length - 1;
@@ -17,4 +18,3 @@ module.exports.NewExpression = (path, {indent, print, maybe}) => {
17
18
 
18
19
  print(')');
19
20
  };
20
-
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const {isCoupleLines} = require('../is');
4
+
4
5
  const isBodyOfArrow = (path) => path.parentPath.node.body === path.node;
5
6
  const isLogical = (path) => path.get('argument').isLogicalExpression();
6
7
 
@@ -59,6 +60,7 @@ module.exports.ObjectProperty = (path, {print, maybe}) => {
59
60
  shorthand,
60
61
  computed,
61
62
  } = path.node;
63
+
62
64
  const manyLines = !isOneLine(path.parentPath);
63
65
 
64
66
  maybe.print(computed, '[');
@@ -88,3 +90,4 @@ function isOneLine(path) {
88
90
 
89
91
  return isForOf(path);
90
92
  }
93
+
@@ -8,8 +8,8 @@ module.exports.ObjectPattern = (path, {indent, print, maybe}) => {
8
8
 
9
9
  const properties = path.get('properties');
10
10
  const n = properties.length - 1;
11
-
12
11
  const is = !isForOf(path) && !path.parentPath.isFunction() && n && checkLength(properties);
12
+
13
13
  maybe.print(is, '\n');
14
14
 
15
15
  for (const [i, property] of properties.entries()) {
@@ -36,6 +36,7 @@ module.exports.ObjectPattern = (path, {indent, print, maybe}) => {
36
36
  if (is) {
37
37
  print(',');
38
38
  print.newline();
39
+
39
40
  continue;
40
41
  }
41
42
 
@@ -55,4 +56,3 @@ function checkLength(properties) {
55
56
 
56
57
  return false;
57
58
  }
58
-
@@ -12,4 +12,3 @@ module.exports.SequenceExpression = (path, {maybe, print}) => {
12
12
  maybe.print(index < n, ' ');
13
13
  }
14
14
  };
15
-
@@ -4,4 +4,3 @@ module.exports.SpreadElement = (path, {print}) => {
4
4
  print('...');
5
5
  print('__argument');
6
6
  };
7
-
@@ -2,11 +2,13 @@
2
2
 
3
3
  module.exports.UnaryExpression = unaryExpression;
4
4
  module.exports.UpdateExpression = unaryExpression;
5
+
5
6
  module.exports.AwaitExpression = (path, {print}) => {
6
7
  printUnary(path, 'await', {
7
8
  print,
8
9
  });
9
10
  };
11
+
10
12
  module.exports.YieldExpression = (path, {print}) => {
11
13
  printUnary(path, 'yield', {
12
14
  print,
@@ -28,19 +30,22 @@ function printUnary(path, name, {print}) {
28
30
  print(`${name} `);
29
31
  print('__argument');
30
32
  }
31
-
32
33
  const isWord = (a) => /delete|typeof/.test(a);
33
34
 
34
35
  function unaryExpression(path, {print, maybe}) {
35
- const {prefix, operator} = path.node;
36
+ const {
37
+ prefix,
38
+ operator,
39
+ } = path.node;
36
40
 
37
41
  if (prefix)
38
42
  print(operator);
39
43
 
40
- maybe.print(isWord(operator), ' ');
44
+ maybe.print(isWord(
45
+ operator,
46
+ ), ' ');
41
47
  print('__argument');
42
48
 
43
49
  if (!prefix)
44
50
  print(operator);
45
51
  }
46
-
@@ -8,6 +8,7 @@ module.exports.TemplateLiteral = (path, {write, traverse}) => {
8
8
 
9
9
  for (const element of path.node.quasis) {
10
10
  write(element.value.raw);
11
+
11
12
  const exp = expressions[i++];
12
13
 
13
14
  if (exp) {
@@ -19,4 +20,3 @@ module.exports.TemplateLiteral = (path, {write, traverse}) => {
19
20
 
20
21
  write('`');
21
22
  };
22
-
@@ -24,7 +24,6 @@ function isMarkedBefore(path) {
24
24
  function isMarkedAfter(path) {
25
25
  return path[WATER_MARK_AFTER];
26
26
  }
27
-
28
27
  module.exports.hasPrevNewline = (path) => {
29
28
  return isMarkedAfter(path.getPrevSibling());
30
29
  };
@@ -4,7 +4,6 @@ const {
4
4
  isNext,
5
5
  isParentProgram,
6
6
  isLast,
7
-
8
7
  } = require('../is');
9
8
 
10
9
  const isFirstStatement = (path) => path.get('body.0')?.isStatement();
@@ -5,4 +5,3 @@ module.exports.DebuggerStatement = (path, {print, indent}) => {
5
5
  print('debugger;');
6
6
  print.newline();
7
7
  };
8
-
@@ -4,4 +4,3 @@ module.exports.ExportNamedDeclaration = (path, {print}) => {
4
4
  print('export ');
5
5
  print('__declaration');
6
6
  };
7
-
@@ -48,4 +48,3 @@ module.exports.ForOfStatement = (path, {indent, print, maybe}) => {
48
48
  markAfter(path);
49
49
  }
50
50
  };
51
-
@@ -17,6 +17,7 @@ module.exports.ImportDeclaration = (path, {print, maybe}) => {
17
17
  print('{');
18
18
  print(spec.get('imported'));
19
19
  print('}');
20
+
20
21
  continue;
21
22
  }
22
23
  }
@@ -8,7 +8,6 @@ module.exports.SwitchStatement = (path, {print, maybe}) => {
8
8
  print('(');
9
9
  print('__discriminant');
10
10
  print(') {');
11
-
12
11
  print.newline();
13
12
 
14
13
  const cases = path.get('cases');
@@ -44,4 +43,3 @@ module.exports.SwitchStatement = (path, {print, maybe}) => {
44
43
 
45
44
  print('}');
46
45
  };
47
-
@@ -1,9 +1,9 @@
1
1
  'use strict';
2
2
 
3
3
  const {isNext} = require('../is');
4
+
4
5
  module.exports.TryStatement = (path, {print, maybe}) => {
5
6
  const finalizer = path.get('finalizer');
6
-
7
7
  print('try ');
8
8
  print('__block');
9
9
  print('__handler');
@@ -34,4 +34,3 @@ module.exports.CatchClause = (path, {print}) => {
34
34
 
35
35
  print(body);
36
36
  };
37
-
@@ -1,14 +1,18 @@
1
1
  'use strict';
2
2
 
3
3
  const fullstore = require('fullstore');
4
-
5
4
  const isObject = (a) => a && typeof a === 'object';
6
5
  const babelTraverse = require('@babel/traverse').default;
7
6
  const expressions = require('./expressions');
8
7
  const statements = require('./statements');
9
8
  const literals = require('./literals');
9
+ const typescript = require('./typescript');
10
10
  const {TYPES} = require('../types');
11
- const {maybeFile, maybePlugin} = require('./maybe');
11
+
12
+ const {
13
+ maybeFile,
14
+ maybePlugin,
15
+ } = require('./maybe');
12
16
 
13
17
  const {
14
18
  createDebug,
@@ -32,6 +36,7 @@ const traversers = {
32
36
  ...expressions,
33
37
  ...statements,
34
38
  ...literals,
39
+ ...typescript,
35
40
  };
36
41
 
37
42
  const GET = '__';
@@ -192,7 +197,6 @@ module.exports.tokenize = (ast, overrides = {}) => {
192
197
  parseLeadingComments(path, printer);
193
198
  maybePlugin(currentTraverse, path, printer);
194
199
  parseTrailingComments(path, printer);
195
-
196
200
  debug(path.type);
197
201
  }
198
202
 
@@ -224,4 +228,3 @@ const createPrint = (path, {traverse, write}) => (maybeLine) => {
224
228
 
225
229
  return write(maybeLine);
226
230
  };
227
-
@@ -0,0 +1,24 @@
1
+ 'use strict';
2
+
3
+ module.exports = {
4
+ TSTypeParameterDeclaration(path, {print}) {
5
+ print('<');
6
+ path.get('params').forEach(print);
7
+ print('>');
8
+ },
9
+ TSTypeParameterInstantiation(path, {print}) {
10
+ print('<');
11
+ path.get('params').forEach(print);
12
+ print('>');
13
+ },
14
+ TSTypeReference(path, {print}) {
15
+ print('__typeName');
16
+ },
17
+ TSTypeParameter(path, {print}) {
18
+ print(path.node.name);
19
+ },
20
+ TSExpressionWithTypeArguments(path, {print}) {
21
+ print('__expression');
22
+ print('__typeParameters');
23
+ },
24
+ };
package/lib/types.js CHANGED
@@ -7,4 +7,3 @@ module.exports.TYPES = {
7
7
  INDENT: 'Indent',
8
8
  DEBUG: 'Debug',
9
9
  };
10
-
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@putout/printer",
3
- "version": "1.12.0",
3
+ "version": "1.13.1",
4
4
  "type": "commonjs",
5
5
  "author": "coderaiser <mnemonic.enemy@gmail.com> (https://github.com/coderaiser)",
6
6
  "description": "Easiest possible opinionated Babel AST printer made with ❤️ to use in 🐊Putout",