@herb-tools/core 0.9.0 → 0.9.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.
@@ -69,7 +69,7 @@ export declare function hasStaticAttributeName(attributeNameNode: HTMLAttributeN
69
69
  /**
70
70
  * Checks if an HTML attribute name node has dynamic content (contains ERB)
71
71
  */
72
- export declare function hasDynamicAttributeName(attributeNameNode: HTMLAttributeNameNode): boolean;
72
+ export declare function hasDynamicAttributeNameNode(attributeNameNode: HTMLAttributeNameNode): boolean;
73
73
  /**
74
74
  * Gets the static string value of an HTML attribute name node
75
75
  * Returns null if the attribute name contains dynamic content (ERB)
@@ -151,9 +151,8 @@ export declare function getAttribute(node: HTMLElementNode | HTMLOpenTagNode | n
151
151
  export declare function hasAttribute(node: HTMLElementNode | HTMLOpenTagNode | null | undefined, attributeName: string): boolean;
152
152
  /**
153
153
  * Checks if an attribute has a dynamic (ERB-containing) name.
154
- * Accepts an HTMLAttributeNode (wraps the core HTMLAttributeNameNode-level check).
155
154
  */
156
- export declare function hasDynamicAttributeNameOnAttribute(attributeNode: HTMLAttributeNode): boolean;
155
+ export declare function hasDynamicAttributeName(attributeNode: HTMLAttributeNode): boolean;
157
156
  /**
158
157
  * Gets the combined string representation of an attribute name (including ERB syntax).
159
158
  * Accepts an HTMLAttributeNode (wraps the core HTMLAttributeNameNode-level check).
@@ -1,5 +1,6 @@
1
1
  import { Location, SerializedLocation } from "./location.js";
2
2
  export type DiagnosticSeverity = "error" | "warning" | "info" | "hint";
3
+ export type DiagnosticTag = "unnecessary" | "deprecated";
3
4
  /**
4
5
  * Base interface for all diagnostic information in Herb tooling.
5
6
  * This includes parser errors, lexer errors, lint offenses, and any other
@@ -26,6 +27,10 @@ export interface Diagnostic {
26
27
  * Optional source that generated this diagnostic (e.g., "parser", "linter", "lexer")
27
28
  */
28
29
  source?: string;
30
+ /**
31
+ * Optional diagnostic tags for additional metadata (e.g., "unnecessary", "deprecated")
32
+ */
33
+ tags?: DiagnosticTag[];
29
34
  }
