herb 0.8.10 → 0.9.0
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.
- checksums.yaml +4 -4
- data/Makefile +11 -3
- data/README.md +64 -34
- data/Rakefile +48 -40
- data/config.yml +317 -34
- data/ext/herb/error_helpers.c +367 -140
- data/ext/herb/error_helpers.h +1 -0
- data/ext/herb/extconf.rb +67 -28
- data/ext/herb/extension.c +317 -51
- data/ext/herb/extension.h +1 -0
- data/ext/herb/extension_helpers.c +23 -14
- data/ext/herb/extension_helpers.h +2 -2
- data/ext/herb/nodes.c +537 -270
- data/ext/herb/nodes.h +1 -0
- data/herb.gemspec +3 -2
- data/lib/herb/ast/helpers.rb +3 -3
- data/lib/herb/ast/node.rb +15 -2
- data/lib/herb/ast/nodes.rb +1132 -157
- data/lib/herb/bootstrap.rb +87 -0
- data/lib/herb/cli.rb +341 -31
- data/lib/herb/configuration.rb +248 -0
- data/lib/herb/defaults.yml +32 -0
- data/lib/herb/engine/compiler.rb +78 -11
- data/lib/herb/engine/debug_visitor.rb +13 -3
- data/lib/herb/engine/error_formatter.rb +13 -9
- data/lib/herb/engine/parser_error_overlay.rb +10 -6
- data/lib/herb/engine/validator.rb +8 -3
- data/lib/herb/engine/validators/nesting_validator.rb +2 -2
- data/lib/herb/engine.rb +82 -35
- data/lib/herb/errors.rb +563 -88
- data/lib/herb/lex_result.rb +1 -0
- data/lib/herb/location.rb +7 -3
- data/lib/herb/parse_result.rb +12 -2
- data/lib/herb/parser_options.rb +57 -0
- data/lib/herb/position.rb +1 -0
- data/lib/herb/prism_inspect.rb +116 -0
- data/lib/herb/project.rb +923 -331
- data/lib/herb/range.rb +1 -0
- data/lib/herb/token.rb +7 -1
- data/lib/herb/version.rb +1 -1
- data/lib/herb/visitor.rb +37 -2
- data/lib/herb/warnings.rb +6 -1
- data/lib/herb.rb +35 -3
- data/sig/herb/ast/helpers.rbs +2 -2
- data/sig/herb/ast/node.rbs +12 -2
- data/sig/herb/ast/nodes.rbs +641 -128
- data/sig/herb/bootstrap.rbs +31 -0
- data/sig/herb/configuration.rbs +89 -0
- data/sig/herb/engine/compiler.rbs +9 -1
- data/sig/herb/engine/debug_visitor.rbs +2 -0
- data/sig/herb/engine/validator.rbs +5 -1
- data/sig/herb/engine.rbs +17 -3
- data/sig/herb/errors.rbs +258 -63
- data/sig/herb/location.rbs +4 -0
- data/sig/herb/parse_result.rbs +4 -2
- data/sig/herb/parser_options.rbs +42 -0
- data/sig/herb/position.rbs +1 -0
- data/sig/herb/prism_inspect.rbs +28 -0
- data/sig/herb/range.rbs +1 -0
- data/sig/herb/token.rbs +6 -0
- data/sig/herb/visitor.rbs +25 -4
- data/sig/herb/warnings.rbs +6 -1
- data/sig/herb.rbs +14 -0
- data/sig/herb_c_extension.rbs +5 -2
- data/sig/serialized_ast_errors.rbs +54 -6
- data/sig/serialized_ast_nodes.rbs +60 -6
- data/src/analyze/action_view/attribute_extraction_helpers.c +290 -0
- data/src/analyze/action_view/content_tag.c +70 -0
- data/src/analyze/action_view/link_to.c +143 -0
- data/src/analyze/action_view/registry.c +60 -0
- data/src/analyze/action_view/tag.c +64 -0
- data/src/analyze/action_view/tag_helper_node_builders.c +305 -0
- data/src/analyze/action_view/tag_helpers.c +748 -0
- data/src/analyze/action_view/turbo_frame_tag.c +88 -0
- data/src/analyze/analyze.c +882 -0
- data/src/{analyzed_ruby.c → analyze/analyzed_ruby.c} +13 -11
- data/src/analyze/builders.c +343 -0
- data/src/analyze/conditional_elements.c +594 -0
- data/src/analyze/conditional_open_tags.c +640 -0
- data/src/analyze/control_type.c +250 -0
- data/src/{analyze_helpers.c → analyze/helpers.c} +48 -23
- data/src/analyze/invalid_structures.c +193 -0
- data/src/{analyze_missing_end.c → analyze/missing_end.c} +33 -22
- data/src/analyze/parse_errors.c +84 -0
- data/src/analyze/prism_annotate.c +397 -0
- data/src/{analyze_transform.c → analyze/transform.c} +17 -3
- data/src/ast_node.c +17 -7
- data/src/ast_nodes.c +662 -387
- data/src/ast_pretty_print.c +190 -6
- data/src/errors.c +1076 -520
- data/src/extract.c +145 -49
- data/src/herb.c +52 -34
- data/src/html_util.c +241 -12
- data/src/include/analyze/action_view/attribute_extraction_helpers.h +36 -0
- data/src/include/analyze/action_view/tag_helper_handler.h +41 -0
- data/src/include/analyze/action_view/tag_helper_node_builders.h +70 -0
- data/src/include/analyze/action_view/tag_helpers.h +38 -0
- data/src/include/{analyze.h → analyze/analyze.h} +14 -4
- data/src/include/{analyzed_ruby.h → analyze/analyzed_ruby.h} +3 -3
- data/src/include/analyze/builders.h +27 -0
- data/src/include/analyze/conditional_elements.h +9 -0
- data/src/include/analyze/conditional_open_tags.h +9 -0
- data/src/include/analyze/control_type.h +14 -0
- data/src/include/{analyze_helpers.h → analyze/helpers.h} +4 -2
- data/src/include/analyze/invalid_structures.h +11 -0
- data/src/include/analyze/prism_annotate.h +16 -0
- data/src/include/ast_node.h +11 -5
- data/src/include/ast_nodes.h +117 -38
- data/src/include/ast_pretty_print.h +5 -0
- data/src/include/element_source.h +3 -8
- data/src/include/errors.h +148 -55
- data/src/include/extract.h +21 -5
- data/src/include/herb.h +18 -6
- data/src/include/herb_prism_node.h +13 -0
- data/src/include/html_util.h +7 -2
- data/src/include/io.h +3 -1
- data/src/include/lex_helpers.h +29 -0
- data/src/include/lexer.h +1 -1
- data/src/include/lexer_peek_helpers.h +87 -13
- data/src/include/lexer_struct.h +2 -0
- data/src/include/location.h +2 -1
- data/src/include/parser.h +27 -2
- data/src/include/parser_helpers.h +19 -3
- data/src/include/pretty_print.h +10 -5
- data/src/include/prism_context.h +45 -0
- data/src/include/prism_helpers.h +10 -7
- data/src/include/prism_serialized.h +12 -0
- data/src/include/token.h +16 -4
- data/src/include/token_struct.h +10 -3
- data/src/include/utf8.h +2 -1
- data/src/include/util/hb_allocator.h +78 -0
- data/src/include/util/hb_arena.h +6 -1
- data/src/include/util/hb_arena_debug.h +12 -1
- data/src/include/util/hb_array.h +7 -3
- data/src/include/util/hb_buffer.h +6 -4
- data/src/include/util/hb_foreach.h +79 -0
- data/src/include/util/hb_narray.h +8 -4
- data/src/include/util/hb_string.h +56 -9
- data/src/include/util.h +6 -3
- data/src/include/version.h +1 -1
- data/src/io.c +3 -2
- data/src/lexer.c +42 -30
- data/src/lexer_peek_helpers.c +12 -74
- data/src/location.c +2 -2
- data/src/main.c +53 -28
- data/src/parser.c +783 -247
- data/src/parser_helpers.c +110 -23
- data/src/parser_match_tags.c +109 -48
- data/src/pretty_print.c +29 -24
- data/src/prism_helpers.c +30 -27
- data/src/ruby_parser.c +2 -0
- data/src/token.c +151 -66
- data/src/token_matchers.c +0 -1
- data/src/utf8.c +7 -6
- data/src/util/hb_allocator.c +341 -0
- data/src/util/hb_arena.c +81 -56
- data/src/util/hb_arena_debug.c +32 -17
- data/src/util/hb_array.c +30 -15
- data/src/util/hb_buffer.c +17 -21
- data/src/util/hb_narray.c +22 -7
- data/src/util/hb_string.c +49 -35
- data/src/util.c +21 -11
- data/src/visitor.c +47 -0
- data/templates/ext/herb/error_helpers.c.erb +24 -11
- data/templates/ext/herb/error_helpers.h.erb +1 -0
- data/templates/ext/herb/nodes.c.erb +50 -16
- data/templates/ext/herb/nodes.h.erb +1 -0
- data/templates/java/error_helpers.c.erb +1 -1
- data/templates/java/nodes.c.erb +30 -8
- data/templates/java/org/herb/ast/Errors.java.erb +24 -1
- data/templates/java/org/herb/ast/Nodes.java.erb +80 -21
- data/templates/javascript/packages/core/src/errors.ts.erb +16 -3
- data/templates/javascript/packages/core/src/node-type-guards.ts.erb +3 -1
- data/templates/javascript/packages/core/src/nodes.ts.erb +109 -32
- data/templates/javascript/packages/node/extension/error_helpers.cpp.erb +13 -4
- data/templates/javascript/packages/node/extension/nodes.cpp.erb +43 -4
- data/templates/lib/herb/ast/nodes.rb.erb +88 -31
- data/templates/lib/herb/errors.rb.erb +15 -3
- data/templates/lib/herb/visitor.rb.erb +2 -2
- data/templates/rust/src/ast/nodes.rs.erb +97 -44
- data/templates/rust/src/errors.rs.erb +2 -1
- data/templates/rust/src/nodes.rs.erb +167 -15
- data/templates/rust/src/union_types.rs.erb +60 -0
- data/templates/rust/src/visitor.rs.erb +81 -0
- data/templates/src/{analyze_missing_end.c.erb → analyze/missing_end.c.erb} +9 -6
- data/templates/src/{analyze_transform.c.erb → analyze/transform.c.erb} +2 -2
- data/templates/src/ast_nodes.c.erb +34 -26
- data/templates/src/ast_pretty_print.c.erb +24 -5
- data/templates/src/errors.c.erb +60 -54
- data/templates/src/include/ast_nodes.h.erb +6 -2
- data/templates/src/include/ast_pretty_print.h.erb +5 -0
- data/templates/src/include/errors.h.erb +15 -11
- data/templates/src/include/util/hb_foreach.h.erb +20 -0
- data/templates/src/parser_match_tags.c.erb +10 -4
- data/templates/src/visitor.c.erb +2 -2
- data/templates/template.rb +204 -29
- data/templates/wasm/error_helpers.cpp.erb +9 -5
- data/templates/wasm/nodes.cpp.erb +41 -4
- metadata +57 -16
- data/src/analyze.c +0 -1608
- data/src/element_source.c +0 -12
- data/src/include/util/hb_system.h +0 -9
- data/src/util/hb_system.c +0 -30
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 10b9ca3614ee3b23c37caf0f7d7363a434c15a39b27e3dc8c83023ec4f0587b1
|
|
4
|
+
data.tar.gz: 4be0d44ce17912901556481b7fb21ee18c5f7b71165c98f4e2cee6961614c626
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '00879b8718267317125d050da50cc6423f33e1765c236c470c5ea5ff1da8e8ad57b1c0c35a8d7a3a4b75200f3f00beacfbc17d14b6d44886cdf8b5e67ac033f0'
|
|
7
|
+
data.tar.gz: b7f7583d3dd1cce9bf9021cc8a33d1936bab1e3e1cd681d77bf6e4f4d9e6be25b332b742ad9c1e5c079f13f363d3a21a3188affbac96f84a77f4160cbb9498a2
|
data/Makefile
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
exec = herb
|
|
2
2
|
test_exec = run_herb_tests
|
|
3
3
|
|
|
4
|
-
sources = $(
|
|
5
|
-
headers = $(
|
|
4
|
+
sources = $(shell find src -name '*.c')
|
|
5
|
+
headers = $(shell find src -name '*.h')
|
|
6
6
|
objects = $(sources:.c=.o)
|
|
7
7
|
|
|
8
8
|
extension_sources = $(wildcard ext/**/*.c)
|
|
@@ -20,6 +20,9 @@ test_sources = $(wildcard test/**/*.c)
|
|
|
20
20
|
test_objects = $(test_sources:.c=.o)
|
|
21
21
|
non_main_objects = $(filter-out src/main.o, $(objects))
|
|
22
22
|
|
|
23
|
+
bench_allocs_exec = bench_allocs
|
|
24
|
+
bench_allocs_source = bench/bench_allocs.c
|
|
25
|
+
|
|
23
26
|
soext ?= $(shell ruby -e 'puts RbConfig::CONFIG["DLEXT"]')
|
|
24
27
|
lib_name = $(build_dir)/lib$(exec).$(soext)
|
|
25
28
|
static_lib_name = $(build_dir)/lib$(exec).a
|
|
@@ -102,9 +105,14 @@ test/%.o: test/%.c templates prism
|
|
|
102
105
|
test: $(test_objects) $(non_main_objects)
|
|
103
106
|
$(cc) $(test_objects) $(non_main_objects) $(test_cflags) $(test_ldflags) -o $(test_exec)
|
|
104
107
|
|
|
108
|
+
.PHONY: bench_allocs
|
|
109
|
+
bench_allocs: $(non_main_objects)
|
|
110
|
+
$(cc) $(bench_allocs_source) $(non_main_objects) $(flags) $(prism_ldflags) -o $(bench_allocs_exec)
|
|
111
|
+
./$(bench_allocs_exec)
|
|
112
|
+
|
|
105
113
|
.PHONY: clean
|
|
106
114
|
clean:
|
|
107
|
-
rm -f $(exec) $(test_exec) $(lib_name) $(shared_lib_name) $(ruby_extension)
|
|
115
|
+
rm -f $(exec) $(test_exec) $(bench_allocs_exec) $(lib_name) $(shared_lib_name) $(ruby_extension)
|
|
108
116
|
rm -rf $(objects) $(test_objects) $(extension_objects) lib/herb/*.bundle tmp
|
|
109
117
|
rm -rf $(prism_path)
|
|
110
118
|
rake prism:clean
|
data/README.md
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
<div align="center">
|
|
2
|
-
<img alt="Herb HTML+ERB
|
|
2
|
+
<img alt="Herb HTML+ERB Toolchain" style="height: 256px" height="256px" src="https://github.com/user-attachments/assets/d0714ee1-ca33-4aa4-aaa9-d632ba79d54a">
|
|
3
3
|
</div>
|
|
4
4
|
|
|
5
5
|
<h2 align="center">Herb</h2>
|
|
6
6
|
|
|
7
|
-
<h4 align="center">HTML+ERB
|
|
7
|
+
<h4 align="center">The modern HTML+ERB Toolchain</h4>
|
|
8
8
|
|
|
9
|
-
<div align="center">
|
|
9
|
+
<div align="center">An ecosystem of powerful and seamless developer tools for HTML+ERB (HTML + Embedded Ruby) templates.</div><br/>
|
|
10
10
|
|
|
11
11
|
<p align="center">
|
|
12
12
|
<a href="https://rubygems.org/gems/herb"><img alt="Gem Version" src="https://img.shields.io/gem/v/herb"></a>
|
|
@@ -25,36 +25,53 @@
|
|
|
25
25
|
|
|
26
26
|
## What is Herb?
|
|
27
27
|
|
|
28
|
-
**Herb** is an ecosystem of developer
|
|
28
|
+
**Herb** is a powerful and seamless HTML-aware ERB toolchain and an ecosystem of developer tools built specifically for **HTML+ERB** (`.html.erb`) files. It is designed to simplify and enhance the experience of working with HTML+ERB templates through precise, accurate tooling.
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
**Parser**
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
At the core of the Herb ecosystem is the **Herb Parser**, a fast, portable, and HTML-aware ERB parser written in C. The parser generates a detailed, accurate syntax tree that serves as the foundation for reliable code analysis, transformations, and developer tooling.
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
**Toolchain**
|
|
35
35
|
|
|
36
|
-
Herb
|
|
36
|
+
The Herb toolchain includes **developer tools** (CLI, language server, formatter, linter, browser dev tools), **language bindings** (for Ruby, Node.js, Java, Rust, and the Browser using WebAssembly), and **utility libraries** (language service, highlighter, minifier, printer).
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
Rich integration for editors like VS Code, Zed, Neovim, and more. It provides diagnostics and real-time feedback to keep your templates error-free.
|
|
38
|
+
All these components leverage the Herb Parser's syntax tree to provide consistent, accurate, and helpful tooling experiences.
|
|
40
39
|
|
|
41
|
-
|
|
42
|
-
Automatic, consistent formatting for HTML+ERB files, reducing manual styling and enforcing a standard across projects. Currently in experimental preview - use with caution on version-controlled files.
|
|
40
|
+
**Engine**
|
|
43
41
|
|
|
44
|
-
-
|
|
45
|
-
Static analysis for your HTML+ERB templates to enforce best practices and quickly identify common mistakes with plenty of rules.
|
|
42
|
+
`Herb::Engine` is a new, HTML-aware ERB rendering engine built on the Herb Parser. It is designed to be API-compatible with [`Erubi::Engine`](https://github.com/jeremyevans/erubi) while adding structural awareness of HTML+ERB content, enabling features like HTML validation, security checks, and precise error reporting.
|
|
46
43
|
|
|
47
|
-
|
|
44
|
+
The Engine powers **ReActionView** and lays the foundation for a modern view layer for Rails and other Ruby web frameworks.
|
|
45
|
+
|
|
46
|
+
| **[ReActionView](https://reactionview.dev)** <br> 🌱 A new ActionView-compatible ERB engine with modern DX, re-imagined with `Herb::Engine`. |
|
|
47
|
+
| --- |
|
|
48
|
+
| [GitHub](https://github.com/marcoroth/reactionview) · [Website](https://reactionview.dev) · [Documentation](https://reactionview.dev/overview) |
|
|
49
|
+
|
|
50
|
+
## Ecosystem
|
|
51
|
+
|
|
52
|
+
The Herb ecosystem offers multiple tools that integrate seamlessly into editors, developer environments, and CI pipelines:
|
|
53
|
+
|
|
54
|
+
| Tool | Description |
|
|
55
|
+
| --- | --- |
|
|
56
|
+
| [Herb Parser](https://herb-tools.dev/projects/parser) | Fast, portable, HTML-aware ERB parser written in C. |
|
|
57
|
+
| [Herb Linter](https://herb-tools.dev/projects/linter) | Static analysis to enforce best practices and identify common mistakes. |
|
|
58
|
+
| [Herb Formatter](https://herb-tools.dev/projects/formatter) | Automatic, consistent formatting for HTML+ERB files. *(experimental)* |
|
|
59
|
+
| [Herb Language Server](https://herb-tools.dev/projects/language-server) | Rich editor integration for VS Code, Zed, Neovim, and more. |
|
|
60
|
+
| [Herb Engine](https://herb-tools.dev/projects/engine) | HTML-aware ERB rendering engine, API-compatible with Erubi. |
|
|
61
|
+
| [Herb Dev Tools](https://herb-tools.dev/projects/dev-tools) | In-browser dev tools for inspecting and debugging templates, shipped with ReActionView. |
|
|
62
|
+
| [ReActionView](https://reactionview.dev) | ActionView-compatible ERB engine with modern DX for Rails. |
|
|
63
|
+
|
|
64
|
+
You can use the Herb Parser programmatically in **Ruby**, **Java**, **Rust**, as well as in **JavaScript** via Node.js, WebAssembly, or directly in browsers.
|
|
48
65
|
|
|
49
66
|
For a complete overview of all available tools, libraries, and integrations, visit the [**Projects page**](https://herb-tools.dev/projects) on our documentation site.
|
|
50
67
|
|
|
51
68
|
## Motivation
|
|
52
69
|
|
|
53
|
-
HTML+ERB templates never really had good, accurate, and reliable tooling. While developer tooling for Ruby code improved significantly in the last few years (especially with the introduction of the new Prism parser), HTML+ERB files remained underserved, lacking fundamental support like syntax checking, auto-formatting, linting, and structural understanding.
|
|
70
|
+
HTML+ERB templates never really had good, accurate, and reliable tooling. While developer tooling for Ruby code improved significantly in the last few years (especially with the introduction of the new [Prism parser](https://github.com/ruby/prism)), HTML+ERB files remained underserved, lacking fundamental support like syntax checking, auto-formatting, linting, and structural understanding.
|
|
54
71
|
|
|
55
72
|
At the same time, with the rise of tools like [Hotwire](https://hotwired.dev), [Stimulus](https://stimulus.hotwired.dev), [Turbo](https://turbo.hotwired.dev), [HTMX](https://htmx.org), [Unpoly](https://unpoly.com), and [Alpine.js](https://alpinejs.dev), advanced HTML templating became increasingly relevant (again). Developers expect modern, reliable, and precise tooling, especially given the robust ecosystem available to JavaScript frameworks and libraries.
|
|
56
73
|
|
|
57
|
-
Herb was built to close this tooling gap,
|
|
74
|
+
Herb was built to close this tooling gap with an HTML-aware approach, understanding both HTML structure and ERB as first-class citizens, to provide the kind of tooling modern developers expect in the age of language servers, LLMs, and AI-driven workflows.
|
|
58
75
|
|
|
59
76
|
## Command-Line Usage
|
|
60
77
|
|
|
@@ -64,6 +81,20 @@ Install the Herb gem via RubyGems:
|
|
|
64
81
|
gem install herb
|
|
65
82
|
```
|
|
66
83
|
|
|
84
|
+
### Installing from a Git branch
|
|
85
|
+
|
|
86
|
+
To test a branch before it's released (e.g. from a fork), add both `prism` and `herb` to your Gemfile:
|
|
87
|
+
|
|
88
|
+
```ruby
|
|
89
|
+
gem "prism", github: "ruby/prism", tag: "v1.9.0"
|
|
90
|
+
gem "herb", github: "fork/herb", branch: "my-branch"
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
The `prism` gem is required because Herb's native C extension compiles against
|
|
94
|
+
Prism's C source, which is vendored automatically during installation.
|
|
95
|
+
|
|
96
|
+
For detailed information, like how you can use Herb programmatically in Ruby and JavaScript, visit the [documentation site](https://herb-tools.dev/bindings/ruby/reference).
|
|
97
|
+
|
|
67
98
|
Basic usage to analyze all HTML+ERB files in your project:
|
|
68
99
|
|
|
69
100
|
```sh
|
|
@@ -86,30 +117,29 @@ Files with parse errors:
|
|
|
86
117
|
Results saved to 2025-06-29_12-16-23_erb_parsing_result_rubyevents.log
|
|
87
118
|
```
|
|
88
119
|
|
|
89
|
-
|
|
120
|
+
Lint your HTML+ERB templates:
|
|
90
121
|
|
|
122
|
+
```sh
|
|
123
|
+
npx @herb-tools/linter
|
|
91
124
|
```
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
Commands:
|
|
98
|
-
bundle exec herb lex [file] Lex a file.
|
|
99
|
-
bundle exec herb parse [file] Parse a file.
|
|
100
|
-
bundle exec herb analyze [path] Analyze a project by passing a directory to the root of the project
|
|
101
|
-
bundle exec herb ruby [file] Extract Ruby from a file.
|
|
102
|
-
bundle exec herb html [file] Extract HTML from a file.
|
|
103
|
-
bundle exec herb playground [file] Open the content of the source file in the playground
|
|
104
|
-
bundle exec herb version Prints the versions of the Herb gem and the libherb library.
|
|
125
|
+
|
|
126
|
+
Format your HTML+ERB templates:
|
|
127
|
+
|
|
128
|
+
```sh
|
|
129
|
+
npx @herb-tools/formatter
|
|
105
130
|
```
|
|
106
131
|
|
|
107
|
-
For detailed information, like how you can use Herb programmatically in Ruby and JavaScript, visit the [documentation site](https://herb-tools.dev/bindings/ruby/reference).
|
|
108
132
|
|
|
109
133
|
|
|
110
|
-
## Background and
|
|
134
|
+
## Background and Talks
|
|
135
|
+
|
|
136
|
+
The **Herb Parser** was first introduced at [**RubyKaigi 2025**](https://rubykaigi.org/2025/presentations/marcoroth.html) in April 2025 with the talk [*Empowering Developers with HTML-Aware ERB Tooling*](https://www.rubyevents.org/talks/empowering-developers-with-html-aware-erb-tooling-rubykaigi-2025).
|
|
137
|
+
|
|
138
|
+
At [**RailsConf 2025**](https://www.rubyevents.org/events/railsconf-2025) in July 2025, the Herb ecosystem was expanded with the talk [*The Modern View Layer Rails Deserves: A Vision for 2025 and Beyond*](https://www.rubyevents.org/talks/the-modern-view-layer-rails-deserves-a-vision-for-2025-and-beyond), introducing the linter, formatter, language server, and the vision for ReActionView.
|
|
139
|
+
|
|
140
|
+
At [**Rails World 2025**](https://www.rubyevents.org/events/rails-world-2025) in September 2025, `Herb::Engine`, ReActionView, and the visual dev tools were launched with the talk [*Introducing ReActionView: An ActionView-Compatible ERB Engine*](https://www.rubyevents.org/talks/introducing-reactionview-an-actionview-compatible-erb-engine).
|
|
111
141
|
|
|
112
|
-
**
|
|
142
|
+
At [**San Francisco Ruby Conference 2025**](https://www.rubyevents.org/events/sfruby-2025) in November 2025, the keynote [*Herb to ReActionView: A New Foundation for the View Layer*](https://www.rubyevents.org/talks/keynote-herb-to-reactionview-a-new-foundation-for-the-view-layer) gave an overview of how Herb came to be, what Herb can do for you today, and how it could enable the next generation of the Rails view layer with ReActionView.
|
|
113
143
|
|
|
114
144
|
## Contributing
|
|
115
145
|
|
data/Rakefile
CHANGED
|
@@ -5,6 +5,34 @@ require "bundler/gem_tasks"
|
|
|
5
5
|
require "rake/testtask"
|
|
6
6
|
|
|
7
7
|
Rake::TestTask.new(:test) do |t|
|
|
8
|
+
t.libs << "test"
|
|
9
|
+
t.libs << "lib"
|
|
10
|
+
t.test_files = FileList["test/**/*_test.rb"].exclude("test/engine/**/*_test.rb", "test/integration/**/*_test.rb")
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
task :test_tip do
|
|
14
|
+
puts "TIP: This only runs core tests. Other test tasks available:"
|
|
15
|
+
puts " rake test:all"
|
|
16
|
+
puts " rake test:engine"
|
|
17
|
+
puts " rake test:integration"
|
|
18
|
+
puts
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
Rake::Task[:test].enhance([:test_tip])
|
|
22
|
+
|
|
23
|
+
Rake::TestTask.new("test:engine") do |t|
|
|
24
|
+
t.libs << "test"
|
|
25
|
+
t.libs << "lib"
|
|
26
|
+
t.test_files = FileList["test/engine/**/*_test.rb"]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
Rake::TestTask.new("test:integration") do |t|
|
|
30
|
+
t.libs << "test"
|
|
31
|
+
t.libs << "lib"
|
|
32
|
+
t.test_files = FileList["test/integration/**/*_test.rb"]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
Rake::TestTask.new("test:all") do |t|
|
|
8
36
|
t.libs << "test"
|
|
9
37
|
t.libs << "lib"
|
|
10
38
|
t.test_files = FileList["test/**/*_test.rb"]
|
|
@@ -22,17 +50,17 @@ end
|
|
|
22
50
|
begin
|
|
23
51
|
require "rake/extensiontask"
|
|
24
52
|
|
|
25
|
-
PLATFORMS =
|
|
26
|
-
aarch64-linux-gnu
|
|
27
|
-
aarch64-linux-musl
|
|
28
|
-
arm-linux-gnu
|
|
29
|
-
arm-linux-musl
|
|
30
|
-
arm64-darwin
|
|
31
|
-
x86_64-darwin
|
|
32
|
-
x86_64-linux-gnu
|
|
33
|
-
x86_64-linux-musl
|
|
34
|
-
x86-linux-gnu
|
|
35
|
-
x86-linux-musl
|
|
53
|
+
PLATFORMS = [
|
|
54
|
+
"aarch64-linux-gnu",
|
|
55
|
+
"aarch64-linux-musl",
|
|
56
|
+
"arm-linux-gnu",
|
|
57
|
+
"arm-linux-musl",
|
|
58
|
+
"arm64-darwin",
|
|
59
|
+
"x86_64-darwin",
|
|
60
|
+
"x86_64-linux-gnu",
|
|
61
|
+
"x86_64-linux-musl",
|
|
62
|
+
"x86-linux-gnu",
|
|
63
|
+
"x86-linux-musl"
|
|
36
64
|
].freeze
|
|
37
65
|
|
|
38
66
|
exttask = Rake::ExtensionTask.new do |ext|
|
|
@@ -121,55 +149,35 @@ end
|
|
|
121
149
|
|
|
122
150
|
desc "Render out template files"
|
|
123
151
|
task :templates do
|
|
124
|
-
require_relative "
|
|
152
|
+
require_relative "lib/herb/bootstrap"
|
|
125
153
|
|
|
126
|
-
|
|
127
|
-
Herb::Template.render(template)
|
|
128
|
-
end
|
|
154
|
+
Herb::Bootstrap.generate_templates
|
|
129
155
|
end
|
|
130
156
|
|
|
131
|
-
prism_vendor_path = "vendor/prism"
|
|
132
|
-
|
|
133
157
|
namespace :prism do
|
|
134
158
|
desc "Setup and vendor Prism"
|
|
135
159
|
task :vendor do
|
|
160
|
+
require_relative "lib/herb/bootstrap"
|
|
161
|
+
|
|
136
162
|
Rake::Task["prism:clean"].execute
|
|
137
163
|
|
|
138
164
|
prism_bundle_path = `bundle show prism`.chomp
|
|
139
165
|
|
|
140
|
-
puts prism_bundle_path
|
|
141
|
-
|
|
142
166
|
if prism_bundle_path.empty?
|
|
143
167
|
puts "Make sure to run `bundle install` in the herb project directory first"
|
|
144
168
|
exit 1
|
|
145
169
|
end
|
|
146
170
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
files = [
|
|
150
|
-
"config.yml",
|
|
151
|
-
"Rakefile",
|
|
152
|
-
"src/",
|
|
153
|
-
"include/",
|
|
154
|
-
"templates/"
|
|
155
|
-
]
|
|
156
|
-
|
|
157
|
-
files.each do |file|
|
|
158
|
-
vendored_file_path = prism_vendor_path + "/#{file}"
|
|
159
|
-
puts "Vendoring '#{file}' Prism file to #{vendored_file_path}"
|
|
160
|
-
FileUtils.cp_r(prism_bundle_path + "/#{file}", prism_vendor_path)
|
|
161
|
-
end
|
|
162
|
-
|
|
163
|
-
prism_ast_header = "#{prism_vendor_path}/include/prism/ast.h"
|
|
171
|
+
puts prism_bundle_path
|
|
164
172
|
|
|
165
|
-
|
|
166
|
-
puts "Generating Prism template files..."
|
|
167
|
-
system("ruby #{prism_vendor_path}/templates/template.rb", exception: true)
|
|
168
|
-
end
|
|
173
|
+
Herb::Bootstrap.vendor_prism(prism_gem_path: prism_bundle_path)
|
|
169
174
|
end
|
|
170
175
|
|
|
171
176
|
desc "Clean vendored Prism in vendor/prism/"
|
|
172
177
|
task :clean do
|
|
178
|
+
require_relative "lib/herb/bootstrap"
|
|
179
|
+
|
|
180
|
+
prism_vendor_path = Herb::Bootstrap::PRISM_VENDOR_DIR
|
|
173
181
|
puts "Cleaning up vendored Prism at #{prism_vendor_path}..."
|
|
174
182
|
begin
|
|
175
183
|
FileUtils.rm_r(prism_vendor_path)
|