Install better-html in a Rails app
mainTo use better-html in your Rails application, add the gem to your Gemfile:
gem "better_html"repository·main·Indexed 19 days ago
https://github.com/shopify/better-htmlA deprecated Ruby gem designed to introduce HTML-aware ERB parsing and runtime safety validations for Rails templates. It provides tools for validating HTML structure, preventing unsafe interpolation in tag or attribute names, and managing an Abstract Syntax Tree (AST) for templates. This library has been superseded by Herb Tools.
To use better-html in your Rails application, add the gem to your Gemfile:
gem "better_html"The better_html gem is deprecated and no longer actively maintained. It has been superseded by the tools and guidance available at https://herb-tools.dev/.
To migrate, you should:
better_html.better_html's runtime checks to the modern ecosystem's template safety and escaping practices.Global configuration is managed via BetterHtml.config. You can configure it using a block in an initializer or by loading a YAML file.
# config/initializers/better_html.rb
BetterHtml.configure do |config|
config.allow_single_quoted_attributes = false
end# config/initializers/better_html.rb
BetterHtml.config = BetterHtml::Config.new(YAML.load_file(file_path, permitted_classes: [Regexp]))# config/initializers/better_html.rb
BetterHtml.configure do |config|
config.allow_single_quoted_attributes = false
endThe library uses a specific hierarchy of error classes to categorize different types of failures:
BetterHtml::HtmlError: The base error class for general HTML-related issues.BetterHtml::InterpolatorError: A subclass of HtmlError used for issues occurring during the interpolation phase.BetterHtml::DontInterpolateHere: Raised when interpolation is attempted in a location where it is explicitly disallowed.BetterHtml::UnsafeHtmlError: Raised when unsafe HTML content is detected during interpolation.BetterHtml::ParserError: A specialized error for syntax or structural issues during the parsing phase, containing positional metadata (line, column, position).To use the html_attributes helper (which provides safer attribute insertion), include BetterHtml::Helpers in your ApplicationHelper:
module ApplicationHelper
include BetterHtml::Helpers
# ...
endmodule ApplicationHelper
include BetterHtml::Helpers
...
endThe behavior of the BetterHtml::BetterErb runtime checks is controlled via the BetterHtml.config object. You can customize validation using the following configuration keys:
disable_parser_validation: If set to true, the library will skip checking for general parser errors.partial_tag_name_pattern: A regular expression that tag names must match to be considered valid.partial_attribute_name_pattern: A regular expression that attribute names must match to be considered valid.allow_single_quoted_attributes: A boolean that, if false, prevents the use of single quotes (') for attribute values.allow_unquoted_attributes: A boolean that, if false, prevents the use of unquoted attribute values.When using BetterHtml::BetterErb, the library performs runtime validation of your HTML to ensure it follows specific patterns and is well-formed. If validation fails, it raises one of two error types:
BetterHtml::HtmlError: Raised when the HTML structure is invalid (e.g., unclosed tags, invalid tag names, or invalid attribute formats) or when the parser encounters syntax errors.BetterHtml::DontInterpolateHere: Raised when you attempt to use ERB interpolation (<%= ... %>) in a location where it is not safe (e.g., inside an HTML tag name or attribute name).Common Error Scenarios:
BetterHtml::HtmlError is raised with the message "Detected an open tag at the end of this document.".BetterHtml::HtmlError is raised.BetterHtml::HtmlError is raised.BetterHtml::DontInterpolateHere.To parse a template, instantiate BetterHtml::Parser with a Parser::Source::Buffer object. You must specify the template_language to determine how the parser handles interpolation.
Supported template_language values:
:html (default): Uses Tokenizer::HtmlErb for ERB-style interpolation.:javascript: Uses Tokenizer::JavascriptErb for JavaScript-style ERB interpolation.:lodash: Uses Tokenizer::HtmlLodash for Lodash-style interpolation.If an unsupported language is provided, an ArgumentError is raised.
parser = BetterHtml::Parser.new(buffer, template_language: :html)The BetterHtml.config method returns the current configuration instance. If no configuration has been initialized, it automatically creates a new instance of BetterHtml::Config. You can also manually set the configuration using BetterHtml.config = <config_object>.
config = BetterHtml.config
# or
BetterHtml.configure { |c| ... }You can configure the BetterHtml module by calling BetterHtml.configure and yielding a block. The block receives the BetterHtml.config object, which allows you to set up the library's settings. This is the standard way to initialize settings in a Rails initializer or at the start of your application.
BetterHtml.configure do |config|
# Set configuration options here
endOnce initialized, you can access the parsed structure of the template via the ast method. This returns a BetterHtml::AST::Node representing the document root.
You can also use nodes_with_type(*type) to quickly retrieve all child nodes that match specific node types (e.g., :tag, :text, :erb).
ast = parser.ast
# Find all tag nodes
tags = parser.nodes_with_type(:tag)If the underlying tokenizer encounters issues, you can retrieve them using the parser_errors method. This returns an array of BetterHtml::Parser::Error objects. Each error contains a descriptive message and a location object indicating where the error occurred in the source buffer.
errors = parser.parser_errors
errors.each do |error|
puts "Error: #{error.message} at #{error.location}"
end