@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/loader.cjs CHANGED
@@ -172,6 +172,9 @@ class Token {
172
172
  static from(token) {
173
173
  return new Token(token.value, Range.from(token.range), Location.from(token.location), token.type);
174
174
  }
175
+ static synthetic(value, type = "SYNTETHIC") {
176
+ return new Token(value, Range.zero, Location.zero, type);
177
+ }
175
178
  constructor(value, range, location, type) {
176
179
  this.value = value;
177
180
  this.range = range;
@@ -206,7 +209,7 @@ class Token {
206
209
  }
207
210
 
208
211
  // NOTE: This file is generated by the templates/template.rb script and should not
209
- // be modified manually. See /Users/marcoroth/Development/herb-release-0.9.2/templates/javascript/packages/core/src/errors.ts.erb
212
+ // be modified manually. See /Users/marcoroth/Development/herb-release-0.9.4/templates/javascript/packages/core/src/errors.ts.erb
210
213
  class HerbError {
211
214
  type;
212
215
  message;
@@ -1480,6 +1483,284 @@ class RenderLayoutWithoutBlockError extends HerbError {
1480
1483
  return output;
1481
1484
  }
1482
1485
  }
1486
+ class StrictLocalsPositionalArgumentError extends HerbError {
1487
+ name;
1488
+ static from(data) {
1489
+ return new StrictLocalsPositionalArgumentError({
1490
+ type: data.type,
1491
+ message: data.message,
1492
+ location: Location.from(data.location),
1493
+ name: data.name,
1494
+ });
1495
+ }
1496
+ constructor(props) {
1497
+ super(props.type, props.message, props.location);
1498
+ this.name = props.name;
1499
+ }
1500
+ toJSON() {
1501
+ return {
1502
+ ...super.toJSON(),
1503
+ type: "STRICT_LOCALS_POSITIONAL_ARGUMENT_ERROR",
1504
+ name: this.name,
1505
+ };
1506
+ }
1507
+ toMonacoDiagnostic() {
1508
+ return {
1509
+ line: this.location.start.line,
1510
+ column: this.location.start.column,
1511
+ endLine: this.location.end.line,
1512
+ endColumn: this.location.end.column,
1513
+ message: this.message,
1514
+ severity: 'error'
1515
+ };
1516
+ }
1517
+ treeInspect() {
1518
+ let output = "";
1519
+ output += `@ StrictLocalsPositionalArgumentError ${this.location.treeInspectWithLabel()}\n`;
1520
+ output += `├── message: "${this.message}"\n`;
1521
+ output += `└── name: ${JSON.stringify(this.name)}\n`;
1522
+ return output;
1523
+ }
1524
+ }
1525
+ class StrictLocalsBlockArgumentError extends HerbError {
1526
+ name;
1527
+ static from(data) {
1528
+ return new StrictLocalsBlockArgumentError({
1529
+ type: data.type,
1530
+ message: data.message,
1531
+ location: Location.from(data.location),
1532
+ name: data.name,
1533
+ });
1534
+ }
1535
+ constructor(props) {
1536
+ super(props.type, props.message, props.location);
1537
+ this.name = props.name;
1538
+ }
1539
+ toJSON() {
1540
+ return {
1541
+ ...super.toJSON(),
1542
+ type: "STRICT_LOCALS_BLOCK_ARGUMENT_ERROR",
1543
+ name: this.name,
1544
+ };
1545
+ }
1546
+ toMonacoDiagnostic() {
1547
+ return {
1548
+ line: this.location.start.line,
1549
+ column: this.location.start.column,
1550
+ endLine: this.location.end.line,
1551
+ endColumn: this.location.end.column,
1552
+ message: this.message,
1553
+ severity: 'error'
1554
+ };
1555
+ }
1556
+ treeInspect() {
1557
+ let output = "";
1558
+ output += `@ StrictLocalsBlockArgumentError ${this.location.treeInspectWithLabel()}\n`;
1559
+ output += `├── message: "${this.message}"\n`;
1560
+ output += `└── name: ${JSON.stringify(this.name)}\n`;
1561
+ return output;
1562
+ }
1563
+ }
1564
+ class StrictLocalsSplatArgumentError extends HerbError {
1565
+ name;
1566
+ static from(data) {
1567
+ return new StrictLocalsSplatArgumentError({
1568
+ type: data.type,
1569
+ message: data.message,
1570
+ location: Location.from(data.location),
1571
+ name: data.name,
1572
+ });
1573
+ }
1574
+ constructor(props) {
1575
+ super(props.type, props.message, props.location);
1576
+ this.name = props.name;
1577
+ }
1578
+ toJSON() {
1579
+ return {
1580
+ ...super.toJSON(),
1581
+ type: "STRICT_LOCALS_SPLAT_ARGUMENT_ERROR",
1582
+ name: this.name,
1583
+ };
1584
+ }
1585
+ toMonacoDiagnostic() {
1586
+ return {
1587
+ line: this.location.start.line,
1588
+ column: this.location.start.column,
1589
+ endLine: this.location.end.line,
1590
+ endColumn: this.location.end.column,
1591
+ message: this.message,
1592
+ severity: 'error'
1593
+ };
1594
+ }
1595
+ treeInspect() {
1596
+ let output = "";
1597
+ output += `@ StrictLocalsSplatArgumentError ${this.location.treeInspectWithLabel()}\n`;
1598
+ output += `├── message: "${this.message}"\n`;
1599
+ output += `└── name: ${JSON.stringify(this.name)}\n`;
1600
+ return output;
1601
+ }
1602
+ }
1603
+ class StrictLocalsMissingParenthesisError extends HerbError {
1604
+ rest;
1605
+ static from(data) {
1606
+ return new StrictLocalsMissingParenthesisError({
1607
+ type: data.type,
1608
+ message: data.message,
1609
+ location: Location.from(data.location),
1610
+ rest: data.rest,
1611
+ });
1612
+ }
1613
+ constructor(props) {
1614
+ super(props.type, props.message, props.location);
1615
+ this.rest = props.rest;
1616
+ }
1617
+ toJSON() {
1618
+ return {
1619
+ ...super.toJSON(),
1620
+ type: "STRICT_LOCALS_MISSING_PARENTHESIS_ERROR",
1621
+ rest: this.rest,
1622
+ };
1623
+ }
1624
+ toMonacoDiagnostic() {
1625
+ return {
1626
+ line: this.location.start.line,
1627
+ column: this.location.start.column,
1628
+ endLine: this.location.end.line,
1629
+ endColumn: this.location.end.column,
1630
+ message: this.message,
1631
+ severity: 'error'
1632
+ };
1633
+ }
1634
+ treeInspect() {
1635
+ let output = "";
1636
+ output += `@ StrictLocalsMissingParenthesisError ${this.location.treeInspectWithLabel()}\n`;
1637
+ output += `├── message: "${this.message}"\n`;
1638
+ output += `└── rest: ${JSON.stringify(this.rest)}\n`;
1639
+ return output;
1640
+ }
1641
+ }
1642
+ class StrictLocalsDuplicateDeclarationError extends HerbError {
1643
+ static from(data) {
1644
+ return new StrictLocalsDuplicateDeclarationError({
1645
+ type: data.type,
1646
+ message: data.message,
1647
+ location: Location.from(data.location),
1648
+ });
1649
+ }
1650
+ constructor(props) {
1651
+ super(props.type, props.message, props.location);
1652
+ }
1653
+ toJSON() {
1654
+ return {
1655
+ ...super.toJSON(),
1656
+ type: "STRICT_LOCALS_DUPLICATE_DECLARATION_ERROR",
1657
+ };
1658
+ }
1659
+ toMonacoDiagnostic() {
1660
+ return {
1661
+ line: this.location.start.line,
1662
+ column: this.location.start.column,
1663
+ endLine: this.location.end.line,
1664
+ endColumn: this.location.end.column,
1665
+ message: this.message,
1666
+ severity: 'error'
1667
+ };
1668
+ }
1669
+ treeInspect() {
1670
+ let output = "";
1671
+ output += `@ StrictLocalsDuplicateDeclarationError ${this.location.treeInspectWithLabel()}\n`;
1672
+ output += `└── message: "${this.message}"\n`;
1673
+ return output;
1674
+ }
1675
+ }
1676
+ class VoidElementContentError extends HerbError {
1677
+ tag_name;
1678
+ helper_name;
1679
+ content_type;
1680
+ static from(data) {
1681
+ return new VoidElementContentError({
1682
+ type: data.type,
1683
+ message: data.message,
1684
+ location: Location.from(data.location),
1685
+ tag_name: data.tag_name ? Token.from(data.tag_name) : null,
1686
+ helper_name: data.helper_name,
1687
+ content_type: data.content_type,
1688
+ });
1689
+ }
1690
+ constructor(props) {
1691
+ super(props.type, props.message, props.location);
1692
+ this.tag_name = props.tag_name;
1693
+ this.helper_name = props.helper_name;
1694
+ this.content_type = props.content_type;
1695
+ }
1696
+ toJSON() {
1697
+ return {
1698
+ ...super.toJSON(),
1699
+ type: "VOID_ELEMENT_CONTENT_ERROR",
1700
+ tag_name: this.tag_name ? this.tag_name.toJSON() : null,
1701
+ helper_name: this.helper_name,
1702
+ content_type: this.content_type,
1703
+ };
1704
+ }
1705
+ toMonacoDiagnostic() {
1706
+ return {
1707
+ line: this.location.start.line,
1708
+ column: this.location.start.column,
1709
+ endLine: this.location.end.line,
1710
+ endColumn: this.location.end.column,
1711
+ message: this.message,
1712
+ severity: 'error'
1713
+ };
1714
+ }
1715
+ treeInspect() {
1716
+ let output = "";
1717
+ output += `@ VoidElementContentError ${this.location.treeInspectWithLabel()}\n`;
1718
+ output += `├── message: "${this.message}"\n`;
1719
+ output += `├── tag_name: ${this.tag_name ? this.tag_name.treeInspect() : "∅"}\n`;
1720
+ output += `├── helper_name: ${JSON.stringify(this.helper_name)}\n`;
1721
+ output += `└── content_type: ${JSON.stringify(this.content_type)}\n`;
1722
+ return output;
1723
+ }
1724
+ }
1725
+ class DotNotationCasingError extends HerbError {
1726
+ segment;
1727
+ static from(data) {
1728
+ return new DotNotationCasingError({
1729
+ type: data.type,
1730
+ message: data.message,
1731
+ location: Location.from(data.location),
1732
+ segment: data.segment ? Token.from(data.segment) : null,
1733
+ });
1734
+ }
1735
+ constructor(props) {
1736
+ super(props.type, props.message, props.location);
1737
+ this.segment = props.segment;
1738
+ }
1739
+ toJSON() {
1740
+ return {
1741
+ ...super.toJSON(),
1742
+ type: "DOT_NOTATION_CASING_ERROR",
1743
+ segment: this.segment ? this.segment.toJSON() : null,
1744
+ };
1745
+ }
1746
+ toMonacoDiagnostic() {
1747
+ return {
1748
+ line: this.location.start.line,
1749
+ column: this.location.start.column,
1750
+ endLine: this.location.end.line,
1751
+ endColumn: this.location.end.column,
1752
+ message: this.message,
1753
+ severity: 'error'
1754
+ };
1755
+ }
1756
+ treeInspect() {
1757
+ let output = "";
1758
+ output += `@ DotNotationCasingError ${this.location.treeInspectWithLabel()}\n`;
1759
+ output += `├── message: "${this.message}"\n`;
1760
+ output += `└── segment: ${this.segment ? this.segment.treeInspect() : "∅"}\n`;
1761
+ return output;
1762
+ }
1763
+ }
1483
1764
  function fromSerializedError(error) {
1484
1765
  switch (error.type) {
1485
1766
  case "UNEXPECTED_ERROR": return UnexpectedError.from(error);
@@ -1512,6 +1793,13 @@ function fromSerializedError(error) {
1512
1793
  case "RENDER_INVALID_AS_OPTION_ERROR": return RenderInvalidAsOptionError.from(error);
1513
1794
  case "RENDER_OBJECT_AND_COLLECTION_ERROR": return RenderObjectAndCollectionError.from(error);
1514
1795
  case "RENDER_LAYOUT_WITHOUT_BLOCK_ERROR": return RenderLayoutWithoutBlockError.from(error);
1796
+ case "STRICT_LOCALS_POSITIONAL_ARGUMENT_ERROR": return StrictLocalsPositionalArgumentError.from(error);
1797
+ case "STRICT_LOCALS_BLOCK_ARGUMENT_ERROR": return StrictLocalsBlockArgumentError.from(error);
1798
+ case "STRICT_LOCALS_SPLAT_ARGUMENT_ERROR": return StrictLocalsSplatArgumentError.from(error);
1799
+ case "STRICT_LOCALS_MISSING_PARENTHESIS_ERROR": return StrictLocalsMissingParenthesisError.from(error);
1800
+ case "STRICT_LOCALS_DUPLICATE_DECLARATION_ERROR": return StrictLocalsDuplicateDeclarationError.from(error);
1801
+ case "VOID_ELEMENT_CONTENT_ERROR": return VoidElementContentError.from(error);
1802
+ case "DOT_NOTATION_CASING_ERROR": return DotNotationCasingError.from(error);
1515
1803
  default:
1516
1804
  throw new Error(`Unknown node type: ${error.type}`);
1517
1805
  }
@@ -20100,7 +20388,7 @@ function deserializePrismNode(bytes, source) {
20100
20388
  }
20101
20389
 
20102
20390
  // NOTE: This file is generated by the templates/template.rb script and should not
20103
- // be modified manually. See /Users/marcoroth/Development/herb-release-0.9.2/templates/javascript/packages/core/src/nodes.ts.erb
20391
+ // be modified manually. See /Users/marcoroth/Development/herb-release-0.9.4/templates/javascript/packages/core/src/nodes.ts.erb
20104
20392
  class Node {
20105
20393
  type;
20106
20394
  location;
@@ -21721,6 +22009,9 @@ class ERBBlockNode extends Node {
21721
22009
  tag_closing;
21722
22010
  prism_node;
21723
22011
  body;
22012
+ rescue_clause;
22013
+ else_clause;
22014
+ ensure_clause;
21724
22015
  end_node;
21725
22016
  static get type() {
21726
22017
  return "AST_ERB_BLOCK_NODE";
@@ -21735,6 +22026,9 @@ class ERBBlockNode extends Node {
21735
22026
  tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
21736
22027
  prism_node: data.prism_node ? new Uint8Array(data.prism_node) : null,
21737
22028
  body: (data.body || []).map(node => fromSerializedNode(node)),
22029
+ rescue_clause: data.rescue_clause ? fromSerializedNode((data.rescue_clause)) : null,
22030
+ else_clause: data.else_clause ? fromSerializedNode((data.else_clause)) : null,
22031
+ ensure_clause: data.ensure_clause ? fromSerializedNode((data.ensure_clause)) : null,
21738
22032
  end_node: data.end_node ? fromSerializedNode((data.end_node)) : null,
21739
22033
  });
21740
22034
  }
@@ -21745,6 +22039,9 @@ class ERBBlockNode extends Node {
21745
22039
  this.tag_closing = props.tag_closing;
21746
22040
  this.prism_node = props.prism_node;
21747
22041
  this.body = props.body;
22042
+ this.rescue_clause = props.rescue_clause;
22043
+ this.else_clause = props.else_clause;
22044
+ this.ensure_clause = props.ensure_clause;
21748
22045
  this.end_node = props.end_node;
21749
22046
  }
21750
22047
  accept(visitor) {
@@ -21753,6 +22050,9 @@ class ERBBlockNode extends Node {
21753
22050
  childNodes() {
21754
22051
  return [
21755
22052
  ...this.body,
22053
+ this.rescue_clause,
22054
+ this.else_clause,
22055
+ this.ensure_clause,
21756
22056
  this.end_node,
21757
22057
  ];
21758
22058
  }
@@ -21768,6 +22068,9 @@ class ERBBlockNode extends Node {
21768
22068
  return [
21769
22069
  ...this.errors,
21770
22070
  ...this.body.map(node => node.recursiveErrors()),
22071
+ this.rescue_clause ? this.rescue_clause.recursiveErrors() : [],
22072
+ this.else_clause ? this.else_clause.recursiveErrors() : [],
22073
+ this.ensure_clause ? this.ensure_clause.recursiveErrors() : [],
21771
22074
  this.end_node ? this.end_node.recursiveErrors() : [],
21772
22075
  ].flat();
21773
22076
  }
@@ -21780,6 +22083,9 @@ class ERBBlockNode extends Node {
21780
22083
  tag_closing: this.tag_closing ? this.tag_closing.toJSON() : null,
21781
22084
  prism_node: this.prism_node ? Array.from(this.prism_node) : null,
21782
22085
  body: this.body.map(node => node.toJSON()),
22086
+ rescue_clause: this.rescue_clause ? this.rescue_clause.toJSON() : null,
22087
+ else_clause: this.else_clause ? this.else_clause.toJSON() : null,
22088
+ ensure_clause: this.ensure_clause ? this.ensure_clause.toJSON() : null,
21783
22089
  end_node: this.end_node ? this.end_node.toJSON() : null,
21784
22090
  };
21785
22091
  }
@@ -21794,6 +22100,9 @@ class ERBBlockNode extends Node {
21794
22100
  output += `├── prism_node: ${this.source ? inspectPrismSerialized(this.prism_node, this.source, "│ ") : `(${this.prism_node.length} bytes)`}\n`;
21795
22101
  }
21796
22102
  output += `├── body: ${this.inspectArray(this.body, "│ ")}`;
22103
+ output += `├── rescue_clause: ${this.inspectNode(this.rescue_clause, "│ ")}`;
22104
+ output += `├── else_clause: ${this.inspectNode(this.else_clause, "│ ")}`;
22105
+ output += `├── ensure_clause: ${this.inspectNode(this.ensure_clause, "│ ")}`;
21797
22106
  output += `└── end_node: ${this.inspectNode(this.end_node, " ")}`;
21798
22107
  return output;
21799
22108
  }
@@ -22863,6 +23172,150 @@ class ERBRenderNode extends Node {
22863
23172
  return output;
22864
23173
  }
22865
23174
  }
23175
+ class RubyStrictLocalNode extends Node {
23176
+ name;
23177
+ default_value;
23178
+ required;
23179
+ double_splat;
23180
+ static get type() {
23181
+ return "AST_RUBY_STRICT_LOCAL_NODE";
23182
+ }
23183
+ static from(data) {
23184
+ return new RubyStrictLocalNode({
23185
+ type: data.type,
23186
+ location: Location.from(data.location),
23187
+ errors: (data.errors || []).map(error => HerbError.from(error)),
23188
+ name: data.name ? Token.from(data.name) : null,
23189
+ default_value: data.default_value ? fromSerializedNode((data.default_value)) : null,
23190
+ required: data.required,
23191
+ double_splat: data.double_splat,
23192
+ });
23193
+ }
23194
+ constructor(props) {
23195
+ super(props.type, props.location, props.errors);
23196
+ this.name = props.name;
23197
+ this.default_value = props.default_value;
23198
+ this.required = props.required;
23199
+ this.double_splat = props.double_splat;
23200
+ }
23201
+ accept(visitor) {
23202
+ visitor.visitRubyStrictLocalNode(this);
23203
+ }
23204
+ childNodes() {
23205
+ return [
23206
+ this.default_value,
23207
+ ];
23208
+ }
23209
+ compactChildNodes() {
23210
+ return this.childNodes().filter(node => node !== null && node !== undefined);
23211
+ }
23212
+ recursiveErrors() {
23213
+ return [
23214
+ ...this.errors,
23215
+ this.default_value ? this.default_value.recursiveErrors() : [],
23216
+ ].flat();
23217
+ }
23218
+ toJSON() {
23219
+ return {
23220
+ ...super.toJSON(),
23221
+ type: "AST_RUBY_STRICT_LOCAL_NODE",
23222
+ name: this.name ? this.name.toJSON() : null,
23223
+ default_value: this.default_value ? this.default_value.toJSON() : null,
23224
+ required: this.required,
23225
+ double_splat: this.double_splat,
23226
+ };
23227
+ }
23228
+ treeInspect() {
23229
+ let output = "";
23230
+ output += `@ RubyStrictLocalNode ${this.location.treeInspectWithLabel()}\n`;
23231
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
23232
+ output += `├── name: ${this.name ? this.name.treeInspect() : "∅"}\n`;
23233
+ output += `├── default_value: ${this.inspectNode(this.default_value, "│ ")}`;
23234
+ output += `├── required: ${typeof this.required === 'boolean' ? String(this.required) : "∅"}\n`;
23235
+ output += `└── double_splat: ${typeof this.double_splat === 'boolean' ? String(this.double_splat) : "∅"}\n`;
23236
+ return output;
23237
+ }
23238
+ }
23239
+ class ERBStrictLocalsNode extends Node {
23240
+ tag_opening;
23241
+ content;
23242
+ tag_closing;
23243
+ // no-op for analyzed_ruby
23244
+ prism_node;
23245
+ locals;
23246
+ static get type() {
23247
+ return "AST_ERB_STRICT_LOCALS_NODE";
23248
+ }
23249
+ static from(data) {
23250
+ return new ERBStrictLocalsNode({
23251
+ type: data.type,
23252
+ location: Location.from(data.location),
23253
+ errors: (data.errors || []).map(error => HerbError.from(error)),
23254
+ tag_opening: data.tag_opening ? Token.from(data.tag_opening) : null,
23255
+ content: data.content ? Token.from(data.content) : null,
23256
+ tag_closing: data.tag_closing ? Token.from(data.tag_closing) : null,
23257
+ // no-op for analyzed_ruby
23258
+ prism_node: data.prism_node ? new Uint8Array(data.prism_node) : null,
23259
+ locals: (data.locals || []).map(node => fromSerializedNode(node)),
23260
+ });
23261
+ }
23262
+ constructor(props) {
23263
+ super(props.type, props.location, props.errors);
23264
+ this.tag_opening = props.tag_opening;
23265
+ this.content = props.content;
23266
+ this.tag_closing = props.tag_closing;
23267
+ // no-op for analyzed_ruby
23268
+ this.prism_node = props.prism_node;
23269
+ this.locals = props.locals;
23270
+ }
23271
+ accept(visitor) {
23272
+ visitor.visitERBStrictLocalsNode(this);
23273
+ }
23274
+ childNodes() {
23275
+ return [
23276
+ ...this.locals,
23277
+ ];
23278
+ }
23279
+ compactChildNodes() {
23280
+ return this.childNodes().filter(node => node !== null && node !== undefined);
23281
+ }
23282
+ get prismNode() {
23283
+ if (!this.prism_node || !this.source)
23284
+ return null;
23285
+ return deserializePrismNode(this.prism_node, this.source);
23286
+ }
23287
+ recursiveErrors() {
23288
+ return [
23289
+ ...this.errors,
23290
+ ...this.locals.map(node => node.recursiveErrors()),
23291
+ ].flat();
23292
+ }
23293
+ toJSON() {
23294
+ return {
23295
+ ...super.toJSON(),
23296
+ type: "AST_ERB_STRICT_LOCALS_NODE",
23297
+ tag_opening: this.tag_opening ? this.tag_opening.toJSON() : null,
23298
+ content: this.content ? this.content.toJSON() : null,
23299
+ tag_closing: this.tag_closing ? this.tag_closing.toJSON() : null,
23300
+ // no-op for analyzed_ruby
23301
+ prism_node: this.prism_node ? Array.from(this.prism_node) : null,
23302
+ locals: this.locals.map(node => node.toJSON()),
23303
+ };
23304
+ }
23305
+ treeInspect() {
23306
+ let output = "";
23307
+ output += `@ ERBStrictLocalsNode ${this.location.treeInspectWithLabel()}\n`;
23308
+ output += `├── errors: ${this.inspectArray(this.errors, "│ ")}`;
23309
+ output += `├── tag_opening: ${this.tag_opening ? this.tag_opening.treeInspect() : "∅"}\n`;
23310
+ output += `├── content: ${this.content ? this.content.treeInspect() : "∅"}\n`;
23311
+ output += `├── tag_closing: ${this.tag_closing ? this.tag_closing.treeInspect() : "∅"}\n`;
23312
+ if (this.prism_node) {
23313
+ output += `├── prism_node: ${this.source ? inspectPrismSerialized(this.prism_node, this.source, "│ ") : `(${this.prism_node.length} bytes)`}\n`;
23314
+ }
23315
+ output += `└── locals: ${this.inspectArray(this.locals, " ")}`;
23316
+ return output;
23317
+ }
23318
+ }
22866
23319
  class ERBYieldNode extends Node {
22867
23320
  tag_opening;
22868
23321
  content;
@@ -23028,6 +23481,8 @@ function fromSerializedNode(node) {
23028
23481
  case "AST_ERB_UNLESS_NODE": return ERBUnlessNode.from(node);
23029
23482
  case "AST_RUBY_RENDER_LOCAL_NODE": return RubyRenderLocalNode.from(node);
23030
23483
  case "AST_ERB_RENDER_NODE": return ERBRenderNode.from(node);
23484
+ case "AST_RUBY_STRICT_LOCAL_NODE": return RubyStrictLocalNode.from(node);
23485
+ case "AST_ERB_STRICT_LOCALS_NODE": return ERBStrictLocalsNode.from(node);
23031
23486
  case "AST_ERB_YIELD_NODE": return ERBYieldNode.from(node);
23032
23487
  case "AST_ERB_IN_NODE": return ERBInNode.from(node);
23033
23488
  default:
@@ -23078,9 +23533,12 @@ const DEFAULT_PARSER_OPTIONS = {
23078
23533
  strict: true,
23079
23534
  action_view_helpers: false,
23080
23535
  render_nodes: false,
23536
+ strict_locals: false,
23081
23537
  prism_nodes: false,
23082
23538
  prism_nodes_deep: false,
23083
23539
  prism_program: false,
23540
+ dot_notation_tags: false,
23541
+ html: true,
23084
23542
  };
23085
23543
  /**
23086
23544
  * Represents the parser options used during parsing.
@@ -23096,12 +23554,18 @@ class ParserOptions {
23096
23554
  action_view_helpers;
23097
23555
  /** Whether ActionView render call detection was enabled during parsing. */
23098
23556
  render_nodes;
23557
+ /** Whether strict locals analysis was enabled during parsing. */
23558
+ strict_locals;
23099
23559
  /** Whether Prism node serialization was enabled during parsing. */
23100
23560
  prism_nodes;
23101
23561
  /** Whether deep Prism node serialization was enabled during parsing. */
23102
23562
  prism_nodes_deep;
23103
23563
  /** Whether the full Prism ProgramNode was serialized on the DocumentNode. */
23104
23564
  prism_program;
23565
+ /** Whether dot-notation component tags (e.g. Dialog.Button) are parsed as HTML elements. */
23566
+ dot_notation_tags;
23567
+ /** Whether HTML tag parsing is enabled during parsing. When false, HTML-like content is treated as literal text. */
23568
+ html;
23105
23569
  static from(options) {
23106
23570
  return new ParserOptions(options);
23107
23571
  }
@@ -23111,9 +23575,12 @@ class ParserOptions {
23111
23575
  this.analyze = options.analyze ?? DEFAULT_PARSER_OPTIONS.analyze;
23112
23576
  this.action_view_helpers = options.action_view_helpers ?? DEFAULT_PARSER_OPTIONS.action_view_helpers;
23113
23577
  this.render_nodes = options.render_nodes ?? DEFAULT_PARSER_OPTIONS.render_nodes;
23578
+ this.strict_locals = options.strict_locals ?? DEFAULT_PARSER_OPTIONS.strict_locals;
23114
23579
  this.prism_nodes = options.prism_nodes ?? DEFAULT_PARSER_OPTIONS.prism_nodes;
23115
23580
  this.prism_nodes_deep = options.prism_nodes_deep ?? DEFAULT_PARSER_OPTIONS.prism_nodes_deep;
23116
23581
  this.prism_program = options.prism_program ?? DEFAULT_PARSER_OPTIONS.prism_program;
23582
+ this.dot_notation_tags = options.dot_notation_tags ?? DEFAULT_PARSER_OPTIONS.dot_notation_tags;
23583
+ this.html = options.html ?? DEFAULT_PARSER_OPTIONS.html;
23117
23584
  }
23118
23585
  }
23119
23586
 
@@ -23190,7 +23657,7 @@ class ParseResult extends Result {
23190
23657
  }
23191
23658
 
23192
23659
  // NOTE: This file is generated by the templates/template.rb script and should not
23193
- // be modified manually. See /Users/marcoroth/Development/herb-release-0.9.2/templates/javascript/packages/core/src/node-type-guards.ts.erb
23660
+ // be modified manually. See /Users/marcoroth/Development/herb-release-0.9.4/templates/javascript/packages/core/src/node-type-guards.ts.erb
23194
23661
  /**
23195
23662
  * Type guard functions for AST nodes.
23196
23663
  * These functions provide type checking by combining both instanceof
@@ -23501,6 +23968,22 @@ function isERBRenderNode(node) {
23501
23968
  return false;
23502
23969
  return node instanceof ERBRenderNode || node.type === "AST_ERB_RENDER_NODE" || node.constructor.type === "AST_ERB_RENDER_NODE";
23503
23970
  }
23971
+ /**
23972
+ * Checks if a node is a RubyStrictLocalNode
23973
+ */
23974
+ function isRubyStrictLocalNode(node) {
23975
+ if (!node)
23976
+ return false;
23977
+ return node instanceof RubyStrictLocalNode || node.type === "AST_RUBY_STRICT_LOCAL_NODE" || node.constructor.type === "AST_RUBY_STRICT_LOCAL_NODE";
23978
+ }
23979
+ /**
23980
+ * Checks if a node is a ERBStrictLocalsNode
23981
+ */
23982
+ function isERBStrictLocalsNode(node) {
23983
+ if (!node)
23984
+ return false;
23985
+ return node instanceof ERBStrictLocalsNode || node.type === "AST_ERB_STRICT_LOCALS_NODE" || node.constructor.type === "AST_ERB_STRICT_LOCALS_NODE";
23986
+ }
23504
23987
  /**
23505
23988
  * Checks if a node is a ERBYieldNode
23506
23989
  */
@@ -23517,6 +24000,31 @@ function isERBInNode(node) {
23517
24000
  return false;
23518
24001
  return node instanceof ERBInNode || node.type === "AST_ERB_IN_NODE" || node.constructor.type === "AST_ERB_IN_NODE";
23519
24002
  }
24003
+ /**
24004
+ * Checks if a node is any ERB node type
24005
+ */
24006
+ function isERBNode(node) {
24007
+ return isERBOpenTagNode(node) ||
24008
+ isERBContentNode(node) ||
24009
+ isERBEndNode(node) ||
24010
+ isERBElseNode(node) ||
24011
+ isERBIfNode(node) ||
24012
+ isERBBlockNode(node) ||
24013
+ isERBWhenNode(node) ||
24014
+ isERBCaseNode(node) ||
24015
+ isERBCaseMatchNode(node) ||
24016
+ isERBWhileNode(node) ||
24017
+ isERBUntilNode(node) ||
24018
+ isERBForNode(node) ||
24019
+ isERBRescueNode(node) ||
24020
+ isERBEnsureNode(node) ||
24021
+ isERBBeginNode(node) ||
24022
+ isERBUnlessNode(node) ||
24023
+ isERBRenderNode(node) ||
24024
+ isERBStrictLocalsNode(node) ||
24025
+ isERBYieldNode(node) ||
24026
+ isERBInNode(node);
24027
+ }
23520
24028
  /**
23521
24029
  * Map of node classes to their corresponding type guard functions
23522
24030
  *
@@ -23566,6 +24074,8 @@ const NODE_TYPE_GUARDS = new Map([
23566
24074
  [ERBUnlessNode, isERBUnlessNode],
23567
24075
  [RubyRenderLocalNode, isRubyRenderLocalNode],
23568
24076
  [ERBRenderNode, isERBRenderNode],
24077
+ [RubyStrictLocalNode, isRubyStrictLocalNode],
24078
+ [ERBStrictLocalsNode, isERBStrictLocalsNode],
23569
24079
  [ERBYieldNode, isERBYieldNode],
23570
24080
  [ERBInNode, isERBInNode],
23571
24081
  ]);
@@ -23618,6 +24128,8 @@ const AST_TYPE_GUARDS = new Map([
23618
24128
  ["AST_ERB_UNLESS_NODE", isERBUnlessNode],
23619
24129
  ["AST_RUBY_RENDER_LOCAL_NODE", isRubyRenderLocalNode],
23620
24130
  ["AST_ERB_RENDER_NODE", isERBRenderNode],
24131
+ ["AST_RUBY_STRICT_LOCAL_NODE", isRubyStrictLocalNode],
24132
+ ["AST_ERB_STRICT_LOCALS_NODE", isERBStrictLocalsNode],
23621
24133
  ["AST_ERB_YIELD_NODE", isERBYieldNode],
23622
24134
  ["AST_ERB_IN_NODE", isERBInNode],
23623
24135
  ]);
@@ -23675,6 +24187,17 @@ function isToken(object) {
23675
24187
  function isParseResult(object) {
23676
24188
  return (object instanceof ParseResult) || (object?.constructor?.name === "ParseResult" && "value" in object);
23677
24189
  }
24190
+
24191
+ /**
24192
+ * Checks if a node is an ERB output node (generates content: <%= %> or <%== %>)
24193
+ */
24194
+ function isERBOutputNode(node) {
24195
+ if (!isERBNode(node))
24196
+ return false;
24197
+ if (!node.tag_opening?.value)
24198
+ return false;
24199
+ return ["<%=", "<%=="].includes(node.tag_opening?.value);
24200
+ }
23678
24201
  /**
23679
24202
  * Extracts a static string from an array of literal nodes
23680
24203
  * Returns null if any node is not a literal node
@@ -23839,12 +24362,88 @@ function getNodesBeforePosition(nodes, position, inclusive = false) {
23839
24362
  function getNodesAfterPosition(nodes, position, inclusive = true) {
23840
24363
  return nodes.filter(node => node.location && isPositionAfter(node.location.start, position, inclusive));
23841
24364
  }
24365
+ // --- AST Mutation Utilities ---
24366
+ const CHILD_ARRAY_PROPS = ["children", "body", "statements", "conditions"];
24367
+ const LINKED_NODE_PROPS = ["subsequent", "else_clause"];
24368
+ /**
24369
+ * Finds the array containing a target node in the AST, along with its index.
24370
+ * Traverses child arrays and linked node properties (e.g., `subsequent`, `else_clause`).
24371
+ *
24372
+ * Useful for autofix operations that need to splice nodes in/out of their parent array.
24373
+ *
24374
+ * @param root - The root node to search from
24375
+ * @param target - The node to find
24376
+ * @returns The containing array and the target's index, or null if not found
24377
+ */
24378
+ function findParentArray(root, target) {
24379
+ const search = (node) => {
24380
+ const record = node;
24381
+ for (const prop of CHILD_ARRAY_PROPS) {
24382
+ const array = record[prop];
24383
+ if (Array.isArray(array)) {
24384
+ const index = array.indexOf(target);
24385
+ if (index !== -1) {
24386
+ return { array, index };
24387
+ }
24388
+ }
24389
+ }
24390
+ for (const prop of CHILD_ARRAY_PROPS) {
24391
+ const array = record[prop];
24392
+ if (Array.isArray(array)) {
24393
+ for (const child of array) {
24394
+ if (child && typeof child === 'object' && 'type' in child) {
24395
+ const result = search(child);
24396
+ if (result) {
24397
+ return result;
24398
+ }
24399
+ }
24400
+ }
24401
+ }
24402
+ }
24403
+ for (const prop of LINKED_NODE_PROPS) {
24404
+ const value = record[prop];
24405
+ if (value && typeof value === 'object' && 'type' in value) {
24406
+ const result = search(value);
24407
+ if (result) {
24408
+ return result;
24409
+ }
24410
+ }
24411
+ }
24412
+ return null;
24413
+ };
24414
+ return search(root);
24415
+ }
24416
+ /**
24417
+ * Creates a synthetic LiteralNode with the given content and zero location.
24418
+ * Useful for inserting whitespace or newlines during AST mutations.
24419
+ */
24420
+ function createLiteral(content) {
24421
+ return new LiteralNode({
24422
+ type: "AST_LITERAL_NODE",
24423
+ content,
24424
+ location: Location.zero,
24425
+ errors: [],
24426
+ });
24427
+ }
23842
24428
  function createSyntheticToken(value, type = "TOKEN_SYNTHETIC") {
23843
24429
  return new Token(value, Range.zero, Location.zero, type);
23844
24430
  }
24431
+ function createERBOutputNode(expression, tagOpening = "<%=", tagClosing = "%>") {
24432
+ return new ERBContentNode({
24433
+ type: "AST_ERB_CONTENT_NODE",
24434
+ tag_opening: createSyntheticToken(tagOpening),
24435
+ content: createSyntheticToken(expression),
24436
+ tag_closing: createSyntheticToken(tagClosing),
24437
+ parsed: false,
24438
+ valid: true,
24439
+ prism_node: null,
24440
+ location: Location.zero,
24441
+ errors: [],
24442
+ });
24443
+ }
23845
24444
 
23846
24445
  // NOTE: This file is generated by the templates/template.rb script and should not
23847
- // be modified manually. See /Users/marcoroth/Development/herb-release-0.9.2/templates/javascript/packages/core/src/visitor.ts.erb
24446
+ // be modified manually. See /Users/marcoroth/Development/herb-release-0.9.4/templates/javascript/packages/core/src/visitor.ts.erb
23848
24447
  class Visitor {
23849
24448
  visit(node) {
23850
24449
  if (!node)
@@ -24032,6 +24631,15 @@ class Visitor {
24032
24631
  this.visitERBNode(node);
24033
24632
  this.visitChildNodes(node);
24034
24633
  }
24634
+ visitRubyStrictLocalNode(node) {
24635
+ this.visitNode(node);
24636
+ this.visitChildNodes(node);
24637
+ }
24638
+ visitERBStrictLocalsNode(node) {
24639
+ this.visitNode(node);
24640
+ this.visitERBNode(node);
24641
+ this.visitChildNodes(node);
24642
+ }
24035
24643
  visitERBYieldNode(node) {
24036
24644
  this.visitNode(node);
24037
24645
  this.visitERBNode(node);
@@ -24064,6 +24672,34 @@ function createWhitespaceNode() {
24064
24672
  });
24065
24673
  }
24066
24674
  class ActionViewTagHelperToHTMLVisitor extends Visitor {
24675
+ shallow;
24676
+ includeBody;
24677
+ constructor(options = {}) {
24678
+ super();
24679
+ this.shallow = options.shallow ?? false;
24680
+ this.includeBody = options.includeBody ?? true;
24681
+ }
24682
+ visitHTMLOpenTagNode(node) {
24683
+ const newChildren = [];
24684
+ for (let index = 0; index < node.children.length; index++) {
24685
+ const child = node.children[index];
24686
+ if (isHTMLAttributeNode(child)) {
24687
+ if (child.equals && child.equals.value !== "=") {
24688
+ asMutable(child).equals = createSyntheticToken("=");
24689
+ }
24690
+ if (child.value) {
24691
+ this.transformAttributeValue(child.value);
24692
+ }
24693
+ const previous = index > 0 ? node.children[index - 1] : null;
24694
+ if (!previous || !isWhitespaceNode(previous)) {
24695
+ newChildren.push(createWhitespaceNode());
24696
+ }
24697
+ }
24698
+ newChildren.push(child);
24699
+ }
24700
+ asMutable(node).children = newChildren;
24701
+ this.visitChildNodes(node);
24702
+ }
24067
24703
  visitHTMLElementNode(node) {
24068
24704
  if (!node.element_source) {
24069
24705
  this.visitChildNodes(node);
@@ -24134,7 +24770,10 @@ class ActionViewTagHelperToHTMLVisitor extends Visitor {
24134
24770
  asMutable(node).close_tag = htmlCloseTag;
24135
24771
  }
24136
24772
  asMutable(node).element_source = "HTML";
24137
- if (node.body) {
24773
+ if (!this.includeBody) {
24774
+ asMutable(node).body = [];
24775
+ }
24776
+ else if (node.body) {
24138
24777
  asMutable(node).body = node.body.map(child => {
24139
24778
  if (isRubyLiteralNode(child)) {
24140
24779
  return new ERBContentNode({
@@ -24149,7 +24788,9 @@ class ActionViewTagHelperToHTMLVisitor extends Visitor {
24149
24788
  prism_node: null
24150
24789
  });
24151
24790
  }
24152
- this.visit(child);
24791
+ if (!this.shallow) {
24792
+ this.visit(child);
24793
+ }
24153
24794
  return child;
24154
24795
  });
24155
24796
  }
@@ -24175,11 +24816,11 @@ class ActionViewTagHelperToHTMLVisitor extends Visitor {
24175
24816
  return child;
24176
24817
  });
24177
24818
  mutableValue.children = newChildren;
24178
- if (!value.quoted) {
24179
- mutableValue.quoted = true;
24180
- mutableValue.open_quote = createSyntheticToken('"');
24181
- mutableValue.close_quote = createSyntheticToken('"');
24182
- }
24819
+ }
24820
+ if (!value.quoted) {
24821
+ mutableValue.quoted = true;
24822
+ mutableValue.open_quote = createSyntheticToken('"');
24823
+ mutableValue.close_quote = createSyntheticToken('"');
24183
24824
  }
24184
24825
  }
24185
24826
  }
@@ -24190,11 +24831,132 @@ class ActionViewTagHelperToHTMLRewriter extends ASTRewriter {
24190
24831
  get description() {
24191
24832
  return "Converts ActionView tag helpers to raw HTML elements";
24192
24833
  }
24834
+ rewrite(node, context) {
24835
+ const visitor = new ActionViewTagHelperToHTMLVisitor({ shallow: context.shallow, includeBody: context.includeBody });
24836
+ visitor.visit(node);
24837
+ return node;
24838
+ }
24839
+ }
24840
+
24841
+ const STRING_NODE_TYPE = "StringNode";
24842
+ const INTERPOLATED_STRING_NODE_TYPE = "InterpolatedStringNode";
24843
+ const EMBEDDED_STATEMENTS_NODE_TYPE = "EmbeddedStatementsNode";
24844
+ class ERBStringToDirectOutputVisitor extends Visitor {
24845
+ root;
24846
+ constructor(root) {
24847
+ super();
24848
+ this.root = root;
24849
+ }
24850
+ visitERBContentNode(node) {
24851
+ if (!isERBOutputNode(node)) {
24852
+ this.visitChildNodes(node);
24853
+ return;
24854
+ }
24855
+ const prismNode = node.prismNode;
24856
+ if (!prismNode) {
24857
+ this.visitChildNodes(node);
24858
+ return;
24859
+ }
24860
+ const source = node.source;
24861
+ if (!source) {
24862
+ this.visitChildNodes(node);
24863
+ return;
24864
+ }
24865
+ if (!ERBStringToDirectOutputRewriter.isStringOutputNode(prismNode)) {
24866
+ this.visitChildNodes(node);
24867
+ return;
24868
+ }
24869
+ const replacementParts = ERBStringToDirectOutputRewriter.extractReplacementParts(prismNode, source);
24870
+ if (!replacementParts) {
24871
+ this.visitChildNodes(node);
24872
+ return;
24873
+ }
24874
+ const tagOpening = node.tag_opening?.value ?? "<%=";
24875
+ const tagClosing = node.tag_closing?.value ?? "%>";
24876
+ const parentInfo = findParentArray(this.root, node);
24877
+ if (!parentInfo) {
24878
+ this.visitChildNodes(node);
24879
+ return;
24880
+ }
24881
+ const { array: parentArray, index: nodeIndex } = parentInfo;
24882
+ const replacementNodes = [];
24883
+ for (const part of replacementParts) {
24884
+ if (part.type === "text") {
24885
+ replacementNodes.push(createLiteral(part.content));
24886
+ }
24887
+ else {
24888
+ replacementNodes.push(createERBOutputNode(` ${part.expression.trim()} `, tagOpening, tagClosing));
24889
+ }
24890
+ }
24891
+ parentArray.splice(nodeIndex, 1, ...replacementNodes);
24892
+ }
24893
+ }
24894
+ class ERBStringToDirectOutputRewriter extends ASTRewriter {
24895
+ get name() {
24896
+ return "erb-string-to-direct-output";
24897
+ }
24898
+ get description() {
24899
+ return "Replaces ERB string output with direct text and expression tags";
24900
+ }
24193
24901
  rewrite(node, _context) {
24194
- const visitor = new ActionViewTagHelperToHTMLVisitor();
24902
+ const visitor = new ERBStringToDirectOutputVisitor(node);
24195
24903
  visitor.visit(node);
24196
24904
  return node;
24197
24905
  }
24906
+ static isStringOutputNode(prismNode) {
24907
+ const nodeType = prismNode.constructor.name;
24908
+ return nodeType === STRING_NODE_TYPE || nodeType === INTERPOLATED_STRING_NODE_TYPE;
24909
+ }
24910
+ static extractStringContent(stringNode, source) {
24911
+ const unescapedValue = stringNode.unescaped?.value;
24912
+ if (typeof unescapedValue === "string") {
24913
+ return unescapedValue;
24914
+ }
24915
+ const location = stringNode.contentLoc;
24916
+ if (location) {
24917
+ return source.substring(location.startOffset, location.startOffset + location.length);
24918
+ }
24919
+ return "";
24920
+ }
24921
+ static extractExpressionSource(embeddedNode, source) {
24922
+ const openingLocation = embeddedNode.openingLoc;
24923
+ const closingLocation = embeddedNode.closingLoc;
24924
+ if (!openingLocation || !closingLocation)
24925
+ return null;
24926
+ const expressionStart = openingLocation.startOffset + openingLocation.length;
24927
+ const expressionEnd = closingLocation.startOffset;
24928
+ return source.substring(expressionStart, expressionEnd);
24929
+ }
24930
+ static extractReplacementParts(prismNode, source) {
24931
+ const nodeType = prismNode.constructor.name;
24932
+ if (nodeType === STRING_NODE_TYPE) {
24933
+ const textContent = this.extractStringContent(prismNode, source);
24934
+ return [{ type: "text", content: textContent }];
24935
+ }
24936
+ if (nodeType === INTERPOLATED_STRING_NODE_TYPE) {
24937
+ const parts = prismNode.parts;
24938
+ if (!parts || parts.length === 0)
24939
+ return null;
24940
+ const replacementParts = [];
24941
+ for (const part of parts) {
24942
+ const partType = part.constructor.name;
24943
+ if (partType === STRING_NODE_TYPE) {
24944
+ const textContent = this.extractStringContent(part, source);
24945
+ if (textContent) {
24946
+ replacementParts.push({ type: "text", content: textContent });
24947
+ }
24948
+ }
24949
+ else if (partType === EMBEDDED_STATEMENTS_NODE_TYPE) {
24950
+ const expression = this.extractExpressionSource(part, source);
24951
+ if (expression) {
24952
+ replacementParts.push({ type: "expression", expression });
24953
+ }
24954
+ }
24955
+ }
24956
+ return replacementParts.length > 0 ? replacementParts : null;
24957
+ }
24958
+ return null;
24959
+ }
24198
24960
  }
24199
24961
 
24200
24962
  function serializeAttributeValue(value) {
@@ -24284,9 +25046,10 @@ class HTMLToActionViewTagHelperVisitor extends Visitor {
24284
25046
  const isAnchor = tagName.value === "a";
24285
25047
  const isTurboFrame = tagName.value === "turbo-frame";
24286
25048
  const isScript = tagName.value === "script";
25049
+ const isImg = tagName.value === "img";
24287
25050
  const attributes = openTag.children.filter(child => !isWhitespaceNode(child));
24288
- const hasSrcAttribute = isScript && attributes.some(child => isHTMLAttributeNode(child) && getStaticAttributeName(child.name) === "src");
24289
- const { attributes: attributesString, href, id, src } = serializeAttributes(attributes, { extractHref: isAnchor, extractId: isTurboFrame, extractSrc: isScript });
25051
+ const hasSrcAttribute = (isScript || isImg) && attributes.some(child => isHTMLAttributeNode(child) && getStaticAttributeName(child.name) === "src");
25052
+ const { attributes: attributesString, href, id, src } = serializeAttributes(attributes, { extractHref: isAnchor, extractId: isTurboFrame, extractSrc: isScript || isImg });
24290
25053
  const hasBody = node.body && node.body.length > 0 && !node.is_void;
24291
25054
  const isInlineContent = hasBody && isTextOnlyBody(node.body);
24292
25055
  let content;
@@ -24307,6 +25070,10 @@ class HTMLToActionViewTagHelperVisitor extends Visitor {
24307
25070
  content = this.buildJavascriptTagContent(node, attributesString, isInlineContent);
24308
25071
  elementSource = "ActionView::Helpers::JavaScriptHelper#javascript_tag";
24309
25072
  }
25073
+ else if (isImg) {
25074
+ content = this.buildImageTagContent(attributesString, src);
25075
+ elementSource = "ActionView::Helpers::AssetTagHelper#image_tag";
25076
+ }
24310
25077
  else {
24311
25078
  content = this.buildTagContent(tagName.value, node, attributesString, isInlineContent);
24312
25079
  elementSource = "ActionView::Helpers::TagHelper#tag";
@@ -24324,7 +25091,7 @@ class HTMLToActionViewTagHelperVisitor extends Visitor {
24324
25091
  asMutable(node).open_tag = erbOpenTag;
24325
25092
  asMutable(node).element_source = elementSource;
24326
25093
  const isInlineLiteralContent = isScript && hasBody && node.body.length === 1 && isLiteralNode(node.body[0]) && !node.body[0].content.includes("\n");
24327
- const isInlineForm = isInlineContent || isInlineLiteralContent || (isTurboFrame && !hasBody) || (isScript && hasSrcAttribute);
25094
+ const isInlineForm = isInlineContent || isInlineLiteralContent || (isTurboFrame && !hasBody) || (isScript && hasSrcAttribute) || isImg;
24328
25095
  if (node.is_void) {
24329
25096
  asMutable(node).close_tag = null;
24330
25097
  }
@@ -24408,6 +25175,15 @@ class HTMLToActionViewTagHelperVisitor extends Visitor {
24408
25175
  const argString = args.join(", ");
24409
25176
  return argString ? ` javascript_include_tag ${argString} ` : ` javascript_include_tag `;
24410
25177
  }
25178
+ buildImageTagContent(attributes, source) {
25179
+ const args = [];
25180
+ if (source)
25181
+ args.push(source);
25182
+ if (attributes)
25183
+ args.push(attributes);
25184
+ const argString = args.join(", ");
25185
+ return argString ? ` image_tag ${argString} ` : ` image_tag `;
25186
+ }
24411
25187
  buildLinkToContent(node, attribute, href, isInlineContent) {
24412
25188
  const args = [];
24413
25189
  if (isInlineContent && isHTMLTextNode(node.body[0])) {
@@ -24431,7 +25207,7 @@ class HTMLToActionViewTagHelperRewriter extends ASTRewriter {
24431
25207
  return "html-to-action-view-tag-helper";
24432
25208
  }
24433
25209
  get description() {
24434
- return "Converts raw HTML elements to ActionView tag helpers (tag.*, turbo_frame_tag, javascript_tag, javascript_include_tag)";
25210
+ return "Converts raw HTML elements to ActionView tag helpers (tag.*, turbo_frame_tag, javascript_tag, javascript_include_tag, image_tag)";
24435
25211
  }
24436
25212
  rewrite(node, _context) {
24437
25213
  const visitor = new HTMLToActionViewTagHelperVisitor();
@@ -24858,6 +25634,15 @@ class IdentityPrinter extends Printer {
24858
25634
  if (node.body) {
24859
25635
  node.body.forEach(child => this.visit(child));
24860
25636
  }
25637
+ if (node.rescue_clause) {
25638
+ this.visit(node.rescue_clause);
25639
+ }
25640
+ if (node.else_clause) {
25641
+ this.visit(node.else_clause);
25642
+ }
25643
+ if (node.ensure_clause) {
25644
+ this.visit(node.ensure_clause);
25645
+ }
24861
25646
  if (node.end_node) {
24862
25647
  this.visit(node.end_node);
24863
25648
  }
@@ -24961,6 +25746,12 @@ class IdentityPrinter extends Printer {
24961
25746
  visitRubyRenderLocalNode(_node) {
24962
25747
  // extracted metadata, nothing to print
24963
25748
  }
25749
+ visitERBStrictLocalsNode(node) {
25750
+ this.printERBNode(node);
25751
+ }
25752
+ visitRubyStrictLocalNode(_node) {
25753
+ // extracted metadata, nothing to print
25754
+ }
24964
25755
  visitERBYieldNode(node) {
24965
25756
  this.printERBNode(node);
24966
25757
  }
@@ -25509,6 +26300,7 @@ class TailwindClassSorterRewriter extends ASTRewriter {
25509
26300
  */
25510
26301
  const builtinRewriters = [
25511
26302
  ActionViewTagHelperToHTMLRewriter,
26303
+ ERBStringToDirectOutputRewriter,
25512
26304
  HTMLToActionViewTagHelperRewriter,
25513
26305
  TailwindClassSorterRewriter
25514
26306
  ];
@@ -25560,6 +26352,7 @@ async function tailwindClassSorter(options = {}) {
25560
26352
  exports.ASTRewriter = ASTRewriter;
25561
26353
  exports.ActionViewTagHelperToHTMLRewriter = ActionViewTagHelperToHTMLRewriter;
25562
26354
  exports.CustomRewriterLoader = CustomRewriterLoader;
26355
+ exports.ERBStringToDirectOutputRewriter = ERBStringToDirectOutputRewriter;
25563
26356
  exports.HTMLToActionViewTagHelperRewriter = HTMLToActionViewTagHelperRewriter;
25564
26357
  exports.StringRewriter = StringRewriter;
25565
26358
  exports.TailwindClassSorterRewriter = TailwindClassSorterRewriter;