@herb-tools/core 0.6.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/herb-core.browser.js +222 -37
- package/dist/herb-core.browser.js.map +1 -1
- package/dist/herb-core.cjs +229 -36
- package/dist/herb-core.cjs.map +1 -1
- package/dist/herb-core.esm.js +222 -37
- package/dist/herb-core.esm.js.map +1 -1
- package/dist/herb-core.umd.js +229 -36
- package/dist/herb-core.umd.js.map +1 -1
- package/dist/types/ast-utils.d.ts +52 -2
- package/dist/types/node-type-guards.d.ts +3 -3
- package/dist/types/nodes.d.ts +38 -0
- package/package.json +1 -1
- package/src/ast-utils.ts +101 -1
- package/src/errors.ts +1 -1
- package/src/node-type-guards.ts +38 -36
- package/src/nodes.ts +137 -1
- package/src/visitor.ts +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { HTMLElementNode, HTMLOpenTagNode, HTMLCloseTagNode } from "./nodes.js";
|
|
2
|
-
import {
|
|
1
|
+
import { Node, ERBContentNode, HTMLElementNode, HTMLOpenTagNode, HTMLCloseTagNode, HTMLAttributeNameNode } from "./nodes.js";
|
|
2
|
+
import type { Location } from "./location.js";
|
|
3
|
+
import type { Position } from "./position.js";
|
|
3
4
|
/**
|
|
4
5
|
* Checks if a node is an ERB output node (generates content: <%= %> or <%== %>)
|
|
5
6
|
*/
|
|
@@ -72,3 +73,52 @@ export declare function getTagName(node: HTMLElementNode | HTMLOpenTagNode | HTM
|
|
|
72
73
|
* Check if a node is a comment (HTML comment or ERB comment)
|
|
73
74
|
*/
|
|
74
75
|
export declare function isCommentNode(node: Node): boolean;
|
|
76
|
+
/**
|
|
77
|
+
* Compares two positions to determine if they are equal
|
|
78
|
+
* Returns true if pos1 and pos2 are at the same location
|
|
79
|
+
*/
|
|
80
|
+
export declare function isPositionEqual(position1: Position, position2: Position): boolean;
|
|
81
|
+
/**
|
|
82
|
+
* Compares two positions to determine if the first comes after the second
|
|
83
|
+
* Returns true if pos1 comes after pos2 in source order
|
|
84
|
+
* @param inclusive - If true, returns true when positions are equal
|
|
85
|
+
*/
|
|
86
|
+
export declare function isPositionAfter(position1: Position, position2: Position, inclusive?: boolean): boolean;
|
|
87
|
+
/**
|
|
88
|
+
* Gets nodes that appear before the specified location in source order
|
|
89
|
+
* Uses line and column positions to determine ordering
|
|
90
|
+
*/
|
|
91
|
+
export declare function getNodesBeforeLocation<T extends Node>(nodes: T[], location: Location): T[];
|
|
92
|
+
/**
|
|
93
|
+
* Gets nodes that appear after the specified location in source order
|
|
94
|
+
* Uses line and column positions to determine ordering
|
|
95
|
+
*/
|
|
96
|
+
export declare function getNodesAfterLocation<T extends Node>(nodes: T[], location: Location): T[];
|
|
97
|
+
/**
|
|
98
|
+
* Splits nodes into before and after the specified location
|
|
99
|
+
* Returns an object with `before` and `after` arrays
|
|
100
|
+
*/
|
|
101
|
+
export declare function splitNodesAroundLocation<T extends Node>(nodes: T[], location: Location): {
|
|
102
|
+
before: T[];
|
|
103
|
+
after: T[];
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* Splits nodes at a specific position
|
|
107
|
+
* Returns nodes that end before the position and nodes that start after the position
|
|
108
|
+
* More precise than splitNodesAroundLocation as it uses a single position point
|
|
109
|
+
* Uses the same defaults as the individual functions: before=exclusive, after=inclusive
|
|
110
|
+
*/
|
|
111
|
+
export declare function splitNodesAroundPosition<T extends Node>(nodes: T[], position: Position): {
|
|
112
|
+
before: T[];
|
|
113
|
+
after: T[];
|
|
114
|
+
};
|
|
115
|
+
/**
|
|
116
|
+
* Gets nodes that end before the specified position
|
|
117
|
+
* @param inclusive - If true, includes nodes that end exactly at the position (default: false, matching half-open interval semantics)
|
|
118
|
+
*/
|
|
119
|
+
export declare function getNodesBeforePosition<T extends Node>(nodes: T[], position: Position, inclusive?: boolean): T[];
|
|
120
|
+
/**
|
|
121
|
+
* Gets nodes that start after the specified position
|
|
122
|
+
* @param inclusive - If true, includes nodes that start exactly at the position (default: true, matching typical boundary behavior)
|
|
123
|
+
*/
|
|
124
|
+
export declare function getNodesAfterPosition<T extends Node>(nodes: T[], position: Position, inclusive?: boolean): T[];
|
|
@@ -164,7 +164,7 @@ export declare const NODE_TYPE_GUARDS: Map<new (...args: any[]) => Node, (node:
|
|
|
164
164
|
* // node is HTMLTextNode
|
|
165
165
|
* }
|
|
166
166
|
*/
|
|
167
|
-
export declare const AST_TYPE_GUARDS: Map<
|
|
167
|
+
export declare const AST_TYPE_GUARDS: Map<NodeType, (node: Node) => boolean>;
|
|
168
168
|
type NodeTypeToClass = {
|
|
169
169
|
"AST_DOCUMENT_NODE": DocumentNode;
|
|
170
170
|
"AST_LITERAL_NODE": LiteralNode;
|
|
@@ -296,8 +296,8 @@ export declare function filterNodes(nodes: Node[] | undefined | null, ...types:
|
|
|
296
296
|
* // node is narrowed to HTMLTextNode
|
|
297
297
|
* }
|
|
298
298
|
*/
|
|
299
|
-
export declare function isNode<T extends NodeType>(node: Node, type: T): node is NodeTypeToClass[T];
|
|
300
|
-
export declare function isNode<T extends new (...args: any[]) => Node>(node: Node, type: T): node is ClassToInstance<T>;
|
|
299
|
+
export declare function isNode<T extends NodeType>(node: Node | null | undefined, type: T): node is NodeTypeToClass[T];
|
|
300
|
+
export declare function isNode<T extends new (...args: any[]) => Node>(node: Node | null | undefined, type: T): node is ClassToInstance<T>;
|
|
301
301
|
export declare function isToken(object: any): object is Token;
|
|
302
302
|
export declare function isParseResult(object: any): object is ParseResult;
|
|
303
303
|
/**
|
package/dist/types/nodes.d.ts
CHANGED
|
@@ -20,9 +20,16 @@ export declare abstract class Node implements BaseNodeProps {
|
|
|
20
20
|
readonly location: Location;
|
|
21
21
|
readonly errors: HerbError[];
|
|
22
22
|
static from(node: SerializedNode): Node;
|
|
23
|
+
static get type(): NodeType;
|
|
23
24
|
constructor(type: NodeType, location: Location, errors: HerbError[]);
|
|
24
25
|
toJSON(): SerializedNode;
|
|
25
26
|
inspect(): string;
|
|
27
|
+
is<T extends Node>(nodeClass: {
|
|
28
|
+
new (...args: any[]): T;
|
|
29
|
+
prototype: T;
|
|
30
|
+
type: NodeType;
|
|
31
|
+
}): this is T;
|
|
32
|
+
isOfType<T extends Node>(type: NodeType): this is T;
|
|
26
33
|
get isSingleLine(): boolean;
|
|
27
34
|
abstract treeInspect(indent?: number): string;
|
|
28
35
|
abstract recursiveErrors(): HerbError[];
|
|
@@ -41,6 +48,7 @@ export interface DocumentNodeProps extends BaseNodeProps {
|
|
|
41
48
|
}
|
|
42
49
|
export declare class DocumentNode extends Node {
|
|
43
50
|
readonly children: Node[];
|
|
51
|
+
static get type(): NodeType;
|
|
44
52
|
static from(data: SerializedDocumentNode): DocumentNode;
|
|
45
53
|
constructor(props: DocumentNodeProps);
|
|
46
54
|
accept(visitor: Visitor): void;
|
|
@@ -59,6 +67,7 @@ export interface LiteralNodeProps extends BaseNodeProps {
|
|
|
59
67
|
}
|
|
60
68
|
export declare class LiteralNode extends Node {
|
|
61
69
|
readonly content: string;
|
|
70
|
+
static get type(): NodeType;
|
|
62
71
|
static from(data: SerializedLiteralNode): LiteralNode;
|
|
63
72
|
constructor(props: LiteralNodeProps);
|
|
64
73
|
accept(visitor: Visitor): void;
|
|
@@ -89,6 +98,7 @@ export declare class HTMLOpenTagNode extends Node {
|
|
|
89
98
|
readonly tag_closing: Token | null;
|
|
90
99
|
readonly children: Node[];
|
|
91
100
|
readonly is_void: boolean;
|
|
101
|
+
static get type(): NodeType;
|
|
92
102
|
static from(data: SerializedHTMLOpenTagNode): HTMLOpenTagNode;
|
|
93
103
|
constructor(props: HTMLOpenTagNodeProps);
|
|
94
104
|
accept(visitor: Visitor): void;
|
|
@@ -116,6 +126,7 @@ export declare class HTMLCloseTagNode extends Node {
|
|
|
116
126
|
readonly tag_name: Token | null;
|
|
117
127
|
readonly children: Node[];
|
|
118
128
|
readonly tag_closing: Token | null;
|
|
129
|
+
static get type(): NodeType;
|
|
119
130
|
static from(data: SerializedHTMLCloseTagNode): HTMLCloseTagNode;
|
|
120
131
|
constructor(props: HTMLCloseTagNodeProps);
|
|
121
132
|
accept(visitor: Visitor): void;
|
|
@@ -146,6 +157,7 @@ export declare class HTMLElementNode extends Node {
|
|
|
146
157
|
readonly body: Node[];
|
|
147
158
|
readonly close_tag: HTMLCloseTagNode | null;
|
|
148
159
|
readonly is_void: boolean;
|
|
160
|
+
static get type(): NodeType;
|
|
149
161
|
static from(data: SerializedHTMLElementNode): HTMLElementNode;
|
|
150
162
|
constructor(props: HTMLElementNodeProps);
|
|
151
163
|
accept(visitor: Visitor): void;
|
|
@@ -173,6 +185,7 @@ export declare class HTMLAttributeValueNode extends Node {
|
|
|
173
185
|
readonly children: Node[];
|
|
174
186
|
readonly close_quote: Token | null;
|
|
175
187
|
readonly quoted: boolean;
|
|
188
|
+
static get type(): NodeType;
|
|
176
189
|
static from(data: SerializedHTMLAttributeValueNode): HTMLAttributeValueNode;
|
|
177
190
|
constructor(props: HTMLAttributeValueNodeProps);
|
|
178
191
|
accept(visitor: Visitor): void;
|
|
@@ -191,6 +204,7 @@ export interface HTMLAttributeNameNodeProps extends BaseNodeProps {
|
|
|
191
204
|
}
|
|
192
205
|
export declare class HTMLAttributeNameNode extends Node {
|
|
193
206
|
readonly children: Node[];
|
|
207
|
+
static get type(): NodeType;
|
|
194
208
|
static from(data: SerializedHTMLAttributeNameNode): HTMLAttributeNameNode;
|
|
195
209
|
constructor(props: HTMLAttributeNameNodeProps);
|
|
196
210
|
accept(visitor: Visitor): void;
|
|
@@ -215,6 +229,7 @@ export declare class HTMLAttributeNode extends Node {
|
|
|
215
229
|
readonly name: HTMLAttributeNameNode | null;
|
|
216
230
|
readonly equals: Token | null;
|
|
217
231
|
readonly value: HTMLAttributeValueNode | null;
|
|
232
|
+
static get type(): NodeType;
|
|
218
233
|
static from(data: SerializedHTMLAttributeNode): HTMLAttributeNode;
|
|
219
234
|
constructor(props: HTMLAttributeNodeProps);
|
|
220
235
|
accept(visitor: Visitor): void;
|
|
@@ -233,6 +248,7 @@ export interface HTMLTextNodeProps extends BaseNodeProps {
|
|
|
233
248
|
}
|
|
234
249
|
export declare class HTMLTextNode extends Node {
|
|
235
250
|
readonly content: string;
|
|
251
|
+
static get type(): NodeType;
|
|
236
252
|
static from(data: SerializedHTMLTextNode): HTMLTextNode;
|
|
237
253
|
constructor(props: HTMLTextNodeProps);
|
|
238
254
|
accept(visitor: Visitor): void;
|
|
@@ -257,6 +273,7 @@ export declare class HTMLCommentNode extends Node {
|
|
|
257
273
|
readonly comment_start: Token | null;
|
|
258
274
|
readonly children: Node[];
|
|
259
275
|
readonly comment_end: Token | null;
|
|
276
|
+
static get type(): NodeType;
|
|
260
277
|
static from(data: SerializedHTMLCommentNode): HTMLCommentNode;
|
|
261
278
|
constructor(props: HTMLCommentNodeProps);
|
|
262
279
|
accept(visitor: Visitor): void;
|
|
@@ -281,6 +298,7 @@ export declare class HTMLDoctypeNode extends Node {
|
|
|
281
298
|
readonly tag_opening: Token | null;
|
|
282
299
|
readonly children: Node[];
|
|
283
300
|
readonly tag_closing: Token | null;
|
|
301
|
+
static get type(): NodeType;
|
|
284
302
|
static from(data: SerializedHTMLDoctypeNode): HTMLDoctypeNode;
|
|
285
303
|
constructor(props: HTMLDoctypeNodeProps);
|
|
286
304
|
accept(visitor: Visitor): void;
|
|
@@ -305,6 +323,7 @@ export declare class XMLDeclarationNode extends Node {
|
|
|
305
323
|
readonly tag_opening: Token | null;
|
|
306
324
|
readonly children: Node[];
|
|
307
325
|
readonly tag_closing: Token | null;
|
|
326
|
+
static get type(): NodeType;
|
|
308
327
|
static from(data: SerializedXMLDeclarationNode): XMLDeclarationNode;
|
|
309
328
|
constructor(props: XMLDeclarationNodeProps);
|
|
310
329
|
accept(visitor: Visitor): void;
|
|
@@ -329,6 +348,7 @@ export declare class CDATANode extends Node {
|
|
|
329
348
|
readonly tag_opening: Token | null;
|
|
330
349
|
readonly children: Node[];
|
|
331
350
|
readonly tag_closing: Token | null;
|
|
351
|
+
static get type(): NodeType;
|
|
332
352
|
static from(data: SerializedCDATANode): CDATANode;
|
|
333
353
|
constructor(props: CDATANodeProps);
|
|
334
354
|
accept(visitor: Visitor): void;
|
|
@@ -347,6 +367,7 @@ export interface WhitespaceNodeProps extends BaseNodeProps {
|
|
|
347
367
|
}
|
|
348
368
|
export declare class WhitespaceNode extends Node {
|
|
349
369
|
readonly value: Token | null;
|
|
370
|
+
static get type(): NodeType;
|
|
350
371
|
static from(data: SerializedWhitespaceNode): WhitespaceNode;
|
|
351
372
|
constructor(props: WhitespaceNodeProps);
|
|
352
373
|
accept(visitor: Visitor): void;
|
|
@@ -377,6 +398,7 @@ export declare class ERBContentNode extends Node {
|
|
|
377
398
|
readonly tag_closing: Token | null;
|
|
378
399
|
readonly parsed: boolean;
|
|
379
400
|
readonly valid: boolean;
|
|
401
|
+
static get type(): NodeType;
|
|
380
402
|
static from(data: SerializedERBContentNode): ERBContentNode;
|
|
381
403
|
constructor(props: ERBContentNodeProps);
|
|
382
404
|
accept(visitor: Visitor): void;
|
|
@@ -401,6 +423,7 @@ export declare class ERBEndNode extends Node {
|
|
|
401
423
|
readonly tag_opening: Token | null;
|
|
402
424
|
readonly content: Token | null;
|
|
403
425
|
readonly tag_closing: Token | null;
|
|
426
|
+
static get type(): NodeType;
|
|
404
427
|
static from(data: SerializedERBEndNode): ERBEndNode;
|
|
405
428
|
constructor(props: ERBEndNodeProps);
|
|
406
429
|
accept(visitor: Visitor): void;
|
|
@@ -428,6 +451,7 @@ export declare class ERBElseNode extends Node {
|
|
|
428
451
|
readonly content: Token | null;
|
|
429
452
|
readonly tag_closing: Token | null;
|
|
430
453
|
readonly statements: Node[];
|
|
454
|
+
static get type(): NodeType;
|
|
431
455
|
static from(data: SerializedERBElseNode): ERBElseNode;
|
|
432
456
|
constructor(props: ERBElseNodeProps);
|
|
433
457
|
accept(visitor: Visitor): void;
|
|
@@ -461,6 +485,7 @@ export declare class ERBIfNode extends Node {
|
|
|
461
485
|
readonly statements: Node[];
|
|
462
486
|
readonly subsequent: Node | null;
|
|
463
487
|
readonly end_node: ERBEndNode | null;
|
|
488
|
+
static get type(): NodeType;
|
|
464
489
|
static from(data: SerializedERBIfNode): ERBIfNode;
|
|
465
490
|
constructor(props: ERBIfNodeProps);
|
|
466
491
|
accept(visitor: Visitor): void;
|
|
@@ -491,6 +516,7 @@ export declare class ERBBlockNode extends Node {
|
|
|
491
516
|
readonly tag_closing: Token | null;
|
|
492
517
|
readonly body: Node[];
|
|
493
518
|
readonly end_node: ERBEndNode | null;
|
|
519
|
+
static get type(): NodeType;
|
|
494
520
|
static from(data: SerializedERBBlockNode): ERBBlockNode;
|
|
495
521
|
constructor(props: ERBBlockNodeProps);
|
|
496
522
|
accept(visitor: Visitor): void;
|
|
@@ -518,6 +544,7 @@ export declare class ERBWhenNode extends Node {
|
|
|
518
544
|
readonly content: Token | null;
|
|
519
545
|
readonly tag_closing: Token | null;
|
|
520
546
|
readonly statements: Node[];
|
|
547
|
+
static get type(): NodeType;
|
|
521
548
|
static from(data: SerializedERBWhenNode): ERBWhenNode;
|
|
522
549
|
constructor(props: ERBWhenNodeProps);
|
|
523
550
|
accept(visitor: Visitor): void;
|
|
@@ -554,6 +581,7 @@ export declare class ERBCaseNode extends Node {
|
|
|
554
581
|
readonly conditions: Node[];
|
|
555
582
|
readonly else_clause: ERBElseNode | null;
|
|
556
583
|
readonly end_node: ERBEndNode | null;
|
|
584
|
+
static get type(): NodeType;
|
|
557
585
|
static from(data: SerializedERBCaseNode): ERBCaseNode;
|
|
558
586
|
constructor(props: ERBCaseNodeProps);
|
|
559
587
|
accept(visitor: Visitor): void;
|
|
@@ -590,6 +618,7 @@ export declare class ERBCaseMatchNode extends Node {
|
|
|
590
618
|
readonly conditions: Node[];
|
|
591
619
|
readonly else_clause: ERBElseNode | null;
|
|
592
620
|
readonly end_node: ERBEndNode | null;
|
|
621
|
+
static get type(): NodeType;
|
|
593
622
|
static from(data: SerializedERBCaseMatchNode): ERBCaseMatchNode;
|
|
594
623
|
constructor(props: ERBCaseMatchNodeProps);
|
|
595
624
|
accept(visitor: Visitor): void;
|
|
@@ -620,6 +649,7 @@ export declare class ERBWhileNode extends Node {
|
|
|
620
649
|
readonly tag_closing: Token | null;
|
|
621
650
|
readonly statements: Node[];
|
|
622
651
|
readonly end_node: ERBEndNode | null;
|
|
652
|
+
static get type(): NodeType;
|
|
623
653
|
static from(data: SerializedERBWhileNode): ERBWhileNode;
|
|
624
654
|
constructor(props: ERBWhileNodeProps);
|
|
625
655
|
accept(visitor: Visitor): void;
|
|
@@ -650,6 +680,7 @@ export declare class ERBUntilNode extends Node {
|
|
|
650
680
|
readonly tag_closing: Token | null;
|
|
651
681
|
readonly statements: Node[];
|
|
652
682
|
readonly end_node: ERBEndNode | null;
|
|
683
|
+
static get type(): NodeType;
|
|
653
684
|
static from(data: SerializedERBUntilNode): ERBUntilNode;
|
|
654
685
|
constructor(props: ERBUntilNodeProps);
|
|
655
686
|
accept(visitor: Visitor): void;
|
|
@@ -680,6 +711,7 @@ export declare class ERBForNode extends Node {
|
|
|
680
711
|
readonly tag_closing: Token | null;
|
|
681
712
|
readonly statements: Node[];
|
|
682
713
|
readonly end_node: ERBEndNode | null;
|
|
714
|
+
static get type(): NodeType;
|
|
683
715
|
static from(data: SerializedERBForNode): ERBForNode;
|
|
684
716
|
constructor(props: ERBForNodeProps);
|
|
685
717
|
accept(visitor: Visitor): void;
|
|
@@ -710,6 +742,7 @@ export declare class ERBRescueNode extends Node {
|
|
|
710
742
|
readonly tag_closing: Token | null;
|
|
711
743
|
readonly statements: Node[];
|
|
712
744
|
readonly subsequent: ERBRescueNode | null;
|
|
745
|
+
static get type(): NodeType;
|
|
713
746
|
static from(data: SerializedERBRescueNode): ERBRescueNode;
|
|
714
747
|
constructor(props: ERBRescueNodeProps);
|
|
715
748
|
accept(visitor: Visitor): void;
|
|
@@ -737,6 +770,7 @@ export declare class ERBEnsureNode extends Node {
|
|
|
737
770
|
readonly content: Token | null;
|
|
738
771
|
readonly tag_closing: Token | null;
|
|
739
772
|
readonly statements: Node[];
|
|
773
|
+
static get type(): NodeType;
|
|
740
774
|
static from(data: SerializedERBEnsureNode): ERBEnsureNode;
|
|
741
775
|
constructor(props: ERBEnsureNodeProps);
|
|
742
776
|
accept(visitor: Visitor): void;
|
|
@@ -776,6 +810,7 @@ export declare class ERBBeginNode extends Node {
|
|
|
776
810
|
readonly else_clause: ERBElseNode | null;
|
|
777
811
|
readonly ensure_clause: ERBEnsureNode | null;
|
|
778
812
|
readonly end_node: ERBEndNode | null;
|
|
813
|
+
static get type(): NodeType;
|
|
779
814
|
static from(data: SerializedERBBeginNode): ERBBeginNode;
|
|
780
815
|
constructor(props: ERBBeginNodeProps);
|
|
781
816
|
accept(visitor: Visitor): void;
|
|
@@ -809,6 +844,7 @@ export declare class ERBUnlessNode extends Node {
|
|
|
809
844
|
readonly statements: Node[];
|
|
810
845
|
readonly else_clause: ERBElseNode | null;
|
|
811
846
|
readonly end_node: ERBEndNode | null;
|
|
847
|
+
static get type(): NodeType;
|
|
812
848
|
static from(data: SerializedERBUnlessNode): ERBUnlessNode;
|
|
813
849
|
constructor(props: ERBUnlessNodeProps);
|
|
814
850
|
accept(visitor: Visitor): void;
|
|
@@ -833,6 +869,7 @@ export declare class ERBYieldNode extends Node {
|
|
|
833
869
|
readonly tag_opening: Token | null;
|
|
834
870
|
readonly content: Token | null;
|
|
835
871
|
readonly tag_closing: Token | null;
|
|
872
|
+
static get type(): NodeType;
|
|
836
873
|
static from(data: SerializedERBYieldNode): ERBYieldNode;
|
|
837
874
|
constructor(props: ERBYieldNodeProps);
|
|
838
875
|
accept(visitor: Visitor): void;
|
|
@@ -860,6 +897,7 @@ export declare class ERBInNode extends Node {
|
|
|
860
897
|
readonly content: Token | null;
|
|
861
898
|
readonly tag_closing: Token | null;
|
|
862
899
|
readonly statements: Node[];
|
|
900
|
+
static get type(): NodeType;
|
|
863
901
|
static from(data: SerializedERBInNode): ERBInNode;
|
|
864
902
|
constructor(props: ERBInNodeProps);
|
|
865
903
|
accept(visitor: Visitor): void;
|
package/package.json
CHANGED
package/src/ast-utils.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
+
Node,
|
|
2
3
|
LiteralNode,
|
|
4
|
+
ERBContentNode,
|
|
3
5
|
ERBIfNode,
|
|
4
6
|
ERBUnlessNode,
|
|
5
7
|
ERBBlockNode,
|
|
@@ -11,6 +13,7 @@ import {
|
|
|
11
13
|
HTMLElementNode,
|
|
12
14
|
HTMLOpenTagNode,
|
|
13
15
|
HTMLCloseTagNode,
|
|
16
|
+
HTMLAttributeNameNode,
|
|
14
17
|
HTMLCommentNode
|
|
15
18
|
} from "./nodes.js"
|
|
16
19
|
|
|
@@ -24,7 +27,8 @@ import {
|
|
|
24
27
|
filterLiteralNodes
|
|
25
28
|
} from "./node-type-guards.js"
|
|
26
29
|
|
|
27
|
-
import {
|
|
30
|
+
import type { Location } from "./location.js"
|
|
31
|
+
import type { Position } from "./position.js"
|
|
28
32
|
|
|
29
33
|
/**
|
|
30
34
|
* Checks if a node is an ERB output node (generates content: <%= %> or <%== %>)
|
|
@@ -189,3 +193,99 @@ export function getTagName(node: HTMLElementNode | HTMLOpenTagNode | HTMLCloseT
|
|
|
189
193
|
export function isCommentNode(node: Node): boolean {
|
|
190
194
|
return isNode(node, HTMLCommentNode) || (isERBNode(node) && !isERBControlFlowNode(node))
|
|
191
195
|
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Compares two positions to determine if the first comes before the second
|
|
199
|
+
* Returns true if pos1 comes before pos2 in source order
|
|
200
|
+
* @param inclusive - If true, returns true when positions are equal
|
|
201
|
+
*/
|
|
202
|
+
function isPositionBefore(position1: Position, position2: Position, inclusive = false): boolean {
|
|
203
|
+
if (position1.line < position2.line) return true
|
|
204
|
+
if (position1.line > position2.line) return false
|
|
205
|
+
|
|
206
|
+
return inclusive ? position1.column <= position2.column : position1.column < position2.column
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Compares two positions to determine if they are equal
|
|
211
|
+
* Returns true if pos1 and pos2 are at the same location
|
|
212
|
+
*/
|
|
213
|
+
export function isPositionEqual(position1: Position, position2: Position): boolean {
|
|
214
|
+
return position1.line === position2.line && position1.column === position2.column
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Compares two positions to determine if the first comes after the second
|
|
219
|
+
* Returns true if pos1 comes after pos2 in source order
|
|
220
|
+
* @param inclusive - If true, returns true when positions are equal
|
|
221
|
+
*/
|
|
222
|
+
export function isPositionAfter(position1: Position, position2: Position, inclusive = false): boolean {
|
|
223
|
+
if (position1.line > position2.line) return true
|
|
224
|
+
if (position1.line < position2.line) return false
|
|
225
|
+
|
|
226
|
+
return inclusive ? position1.column >= position2.column : position1.column > position2.column
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Gets nodes that appear before the specified location in source order
|
|
231
|
+
* Uses line and column positions to determine ordering
|
|
232
|
+
*/
|
|
233
|
+
export function getNodesBeforeLocation<T extends Node>(nodes: T[], location: Location): T[] {
|
|
234
|
+
return nodes.filter(node =>
|
|
235
|
+
node.location && isPositionBefore(node.location.end, location.start)
|
|
236
|
+
)
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Gets nodes that appear after the specified location in source order
|
|
241
|
+
* Uses line and column positions to determine ordering
|
|
242
|
+
*/
|
|
243
|
+
export function getNodesAfterLocation<T extends Node>(nodes: T[], location: Location): T[] {
|
|
244
|
+
return nodes.filter(node =>
|
|
245
|
+
node.location && isPositionAfter(node.location.start, location.end)
|
|
246
|
+
)
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Splits nodes into before and after the specified location
|
|
251
|
+
* Returns an object with `before` and `after` arrays
|
|
252
|
+
*/
|
|
253
|
+
export function splitNodesAroundLocation<T extends Node>(nodes: T[], location: Location): { before: T[], after: T[] } {
|
|
254
|
+
return {
|
|
255
|
+
before: getNodesBeforeLocation(nodes, location),
|
|
256
|
+
after: getNodesAfterLocation(nodes, location)
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Splits nodes at a specific position
|
|
262
|
+
* Returns nodes that end before the position and nodes that start after the position
|
|
263
|
+
* More precise than splitNodesAroundLocation as it uses a single position point
|
|
264
|
+
* Uses the same defaults as the individual functions: before=exclusive, after=inclusive
|
|
265
|
+
*/
|
|
266
|
+
export function splitNodesAroundPosition<T extends Node>(nodes: T[], position: Position): { before: T[], after: T[] } {
|
|
267
|
+
return {
|
|
268
|
+
before: getNodesBeforePosition(nodes, position), // uses default: inclusive = false
|
|
269
|
+
after: getNodesAfterPosition(nodes, position) // uses default: inclusive = true
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Gets nodes that end before the specified position
|
|
275
|
+
* @param inclusive - If true, includes nodes that end exactly at the position (default: false, matching half-open interval semantics)
|
|
276
|
+
*/
|
|
277
|
+
export function getNodesBeforePosition<T extends Node>(nodes: T[], position: Position, inclusive = false): T[] {
|
|
278
|
+
return nodes.filter(node =>
|
|
279
|
+
node.location && isPositionBefore(node.location.end, position, inclusive)
|
|
280
|
+
)
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Gets nodes that start after the specified position
|
|
285
|
+
* @param inclusive - If true, includes nodes that start exactly at the position (default: true, matching typical boundary behavior)
|
|
286
|
+
*/
|
|
287
|
+
export function getNodesAfterPosition<T extends Node>(nodes: T[], position: Position, inclusive = true): T[] {
|
|
288
|
+
return nodes.filter(node =>
|
|
289
|
+
node.location && isPositionAfter(node.location.start, position, inclusive)
|
|
290
|
+
)
|
|
291
|
+
}
|
package/src/errors.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// NOTE: This file is generated by the templates/template.rb script and should not
|
|
2
|
-
// be modified manually. See /Users/marcoroth/Development/herb-release-0.6.
|
|
2
|
+
// be modified manually. See /Users/marcoroth/Development/herb-release-0.6.1/templates/javascript/packages/core/src/errors.ts.erb
|
|
3
3
|
|
|
4
4
|
import { Location, SerializedLocation } from "./location.js"
|
|
5
5
|
import { Token, SerializedToken } from "./token.js"
|