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