Skip to content

Commit 475830e

Browse files
Lusqinhafelixefelipesantos92marcoroth
authored
Extractor: Add extract_ruby_options across all language bindings (#675)
This pull request adds `semicolons`, `comments`, and `preserve_positions` options to `Herb.extract_ruby` across all language bindings (Ruby, JavaScript, Java, Rust). This was originally requested to use the extract Ruby code with semicolons in Steep/RBS, more specifically in this PR: soutaro/steep#1836. It's because we need the Ruby code with semicolons to display the static typing errors correctly. I think this functionality could also be used in others projects like Sorbet and Packwerk. Resolves #100 --------- Co-authored-by: Felipe Felix <felipe.felix@maino.com.br> Co-authored-by: Everton <e.santos081992@gmail.com> Co-authored-by: Marco Roth <marco.roth@intergga.ch>
1 parent 41835f1 commit 475830e

27 files changed

Lines changed: 1032 additions & 50 deletions

File tree

docs/docs/bindings/java/reference.md

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ The `Herb` class provides the following static methods:
1414
* `Herb.parse(source)`
1515
* `Herb.parse(source, options)`
1616
* `Herb.extractRuby(source)`
17+
* `Herb.extractRuby(source, options)`
1718
* `Herb.extractHTML(source)`
1819
* `Herb.version()`
1920
* `Herb.herbVersion()`
@@ -154,10 +155,104 @@ String source = "<p>Hello <%= user.name %></p>";
154155

155156
String ruby = Herb.extractRuby(source);
156157
System.out.println(ruby);
157-
// Output: " user.name "
158+
// Output: " user.name ; "
158159
```
159160
:::
160161

162+
### `Herb.extractRuby(String source, ExtractRubyOptions options)`
163+
164+
Extract Ruby with custom options.
165+
166+
#### Default behavior
167+
168+
By default, the output is position-preserving with semicolons:
169+
170+
:::code-group
171+
```java
172+
import org.herb.Herb;
173+
174+
String source = "<% x = 1 %> <% y = 2 %>";
175+
String ruby = Herb.extractRuby(source);
176+
177+
System.out.println(ruby);
178+
// Output: " x = 1 ; y = 2 ;"
179+
```
180+
:::
181+
182+
#### Without semicolons
183+
184+
:::code-group
185+
```java
186+
import org.herb.Herb;
187+
import org.herb.ExtractRubyOptions;
188+
189+
String source = "<% x = 1 %> <% y = 2 %>";
190+
ExtractRubyOptions options = ExtractRubyOptions.create().semicolons(false);
191+
String ruby = Herb.extractRuby(source, options);
192+
193+
System.out.println(ruby);
194+
// Output: " x = 1 y = 2 "
195+
```
196+
:::
197+
198+
#### Including ERB comments
199+
200+
:::code-group
201+
```java
202+
import org.herb.Herb;
203+
import org.herb.ExtractRubyOptions;
204+
205+
String source = "<%# comment %>\n<% code %>";
206+
ExtractRubyOptions options = ExtractRubyOptions.create().comments(true);
207+
String ruby = Herb.extractRuby(source, options);
208+
209+
System.out.println(ruby);
210+
// Output: " # comment \n code ;"
211+
```
212+
:::
213+
214+
#### Without position preservation
215+
216+
Use `preservePositions(false)` for readable output where each ERB tag is placed on its own line:
217+
218+
:::code-group
219+
```java
220+
import org.herb.Herb;
221+
import org.herb.ExtractRubyOptions;
222+
223+
String source = "<%# comment %><%= something %>";
224+
ExtractRubyOptions options = ExtractRubyOptions.create().preservePositions(false).comments(true);
225+
String ruby = Herb.extractRuby(source, options);
226+
227+
System.out.println(ruby);
228+
// Output: "# comment \n something "
229+
```
230+
:::
231+
232+
### `ExtractRubyOptions`
233+
234+
The `ExtractRubyOptions` class provides fluent configuration:
235+
236+
```java
237+
public class ExtractRubyOptions {
238+
public ExtractRubyOptions semicolons(boolean value);
239+
public ExtractRubyOptions comments(boolean value);
240+
public ExtractRubyOptions preservePositions(boolean value);
241+
242+
public static ExtractRubyOptions create();
243+
}
244+
```
245+
246+
| Option | Default | Description |
247+
|--------|---------|-------------|
248+
| `semicolons` | `true` | Add ` ;` at the end of each ERB tag to separate statements |
249+
| `comments` | `false` | Include ERB comments (`<%# %>`) in the output |
250+
| `preservePositions` | `true` | Maintain character positions by padding with whitespace |
251+
252+
> [!TIP]
253+
> Use `preservePositions(false)` when you need readable Ruby output.
254+
> Use `preservePositions(true)` (default) when you need accurate error position mapping.
255+
161256
### `Herb.extractHTML(String source)`
162257

163258
The `extractHTML` method extracts only the HTML parts of an HTML document with embedded Ruby.

docs/docs/bindings/javascript/reference.md

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ Learn more on [how to install and load the NPM packages](/bindings/javascript/#i
4242
- **`Herb.lexFile(path: string): LexResult`**
4343
- **`Herb.parse(source: string): ParseResult`**
4444
- **`Herb.parseFile(path: string): ParseResult`**
45-
- **`Herb.extractRuby(source: string): string`**
45+
- **`Herb.extractRuby(source: string, options?: ExtractRubyOptions): string`**
4646
- **`Herb.extractHTML(source: string): string`**
4747
- **`Herb.version: string`**
4848

@@ -134,7 +134,7 @@ console.log(result)
134134

135135
Herb allows you to extract either Ruby or HTML from mixed content.
136136

137-
### `Herb.extractRuby(source)`
137+
### `Herb.extractRuby(source, options?)`
138138

139139
The `Herb.extractRuby` method allows you to extract only the Ruby parts of an HTML document with embedded Ruby.
140140

@@ -148,10 +148,66 @@ const source = "<p>Hello <%= user.name %></p>"
148148
const ruby = Herb.extractRuby(source)
149149

150150
console.log(ruby);
151-
// Outputs: " user.name "
151+
// Outputs: " user.name ; "
152152
```
153153
:::
154154

155+
#### Options
156+
157+
```typescript
158+
interface ExtractRubyOptions {
159+
semicolons?: boolean // default: true
160+
comments?: boolean // default: false
161+
preserve_positions?: boolean // default: true
162+
}
163+
```
164+
165+
| Option | Type | Default | Description |
166+
|--------|------|---------|-------------|
167+
| `semicolons` | `boolean` | `true` | Add ` ;` at the end of each ERB tag to separate statements |
168+
| `comments` | `boolean` | `false` | Include ERB comments (`<%# %>`) in the output |
169+
| `preserve_positions` | `boolean` | `true` | Maintain character positions by padding with whitespace |
170+
171+
#### Examples
172+
173+
**Default behavior** (position-preserving with semicolons):
174+
175+
```js
176+
const source = "<% x = 1 %> <% y = 2 %>"
177+
178+
Herb.extractRuby(source)
179+
// => " x = 1 ; y = 2 ;"
180+
```
181+
182+
**Without semicolons:**
183+
184+
```js
185+
Herb.extractRuby(source, { semicolons: false })
186+
// => " x = 1 y = 2 "
187+
```
188+
189+
**Including ERB comments:**
190+
191+
```js
192+
const source = "<%# comment %>\n<% code %>"
193+
194+
Herb.extractRuby(source, { comments: true })
195+
// => " # comment \n code ;"
196+
```
197+
198+
**Without position preservation** (readable output, each tag on its own line):
199+
200+
```js
201+
const source = "<%# comment %><%= something %>"
202+
203+
Herb.extractRuby(source, { preserve_positions: false, comments: true })
204+
// => "# comment \n something "
205+
```
206+
207+
> [!TIP]
208+
> Use `preserve_positions: false` when you need readable Ruby output.
209+
> Use `preserve_positions: true` (default) when you need accurate error position mapping.
210+
155211
### `Herb.extractHTML(source)`
156212

157213
The `Herb.extractHTML` method allows you to extract only the HTML parts of an HTML document with embedded Ruby.

docs/docs/bindings/ruby/reference.md

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ Herb.parse_file("./index.html.erb").value
118118

119119
## Extracting Code
120120

121-
### `Herb.extract_ruby(source)`
121+
### `Herb.extract_ruby(source, **options)`
122122

123123
The `Herb.extract_ruby` method allows you to extract only the Ruby parts of an HTML document with embedded Ruby.
124124

@@ -127,10 +127,58 @@ The `Herb.extract_ruby` method allows you to extract only the Ruby parts of an H
127127
source = %(<p>Hello <%= user.name %></p>)
128128

129129
Herb.extract_ruby(source)
130-
# => " user.name "
130+
# => " user.name ; "
131131
```
132132
:::
133133

134+
#### Options
135+
136+
| Option | Type | Default | Description |
137+
|--------|------|---------|-------------|
138+
| `semicolons` | `Boolean` | `true` | Add ` ;` at the end of each ERB tag to separate statements |
139+
| `comments` | `Boolean` | `false` | Include ERB comments (`<%# %>`) in the output |
140+
| `preserve_positions` | `Boolean` | `true` | Maintain character positions by padding with whitespace |
141+
142+
#### Examples
143+
144+
**Default behavior** (position-preserving with semicolons):
145+
146+
```ruby
147+
source = "<% x = 1 %> <% y = 2 %>"
148+
149+
Herb.extract_ruby(source)
150+
# => " x = 1 ; y = 2 ;"
151+
```
152+
153+
**Without semicolons:**
154+
155+
```ruby
156+
Herb.extract_ruby(source, semicolons: false)
157+
# => " x = 1 y = 2 "
158+
```
159+
160+
**Including ERB comments:**
161+
162+
```ruby
163+
source = "<%# comment %>\n<% code %>"
164+
165+
Herb.extract_ruby(source, comments: true)
166+
# => " # comment \n code ;"
167+
```
168+
169+
**Without position preservation** (readable output, each tag on its own line):
170+
171+
```ruby
172+
source = "<%# comment %><%= something %>"
173+
174+
Herb.extract_ruby(source, preserve_positions: false, comments: true)
175+
# => "# comment \n something "
176+
```
177+
178+
> [!TIP]
179+
> Use `preserve_positions: false` when you need readable Ruby output.
180+
> Use `preserve_positions: true` (default) when you need accurate error position mapping.
181+
134182
### `Herb.extract_html(source)`
135183

136184
The `Herb.extract_html` method allows you to extract only the HTML parts of an HTML document with embedded Ruby.

0 commit comments

Comments
 (0)