@herb-tools/rewriter 0.9.2 → 0.9.4

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.cjs CHANGED
@@ -168,6 +168,9 @@ class Token {
168
168
  static from(token) {
169
169
  return new Token(token.value, Range.from(token.range), Location.from(token.location), token.type);
170
170
  }
171
+ static synthetic(value, type = "SYNTETHIC") {
172
+ return new Token(value, Range.zero, Location.zero, type);
173
+ }
171
174
  constructor(value, range, location, type) {
172
175
  this.value = value;
173
176
  this.range = range;
@@ -202,7 +205,7 @@ class Token {
202
205
  }
203
206
 
204
207
  // NOTE: This file is generated by the templates/template.rb script and should not
205
- // be modified manually. See /Users/marcoroth/Development/herb-release-0.9.2/templates/javascript/packages/core/src/errors.ts.erb
208
+ // be modified manually. See /Users/marcoroth/Development/herb-release-0.9.4/templates/javascript/packages/core/src/errors.ts.erb
206
209
  class HerbError {
207
210
  type;
208
211
  message;
@@ -1476,6 +1479,284 @@ class RenderLayoutWithoutBlockError extends HerbError {
1476
1479
  return output;
1477
1480
  }
1478
1481
  }
1482
+ class StrictLocalsPositionalArgumentError extends HerbError {
1483
+ name;
1484
+ static from(data) {
1485
+ return new StrictLocalsPositionalArgumentError({
1486
+ type: data.type,
1487
+ message: data.message,
1488
+ location: Location.from(data.location),
1489
+ name: data.name,
1490
+ });
1491
+ }
1492
+ constructor(props) {
1493
+ super(props.type, props.message, props.location);
1494
+ this.name = props.name;
1495
+ }
1496
+ toJSON() {
1497
+ return {
1498
+ ...super.toJSON(),
1499
+ type: "STRICT_LOCALS_POSITIONAL_ARGUMENT_ERROR",
1500
+ name: this.name,
1501
+ };
1502
+ }
1503
+ toMonacoDiagnostic() {
1504
+ return {
1505
+ line: this.location.start.line,
1506
+ column: this.location.start.column,
1507
+ endLine: this.location.end.line,
1508
+ endColumn: this.location.end.column,
1509
+ message: this.message,
1510
+ severity: 'error'
1511
+ };
1512
+ }
1513
+ treeInspect() {
1514
+ let output = "";
1515
+ output += `@ StrictLocalsPositionalArgumentError ${this.location.treeInspectWithLabel()}\n`;
1516
+ output += `├── message: "${this.message}"\n`;
1517
+ output += `└── name: ${JSON.stringify(this.name)}\n`;
1518
+ return output;
1519
+ }
1520
+ }
1521
+ class StrictLocalsBlockArgumentError extends HerbError {
1522
+ name;
1523
+ static from(data) {
1524
+ return new StrictLocalsBlockArgumentError({
1525
+ type: data.type,
1526
+ message: data.message,
1527
+ location: Location.from(data.location),
1528
+ name: data.name,
1529
+ });
1530
+ }
1531
+ constructor(props) {
1532
+ super(props.type, props.message, props.location);
1533
+ this.name = props.name;
1534
+ }
1535
+ toJSON() {
1536
+ return {
1537
+ ...super.toJSON(),
1538
+ type: "STRICT_LOCALS_BLOCK_ARGUMENT_ERROR",
1539
+ name: this.name,
1540
+ };
1541
+ }
1542
+ toMonacoDiagnostic() {
1543
+ return {
1544
+ line: this.location.start.line,
1545
+ column: this.location.start.column,
1546
+ endLine: this.location.end.line,
1547
+ endColumn: this.location.end.column,
1548
+ message: this.message,
1549
+ severity: 'error'
1550
+ };
1551
+ }
1552
+ treeInspect() {
1553
+ let output = "";
1554
+ output += `@ StrictLocalsBlockArgumentError ${this.location.treeInspectWithLabel()}\n`;
1555
+ output += `├── message: "${this.message}"\n`;
1556
+ output += `└── name: ${JSON.stringify(this.name)}\n`;
1557
+ return output;
1558
+ }
1559
+ }
1560
+ class StrictLocalsSplatArgumentError extends HerbError {
1561
+ name;
1562
+ static from(data) {
1563
+ return new StrictLocalsSplatArgumentError({
1564
+ type: data.type,
1565
+ message: data.message,
1566
+ location: Location.from(data.location),
1567
+ name: data.name,
1568
+ });
1569
+ }
1570
+ constructor(props) {
1571
+ super(props.type, props.message, props.location);
1572
+ this.name = props.name;
1573
+ }
1574
+ toJSON() {
1575
+ return {
1576
+ ...super.toJSON(),
1577
+ type: "STRICT_LOCALS_SPLAT_ARGUMENT_ERROR",
1578
+ name: this.name,
1579
+ };
1580
+ }
1581
+ toMonacoDiagnostic() {
1582
+ return {
1583
+ line: this.location.start.line,
1584
+ column: this.location.start.column,
1585
+ endLine: this.location.end.line,
1586
+ endColumn: this.location.end.column,
1587
+ message: this.message,
1588
+ severity: 'error'
1589
+ };
1590
+ }
1591
+ treeInspect() {
1592
+ let output = "";
1593
+ output += `@ StrictLocalsSplatArgumentError ${this.location.treeInspectWithLabel()}\n`;
1594
+ output += `├── message: "${this.message}"\n`;
1595
+ output += `└── name: ${JSON.stringify(this.name)}\n`;
1596
+ return output;
1597
+ }
1598
+ }
1599
+ class StrictLocalsMissingParenthesisError extends HerbError {
1600
+ rest;
1601
+ static from(data) {
1602
+ return new StrictLocalsMissingParenthesisError({
1603
+ type: data.type,
1604
+ message: data.message,
1605
+ location: Location.from(data.location),
1606
+ rest: data.rest,
1607
+ });
1608
+ }
1609
+ constructor(props) {
1610
+ super(props.type, props.message, props.location);
1611
+ this.rest = props.rest;
1612
+ }
1613
+ toJSON() {
1614
+ return {
1615
+ ...super.toJSON(),
1616
+ type: "STRICT_LOCALS_MISSING_PARENTHESIS_ERROR",
1617
+ rest: this.rest,
1618
+ };
1619
+ }
1620
+ toMonacoDiagnostic() {
1621
+ return {
1622
+ line: this.location.start.line,
1623
+ column: this.location.start.column,
1624
+ endLine: this.location.end.line,
1625
+ endColumn: this.location.end.column,
1626
+ message: this.message,
1627
+ severity: 'error'
1628
+ };
1629
+ }
1630
+ treeInspect() {
1631
+ let output = "";
1632
+ output += `@ StrictLocalsMissingParenthesisError ${this.location.treeInspectWithLabel()}\n`;
1633
+ output += `├── message: "${this.message}"\n`;
1634
+ output += `└── rest: ${JSON.stringify(this.rest)}\n`;
1635
+ return output;
1636
+ }
1637
+ }
1638
+ class StrictLocalsDuplicateDeclarationError extends HerbError {
1639
+ static from(data) {
1640
+ return new StrictLocalsDuplicateDeclarationError({
1641
+ type: data.type,
1642
+ message: data.message,
1643
+ location: Location.from(data.location),
1644
+ });
1645
+ }
1646
+ constructor(props) {
1647
+ super(props.type, props.message, props.location);
1648
+ }
1649
+ toJSON() {
1650
+ return {
1651
+ ...super.toJSON(),
1652
+ type: "STRICT_LOCALS_DUPLICATE_DECLARATION_ERROR",
1653
+ };
1654
+ }
1655
+ toMonacoDiagnostic() {
1656
+ return {
1657
+ line: this.location.start.line,
1658
+ column: this.location.start.column,
1659
+ endLine: this.location.end.line,
1660
+ endColumn: this.location.end.column,
1661
+ message: this.message,
1662
+ severity: 'error'
1663
+ };
1664
+ }
1665
+ treeInspect() {
1666
+ let output = "";
1667
+ output += `@ StrictLocalsDuplicateDeclarationError ${this.location.treeInspectWithLabel()}\n`;
1668
+ output += `└── message: "${this.message}"\n`;
1669
+ return output;
1670
+ }
1671
+ }
1672
+ class VoidElementContentError extends HerbError {
1673
+ tag_name;
1674
+ helper_name;
1675
+ content_type;
1676
+ static from(data) {
1677
+ return new VoidElementContentError({
1678
+ type: data.type,
1679
+ message: data.message,
1680
+ location: Location.from(data.location),
1681
+ tag_name: data.tag_name ? Token.from(data.tag_name) : null,
1682
+ helper_name: data.helper_name,
1683
+ content_type: data.content_type,
1684
+ });
1685
+ }
1686
+ constructor(props) {
1687
+ super(props.type, props.message, props.location);
1688
+ this.tag_name = props.tag_name;
1689
+ this.helper_name = props.helper_name;
1690
+ this.content_type = props.content_type;
1691
+ }
1692
+ toJSON() {
1693
+ return {
1694
+ ...super.toJSON(),
1695
+ type: "VOID_ELEMENT_CONTENT_ERROR",
1696
+ tag_name: this.tag_name ? this.tag_name.toJSON() : null,
1697
+ helper_name: this.helper_name,
1698
+ content_type: this.content_type,
1699
+ };
1700
+ }
1701
+ toMonacoDiagnostic() {
1702
+ return {
1703
+ line: this.location.start.line,
1704
+ column: this.location.start.column,
1705
+ endLine: this.location.end.line,
1706
+ endColumn: this.location.end.column,
1707
+ message: this.message,
1708
+ severity: 'error'
1709
+ };
1710
+ }
1711
+ treeInspect() {
1712
+ let output = "";
1713
+ output += `@ VoidElementContentError ${this.location.treeInspectWithLabel()}\n`;
1714
+ output += `├── message: "${this.message}"\n`;
1715
+ output += `├── tag_name: ${this.tag_name ? this.tag_name.treeInspect() : "∅"}\n`;
1716
+ output += `├── helper_name: ${JSON.stringify(this.helper_name)}\n`;
1717
+ output += `└── content_type: ${JSON.stringify(this.content_type)}\n`;
1718
+ return output;
1719
+ }
1720
+ }
1721
+ class DotNotationCasingError extends HerbError {
1722
+ segment;
1723
+ static from(data) {
1724
+ return new DotNotationCasingError({
1725
+ type: data.type,
1726
+ message: data.message,
1727
+ location: Location.from(data.location),
1728
+ segment: data.segment ? Token.from(data.segment) : null,
1729
+ });
1730
+ }
1731
+ constructor(props) {
1732
+ super(props.type, props.message, props.location);
1733
+ this.segment = props.segment;
1734
+ }
1735
+ toJSON() {
1736
+ return {
1737
+ ...super.toJSON(),
1738
+ type: "DOT_NOTATION_CASING_ERROR",
1739
+ segment: this.segment ? this.segment.toJSON() : null,
1740
+ };
1741
+ }
1742
+ toMonacoDiagnostic() {
1743
+ return {
1744
+ line: this.location.start.line,
1745
+ column: this.location.start.column,
1746
+ endLine: this.location.end.line,
1747
+ endColumn: this.location.end.column,
1748
+ message: this.message,
1749
+ severity: 'error'
1750
+ };
1751
+ }
1752
+ treeInspect() {
1753
+ let output = "";
1754
+ output += `@ DotNotationCasingError ${this.location.treeInspectWithLabel()}\n`;
1755
+ output += `├── message: "${this.message}"\n`;
1756
+ output += `└── segment: ${this.segment ? this.segment.treeInspect() : "∅"}\n`;
1757
+ return output;
1758
+ }
1759
+ }
1479
1760
  function fromSerializedError(error) {
1480
1761
  switch (error.type) {
1481
1762
  case "UNEXPECTED_ERROR": return UnexpectedError.from(error);
@@ -1508,6 +1789,13 @@ function fromSerializedError(error) {
1508
1789
  case "RENDER_INVALID_AS_OPTION_ERROR": return RenderInvalidAsOptionError.from(error);
1509
1790
  case "RENDER_OBJECT_AND_COLLECTION_ERROR": return RenderObjectAndCollectionError.from(error);
1510
1791
  case "RENDER_LAYOUT_WITHOUT_BLOCK_ERROR": return RenderLayoutWithoutBlockError.from(error);
1792
+ case "STRICT_LOCALS_POSITIONAL_ARGUMENT_ERROR": return StrictLocalsPositionalArgumentError.from(error);
1793
+ case "STRICT_LOCALS_BLOCK_ARGUMENT_ERROR": return StrictLocalsBlockArgumentError.from(error);
1794
+ case "STRICT_LOCALS_SPLAT_ARGUMENT_ERROR": return StrictLocalsSplatArgumentError.from(error);
1795
+ case "STRICT_LOCALS_MISSING_PARENTHESIS_ERROR": return StrictLocalsMissingParenthesisError.from(error);
1796
+ case "STRICT_LOCALS_DUPLICATE_DECLARATION_ERROR": return StrictLocalsDuplicateDeclarationError.from(error);
1797
+ case "VOID_ELEMENT_CONTENT_ERROR": return VoidElementContentError.from(error);
1798
+ case "DOT_NOTATION_CASING_ERROR": return DotNotationCasingError.from(error);
1511
1799
  default:
1512
1800
  throw new Error(`Unknown node type: ${error.type}`);
1513
1801
  }
@@ -20096,7 +20384,7 @@ function deserializePrismNode(bytes, source) {
20096
20384
  }
20097
20385
 
20098
20386
  // NOTE: This file is generated by the templates/template.rb script and should not
20099
- // be modified manually. See /Users/marcoroth/Development/herb-release-0.9.2/templates/javascript/packages/core/src/nodes.ts.erb
20387
+ // be modified manually. See /Users/marcoroth/Development/herb-release-0.9.4/templates/javascript/packages/core/src/nodes.ts.erb
20100
20388
  class Node {
20101
20389
  type;
20102
20390
  location;
@@ -21717,6 +22005,9 @@ class ERBBlockNode extends Node {
21717
22005
  tag_closing;
21718
22006
  prism_node;
21719
22007
  body;
22008
+ rescue_clause;
22009
+ else_clause;
22010
+ ensure_clause;
21720
22011
  end_node;
21721
22012
  static get type() {
21722
22013
  return "AST_ERB_BLOCK_NODE";
@@ -21731,6 +22022,9 @@ class ERBBlockNode extends Node {
21731
22022
  tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
21732
22023
  prism_node: data.prism_node ? new Uint8Array(data.prism_node) : null,
21733
22024
  body: (data.body || []).map(node => fromSerializedNode(node)),
22025
+ rescue_clause: data.rescue_clause ? fromSerializedNode((data.rescue_clause)) : null,
22026
+ else_clause: data.else_clause ? fromSerializedNode((data.else_clause)) : null,
22027
+ ensure_clause: data.ensure_clause ? fromSerializedNode((data.ensure_clause)) : null,
21734
22028
  end_node: data.end_node ? fromSerializedNode((data.end_node)) : null,
21735
22029
  });
21736
22030
  }
@@ -21741,6 +22035,9 @@ class ERBBlockNode extends Node {
21741
22035
  this.tag_closing = props.tag_closing;
21742
22036
  this.prism_node = props.prism_node;
21743
22037
  this.body = props.body;
22038
+ this.rescue_clause = props.rescue_clause;
22039
+ this.else_clause = props.else_clause;
22040
+ this.ensure_clause = props.ensure_clause;
21744
22041
  this.end_node = props.end_node;
21745
22042
  }
21746
22043
  accept(visitor) {
@@ -21749,6 +22046,9 @@ class ERBBlockNode extends Node {
21749
22046
  childNodes() {
21750
22047
  return [
21751
22048
  ...this.body,
22049
+ this.rescue_clause,
22050
+ this.else_clause,
22051
+ this.ensure_clause,
21752
22052
  this.end_node,
21753
22053
  ];
21754
22054
  }
@@ -21764,6 +22064,9 @@ class ERBBlockNode extends Node {
21764
22064
  return [
21765
22065
  ...this.errors,
21766
22066
  ...this.body.map(node => node.recursiveErrors()),
22067
+ this.rescue_clause ? this.rescue_clause.recursiveErrors() : [],
22068
+ this.else_clause ? this.else_clause.recursiveErrors() : [],
22069
+ this.ensure_clause ? this.ensure_clause.recursiveErrors() : [],
21767
22070
  this.end_node ? this.end_node.recursiveErrors() : [],
21768
22071
  ].flat();
21769
22072
  }
@@ -21776,6 +22079,9 @@ class ERBBlockNode extends Node {
21776
22079
  tag_closing: this.tag_closing ? this.tag_closing.toJSON() : null,
21777
22080
  prism_node: this.prism_node ? Array.from(this.prism_node) : null,
21778
22081
  body: this.body.map(node => node.toJSON()),
22082
+ rescue_clause: this.rescue_clause ? this.rescue_clause.toJSON() : null,
22083
+ else_clause: this.else_clause ? this.else_clause.toJSON() : null,
22084
+ ensure_clause: this.ensure_clause ? this.ensure_clause.toJSON() : null,
21779
22085
  end_node: this.end_node ? this.end_node.toJSON() : null,
21780
22086
  };
21781
22087
  }
@@ -21790,6 +22096,9 @@ class ERBBlockNode extends Node {
21790
22096
  output += `├── prism_node: ${this.source ? inspectPrismSerialized(this.prism_node, this.source, "│ ") : `(${this.prism_node.length} bytes)`}\n`;
21791
22097
  }
21792
22098
  output += `├── body: ${this.inspectArray(this.body, "│ ")}`;
22099
+ output += `├── rescue_clause: ${this.inspectNode(this.rescue_clause, "│ ")}`;
22100
+ output += `├── else_clause: ${this.inspectNode(this.else_clause, "│ ")}`;
22101
+ output += `├── ensure_clause: ${this.inspectNode(this.ensure_clause, "│ ")}`;
21793
22102
  output += `└── end_node: ${this.inspectNode(this.end_node, " ")}`;
21794
22103
  return output;
21795
22104
  }
@@ -22859,6 +23168,150 @@ class ERBRenderNode extends Node {
22859
23168
  return output;
22860
23169
  }
22861
23170
  }
23171
+ class RubyStrictLocalNode extends Node {
23172
+ name;
23173
+ default_value;
23174
+ required;
23175
+ double_splat;
23176
+ static get type() {
23177
+ return "AST_RUBY_STRICT_LOCAL_NODE";
23178
+ }
23179
+ static from(data) {
23180
+ return new RubyStrictLocalNode({
23181
+ type: data.type,
23182
+ location: Location.from(data.location),
23183
+ errors: (data.errors || []).map(error => HerbError.from(error)),
23184
+ name: data.name ? Token.from(data.name) : null,
23185
+ default_value: data.default_value ? fromSerializedNode((data.default_value)) : null,
23186
+ required: data.required,
23187
+ double_splat: data.double_splat,
23188
+ });
23189
+ }
23190
+ constructor(props) {
23191
+ super(props.type, props.location, props.errors);
23192
+ this.name = props.name;
23193
+ this.default_value = props.default_value;
23194
+ this.required = props.required;
23195
+ this.double_splat = props.double_splat;
23196
+ }
23197
+ accept(visitor) {
23198
+ visitor.visitRubyStrictLocalNode(this);
23199
+ }
23200
+ childNodes() {
23201
+ return [
23202
+ this.default_value,
23203
+ ];
23204
+ }
23205
+ compactChildNodes() {
23206
+ return this.childNodes().filter(node => node !== null && node !== undefined);
23207
+ }
23208
+ recursiveErrors() {
23209
+ return [
23210
+ ...this.errors,
23211
+ this.default_value ? this.default_value.recursiveErrors() : [],
23212
+ ].flat();
23213
+ }
23214
+ toJSON() {
23215
+ return {
23216
+ ...super.toJSON(),
23217
+ type: "AST_RUBY_STRICT_LOCAL_NODE",
23218
+ name: this.name ? this.name.toJSON() : null,
23219
+ default_value: this.default_value ? this.default_value.toJSON() : null,
23220
+ required: this.required,
23221
+ double_splat: this.double_splat,
23222
+ };
23223
+ }
23224
+ treeInspect() {
23225
+ let output = "";
23226
+ output += `@ RubyStrictLocalNode ${this.location.treeInspectWithLabel()}\n`;
23227
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
23228
+ output += `├── name: ${this.name ? this.name.treeInspect() : "∅"}\n`;
23229
+ output += `├── default_value: ${this.inspectNode(this.default_value, "│ ")}`;
23230
+ output += `├── required: ${typeof this.required === 'boolean' ? String(this.required) : "∅"}\n`;
23231
+ output += `└── double_splat: ${typeof this.double_splat === 'boolean' ? String(this.double_splat) : "∅"}\n`;
23232
+ return output;
23233
+ }
23234
+ }
23235
+ class ERBStrictLocalsNode extends Node {
23236
+ tag_opening;
23237
+ content;
23238
+ tag_closing;
23239
+ // no-op for analyzed_ruby
23240
+ prism_node;
23241
+ locals;
23242
+ static get type() {
23243
+ return "AST_ERB_STRICT_LOCALS_NODE";
23244
+ }
23245
+ static from(data) {
23246
+ return new ERBStrictLocalsNode({
23247
+ type: data.type,
23248
+ location: Location.from(data.location),
23249
+ errors: (data.errors || []).map(error => HerbError.from(error)),
23250
+ tag_opening: data.tag_opening ? Token.from(data.tag_opening) : null,
23251
+ content: data.content ? Token.from(data.content) : null,
23252
+ tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
23253
+ // no-op for analyzed_ruby
23254
+ prism_node: data.prism_node ? new Uint8Array(data.prism_node) : null,
23255
+ locals: (data.locals || []).map(node => fromSerializedNode(node)),
23256
+ });
23257
+ }
23258
+ constructor(props) {
23259
+ super(props.type, props.location, props.errors);
23260
+ this.tag_opening = props.tag_opening;
23261
+ this.content = props.content;
23262
+ this.tag_closing = props.tag_closing;
23263
+ // no-op for analyzed_ruby
23264
+ this.prism_node = props.prism_node;
23265
+ this.locals = props.locals;
23266
+ }
23267
+ accept(visitor) {
23268
+ visitor.visitERBStrictLocalsNode(this);
23269
+ }
23270
+ childNodes() {
23271
+ return [
23272
+ ...this.locals,
23273
+ ];
23274
+ }
23275
+ compactChildNodes() {
23276
+ return this.childNodes().filter(node => node !== null && node !== undefined);
23277
+ }
23278
+ get prismNode() {
23279
+ if (!this.prism_node || !this.source)
23280
+ return null;
23281
+ return deserializePrismNode(this.prism_node, this.source);
23282
+ }
23283
+ recursiveErrors() {
23284
+ return [
23285
+ ...this.errors,
23286
+ ...this.locals.map(node => node.recursiveErrors()),
23287
+ ].flat();
23288
+ }
23289
+ toJSON() {
23290
+ return {
23291
+ ...super.toJSON(),
23292
+ type: "AST_ERB_STRICT_LOCALS_NODE",
23293
+ tag_opening: this.tag_opening ? this.tag_opening.toJSON() : null,
23294
+ content: this.content ? this.content.toJSON() : null,
23295
+ tag_closing: this.tag_closing ? this.tag_closing.toJSON() : null,
23296
+ // no-op for analyzed_ruby
23297
+ prism_node: this.prism_node ? Array.from(this.prism_node) : null,
23298
+ locals: this.locals.map(node => node.toJSON()),
23299
+ };
23300
+ }
23301
+ treeInspect() {
23302
+ let output = "";
23303
+ output += `@ ERBStrictLocalsNode ${this.location.treeInspectWithLabel()}\n`;
23304
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
23305
+ output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
23306
+ output += `├── content: ${this.content ? this.content.treeInspect() : "∅"}\n`;
23307
+ output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
23308
+ if (this.prism_node) {
23309
+ output += `├── prism_node: ${this.source ? inspectPrismSerialized(this.prism_node, this.source, "│ ") : `(${this.prism_node.length} bytes)`}\n`;
23310
+ }
23311
+ output += `└── locals: ${this.inspectArray(this.locals, " ")}`;
23312
+ return output;
23313
+ }
23314
+ }
22862
23315
  class ERBYieldNode extends Node {
22863
23316
  tag_opening;
22864
23317
  content;
@@ -23024,6 +23477,8 @@ function fromSerializedNode(node) {
23024
23477
  case "AST_ERB_UNLESS_NODE": return ERBUnlessNode.from(node);
23025
23478
  case "AST_RUBY_RENDER_LOCAL_NODE": return RubyRenderLocalNode.from(node);
23026
23479
  case "AST_ERB_RENDER_NODE": return ERBRenderNode.from(node);
23480
+ case "AST_RUBY_STRICT_LOCAL_NODE": return RubyStrictLocalNode.from(node);
23481
+ case "AST_ERB_STRICT_LOCALS_NODE": return ERBStrictLocalsNode.from(node);
23027
23482
  case "AST_ERB_YIELD_NODE": return ERBYieldNode.from(node);
23028
23483
  case "AST_ERB_IN_NODE": return ERBInNode.from(node);
23029
23484
  default:
@@ -23074,9 +23529,12 @@ const DEFAULT_PARSER_OPTIONS = {
23074
23529
  strict: true,
23075
23530
  action_view_helpers: false,
23076
23531
  render_nodes: false,
23532
+ strict_locals: false,
23077
23533
  prism_nodes: false,
23078
23534
  prism_nodes_deep: false,
23079
23535
  prism_program: false,
23536
+ dot_notation_tags: false,
23537
+ html: true,
23080
23538
  };
23081
23539
  /**
23082
23540
  * Represents the parser options used during parsing.
@@ -23092,12 +23550,18 @@ class ParserOptions {
23092
23550
  action_view_helpers;
23093
23551
  /** Whether ActionView render call detection was enabled during parsing. */
23094
23552
  render_nodes;
23553
+ /** Whether strict locals analysis was enabled during parsing. */
23554
+ strict_locals;
23095
23555
  /** Whether Prism node serialization was enabled during parsing. */
23096
23556
  prism_nodes;
23097
23557
  /** Whether deep Prism node serialization was enabled during parsing. */
23098
23558
  prism_nodes_deep;
23099
23559
  /** Whether the full Prism ProgramNode was serialized on the DocumentNode. */
23100
23560
  prism_program;
23561
+ /** Whether dot-notation component tags (e.g. Dialog.Button) are parsed as HTML elements. */
23562
+ dot_notation_tags;
23563
+ /** Whether HTML tag parsing is enabled during parsing. When false, HTML-like content is treated as literal text. */
23564
+ html;
23101
23565
  static from(options) {
23102
23566
  return new ParserOptions(options);
23103
23567
  }
@@ -23107,9 +23571,12 @@ class ParserOptions {
23107
23571
  this.analyze = options.analyze ?? DEFAULT_PARSER_OPTIONS.analyze;
23108
23572
  this.action_view_helpers = options.action_view_helpers ?? DEFAULT_PARSER_OPTIONS.action_view_helpers;
23109
23573
  this.render_nodes = options.render_nodes ?? DEFAULT_PARSER_OPTIONS.render_nodes;
23574
+ this.strict_locals = options.strict_locals ?? DEFAULT_PARSER_OPTIONS.strict_locals;
23110
23575
  this.prism_nodes = options.prism_nodes ?? DEFAULT_PARSER_OPTIONS.prism_nodes;
23111
23576
  this.prism_nodes_deep = options.prism_nodes_deep ?? DEFAULT_PARSER_OPTIONS.prism_nodes_deep;
23112
23577
  this.prism_program = options.prism_program ?? DEFAULT_PARSER_OPTIONS.prism_program;
23578
+ this.dot_notation_tags = options.dot_notation_tags ?? DEFAULT_PARSER_OPTIONS.dot_notation_tags;
23579
+ this.html = options.html ?? DEFAULT_PARSER_OPTIONS.html;
23113
23580
  }
23114
23581
  }
23115
23582
 
@@ -23186,7 +23653,7 @@ class ParseResult extends Result {
23186
23653
  }
23187
23654
 
23188
23655
  // NOTE: This file is generated by the templates/template.rb script and should not
23189
- // be modified manually. See /Users/marcoroth/Development/herb-release-0.9.2/templates/javascript/packages/core/src/node-type-guards.ts.erb
23656
+ // be modified manually. See /Users/marcoroth/Development/herb-release-0.9.4/templates/javascript/packages/core/src/node-type-guards.ts.erb
23190
23657
  /**
23191
23658
  * Type guard functions for AST nodes.
23192
23659
  * These functions provide type checking by combining both instanceof
@@ -23497,6 +23964,22 @@ function isERBRenderNode(node) {
23497
23964
  return false;
23498
23965
  return node instanceof ERBRenderNode || node.type === "AST_ERB_RENDER_NODE" || node.constructor.type === "AST_ERB_RENDER_NODE";
23499
23966
  }
23967
+ /**
23968
+ * Checks if a node is a RubyStrictLocalNode
23969
+ */
23970
+ function isRubyStrictLocalNode(node) {
23971
+ if (!node)
23972
+ return false;
23973
+ return node instanceof RubyStrictLocalNode || node.type === "AST_RUBY_STRICT_LOCAL_NODE" || node.constructor.type === "AST_RUBY_STRICT_LOCAL_NODE";
23974
+ }
23975
+ /**
23976
+ * Checks if a node is a ERBStrictLocalsNode
23977
+ */
23978
+ function isERBStrictLocalsNode(node) {
23979
+ if (!node)
23980
+ return false;
23981
+ return node instanceof ERBStrictLocalsNode || node.type === "AST_ERB_STRICT_LOCALS_NODE" || node.constructor.type === "AST_ERB_STRICT_LOCALS_NODE";
23982
+ }
23500
23983
  /**
23501
23984
  * Checks if a node is a ERBYieldNode
23502
23985
  */
@@ -23513,6 +23996,31 @@ function isERBInNode(node) {
23513
23996
  return false;
23514
23997
  return node instanceof ERBInNode || node.type === "AST_ERB_IN_NODE" || node.constructor.type === "AST_ERB_IN_NODE";
23515
23998
  }
23999
+ /**
24000
+ * Checks if a node is any ERB node type
24001
+ */
24002
+ function isERBNode(node) {
24003
+ return isERBOpenTagNode(node) ||
24004
+ isERBContentNode(node) ||
24005
+ isERBEndNode(node) ||
24006
+ isERBElseNode(node) ||
24007
+ isERBIfNode(node) ||
24008
+ isERBBlockNode(node) ||
24009
+ isERBWhenNode(node) ||
24010
+ isERBCaseNode(node) ||
24011
+ isERBCaseMatchNode(node) ||
24012
+ isERBWhileNode(node) ||
24013
+ isERBUntilNode(node) ||
24014
+ isERBForNode(node) ||
24015
+ isERBRescueNode(node) ||
24016
+ isERBEnsureNode(node) ||
24017
+ isERBBeginNode(node) ||
24018
+ isERBUnlessNode(node) ||
24019
+ isERBRenderNode(node) ||
24020
+ isERBStrictLocalsNode(node) ||
24021
+ isERBYieldNode(node) ||
24022
+ isERBInNode(node);
24023
+ }
23516
24024
  /**
23517
24025
  * Map of node classes to their corresponding type guard functions
23518
24026
  *
@@ -23562,6 +24070,8 @@ const NODE_TYPE_GUARDS = new Map([
23562
24070
  [ERBUnlessNode, isERBUnlessNode],
23563
24071
  [RubyRenderLocalNode, isRubyRenderLocalNode],
23564
24072
  [ERBRenderNode, isERBRenderNode],
24073
+ [RubyStrictLocalNode, isRubyStrictLocalNode],
24074
+ [ERBStrictLocalsNode, isERBStrictLocalsNode],
23565
24075
  [ERBYieldNode, isERBYieldNode],
23566
24076
  [ERBInNode, isERBInNode],
23567
24077
  ]);
@@ -23614,6 +24124,8 @@ const AST_TYPE_GUARDS = new Map([
23614
24124
  ["AST_ERB_UNLESS_NODE", isERBUnlessNode],
23615
24125
  ["AST_RUBY_RENDER_LOCAL_NODE", isRubyRenderLocalNode],
23616
24126
  ["AST_ERB_RENDER_NODE", isERBRenderNode],
24127
+ ["AST_RUBY_STRICT_LOCAL_NODE", isRubyStrictLocalNode],
24128
+ ["AST_ERB_STRICT_LOCALS_NODE", isERBStrictLocalsNode],
23617
24129
  ["AST_ERB_YIELD_NODE", isERBYieldNode],
23618
24130
  ["AST_ERB_IN_NODE", isERBInNode],
23619
24131
  ]);
@@ -23671,6 +24183,17 @@ function isToken(object) {
23671
24183
  function isParseResult(object) {
23672
24184
  return (object instanceof ParseResult) || (object?.constructor?.name === "ParseResult" && "value" in object);
23673
24185
  }
24186
+
24187
+ /**
24188
+ * Checks if a node is an ERB output node (generates content: <%= %> or <%== %>)
24189
+ */
24190
+ function isERBOutputNode(node) {
24191
+ if (!isERBNode(node))
24192
+ return false;
24193
+ if (!node.tag_opening?.value)
24194
+ return false;
24195
+ return ["<%=", "<%=="].includes(node.tag_opening?.value);
24196
+ }
23674
24197
  /**
23675
24198
  * Extracts a static string from an array of literal nodes
23676
24199
  * Returns null if any node is not a literal node
@@ -23730,12 +24253,88 @@ function getNodesBeforePosition(nodes, position, inclusive = false) {
23730
24253
  function getNodesAfterPosition(nodes, position, inclusive = true) {
23731
24254
  return nodes.filter(node => node.location && isPositionAfter(node.location.start, position, inclusive));
23732
24255
  }
24256
+ // --- AST Mutation Utilities ---
24257
+ const CHILD_ARRAY_PROPS = ["children", "body", "statements", "conditions"];
24258
+ const LINKED_NODE_PROPS = ["subsequent", "else_clause"];
24259
+ /**
24260
+ * Finds the array containing a target node in the AST, along with its index.
24261
+ * Traverses child arrays and linked node properties (e.g., `subsequent`, `else_clause`).
24262
+ *
24263
+ * Useful for autofix operations that need to splice nodes in/out of their parent array.
24264
+ *
24265
+ * @param root - The root node to search from
24266
+ * @param target - The node to find
24267
+ * @returns The containing array and the target's index, or null if not found
24268
+ */
24269
+ function findParentArray(root, target) {
24270
+ const search = (node) => {
24271
+ const record = node;
24272
+ for (const prop of CHILD_ARRAY_PROPS) {
24273
+ const array = record[prop];
24274
+ if (Array.isArray(array)) {
24275
+ const index = array.indexOf(target);
24276
+ if (index !== -1) {
24277
+ return { array, index };
24278
+ }
24279
+ }
24280
+ }
24281
+ for (const prop of CHILD_ARRAY_PROPS) {
24282
+ const array = record[prop];
24283
+ if (Array.isArray(array)) {
24284
+ for (const child of array) {
24285
+ if (child && typeof child === 'object' && 'type' in child) {
24286
+ const result = search(child);
24287
+ if (result) {
24288
+ return result;
24289
+ }
24290
+ }
24291
+ }
24292
+ }
24293
+ }
24294
+ for (const prop of LINKED_NODE_PROPS) {
24295
+ const value = record[prop];
24296
+ if (value && typeof value === 'object' && 'type' in value) {
24297
+ const result = search(value);
24298
+ if (result) {
24299
+ return result;
24300
+ }
24301
+ }
24302
+ }
24303
+ return null;
24304
+ };
24305
+ return search(root);
24306
+ }
24307
+ /**
24308
+ * Creates a synthetic LiteralNode with the given content and zero location.
24309
+ * Useful for inserting whitespace or newlines during AST mutations.
24310
+ */
24311
+ function createLiteral(content) {
24312
+ return new LiteralNode({
24313
+ type: "AST_LITERAL_NODE",
24314
+ content,
24315
+ location: Location.zero,
24316
+ errors: [],
24317
+ });
24318
+ }
23733
24319
  function createSyntheticToken(value, type = "TOKEN_SYNTHETIC") {
23734
24320
  return new Token(value, Range.zero, Location.zero, type);
23735
24321
  }
24322
+ function createERBOutputNode(expression, tagOpening = "<%=", tagClosing = "%>") {
24323
+ return new ERBContentNode({
24324
+ type: "AST_ERB_CONTENT_NODE",
24325
+ tag_opening: createSyntheticToken(tagOpening),
24326
+ content: createSyntheticToken(expression),
24327
+ tag_closing: createSyntheticToken(tagClosing),
24328
+ parsed: false,
24329
+ valid: true,
24330
+ prism_node: null,
24331
+ location: Location.zero,
24332
+ errors: [],
24333
+ });
24334
+ }
23736
24335
 
23737
24336
  // NOTE: This file is generated by the templates/template.rb script and should not
23738
- // be modified manually. See /Users/marcoroth/Development/herb-release-0.9.2/templates/javascript/packages/core/src/visitor.ts.erb
24337
+ // be modified manually. See /Users/marcoroth/Development/herb-release-0.9.4/templates/javascript/packages/core/src/visitor.ts.erb
23739
24338
  class Visitor {
23740
24339
  visit(node) {
23741
24340
  if (!node)
@@ -23923,6 +24522,15 @@ class Visitor {
23923
24522
  this.visitERBNode(node);
23924
24523
  this.visitChildNodes(node);
23925
24524
  }
24525
+ visitRubyStrictLocalNode(node) {
24526
+ this.visitNode(node);
24527
+ this.visitChildNodes(node);
24528
+ }
24529
+ visitERBStrictLocalsNode(node) {
24530
+ this.visitNode(node);
24531
+ this.visitERBNode(node);
24532
+ this.visitChildNodes(node);
24533
+ }
23926
24534
  visitERBYieldNode(node) {
23927
24535
  this.visitNode(node);
23928
24536
  this.visitERBNode(node);
@@ -23955,6 +24563,34 @@ function createWhitespaceNode() {
23955
24563
  });
23956
24564
  }
23957
24565
  class ActionViewTagHelperToHTMLVisitor extends Visitor {
24566
+ shallow;
24567
+ includeBody;
24568
+ constructor(options = {}) {
24569
+ super();
24570
+ this.shallow = options.shallow ?? false;
24571
+ this.includeBody = options.includeBody ?? true;
24572
+ }
24573
+ visitHTMLOpenTagNode(node) {
24574
+ const newChildren = [];
24575
+ for (let index = 0; index < node.children.length; index++) {
24576
+ const child = node.children[index];
24577
+ if (isHTMLAttributeNode(child)) {
24578
+ if (child.equals && child.equals.value !== "=") {
24579
+ asMutable(child).equals = createSyntheticToken("=");
24580
+ }
24581
+ if (child.value) {
24582
+ this.transformAttributeValue(child.value);
24583
+ }
24584
+ const previous = index > 0 ? node.children[index - 1] : null;
24585
+ if (!previous || !isWhitespaceNode(previous)) {
24586
+ newChildren.push(createWhitespaceNode());
24587
+ }
24588
+ }
24589
+ newChildren.push(child);
24590
+ }
24591
+ asMutable(node).children = newChildren;
24592
+ this.visitChildNodes(node);
24593
+ }
23958
24594
  visitHTMLElementNode(node) {
23959
24595
  if (!node.element_source) {
23960
24596
  this.visitChildNodes(node);
@@ -24025,7 +24661,10 @@ class ActionViewTagHelperToHTMLVisitor extends Visitor {
24025
24661
  asMutable(node).close_tag = htmlCloseTag;
24026
24662
  }
24027
24663
  asMutable(node).element_source = "HTML";
24028
- if (node.body) {
24664
+ if (!this.includeBody) {
24665
+ asMutable(node).body = [];
24666
+ }
24667
+ else if (node.body) {
24029
24668
  asMutable(node).body = node.body.map(child => {
24030
24669
  if (isRubyLiteralNode(child)) {
24031
24670
  return new ERBContentNode({
@@ -24040,7 +24679,9 @@ class ActionViewTagHelperToHTMLVisitor extends Visitor {
24040
24679
  prism_node: null
24041
24680
  });
24042
24681
  }
24043
- this.visit(child);
24682
+ if (!this.shallow) {
24683
+ this.visit(child);
24684
+ }
24044
24685
  return child;
24045
24686
  });
24046
24687
  }
@@ -24066,11 +24707,11 @@ class ActionViewTagHelperToHTMLVisitor extends Visitor {
24066
24707
  return child;
24067
24708
  });
24068
24709
  mutableValue.children = newChildren;
24069
- if (!value.quoted) {
24070
- mutableValue.quoted = true;
24071
- mutableValue.open_quote = createSyntheticToken('"');
24072
- mutableValue.close_quote = createSyntheticToken('"');
24073
- }
24710
+ }
24711
+ if (!value.quoted) {
24712
+ mutableValue.quoted = true;
24713
+ mutableValue.open_quote = createSyntheticToken('"');
24714
+ mutableValue.close_quote = createSyntheticToken('"');
24074
24715
  }
24075
24716
  }
24076
24717
  }
@@ -24081,11 +24722,132 @@ class ActionViewTagHelperToHTMLRewriter extends ASTRewriter {
24081
24722
  get description() {
24082
24723
  return "Converts ActionView tag helpers to raw HTML elements";
24083
24724
  }
24725
+ rewrite(node, context) {
24726
+ const visitor = new ActionViewTagHelperToHTMLVisitor({ shallow: context.shallow, includeBody: context.includeBody });
24727
+ visitor.visit(node);
24728
+ return node;
24729
+ }
24730
+ }
24731
+
24732
+ const STRING_NODE_TYPE = "StringNode";
24733
+ const INTERPOLATED_STRING_NODE_TYPE = "InterpolatedStringNode";
24734
+ const EMBEDDED_STATEMENTS_NODE_TYPE = "EmbeddedStatementsNode";
24735
+ class ERBStringToDirectOutputVisitor extends Visitor {
24736
+ root;
24737
+ constructor(root) {
24738
+ super();
24739
+ this.root = root;
24740
+ }
24741
+ visitERBContentNode(node) {
24742
+ if (!isERBOutputNode(node)) {
24743
+ this.visitChildNodes(node);
24744
+ return;
24745
+ }
24746
+ const prismNode = node.prismNode;
24747
+ if (!prismNode) {
24748
+ this.visitChildNodes(node);
24749
+ return;
24750
+ }
24751
+ const source = node.source;
24752
+ if (!source) {
24753
+ this.visitChildNodes(node);
24754
+ return;
24755
+ }
24756
+ if (!ERBStringToDirectOutputRewriter.isStringOutputNode(prismNode)) {
24757
+ this.visitChildNodes(node);
24758
+ return;
24759
+ }
24760
+ const replacementParts = ERBStringToDirectOutputRewriter.extractReplacementParts(prismNode, source);
24761
+ if (!replacementParts) {
24762
+ this.visitChildNodes(node);
24763
+ return;
24764
+ }
24765
+ const tagOpening = node.tag_opening?.value ?? "<%=";
24766
+ const tagClosing = node.tag_closing?.value ?? "%>";
24767
+ const parentInfo = findParentArray(this.root, node);
24768
+ if (!parentInfo) {
24769
+ this.visitChildNodes(node);
24770
+ return;
24771
+ }
24772
+ const { array: parentArray, index: nodeIndex } = parentInfo;
24773
+ const replacementNodes = [];
24774
+ for (const part of replacementParts) {
24775
+ if (part.type === "text") {
24776
+ replacementNodes.push(createLiteral(part.content));
24777
+ }
24778
+ else {
24779
+ replacementNodes.push(createERBOutputNode(` ${part.expression.trim()} `, tagOpening, tagClosing));
24780
+ }
24781
+ }
24782
+ parentArray.splice(nodeIndex, 1, ...replacementNodes);
24783
+ }
24784
+ }
24785
+ class ERBStringToDirectOutputRewriter extends ASTRewriter {
24786
+ get name() {
24787
+ return "erb-string-to-direct-output";
24788
+ }
24789
+ get description() {
24790
+ return "Replaces ERB string output with direct text and expression tags";
24791
+ }
24084
24792
  rewrite(node, _context) {
24085
- const visitor = new ActionViewTagHelperToHTMLVisitor();
24793
+ const visitor = new ERBStringToDirectOutputVisitor(node);
24086
24794
  visitor.visit(node);
24087
24795
  return node;
24088
24796
  }
24797
+ static isStringOutputNode(prismNode) {
24798
+ const nodeType = prismNode.constructor.name;
24799
+ return nodeType === STRING_NODE_TYPE || nodeType === INTERPOLATED_STRING_NODE_TYPE;
24800
+ }
24801
+ static extractStringContent(stringNode, source) {
24802
+ const unescapedValue = stringNode.unescaped?.value;
24803
+ if (typeof unescapedValue === "string") {
24804
+ return unescapedValue;
24805
+ }
24806
+ const location = stringNode.contentLoc;
24807
+ if (location) {
24808
+ return source.substring(location.startOffset, location.startOffset + location.length);
24809
+ }
24810
+ return "";
24811
+ }
24812
+ static extractExpressionSource(embeddedNode, source) {
24813
+ const openingLocation = embeddedNode.openingLoc;
24814
+ const closingLocation = embeddedNode.closingLoc;
24815
+ if (!openingLocation || !closingLocation)
24816
+ return null;
24817
+ const expressionStart = openingLocation.startOffset + openingLocation.length;
24818
+ const expressionEnd = closingLocation.startOffset;
24819
+ return source.substring(expressionStart, expressionEnd);
24820
+ }
24821
+ static extractReplacementParts(prismNode, source) {
24822
+ const nodeType = prismNode.constructor.name;
24823
+ if (nodeType === STRING_NODE_TYPE) {
24824
+ const textContent = this.extractStringContent(prismNode, source);
24825
+ return [{ type: "text", content: textContent }];
24826
+ }
24827
+ if (nodeType === INTERPOLATED_STRING_NODE_TYPE) {
24828
+ const parts = prismNode.parts;
24829
+ if (!parts || parts.length === 0)
24830
+ return null;
24831
+ const replacementParts = [];
24832
+ for (const part of parts) {
24833
+ const partType = part.constructor.name;
24834
+ if (partType === STRING_NODE_TYPE) {
24835
+ const textContent = this.extractStringContent(part, source);
24836
+ if (textContent) {
24837
+ replacementParts.push({ type: "text", content: textContent });
24838
+ }
24839
+ }
24840
+ else if (partType === EMBEDDED_STATEMENTS_NODE_TYPE) {
24841
+ const expression = this.extractExpressionSource(part, source);
24842
+ if (expression) {
24843
+ replacementParts.push({ type: "expression", expression });
24844
+ }
24845
+ }
24846
+ }
24847
+ return replacementParts.length > 0 ? replacementParts : null;
24848
+ }
24849
+ return null;
24850
+ }
24089
24851
  }
24090
24852
 
24091
24853
  function serializeAttributeValue(value) {
@@ -24175,9 +24937,10 @@ class HTMLToActionViewTagHelperVisitor extends Visitor {
24175
24937
  const isAnchor = tagName.value === "a";
24176
24938
  const isTurboFrame = tagName.value === "turbo-frame";
24177
24939
  const isScript = tagName.value === "script";
24940
+ const isImg = tagName.value === "img";
24178
24941
  const attributes = openTag.children.filter(child => !isWhitespaceNode(child));
24179
- const hasSrcAttribute = isScript && attributes.some(child => isHTMLAttributeNode(child) && getStaticAttributeName(child.name) === "src");
24180
- const { attributes: attributesString, href, id, src } = serializeAttributes(attributes, { extractHref: isAnchor, extractId: isTurboFrame, extractSrc: isScript });
24942
+ const hasSrcAttribute = (isScript || isImg) && attributes.some(child => isHTMLAttributeNode(child) && getStaticAttributeName(child.name) === "src");
24943
+ const { attributes: attributesString, href, id, src } = serializeAttributes(attributes, { extractHref: isAnchor, extractId: isTurboFrame, extractSrc: isScript || isImg });
24181
24944
  const hasBody = node.body && node.body.length > 0 && !node.is_void;
24182
24945
  const isInlineContent = hasBody && isTextOnlyBody(node.body);
24183
24946
  let content;
@@ -24198,6 +24961,10 @@ class HTMLToActionViewTagHelperVisitor extends Visitor {
24198
24961
  content = this.buildJavascriptTagContent(node, attributesString, isInlineContent);
24199
24962
  elementSource = "ActionView::Helpers::JavaScriptHelper#javascript_tag";
24200
24963
  }
24964
+ else if (isImg) {
24965
+ content = this.buildImageTagContent(attributesString, src);
24966
+ elementSource = "ActionView::Helpers::AssetTagHelper#image_tag";
24967
+ }
24201
24968
  else {
24202
24969
  content = this.buildTagContent(tagName.value, node, attributesString, isInlineContent);
24203
24970
  elementSource = "ActionView::Helpers::TagHelper#tag";
@@ -24215,7 +24982,7 @@ class HTMLToActionViewTagHelperVisitor extends Visitor {
24215
24982
  asMutable(node).open_tag = erbOpenTag;
24216
24983
  asMutable(node).element_source = elementSource;
24217
24984
  const isInlineLiteralContent = isScript && hasBody && node.body.length === 1 && isLiteralNode(node.body[0]) && !node.body[0].content.includes("\n");
24218
- const isInlineForm = isInlineContent || isInlineLiteralContent || (isTurboFrame && !hasBody) || (isScript && hasSrcAttribute);
24985
+ const isInlineForm = isInlineContent || isInlineLiteralContent || (isTurboFrame && !hasBody) || (isScript && hasSrcAttribute) || isImg;
24219
24986
  if (node.is_void) {
24220
24987
  asMutable(node).close_tag = null;
24221
24988
  }
@@ -24299,6 +25066,15 @@ class HTMLToActionViewTagHelperVisitor extends Visitor {
24299
25066
  const argString = args.join(", ");
24300
25067
  return argString ? ` javascript_include_tag ${argString} ` : ` javascript_include_tag `;
24301
25068
  }
25069
+ buildImageTagContent(attributes, source) {
25070
+ const args = [];
25071
+ if (source)
25072
+ args.push(source);
25073
+ if (attributes)
25074
+ args.push(attributes);
25075
+ const argString = args.join(", ");
25076
+ return argString ? ` image_tag ${argString} ` : ` image_tag `;
25077
+ }
24302
25078
  buildLinkToContent(node, attribute, href, isInlineContent) {
24303
25079
  const args = [];
24304
25080
  if (isInlineContent && isHTMLTextNode(node.body[0])) {
@@ -24322,7 +25098,7 @@ class HTMLToActionViewTagHelperRewriter extends ASTRewriter {
24322
25098
  return "html-to-action-view-tag-helper";
24323
25099
  }
24324
25100
  get description() {
24325
- return "Converts raw HTML elements to ActionView tag helpers (tag.*, turbo_frame_tag, javascript_tag, javascript_include_tag)";
25101
+ return "Converts raw HTML elements to ActionView tag helpers (tag.*, turbo_frame_tag, javascript_tag, javascript_include_tag, image_tag)";
24326
25102
  }
24327
25103
  rewrite(node, _context) {
24328
25104
  const visitor = new HTMLToActionViewTagHelperVisitor();
@@ -24749,6 +25525,15 @@ class IdentityPrinter extends Printer {
24749
25525
  if (node.body) {
24750
25526
  node.body.forEach(child => this.visit(child));
24751
25527
  }
25528
+ if (node.rescue_clause) {
25529
+ this.visit(node.rescue_clause);
25530
+ }
25531
+ if (node.else_clause) {
25532
+ this.visit(node.else_clause);
25533
+ }
25534
+ if (node.ensure_clause) {
25535
+ this.visit(node.ensure_clause);
25536
+ }
24752
25537
  if (node.end_node) {
24753
25538
  this.visit(node.end_node);
24754
25539
  }
@@ -24852,6 +25637,12 @@ class IdentityPrinter extends Printer {
24852
25637
  visitRubyRenderLocalNode(_node) {
24853
25638
  // extracted metadata, nothing to print
24854
25639
  }
25640
+ visitERBStrictLocalsNode(node) {
25641
+ this.printERBNode(node);
25642
+ }
25643
+ visitRubyStrictLocalNode(_node) {
25644
+ // extracted metadata, nothing to print
25645
+ }
24855
25646
  visitERBYieldNode(node) {
24856
25647
  this.printERBNode(node);
24857
25648
  }
@@ -24982,6 +25773,7 @@ function rewriteString(herb, template, rewriters, options = {}) {
24982
25773
 
24983
25774
  exports.ASTRewriter = ASTRewriter;
24984
25775
  exports.ActionViewTagHelperToHTMLRewriter = ActionViewTagHelperToHTMLRewriter;
25776
+ exports.ERBStringToDirectOutputRewriter = ERBStringToDirectOutputRewriter;
24985
25777
  exports.HTMLToActionViewTagHelperRewriter = HTMLToActionViewTagHelperRewriter;
24986
25778
  exports.StringRewriter = StringRewriter;
24987
25779
  exports.asMutable = asMutable;