30
35
  /**
31
36
  * Serialized form of a Diagnostic for JSON representation
@@ -36,6 +41,7 @@ export interface SerializedDiagnostic {
36
41
  severity: DiagnosticSeverity;
37
42
  code?: string;
38
43
  source?: string;
44
+ tags?: DiagnosticTag[];
39
45
  }
40
46
  export type MonacoSeverity = "error" | "warning" | "info";
41
47
  /**
@@ -2,7 +2,7 @@ import { Location, SerializedLocation } from "./location.js";
2
2
  import { Position, SerializedPosition } from "./position.js";
3
3
  import { Token, SerializedToken } from "./token.js";
4
4
  import { Diagnostic, MonacoDiagnostic } from "./diagnostic.js";
5
- export type HerbErrorType = "UNEXPECTED_ERROR" | "UNEXPECTED_TOKEN_ERROR" | "MISSING_OPENING_TAG_ERROR" | "MISSING_CLOSING_TAG_ERROR" | "TAG_NAMES_MISMATCH_ERROR" | "VOID_ELEMENT_CLOSING_TAG_ERROR" | "UNCLOSED_ELEMENT_ERROR" | "RUBY_PARSE_ERROR" | "ERB_CONTROL_FLOW_SCOPE_ERROR" | "MISSING_ERB_END_TAG_ERROR" | "ERB_MULTIPLE_BLOCKS_IN_TAG_ERROR" | "ERB_CASE_WITH_CONDITIONS_ERROR" | "CONDITIONAL_ELEMENT_MULTIPLE_TAGS_ERROR" | "CONDITIONAL_ELEMENT_CONDITION_MISMATCH_ERROR" | "INVALID_COMMENT_CLOSING_TAG_ERROR" | "OMITTED_CLOSING_TAG_ERROR" | "UNCLOSED_OPEN_TAG_ERROR" | "UNCLOSED_CLOSE_TAG_ERROR" | "UNCLOSED_QUOTE_ERROR" | "MISSING_ATTRIBUTE_VALUE_ERROR" | "UNCLOSED_ERB_TAG_ERROR" | "STRAY_ERB_CLOSING_TAG_ERROR" | "NESTED_ERB_TAG_ERROR";
5
+ export type HerbErrorType = "UNEXPECTED_ERROR" | "UNEXPECTED_TOKEN_ERROR" | "MISSING_OPENING_TAG_ERROR" | "MISSING_CLOSING_TAG_ERROR" | "TAG_NAMES_MISMATCH_ERROR" | "VOID_ELEMENT_CLOSING_TAG_ERROR" | "UNCLOSED_ELEMENT_ERROR" | "RUBY_PARSE_ERROR" | "ERB_CONTROL_FLOW_SCOPE_ERROR" | "MISSING_ERB_END_TAG_ERROR" | "ERB_MULTIPLE_BLOCKS_IN_TAG_ERROR" | "ERB_CASE_WITH_CONDITIONS_ERROR" | "CONDITIONAL_ELEMENT_MULTIPLE_TAGS_ERROR" | "CONDITIONAL_ELEMENT_CONDITION_MISMATCH_ERROR" | "INVALID_COMMENT_CLOSING_TAG_ERROR" | "OMITTED_CLOSING_TAG_ERROR" | "UNCLOSED_OPEN_TAG_ERROR" | "UNCLOSED_CLOSE_TAG_ERROR" | "UNCLOSED_QUOTE_ERROR" | "MISSING_ATTRIBUTE_VALUE_ERROR" | "UNCLOSED_ERB_TAG_ERROR" | "STRAY_ERB_CLOSING_TAG_ERROR" | "NESTED_ERB_TAG_ERROR" | "RENDER_AMBIGUOUS_LOCALS_ERROR" | "RENDER_MISSING_LOCALS_ERROR" | "RENDER_NO_ARGUMENTS_ERROR" | "RENDER_CONFLICTING_PARTIAL_ERROR" | "RENDER_INVALID_AS_OPTION_ERROR" | "RENDER_OBJECT_AND_COLLECTION_ERROR" | "RENDER_LAYOUT_WITHOUT_BLOCK_ERROR";
6
6
  export type SerializedErrorType = string;
7
7
  export interface SerializedHerbError {
8
8
  type: string;
@@ -527,4 +527,144 @@ export declare class NestedERBTagError extends HerbError {
527
527
  toMonacoDiagnostic(): MonacoDiagnostic;
528
528
  treeInspect(): string;
529
529
  }
530
+ export interface SerializedRenderAmbiguousLocalsError {
531
+ type: "RENDER_AMBIGUOUS_LOCALS_ERROR";
532
+ message: string;
533
+ location: SerializedLocation;
534
+ partial: string;
535
+ }
536
+ export interface RenderAmbiguousLocalsErrorProps {
537
+ type: string;
538
+ message: string;
539
+ location: Location;
540
+ partial: string;
541
+ }
542
+ export declare class RenderAmbiguousLocalsError extends HerbError {
543
+ readonly partial: string;
544
+ static from(data: SerializedRenderAmbiguousLocalsError): RenderAmbiguousLocalsError;
545
+ constructor(props: RenderAmbiguousLocalsErrorProps);
546
+ toJSON(): SerializedRenderAmbiguousLocalsError;
547
+ toMonacoDiagnostic(): MonacoDiagnostic;
548
+ treeInspect(): string;
549
+ }
550
+ export interface SerializedRenderMissingLocalsError {
551
+ type: "RENDER_MISSING_LOCALS_ERROR";
552
+ message: string;
553
+ location: SerializedLocation;
554
+ partial: string;
555
+ keywords: string;
556
+ }
557
+ export interface RenderMissingLocalsErrorProps {
558
+ type: string;
559
+ message: string;
560
+ location: Location;
561
+ partial: string;
562
+ keywords: string;
563
+ }
564
+ export declare class RenderMissingLocalsError extends HerbError {
565
+ readonly partial: string;
566
+ readonly keywords: string;
567
+ static from(data: SerializedRenderMissingLocalsError): RenderMissingLocalsError;
568
+ constructor(props: RenderMissingLocalsErrorProps);
569
+ toJSON(): SerializedRenderMissingLocalsError;
570
+ toMonacoDiagnostic(): MonacoDiagnostic;
571
+ treeInspect(): string;
572
+ }
573
+ export interface SerializedRenderNoArgumentsError {
574
+ type: "RENDER_NO_ARGUMENTS_ERROR";
575
+ message: string;
576
+ location: SerializedLocation;
577
+ }
578
+ export interface RenderNoArgumentsErrorProps {
579
+ type: string;
580
+ message: string;
581
+ location: Location;
582
+ }
583
+ export declare class RenderNoArgumentsError extends HerbError {
584
+ static from(data: SerializedRenderNoArgumentsError): RenderNoArgumentsError;
585
+ constructor(props: RenderNoArgumentsErrorProps);
586
+ toJSON(): SerializedRenderNoArgumentsError;
587
+ toMonacoDiagnostic(): MonacoDiagnostic;
588
+ treeInspect(): string;
589
+ }
590
+ export interface SerializedRenderConflictingPartialError {
591
+ type: "RENDER_CONFLICTING_PARTIAL_ERROR";
592
+ message: string;
593
+ location: SerializedLocation;
594
+ positional_partial: string;
595
+ keyword_partial: string;
596
+ }
597
+ export interface RenderConflictingPartialErrorProps {
598
+ type: string;
599
+ message: string;
600
+ location: Location;
601
+ positional_partial: string;
602
+ keyword_partial: string;
603
+ }
604
+ export declare class RenderConflictingPartialError extends HerbError {
605
+ readonly positional_partial: string;
606
+ readonly keyword_partial: string;
607
+ static from(data: SerializedRenderConflictingPartialError): RenderConflictingPartialError;
608
+ constructor(props: RenderConflictingPartialErrorProps);
609
+ toJSON(): SerializedRenderConflictingPartialError;
610
+ toMonacoDiagnostic(): MonacoDiagnostic;
611
+ treeInspect(): string;
612
+ }
613
+ export interface SerializedRenderInvalidAsOptionError {
614
+ type: "RENDER_INVALID_AS_OPTION_ERROR";
615
+ message: string;
616
+ location: SerializedLocation;
617
+ as_value: string;
618
+ }
619
+ export interface RenderInvalidAsOptionErrorProps {
620
+ type: string;
621
+ message: string;
622
+ location: Location;
623
+ as_value: string;
624
+ }
625
+ export declare class RenderInvalidAsOptionError extends HerbError {
626
+ readonly as_value: string;
627
+ static from(data: SerializedRenderInvalidAsOptionError): RenderInvalidAsOptionError;
628
+ constructor(props: RenderInvalidAsOptionErrorProps);
629
+ toJSON(): SerializedRenderInvalidAsOptionError;
630
+ toMonacoDiagnostic(): MonacoDiagnostic;
631
+ treeInspect(): string;
632
+ }
633
+ export interface SerializedRenderObjectAndCollectionError {
634
+ type: "RENDER_OBJECT_AND_COLLECTION_ERROR";
635
+ message: string;
636
+ location: SerializedLocation;
637
+ }
638
+ export interface RenderObjectAndCollectionErrorProps {
639
+ type: string;
640
+ message: string;
641
+ location: Location;
642
+ }
643
+ export declare class RenderObjectAndCollectionError extends HerbError {
644
+ static from(data: SerializedRenderObjectAndCollectionError): RenderObjectAndCollectionError;
645
+ constructor(props: RenderObjectAndCollectionErrorProps);
646
+ toJSON(): SerializedRenderObjectAndCollectionError;
647
+ toMonacoDiagnostic(): MonacoDiagnostic;
648
+ treeInspect(): string;
649
+ }
650
+ export interface SerializedRenderLayoutWithoutBlockError {
651
+ type: "RENDER_LAYOUT_WITHOUT_BLOCK_ERROR";
652
+ message: string;
653
+ location: SerializedLocation;
654
+ layout: string;
655
+ }
656
+ export interface RenderLayoutWithoutBlockErrorProps {
657
+ type: string;
658
+ message: string;
659
+ location: Location;
660
+ layout: string;
661
+ }
662
+ export declare class RenderLayoutWithoutBlockError extends HerbError {
663
+ readonly layout: string;
664
+ static from(data: SerializedRenderLayoutWithoutBlockError): RenderLayoutWithoutBlockError;
665
+ constructor(props: RenderLayoutWithoutBlockErrorProps);
666
+ toJSON(): SerializedRenderLayoutWithoutBlockError;
667
+ toMonacoDiagnostic(): MonacoDiagnostic;
668
+ treeInspect(): string;
669
+ }
530
670
  export declare function fromSerializedError(error: SerializedHerbError): HerbError;
@@ -1,7 +1,7 @@
1
1
  import type { Node, NodeType, ERBNode } from "./nodes.js";
2
2
  import { Token } from "./token.js";
3
3
  import { ParseResult } from "./parse-result.js";
4
- import { DocumentNode, LiteralNode, HTMLOpenTagNode, HTMLConditionalOpenTagNode, HTMLCloseTagNode, HTMLOmittedCloseTagNode, HTMLVirtualCloseTagNode, HTMLElementNode, HTMLConditionalElementNode, HTMLAttributeValueNode, HTMLAttributeNameNode, HTMLAttributeNode, RubyLiteralNode, RubyHTMLAttributesSplatNode, ERBOpenTagNode, HTMLTextNode, HTMLCommentNode, HTMLDoctypeNode, XMLDeclarationNode, CDATANode, WhitespaceNode, ERBContentNode, ERBEndNode, ERBElseNode, ERBIfNode, ERBBlockNode, ERBWhenNode, ERBCaseNode, ERBCaseMatchNode, ERBWhileNode, ERBUntilNode, ERBForNode, ERBRescueNode, ERBEnsureNode, ERBBeginNode, ERBUnlessNode, ERBYieldNode, ERBInNode } from "./nodes.js";
4
+ import { DocumentNode, LiteralNode, HTMLOpenTagNode, HTMLConditionalOpenTagNode, HTMLCloseTagNode, HTMLOmittedCloseTagNode, HTMLVirtualCloseTagNode, HTMLElementNode, HTMLConditionalElementNode, HTMLAttributeValueNode, HTMLAttributeNameNode, HTMLAttributeNode, RubyLiteralNode, RubyHTMLAttributesSplatNode, ERBOpenTagNode, HTMLTextNode, HTMLCommentNode, HTMLDoctypeNode, XMLDeclarationNode, CDATANode, WhitespaceNode, ERBContentNode, ERBEndNode, ERBElseNode, ERBIfNode, ERBBlockNode, ERBWhenNode, ERBCaseNode, ERBCaseMatchNode, ERBWhileNode, ERBUntilNode, ERBForNode, ERBRescueNode, ERBEnsureNode, ERBBeginNode, ERBUnlessNode, RubyRenderLocalNode, ERBRenderNode, ERBYieldNode, ERBInNode } from "./nodes.js";
5
5
  /**
6
6
  * Type guard functions for AST nodes.
7
7
  * These functions provide type checking by combining both instanceof
@@ -152,6 +152,14 @@ export declare function isERBBeginNode(node: Node | null | undefined): node is E
152
152
  * Checks if a node is a ERBUnlessNode
153
153
  */
