diff --git a/.clang-format-ignore b/.clang-format-ignore
index 992622d28..9778be4ea 100644
--- a/.clang-format-ignore
+++ b/.clang-format-ignore
@@ -10,4 +10,8 @@ src/include/ast/ast_pretty_print.h
src/include/errors.h
src/include/lib/hb_foreach.h
src/parser/match_tags.c
+src/analyze/action_view/helper_registry.c
+src/analyze/action_view/generated_handlers.c
+src/analyze/action_view/generated_handlers.h
+src/include/analyze/action_view/helper_registry.h
src/visitor.c
diff --git a/.gitignore b/.gitignore
index cfdcbd0ee..15fc9defb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -98,7 +98,9 @@ java/nodes.h
java/org/herb/ast/Errors.java
java/org/herb/ast/Nodes.java
java/org/herb/ast/NodeVisitor.java
+java/org/herb/ast/HelperRegistry.java
java/org/herb/ast/Visitor.java
+javascript/packages/core/src/action-view-helpers.ts
javascript/packages/core/src/errors.ts
javascript/packages/core/src/html-entities.json
javascript/packages/core/src/node-type-guards.ts
@@ -108,9 +110,11 @@ javascript/packages/node/extension/error_helpers.cpp
javascript/packages/node/extension/error_helpers.h
javascript/packages/node/extension/nodes.cpp
javascript/packages/node/extension/nodes.h
+lib/herb/action_view/helper_registry.rb
lib/herb/ast/nodes.rb
lib/herb/errors.rb
lib/herb/visitor.rb
+rust/src/action_view_helpers.rs
rust/src/ast/nodes.rs
rust/src/errors.rs
rust/src/nodes.rs
@@ -118,11 +122,15 @@ rust/src/union_types.rs
rust/src/visitor.rs
sig/serialized_ast_errors.rbs
sig/serialized_ast_nodes.rbs
+src/analyze/action_view/helper_registry.c
+src/analyze/action_view/generated_handlers.c
+src/analyze/action_view/generated_handlers.h
src/analyze/missing_end.c
src/analyze/transform.c
src/ast/ast_nodes.c
src/ast/ast_pretty_print.c
src/errors.c
+src/include/analyze/action_view/helper_registry.h
src/include/ast/ast_nodes.h
src/include/ast/ast_pretty_print.h
src/include/errors.h
diff --git a/.rubocop.yml b/.rubocop.yml
index 86c75bb6c..48c105aca 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -7,6 +7,7 @@ AllCops:
- 'vendor/**/*'
- 'tmp/**/*'
- 'node_modules/**/*'
+ - 'lib/herb/action_view/**/*'
Style/StringLiterals:
Enabled: true
@@ -104,6 +105,7 @@ Metrics/ClassLength:
- lib/herb/visitor.rb
- lib/herb/ast/nodes.rb
- test/**/*_test.rb
+ - templates/template.rb
Metrics/ModuleLength:
Exclude:
diff --git a/config/action_view_helpers/actioncable/action_cable_helper/action_cable_meta_tag.yml b/config/action_view_helpers/actioncable/action_cable_helper/action_cable_meta_tag.yml
new file mode 100644
index 000000000..dcc4290e4
--- /dev/null
+++ b/config/action_view_helpers/actioncable/action_cable_helper/action_cable_meta_tag.yml
@@ -0,0 +1,20 @@
+---
+name: action_cable_meta_tag
+source: "ActionCable::Helpers::ActionCableHelper#action_cable_meta_tag"
+gem: actioncable
+output: html
+visibility: public
+supported: false
+supports_block: false
+description: |-
+ Returns an `"action-cable-url"` `` tag with the value of the URL specified in your configuration. Ensure this is above your JavaScript tag. Used by Action Cable to determine the URL of your WebSocket server.
+signature: "action_cable_meta_tag"
+documentation_url: "https://api.rubyonrails.org/classes/ActionCable/Helpers/ActionCableHelper.html#method-i-action_cable_meta_tag"
+tag:
+ name: meta
+ is_void: true
+ preferred: false
+ detect_style: call_name
+arguments: []
+options: []
+special_behaviors: []
diff --git a/config/action_view_helpers/actionpack/content_security_policy/content_security_policy?.yml b/config/action_view_helpers/actionpack/content_security_policy/content_security_policy?.yml
new file mode 100644
index 000000000..9c20e36bb
--- /dev/null
+++ b/config/action_view_helpers/actionpack/content_security_policy/content_security_policy?.yml
@@ -0,0 +1,16 @@
+---
+name: content_security_policy?
+source: "ActionController::ContentSecurityPolicy#content_security_policy?"
+gem: actionpack
+output: boolean
+visibility: public
+supported: false
+supports_block: false
+description: |-
+ Returns whether a Content-Security-Policy is present for the current request.
+signature: "content_security_policy?"
+documentation_url: ""
+tag: null
+arguments: []
+options: []
+special_behaviors: []
diff --git a/config/action_view_helpers/actionpack/content_security_policy/content_security_policy_nonce.yml b/config/action_view_helpers/actionpack/content_security_policy/content_security_policy_nonce.yml
new file mode 100644
index 000000000..f1662ef88
--- /dev/null
+++ b/config/action_view_helpers/actionpack/content_security_policy/content_security_policy_nonce.yml
@@ -0,0 +1,16 @@
+---
+name: content_security_policy_nonce
+source: "ActionController::ContentSecurityPolicy#content_security_policy_nonce"
+gem: actionpack
+output: text
+visibility: public
+supported: false
+supports_block: false
+description: |-
+ Returns the Content-Security-Policy nonce for the current request. This nonce value is used in `