![Create React App Officially Deprecated Amid React 19 Compatibility Issues](https://cdn.sanity.io/images/cgdhsj6q/production/04fa08cf844d798abc0e1a6391c129363cc7e2ab-1024x1024.webp?w=400&fit=max&auto=format)
Security News
Create React App Officially Deprecated Amid React 19 Compatibility Issues
Create React App is officially deprecated due to React 19 issues and lack of maintenance—developers should switch to Vite or other modern alternatives.
Hexp (pronounced [ˈɦækspi:]) is a DOM API for Ruby. It lets you treat HTML in your applications as objects, instead of strings. It is a standalone, framework independent library. You can use it to build full web pages, or just to clean up your helpers and presenters.
The three central classes are Hexp::Node
, Hexp::TextNode
, and Hexp::List
. Instances of these classes are immutable. You can mostly treat TextNode
as a String
and List
as an Array
, except that they're immutable, and come with some extra convenience functions.
Take this bit of HTML
<nav id="menu">
<ul>
<li>Home</li>
<li>Lolcats</li>
<li>Games</li>
</ul>
</nav>
If we would spell out all the objects, it would be represented as
include Hexp
Node.new(:nav, {"id"=>"menu"},
List.new([
Node.new(:ul, {},
List.new([
Node.new(:li, {}, List.new([TextNode.new("Home")])),
Node.new(:li, {}, List.new([TextNode.new("lolcats")])),
Node.new(:li, {}, List.new([TextNode.new("Games")]))
])
)
])
)
The Hexp::Node
constructor is lenient though. It knows how to wrap things in TextNode
and List
instances, and it will let you omit the attributes Hash if it's empty, so you never actually type all of that out.
The above simplifies to:
Node.new(:nav, {"id"=>"menu"},
Node.new(:ul,
Node.new(:li, "Home"),
Node.new(:li, "lolcats"),
Node.new(:li, "Games")
)
)
There's also a shorthand syntax:
node = H[:nav, {"id"=>"menu"},
H[:ul,
H[:li, "Home"],
H[:li, "Lolcats"],
H[:li, "Games"]]]
puts node.to_html
If the first argument to H[...]
is a Symbol, then the result is a Node
, otherwise it's a List
.
You can parse exisiting HTML to Hexp with Hexp.parse(...)
.
A Node
has a #tag
, #attrs
and #children
. The methods #set_tag
, #set_attrs
and #set_children
return a new updated instance.
node = H[:p, { class: 'bold' }, "A lovely paragraph"]
node.tag # => :p
node.attrs # => {"class"=>"bold"}
node.children # => ["A lovely paragraph"]
node.set_tag(:div)
# => H[:div, {"class"=>"bold"}, ["A lovely paragraph"]]
node.set_attrs({id: 'para-1'})
# => H[:p, {"id"=>"para-1"}, ["A lovely paragraph"]]
node.set_children(H[:em, "Ginsberg said:"], "The starry dynamo in the machinery of night")
# => H[:p, {"class"=>"bold"}, [H[:em, ["Ginsberg said:"]], "The starry dynamo in the machinery of night"]]
node.tag?(:p) # => true
node.text? # => false
node.children.first.text? # => true
# [] : As in Nokogiri/Hpricot, attributes can be accessed with hash syntax
node['class'] # => "bold"
# attr : Analogues to jQuery's `attr`, read-write based on arity
node.attr('class') # => "bold"
node.attr('class', 'bourgeois') # => H[:p, {"class"=>"bourgeois"}, ["A lovely paragraph"]]
node.has_attr?('class') # => true
node.class?('bold') # => true
node.add_class('daring') # => H[:p, {"class"=>"bold daring"}, ["A lovely paragraph"]]
node.class_list # => ["bold"]
node.remove_class('bold') # => H[:p, ["A lovely paragraph"]]
node.remove_attr('class') # => H[:p, ["A lovely paragraph"]]
# merge_attrs : Does a Hash#merge on the attributes, but the class
# attribute is treated special. aliased to %
node.merge_attrs(class: 'daring', id: 'poem')
# => H[:p, {"class"=>"bold daring", "id"=>"poem"}, ["A lovely paragraph"]]
node.empty? # => false
node.append(H[:blink, "ARRSOME"], H[:p, "bye"]) # => H[:p, {"class"=>"bold"}, ["A lovely paragraph", H[:blink, ["ARRSOME"]], H[:p, ["bye"]]]]
node.text # => "A lovely paragraph"
node.map_children { |ch| ch.text? ? ch.upcase : ch } # => H[:p, {"class"=>"bold"}, ["A LOVELY PARAGRAPH"]]
node.select('p')
# => #<Enumerator: #<Hexp::Node::CssSelection @node=H[:p, {"class"=>"bold"}, ["A lovely paragraph"]] @css_selector="p" matches=true>:each>
node.replace('.warn') {|warning| warning.add_class('bold') }
puts node.pp
node.to_html
node.to_dom # => Convert to Nokogiri
A Hexp::List
wraps and delegates to a Ruby Array, so it has the same
API as Array. Methods which mutate the Array will raise an exception.
Additionally Hexp::List
implements to_html
, append
, and +
. Just like built-in collections, the class implements []
as an alternative constructor.
Equality checks with ==
only compare value equality, so comparing to an Array with the same content returns true. Use eql?
for a stronger "type and value" equality.
list = Hexp::List[H[:p, "hello, world!"]]
list.append("what", "a", "nice", "day")
#=> [H[:p, ["hello, world!"]], "what", "a", "nice", "day"]
There is a thin layer of Rails integration included. This makes Hexp aware of the html_safe
/ html_safe?
convention used to distinguish text from markup. It also aliases to_html
to to_s
, so Hexp nodes and lists can be used transparently in templates.
<%= H[:p, legacy_helper] %>
You need to explicitly opt-in to this behaviour. The easiest is to add a 'require' to your Gemfile
gem 'hexp', require: 'hexp-rails'
If you like the Builder syntax available in other gems like Builder and Hpricot, you can use Hexp.build
to achieve the same
Hexp.build do
div id: 'warning-sign' do
span "It's happening!"
ul.warn_list do
li "Cats are taking over the world"
li "The price of lasagne has continued to rise"
end
end
end
# H[:div, {"id"=>"warning-sign"}, [
# H[:span, [
# "It's happening!"]],
# H[:ul, {"class"=>"warn_list"}],
# H[:li, [
# "Cats are taking over the world"]],
# H[:li, [
# "The price of lasagne has continued to rise"]]]]
When an object implements to_hexp
it can be used where you would otherwise use a node. This can be useful for instance to create components that know how to render themselves.
Yaks does not contain any core extensions, but there is an optional, opt-in, implementation of to_hexp
for NilClass, so nils in a list of nodes won't raise an error. This lets you write things like
H[:p,
some_node if some_condition?,
other_node if other_condition?
]
You can use it with require 'hexp/core_ext/nil'
. Loading hexp-rails
will automatically include this because, let's be honest, if you're using Rails a single monkey patch won't make the difference.
FAQs
Unknown package
We found that hexp demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Create React App is officially deprecated due to React 19 issues and lack of maintenance—developers should switch to Vite or other modern alternatives.
Security News
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
Security News
The Linux Foundation is warning open source developers that compliance with global sanctions is mandatory, highlighting legal risks and restrictions on contributions.