154
154
  export declare function isERBUnlessNode(node: Node | null | undefined): node is ERBUnlessNode;
155
+ /**
156
+ * Checks if a node is a RubyRenderLocalNode
157
+ */
158
+ export declare function isRubyRenderLocalNode(node: Node | null | undefined): node is RubyRenderLocalNode;
159
+ /**
160
+ * Checks if a node is a ERBRenderNode
161
+ */
162
+ export declare function isERBRenderNode(node: Node | null | undefined): node is ERBRenderNode;
155
163
  /**
156
164
  * Checks if a node is a ERBYieldNode
157
165
  */
@@ -230,6 +238,8 @@ type NodeTypeToClass = {
230
238
  "AST_ERB_ENSURE_NODE": ERBEnsureNode;
231
239
  "AST_ERB_BEGIN_NODE": ERBBeginNode;
232
240
  "AST_ERB_UNLESS_NODE": ERBUnlessNode;
241
+ "AST_RUBY_RENDER_LOCAL_NODE": RubyRenderLocalNode;
242
+ "AST_ERB_RENDER_NODE": ERBRenderNode;
233
243
  "AST_ERB_YIELD_NODE": ERBYieldNode;
234
244
  "AST_ERB_IN_NODE": ERBInNode;
235
245
  };
@@ -486,6 +496,14 @@ export declare function filterERBBeginNodes(nodes: Node[]): ERBBeginNode[];
486
496
  * Filters an array of nodes to only include ERBUnlessNode nodes
