Skip to content

Java: Add Herb Java JNI Bindings#766

Merged
marcoroth merged 5 commits intomainfrom
herb-java-jni
Nov 2, 2025
Merged

Java: Add Herb Java JNI Bindings#766
marcoroth merged 5 commits intomainfrom
herb-java-jni

Conversation

@marcoroth
Copy link
Owner

@marcoroth marcoroth commented Nov 2, 2025

This pull request adds Java bindings for Herb using the JNI (Java Native Interface), allowing Java applications to parse and analyze ERB templates with the same implementation as the native C, Ruby C-Extension, C++ Emscripten WASM and the C++ Node.js NAPI bindings.

Building the Java bindings requires Java and a C compiler:

cd java
make

Once built, you can use the herb-java CLI tool:

herb-java version

herb java v0.7.5, libprism v1.6.0, libherb v0.7.5 (Java JNI)

herb-java lex examples/test.html.erb

#<Herb::Token type="TOKEN_HTML_TAG_START" value="<" range=[0, 1] start=(1:0) end=(1:1)>
#<Herb::Token type="TOKEN_IDENTIFIER" value="h1" range=[1, 3] start=(1:1) end=(1:3)>
#<Herb::Token type="TOKEN_WHITESPACE" value=" " range=[3, 4] start=(1:3) end=(1:4)>
#<Herb::Token type="TOKEN_IDENTIFIER" value="class" range=[4, 9] start=(1:4) end=(1:9)>
#<Herb::Token type="TOKEN_EQUALS" value="=" range=[9, 10] start=(1:9) end=(1:10)>
#<Herb::Token type="TOKEN_QUOTE" value="\"" range=[10, 11] start=(1:10) end=(1:11)>
#<Herb::Token type="TOKEN_IDENTIFIER" value="title" range=[11, 16] start=(1:11) end=(1:16)>
#<Herb::Token type="TOKEN_QUOTE" value="\"" range=[16, 17] start=(1:16) end=(1:17)>
#<Herb::Token type="TOKEN_HTML_TAG_END" value=">" range=[17, 18] start=(1:17) end=(1:18)>
#<Herb::Token type="TOKEN_ERB_START" value="<%=" range=[18, 21] start=(1:18) end=(1:21)>
#<Herb::Token type="TOKEN_ERB_CONTENT" value=" content " range=[21, 30] start=(1:21) end=(1:30)>
#<Herb::Token type="TOKEN_ERB_END" value="%>" range=[30, 32] start=(1:30) end=(1:32)>
#<Herb::Token type="TOKEN_HTML_TAG_START_CLOSE" value="</" range=[32, 34] start=(1:32) end=(1:34)>
#<Herb::Token type="TOKEN_IDENTIFIER" value="h1" range=[34, 36] start=(1:34) end=(1:36)>
#<Herb::Token type="TOKEN_HTML_TAG_END" value=">" range=[36, 37] start=(1:36) end=(1:37)>
#<Herb::Token type="TOKEN_NEWLINE" value="\n" range=[37, 38] start=(1:37) end=(2:0)>
#<Herb::Token type="TOKEN_EOF" value="<EOF>" range=[38, 38] start=(2:0) end=(2:0)>

herb-java parse examples/test.html.erb

@ DocumentNode (location: (1:0)-(2:0))
└── children: (2 items)
    ├── @ HTMLElementNode (location: (1:0)-(1:37))
       ├── open_tag:
          └── @ HTMLOpenTagNode (location: (1:0)-(1:18))
              ├── tag_opening: "<" (location: (1:0)-(1:1))
              ├── tag_name: "h1" (location: (1:1)-(1:3))
              ├── tag_closing: ">" (location: (1:17)-(1:18))
              ├── children: (1 item)
                 └── @ HTMLAttributeNode (location: (1:4)-(1:17))
                     ├── name:
                        └── @ HTMLAttributeNameNode (location: (1:4)-(1:9))
                            └── children: (1 item)
                                └── @ LiteralNode (location: (1:4)-(1:9))
                                    └── content: "class"
                     
                     ├── equals: "=" (location: (1:9)-(1:10))
                     └── value:
                         └── @ HTMLAttributeValueNode (location: (1:10)-(1:17))
                             ├── open_quote: "\"" (location: (1:10)-(1:11))
                             ├── children: (1 item)
                                └── @ LiteralNode (location: (1:11)-(1:16))
                                    └── content: "title"
                             ├── close_quote: "\"" (location: (1:16)-(1:17))
                             └── quoted: true
              └── is_void: false
       
       ├── tag_name: "h1" (location: (1:1)-(1:3))├── body: (1 item)
          └── @ ERBContentNode (location: (1:18)-(1:32))
              ├── tag_opening: "<%=" (location: (1:18)-(1:21))
              ├── content: " content " (location: (1:21)-(1:30))
              ├── tag_closing: "%>" (location: (1:30)-(1:32))
              ├── parsed: true
              └── valid: true
       ├── close_tag:
          └── @ HTMLCloseTagNode (location: (1:32)-(1:37))
              ├── tag_opening: "</" (location: (1:32)-(1:34))
              ├── tag_name: "h1" (location: (1:34)-(1:36))
              ├── children: []
              └── tag_closing: ">" (location: (1:36)-(1:37))
       
       ├── is_void: false
       └── source: ""
    
    └── @ HTMLTextNode (location: (1:37)-(2:0))
        └── content: "\n"

Resolves #648

@github-actions github-actions bot added the c label Nov 2, 2025
@marcoroth marcoroth added the java label Nov 2, 2025
@marcoroth marcoroth changed the title Herb: Add Herb Java JNI Bindings Java: Add Herb Java JNI Bindings Nov 2, 2025
@github-actions github-actions bot added documentation Improvements or additions to documentation javascript labels Nov 2, 2025
@marcoroth marcoroth marked this pull request as ready for review November 2, 2025 17:09
@marcoroth marcoroth merged commit ff7ad02 into main Nov 2, 2025
10 checks passed
@marcoroth marcoroth deleted the herb-java-jni branch November 2, 2025 18:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c documentation Improvements or additions to documentation java

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Herb: Java Bindings

1 participant