espolar 0.3.1 → 0.4.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/dist/index.d.ts CHANGED
@@ -94,7 +94,15 @@ interface PrinterContext<Data = any> {
94
94
  writeNode(node: AST.Node | null | undefined): void;
95
95
  writeNodeList(nodes: readonly (AST.Node | null)[], separator: string): void;
96
96
  writeExpressionListWithCommaSep(nodes: readonly (AST.Expression | AST.SpreadElement | null)[]): void;
97
- writeNodeListWithNewLineSep(nodes: readonly (AST.ProgramStatement | AST.ClassElement)[]): void;
97
+ /**
98
+ * Write `nodes` with "newline" separator, but if the node is ranged and either:
99
+ * - it is the first node with `lastRangeEnd` provided, or
100
+ * - the previous adjacent node is ranged too,
101
+ * Then the source text ranging between the two adjacent nodes will be preserved instead of printing a newline character.
102
+ * @param nodes
103
+ * @param lastRangeEnd
104
+ */
105
+ writeNodeListWithNewLineSep(nodes: readonly (AST.ProgramStatement | AST.ClassElement)[], lastRangeEnd?: number): void;
98
106
  writeSource(start: number, end: number, data?: Data): void;
99
107
  writePreservedNode(node: AST.Node): void;
100
108
  appendMapping(sourceRange: SourceRange, generatedStart: number, generatedEnd: number, data?: Data): void;
package/dist/index.js CHANGED
@@ -1,4 +1,8 @@
1
1
  //#region src/printers.ts
2
+ /**
3
+ * Precedence table for expressions.
4
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#table
5
+ */
2
6
  const EXPRESSIONS_PRECEDENCE = {
3
7
  ArrayPattern: 20,
4
8
  ObjectPattern: 20,
@@ -274,7 +278,7 @@ const defaultPrinters = {
274
278
  TSIntrinsicKeyword: printKeywordType
275
279
  };
276
280
  function printProgram(program, context) {
277
- context.writeNodeListWithNewLineSep(program.body);
281
+ context.writeNodeListWithNewLineSep(program.body, program.range?.[0]);
278
282
  }
279
283
  function canStartExpressionStatement(node) {
280
284
  let lhs;
@@ -335,8 +339,11 @@ function printVariableDeclaration(declaration, context) {
335
339
  context.write(";");
336
340
  }
337
341
  function printVariableDeclarator(declarator, context) {
338
- context.writeNode(declarator.id);
339
- if (declarator.definite === true) context.write("!");
342
+ if (declarator.definite === true) {
343
+ context.write(String(declarator.id.name));
344
+ context.write("!");
345
+ writeOptionalTypeAnnotation(declarator.id, context);
346
+ } else context.writeNode(declarator.id);
340
347
  if (declarator.init) {
341
348
  context.write(" = ");
342
349
  if (expectAssignmentExprNeedsParen(declarator.init)) {
@@ -350,8 +357,10 @@ function printBlockStatement(block, context) {
350
357
  const body = block.body;
351
358
  context.write("{");
352
359
  if (body.length > 0) {
353
- context.write("\n");
354
- context.writeNodeListWithNewLineSep(body);
360
+ let lastRangeEnd;
361
+ if (block.range) lastRangeEnd = block.range[0] + 1;
362
+ else context.write("\n");
363
+ context.writeNodeListWithNewLineSep(body, lastRangeEnd);
355
364
  context.write("\n");
356
365
  }
357
366
  context.write("}");
@@ -870,8 +879,10 @@ function printClassBody(node, context) {
870
879
  context.write("{");
871
880
  const body = node.body;
872
881
  if (body.length > 0) {
873
- context.write("\n");
874
- context.writeNodeListWithNewLineSep(body);
882
+ let lastRangeEnd;
883
+ if (node.range) lastRangeEnd = node.range[0] + 1;
884
+ else context.write("\n");
885
+ context.writeNodeListWithNewLineSep(body, lastRangeEnd);
875
886
  context.write("\n");
876
887
  }
877
888
  context.write("}");
@@ -880,8 +891,10 @@ function printStaticBlock(node, context) {
880
891
  context.write("static {");
881
892
  const body = node.body;
882
893
  if (body.length > 0) {
883
- context.write("\n");
884
- context.writeNodeListWithNewLineSep(body);
894
+ let lastRangeEnd;
895
+ if (node.range) lastRangeEnd = node.range[0] + 1;
896
+ else context.write("\n");
897
+ context.writeNodeListWithNewLineSep(body, lastRangeEnd);
885
898
  context.write("\n");
886
899
  }
887
900
  context.write("}");
@@ -1425,8 +1438,11 @@ function printTSModuleDeclaration(node, context) {
1425
1438
  }
1426
1439
  }
1427
1440
  function printTSModuleBlock(node, context) {
1428
- context.write("{\n");
1429
- context.writeNodeListWithNewLineSep(node.body);
1441
+ context.write("{");
1442
+ let lastRangeEnd;
1443
+ if (node.range) lastRangeEnd = node.range[0] + 1;
1444
+ else context.write("\n");
1445
+ context.writeNodeListWithNewLineSep(node.body, lastRangeEnd);
1430
1446
  context.write("\n}");
1431
1447
  }
1432
1448
  function printTSDeclareFunction(node, context) {
@@ -1639,14 +1655,12 @@ function createPrinterContext(options) {
1639
1655
  needsSeparator = true;
1640
1656
  }
1641
1657
  },
1642
- writeNodeListWithNewLineSep(nodes) {
1643
- let lastRangeEnd;
1658
+ writeNodeListWithNewLineSep(nodes, lastRangeEnd) {
1644
1659
  let wroteNode = false;
1645
1660
  for (const node of nodes) {
1646
- if (!node) continue;
1647
1661
  const range = getNodeRange(node);
1648
- if (wroteNode) if (lastRangeEnd !== void 0 && range && range.start >= lastRangeEnd) context.writeSource(lastRangeEnd, range.start, getMappingData(null));
1649
- else context.write("\n");
1662
+ if (lastRangeEnd !== void 0 && range && range.start >= lastRangeEnd) context.writeSource(lastRangeEnd, range.start, getMappingData(null));
1663
+ else if (wroteNode) context.write("\n");
1650
1664
  context.writeNode(node);
1651
1665
  wroteNode = true;
1652
1666
  if (range) lastRangeEnd = range.end;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "espolar",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "types": "./dist/index.d.ts",
6
6
  "exports": {
package/src/api.ts CHANGED
@@ -57,8 +57,17 @@ export interface PrinterContext<Data = any> {
57
57
  writeExpressionListWithCommaSep(
58
58
  nodes: readonly (AST.Expression | AST.SpreadElement | null)[],
59
59
  ): void;
60
+ /**
61
+ * Write `nodes` with "newline" separator, but if the node is ranged and either:
62
+ * - it is the first node with `lastRangeEnd` provided, or
63
+ * - the previous adjacent node is ranged too,
64
+ * Then the source text ranging between the two adjacent nodes will be preserved instead of printing a newline character.
65
+ * @param nodes
66
+ * @param lastRangeEnd
67
+ */
60
68
  writeNodeListWithNewLineSep(
61
69
  nodes: readonly (AST.ProgramStatement | AST.ClassElement)[],
70
+ lastRangeEnd?: number,
62
71
  ): void;
63
72
  writeSource(start: number, end: number, data?: Data): void;
64
73
  writePreservedNode(node: AST.Node): void;
package/src/printer.ts CHANGED
@@ -220,35 +220,21 @@ function createPrinterContext<Data>(
220
220
  needsSeparator = true;
221
221
  }
222
222
  },
223
- writeNodeListWithNewLineSep(nodes) {
224
- let lastRangeEnd: number | undefined;
223
+ writeNodeListWithNewLineSep(nodes, lastRangeEnd) {
225
224
  let wroteNode = false;
226
-
227
225
  for (const node of nodes) {
228
- if (!node) {
229
- continue;
230
- }
231
-
232
226
  const range = getNodeRange(node);
233
- if (wroteNode) {
234
- if (
235
- lastRangeEnd !== undefined &&
236
- range &&
237
- range.start >= lastRangeEnd
238
- ) {
239
- context.writeSource(
240
- lastRangeEnd,
241
- range.start,
242
- getMappingData(null),
243
- );
244
- } else {
245
- context.write("\n");
246
- }
227
+ if (
228
+ lastRangeEnd !== undefined &&
229
+ range &&
230
+ range.start >= lastRangeEnd
231
+ ) {
232
+ context.writeSource(lastRangeEnd, range.start, getMappingData(null));
233
+ } else if (wroteNode) {
234
+ context.write("\n");
247
235
  }
248
-
249
236
  context.writeNode(node);
250
237
  wroteNode = true;
251
-
252
238
  if (range) {
253
239
  lastRangeEnd = range.end;
254
240
  } else {
package/src/printers.ts CHANGED
@@ -1,6 +1,10 @@
1
1
  import type { PrinterContext, Printers } from "./api.ts";
2
2
  import type { AST, AST_NODE_TYPES, Comment } from "./types.ts";
3
3
 
4
+ /**
5
+ * Precedence table for expressions.
6
+ * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#table
7
+ */
4
8
  const EXPRESSIONS_PRECEDENCE = {
5
9
  // LHS of =, must NOT parenthesized
6
10
  ArrayPattern: 20,
@@ -48,7 +52,9 @@ const EXPRESSIONS_PRECEDENCE = {
48
52
 
49
53
  // ranges from 13-5 depending on operator
50
54
  BinaryExpression: 13,
51
- // as/satisfies have same precedence as relational operators
55
+ // as/satisfies have same precedence as relational operators, e.g.
56
+ // `1 < 2 as number` is `(1 < 2) as number`, but
57
+ // `1 === 2 as number` is `1 === (2 as number)`
52
58
  TSAsExpression: 9,
53
59
  TSSatisfiesExpression: 9,
54
60
  // ranges from 4-3 depending on operator
@@ -426,7 +432,7 @@ export const defaultPrinters = {
426
432
  // JS – Statements
427
433
 
428
434
  function printProgram(program: AST.Program, context: PrinterContext): void {
429
- context.writeNodeListWithNewLineSep(program.body);
435
+ context.writeNodeListWithNewLineSep(program.body, program.range?.[0]);
430
436
  }
431
437
 
432
438
  function canStartExpressionStatement(
@@ -518,9 +524,18 @@ function printVariableDeclarator(
518
524
  declarator: AST.VariableDeclarator,
519
525
  context: PrinterContext,
520
526
  ): void {
521
- context.writeNode(declarator.id);
522
527
  if (declarator.definite === true) {
528
+ context.write(String((declarator.id as AST.Identifier).name));
523
529
  context.write("!");
530
+ writeOptionalTypeAnnotation(
531
+ declarator.id as unknown as {
532
+ optional?: boolean;
533
+ typeAnnotation?: AST.Node | null;
534
+ },
535
+ context,
536
+ );
537
+ } else {
538
+ context.writeNode(declarator.id);
524
539
  }
525
540
  if (declarator.init) {
526
541
  context.write(" = ");
@@ -542,8 +557,13 @@ function printBlockStatement(
542
557
  const body = block.body;
543
558
  context.write("{");
544
559
  if (body.length > 0) {
545
- context.write("\n");
546
- context.writeNodeListWithNewLineSep(body);
560
+ let lastRangeEnd: number | undefined;
561
+ if (block.range) {
562
+ lastRangeEnd = block.range[0] + 1;
563
+ } else {
564
+ context.write("\n");
565
+ }
566
+ context.writeNodeListWithNewLineSep(body, lastRangeEnd);
547
567
  context.write("\n");
548
568
  }
549
569
  context.write("}");
@@ -1457,8 +1477,13 @@ function printClassBody(node: AST.ClassBody, context: PrinterContext): void {
1457
1477
  context.write("{");
1458
1478
  const body = node.body;
1459
1479
  if (body.length > 0) {
1460
- context.write("\n");
1461
- context.writeNodeListWithNewLineSep(body);
1480
+ let lastRangeEnd: number | undefined;
1481
+ if (node.range) {
1482
+ lastRangeEnd = node.range[0] + 1;
1483
+ } else {
1484
+ context.write("\n");
1485
+ }
1486
+ context.writeNodeListWithNewLineSep(body, lastRangeEnd);
1462
1487
  context.write("\n");
1463
1488
  }
1464
1489
  context.write("}");
@@ -1471,8 +1496,13 @@ function printStaticBlock(
1471
1496
  context.write("static {");
1472
1497
  const body = node.body;
1473
1498
  if (body.length > 0) {
1474
- context.write("\n");
1475
- context.writeNodeListWithNewLineSep(body);
1499
+ let lastRangeEnd: number | undefined;
1500
+ if (node.range) {
1501
+ lastRangeEnd = node.range[0] + 1;
1502
+ } else {
1503
+ context.write("\n");
1504
+ }
1505
+ context.writeNodeListWithNewLineSep(body, lastRangeEnd);
1476
1506
  context.write("\n");
1477
1507
  }
1478
1508
  context.write("}");
@@ -2512,8 +2542,14 @@ function printTSModuleBlock(
2512
2542
  node: AST.TSModuleBlock,
2513
2543
  context: PrinterContext,
2514
2544
  ): void {
2515
- context.write("{\n");
2516
- context.writeNodeListWithNewLineSep(node.body);
2545
+ context.write("{");
2546
+ let lastRangeEnd: number | undefined;
2547
+ if (node.range) {
2548
+ lastRangeEnd = node.range[0] + 1;
2549
+ } else {
2550
+ context.write("\n");
2551
+ }
2552
+ context.writeNodeListWithNewLineSep(node.body, lastRangeEnd);
2517
2553
  context.write("\n}");
2518
2554
  }
2519
2555