487
497
  */
488
498
  export declare function filterERBUnlessNodes(nodes: Node[]): ERBUnlessNode[];
499
+ /**
500
+ * Filters an array of nodes to only include RubyRenderLocalNode nodes
501
+ */
502
+ export declare function filterRubyRenderLocalNodes(nodes: Node[]): RubyRenderLocalNode[];
503
+ /**
504
+ * Filters an array of nodes to only include ERBRenderNode nodes
505
+ */
506
+ export declare function filterERBRenderNodes(nodes: Node[]): ERBRenderNode[];
489
507
  /**
490
508
  * Filters an array of nodes to only include ERBYieldNode nodes
491
509
  */
@@ -1160,6 +1160,115 @@ export declare class ERBUnlessNode extends Node {
1160
1160
  toJSON(): SerializedERBUnlessNode;
1161
1161
  treeInspect(): string;
1162
1162
  }
1163
+ export interface SerializedRubyRenderLocalNode extends SerializedNode {
1164
+ type: "AST_RUBY_RENDER_LOCAL_NODE";
1165
+ name: SerializedToken | null;
1166
+ value: SerializedRubyLiteralNode | null;
1167
+ }
1168
+ export interface RubyRenderLocalNodeProps extends Omit<BaseNodeProps, 'type'> {
1169
+ type: "AST_RUBY_RENDER_LOCAL_NODE";
1170
+ name: Token | null;
1171
+ value: RubyLiteralNode | null;
1172
+ }
1173
+ export declare class RubyRenderLocalNode extends Node {
1174
+ readonly type: "AST_RUBY_RENDER_LOCAL_NODE";
1175
+ readonly name: Token | null;
1176
+ readonly value: RubyLiteralNode | null;
1177
+ static get type(): NodeType;
1178
+ static from(data: SerializedRubyRenderLocalNode): RubyRenderLocalNode;
1179
+ constructor(props: RubyRenderLocalNodeProps);
1180
+ accept(visitor: Visitor): void;
1181
+ childNodes(): (Node | null | undefined)[];
1182
+ compactChildNodes(): Node[];
1183
+ recursiveErrors(): HerbError[];
1184
+ toJSON(): SerializedRubyRenderLocalNode;
1185
+ treeInspect(): string;
1186
+ }
1187
+ export interface SerializedERBRenderNode extends SerializedNode {
1188
+ type: "AST_ERB_RENDER_NODE";
1189
+ tag_opening: SerializedToken | null;
1190
+ content: SerializedToken | null;
1191
+ tag_closing: SerializedToken | null;
1192
+ prism_node: number[] | null;
1193
+ partial: SerializedToken | null;
1194
+ template_path: SerializedToken | null;
1195
+ layout: SerializedToken | null;
1196
+ file: SerializedToken | null;
1197
+ inline_template: SerializedToken | null;
1198
+ body: SerializedToken | null;
1199
+ plain: SerializedToken | null;
1200
+ html: SerializedToken | null;
1201
+ renderable: SerializedToken | null;
1202
+ collection: SerializedToken | null;
1203
+ object: SerializedToken | null;
1204
+ as_name: SerializedToken | null;
1205
+ spacer_template: SerializedToken | null;
1206
+ formats: SerializedToken | null;
1207
+ variants: SerializedToken | null;
1208
+ handlers: SerializedToken | null;
1209
+ content_type: SerializedToken | null;
1210
+ locals: SerializedNode[];
1211
+ }
1212
+ export interface ERBRenderNodeProps extends Omit<BaseNodeProps, 'type'> {
1213
+ type: "AST_ERB_RENDER_NODE";
1214
+ tag_opening: Token | null;
1215
+ content: Token | null;
1216
+ tag_closing: Token | null;
1217
+ prism_node: Uint8Array | null;
1218
+ partial: Token | null;
1219
+ template_path: Token | null;
1220
+ layout: Token | null;
1221
+ file: Token | null;
1222
+ inline_template: Token | null;
1223
+ body: Token | null;
1224
+ plain: Token | null;
1225
+ html: Token | null;
1226
+ renderable: Token | null;
1227
+ collection: Token | null;
1228
+ object: Token | null;
1229
+ as_name: Token | null;
1230
+ spacer_template: Token | null;
1231
+ formats: Token | null;
1232
+ variants: Token | null;
1233
+ handlers: Token | null;
1234
+ content_type: Token | null;
1235
+ locals: any[];
1236
+ }
1237
+ export declare class ERBRenderNode extends Node {
1238
+ readonly type: "AST_ERB_RENDER_NODE";
1239
+ readonly tag_opening: Token | null;
1240
+ readonly content: Token | null;
1241
+ readonly tag_closing: Token | null;
1242
+ readonly prism_node: Uint8Array | null;
1243
+ readonly partial: Token | null;
1244
+ readonly template_path: Token | null;
1245
+ readonly layout: Token | null;
1246
+ readonly file: Token | null;
1247
+ readonly inline_template: Token | null;
1248
+ readonly body: Token | null;
1249
+ readonly plain: Token | null;
1250
+ readonly html: Token | null;
1251
+ readonly renderable: Token | null;
1252
+ readonly collection: Token | null;
1253
+ readonly object: Token | null;
1254
+ readonly as_name: Token | null;
1255
+ readonly spacer_template: Token | null;
1256
+ readonly formats: Token | null;
1257
+ readonly variants: Token | null;
1258
+ readonly handlers: Token | null;
1259
+ readonly content_type: Token | null;
1260
+ readonly locals: Node[];
1261
+ static get type(): NodeType;
1262
+ static from(data: SerializedERBRenderNode): ERBRenderNode;
1263
+ constructor(props: ERBRenderNodeProps);
1264
+ accept(visitor: Visitor): void;
1265
+ childNodes(): (Node | null | undefined)[];
1266
+ compactChildNodes(): Node[];
1267
+ get prismNode(): PrismNode | null;
1268
+ recursiveErrors(): HerbError[];
1269
+ toJSON(): SerializedERBRenderNode;
1270
+ treeInspect(): string;
1271
+ }
1163
1272
  export interface SerializedERBYieldNode extends SerializedNode {
1164
1273
  type: "AST_ERB_YIELD_NODE";
1165
1274
  tag_opening: SerializedToken | null;
@@ -1220,7 +1329,7 @@ export declare class ERBInNode extends Node {
1220
1329
  toJSON(): SerializedERBInNode;
1221
1330
  treeInspect(): string;
1222
1331
  }
1223
- export type ConcreteNode = DocumentNode | LiteralNode | HTMLOpenTagNode | HTMLConditionalOpenTagNode | HTMLCloseTagNode | HTMLOmittedCloseTagNode | HTMLVirtualCloseTagNode | HTMLElementNode | HTMLConditionalElementNode | HTMLAttributeValueNode | HTMLAttributeNameNode | HTMLAttributeNode | RubyLiteralNode | RubyHTMLAttributesSplatNode | ERBOpenTagNode | HTMLTextNode | HTMLCommentNode | HTMLDoctypeNode | XMLDeclarationNode | CDATANode | WhitespaceNode | ERBContentNode | ERBEndNode | ERBElseNode | ERBIfNode | ERBBlockNode | ERBWhenNode | ERBCaseNode | ERBCaseMatchNode | ERBWhileNode | ERBUntilNode | ERBForNode | ERBRescueNode | ERBEnsureNode | ERBBeginNode | ERBUnlessNode | ERBYieldNode | ERBInNode;
1332
+ export type ConcreteNode = DocumentNode | LiteralNode | HTMLOpenTagNode | HTMLConditionalOpenTagNode | HTMLCloseTagNode | HTMLOmittedCloseTagNode | HTMLVirtualCloseTagNode | HTMLElementNode | HTMLConditionalElementNode | HTMLAttributeValueNode | HTMLAttributeNameNode | HTMLAttributeNode | RubyLiteralNode | RubyHTMLAttributesSplatNode | ERBOpenTagNode | HTMLTextNode | HTMLCommentNode | HTMLDoctypeNode | XMLDeclarationNode | CDATANode | WhitespaceNode | ERBContentNode | ERBEndNode | ERBElseNode | ERBIfNode | ERBBlockNode | ERBWhenNode | ERBCaseNode | ERBCaseMatchNode | ERBWhileNode | ERBUntilNode | ERBForNode | ERBRescueNode | ERBEnsureNode | ERBBeginNode | ERBUnlessNode | RubyRenderLocalNode | ERBRenderNode | ERBYieldNode | ERBInNode;
1224
1333
  export declare function fromSerializedNode(node: SerializedDocumentNode): DocumentNode;
1225
1334
  export declare function fromSerializedNode(node: SerializedLiteralNode): LiteralNode;
1226
1335
  export declare function fromSerializedNode(node: SerializedHTMLOpenTagNode): HTMLOpenTagNode;
@@ -1257,10 +1366,12 @@ export declare function fromSerializedNode(node: SerializedERBRescueNode): ERBRe
1257
1366
  export declare function fromSerializedNode(node: SerializedERBEnsureNode): ERBEnsureNode;
1258
1367
  export declare function fromSerializedNode(node: SerializedERBBeginNode): ERBBeginNode;
1259
1368
  export declare function fromSerializedNode(node: SerializedERBUnlessNode): ERBUnlessNode;
1369
+ export declare function fromSerializedNode(node: SerializedRubyRenderLocalNode): RubyRenderLocalNode;
1370
+ export declare function fromSerializedNode(node: SerializedERBRenderNode): ERBRenderNode;
1260
1371
  export declare function fromSerializedNode(node: SerializedERBYieldNode): ERBYieldNode;
1261
1372
  export declare function fromSerializedNode(node: SerializedERBInNode): ERBInNode;
1262
1373
  export declare function fromSerializedNode(node: SerializedNode): Node;
1263
- export type NodeType = "AST_DOCUMENT_NODE" | "AST_LITERAL_NODE" | "AST_HTML_OPEN_TAG_NODE" | "AST_HTML_CONDITIONAL_OPEN_TAG_NODE" | "AST_HTML_CLOSE_TAG_NODE" | "AST_HTML_OMITTED_CLOSE_TAG_NODE" | "AST_HTML_VIRTUAL_CLOSE_TAG_NODE" | "AST_HTML_ELEMENT_NODE" | "AST_HTML_CONDITIONAL_ELEMENT_NODE" | "AST_HTML_ATTRIBUTE_VALUE_NODE" | "AST_HTML_ATTRIBUTE_NAME_NODE" | "AST_HTML_ATTRIBUTE_NODE" | "AST_RUBY_LITERAL_NODE" | "AST_RUBY_HTML_ATTRIBUTES_SPLAT_NODE" | "AST_ERB_OPEN_TAG_NODE" | "AST_HTML_TEXT_NODE" | "AST_HTML_COMMENT_NODE" | "AST_HTML_DOCTYPE_NODE" | "AST_XML_DECLARATION_NODE" | "AST_CDATA_NODE" | "AST_WHITESPACE_NODE" | "AST_ERB_CONTENT_NODE" | "AST_ERB_END_NODE" | "AST_ERB_ELSE_NODE" | "AST_ERB_IF_NODE" | "AST_ERB_BLOCK_NODE" | "AST_ERB_WHEN_NODE" | "AST_ERB_CASE_NODE" | "AST_ERB_CASE_MATCH_NODE" | "AST_ERB_WHILE_NODE" | "AST_ERB_UNTIL_NODE" | "AST_ERB_FOR_NODE" | "AST_ERB_RESCUE_NODE" | "AST_ERB_ENSURE_NODE" | "AST_ERB_BEGIN_NODE" | "AST_ERB_UNLESS_NODE" | "AST_ERB_YIELD_NODE" | "AST_ERB_IN_NODE";
1374
+ export type NodeType = "AST_DOCUMENT_NODE" | "AST_LITERAL_NODE" | "AST_HTML_OPEN_TAG_NODE" | "AST_HTML_CONDITIONAL_OPEN_TAG_NODE" | "AST_HTML_CLOSE_TAG_NODE" | "AST_HTML_OMITTED_CLOSE_TAG_NODE" | "AST_HTML_VIRTUAL_CLOSE_TAG_NODE" | "AST_HTML_ELEMENT_NODE" | "AST_HTML_CONDITIONAL_ELEMENT_NODE" | "AST_HTML_ATTRIBUTE_VALUE_NODE" | "AST_HTML_ATTRIBUTE_NAME_NODE" | "AST_HTML_ATTRIBUTE_NODE" | "AST_RUBY_LITERAL_NODE" | "AST_RUBY_HTML_ATTRIBUTES_SPLAT_NODE" | "AST_ERB_OPEN_TAG_NODE" | "AST_HTML_TEXT_NODE" | "AST_HTML_COMMENT_NODE" | "AST_HTML_DOCTYPE_NODE" | "AST_XML_DECLARATION_NODE" | "AST_CDATA_NODE" | "AST_WHITESPACE_NODE" | "AST_ERB_CONTENT_NODE" | "AST_ERB_END_NODE" | "AST_ERB_ELSE_NODE" | "AST_ERB_IF_NODE" | "AST_ERB_BLOCK_NODE" | "AST_ERB_WHEN_NODE" | "AST_ERB_CASE_NODE" | "AST_ERB_CASE_MATCH_NODE" | "AST_ERB_WHILE_NODE" | "AST_ERB_UNTIL_NODE" | "AST_ERB_FOR_NODE" | "AST_ERB_RESCUE_NODE" | "AST_ERB_ENSURE_NODE" | "AST_ERB_BEGIN_NODE" | "AST_ERB_UNLESS_NODE" | "AST_RUBY_RENDER_LOCAL_NODE" | "AST_ERB_RENDER_NODE" | "AST_ERB_YIELD_NODE" | "AST_ERB_IN_NODE";
1264
1375
  export type ERBNodeType = Extract<NodeType, `AST_ERB_${string}`>;
1265
- export type ERBNode = ERBOpenTagNode | ERBContentNode | ERBEndNode | ERBElseNode | ERBIfNode | ERBBlockNode | ERBWhenNode | ERBCaseNode | ERBCaseMatchNode | ERBWhileNode | ERBUntilNode | ERBForNode | ERBRescueNode | ERBEnsureNode | ERBBeginNode | ERBUnlessNode | ERBYieldNode | ERBInNode;
1266
- export declare const ERBNodeClasses: (typeof ERBOpenTagNode | typeof ERBContentNode | typeof ERBEndNode | typeof ERBElseNode | typeof ERBIfNode | typeof ERBBlockNode | typeof ERBWhenNode | typeof ERBCaseNode | typeof ERBCaseMatchNode | typeof ERBWhileNode | typeof ERBUntilNode | typeof ERBForNode | typeof ERBRescueNode | typeof ERBEnsureNode | typeof ERBBeginNode | typeof ERBUnlessNode | typeof ERBYieldNode | typeof ERBInNode)[];
1376
+ export type ERBNode = ERBOpenTagNode | ERBContentNode | ERBEndNode | ERBElseNode | ERBIfNode | ERBBlockNode | ERBWhenNode | ERBCaseNode | ERBCaseMatchNode | ERBWhileNode | ERBUntilNode | ERBForNode | ERBRescueNode | ERBEnsureNode | ERBBeginNode | ERBUnlessNode | ERBRenderNode | ERBYieldNode | ERBInNode;
1377
+ export declare const ERBNodeClasses: (typeof ERBOpenTagNode | typeof ERBContentNode | typeof ERBEndNode | typeof ERBElseNode | typeof ERBIfNode | typeof ERBBlockNode | typeof ERBWhenNode | typeof ERBCaseNode | typeof ERBCaseMatchNode | typeof ERBWhileNode | typeof ERBUntilNode | typeof ERBForNode | typeof ERBRescueNode | typeof ERBEnsureNode | typeof ERBBeginNode | typeof ERBUnlessNode | typeof ERBRenderNode | typeof ERBYieldNode | typeof ERBInNode)[];
@@ -3,6 +3,7 @@ export interface ParseOptions {
3
3
  analyze?: boolean;
4
4
  strict?: boolean;
5
5
  action_view_helpers?: boolean;
6
+ render_nodes?: boolean;
6
7
  prism_nodes?: boolean;
7
8
  prism_nodes_deep?: boolean;
8
9
  prism_program?: boolean;
@@ -21,6 +22,8 @@ export declare class ParserOptions {
21
22
  readonly analyze: boolean;
22
23
  /** Whether ActionView tag helper transformation was enabled during parsing. */
23
24
  readonly action_view_helpers: boolean;
25
+ /** Whether ActionView render call detection was enabled during parsing. */
26
+ readonly render_nodes: boolean;
24
27
  /** Whether Prism node serialization was enabled during parsing. */
25
28
  readonly prism_nodes: boolean;
26
29
  /** Whether deep Prism node serialization was enabled during parsing. */
@@ -1,4 +1,4 @@
1
- import { Node, ERBNode, DocumentNode, LiteralNode, HTMLOpenTagNode, HTMLConditionalOpenTagNode, HTMLCloseTagNode, HTMLOmittedCloseTagNode, HTMLVirtualCloseTagNode, HTMLElementNode, HTMLConditionalElementNode, HTMLAttributeValueNode, HTMLAttributeNameNode, HTMLAttributeNode, RubyLiteralNode, RubyHTMLAttributesSplatNode, ERBOpenTagNode, HTMLTextNode, HTMLCommentNode, HTMLDoctypeNode, XMLDeclarationNode, CDATANode, WhitespaceNode, ERBContentNode, ERBEndNode, ERBElseNode, ERBIfNode, ERBBlockNode, ERBWhenNode, ERBCaseNode, ERBCaseMatchNode, ERBWhileNode, ERBUntilNode, ERBForNode, ERBRescueNode, ERBEnsureNode, ERBBeginNode, ERBUnlessNode, ERBYieldNode, ERBInNode } from "./nodes.js";
1
+ import { Node, ERBNode, DocumentNode, LiteralNode, HTMLOpenTagNode, HTMLConditionalOpenTagNode, HTMLCloseTagNode, HTMLOmittedCloseTagNode, HTMLVirtualCloseTagNode, HTMLElementNode, HTMLConditionalElementNode, HTMLAttributeValueNode, HTMLAttributeNameNode, HTMLAttributeNode, RubyLiteralNode, RubyHTMLAttributesSplatNode, ERBOpenTagNode, HTMLTextNode, HTMLCommentNode, HTMLDoctypeNode, XMLDeclarationNode, CDATANode, WhitespaceNode, ERBContentNode, ERBEndNode, ERBElseNode, ERBIfNode, ERBBlockNode, ERBWhenNode, ERBCaseNode, ERBCaseMatchNode, ERBWhileNode, ERBUntilNode, ERBForNode, ERBRescueNode, ERBEnsureNode, ERBBeginNode, ERBUnlessNode, RubyRenderLocalNode, ERBRenderNode, ERBYieldNode, ERBInNode } from "./nodes.js";
2
2
  /**
3
3
  * Interface that enforces all node visit methods are implemented
4
4
  * This ensures that any class implementing IVisitor must have a visit method for every node type
@@ -43,6 +43,8 @@ export interface IVisitor {
43
43
  visitERBEnsureNode(node: ERBEnsureNode): void;
44
44
  visitERBBeginNode(node: ERBBeginNode): void;
45
45
  visitERBUnlessNode(node: ERBUnlessNode): void;
46
+ visitRubyRenderLocalNode(node: RubyRenderLocalNode): void;
47
+ visitERBRenderNode(node: ERBRenderNode): void;
46
48
  visitERBYieldNode(node: ERBYieldNode): void;
47
49
  visitERBInNode(node: ERBInNode): void;
48
50
  visitNode(node: Node): void;
@@ -90,6 +92,8 @@ export declare class Visitor implements IVisitor {
90
92
  visitERBEnsureNode(node: ERBEnsureNode): void;
91
93
  visitERBBeginNode(node: ERBBeginNode): void;
92
94
  visitERBUnlessNode(node: ERBUnlessNode): void;
95
+ visitRubyRenderLocalNode(node: RubyRenderLocalNode): void;
96
+ visitERBRenderNode(node: ERBRenderNode): void;
93
97
  visitERBYieldNode(node: ERBYieldNode): void;
94
98
  visitERBInNode(node: ERBInNode): void;
95
99
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@herb-tools/core",
3
- "version": "0.9.0",
3
+ "version": "0.9.1",
4
4
  "description": "Core module exporting shared interfaces, AST node definitions, and common utilities for Herb",
5
5
  "license": "MIT",
6
6
  "homepage": "https://herb-tools.dev",
package/src/ast-utils.ts CHANGED
@@ -188,7 +188,7 @@ export function hasStaticAttributeName(attributeNameNode: HTMLAttributeNameNode)
188
188
  /**
189
189
  * Checks if an HTML attribute name node has dynamic content (contains ERB)
190
190
  */
191
- export function hasDynamicAttributeName(attributeNameNode: HTMLAttributeNameNode): boolean {
191
+ export function hasDynamicAttributeNameNode(attributeNameNode: HTMLAttributeNameNode): boolean {
192
192
  if (!attributeNameNode.children) {
193
193
  return false
194
194
  }
@@ -383,12 +383,11 @@ export function hasAttribute(node: HTMLElementNode | HTMLOpenTagNode | null | un
383
383
 
384
384
  /**
385
385
  * Checks if an attribute has a dynamic (ERB-containing) name.
386
- * Accepts an HTMLAttributeNode (wraps the core HTMLAttributeNameNode-level check).
387
386
  */
388
- export function hasDynamicAttributeNameOnAttribute(attributeNode: HTMLAttributeNode): boolean {
387
+ export function hasDynamicAttributeName(attributeNode: HTMLAttributeNode): boolean {
389
388
  if (!isHTMLAttributeNameNode(attributeNode.name)) return false
390
389
 
391
- return hasDynamicAttributeName(attributeNode.name)
390
+ return hasDynamicAttributeNameNode(attributeNode.name)
392
391
  }
393
392
 
394
393
  /**
package/src/diagnostic.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { Location, SerializedLocation } from "./location.js"
2
2
 
3
3
  export type DiagnosticSeverity = "error" | "warning" | "info" | "hint"
4
+ export type DiagnosticTag = "unnecessary" | "deprecated"
4
5
 
5
6
  /**
6
7
  * Base interface for all diagnostic information in Herb tooling.
@@ -32,6 +33,11 @@ export interface Diagnostic {
32
33
  * Optional source that generated this diagnostic (e.g., "parser", "linter", "lexer")
33
34
  */
34
35
  source?: string
36
+
37
+ /**
38
+ * Optional diagnostic tags for additional metadata (e.g., "unnecessary", "deprecated")
39
+ */
40
+ tags?: DiagnosticTag[]
35
41
  }
36
42
 
37
43
  /**
@@ -43,6 +49,7 @@ export interface SerializedDiagnostic {
43
49
  severity: DiagnosticSeverity
44
50
  code?: string
45
51
  source?: string
52
+ tags?: DiagnosticTag[]
46
53
  }
47
54
 
48
55
  export type MonacoSeverity = "error" | "warning" | "info"