Class: Hexp::Node

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
Attributes, Children
Defined in:
lib/hexp/node.rb,
lib/hexp-rails.rb,
lib/hexp/node/pp.rb,
lib/hexp/node/domize.rb,
lib/hexp/node/children.rb,
lib/hexp/node/rewriter.rb,
lib/hexp/node/normalize.rb,
lib/hexp/node/selection.rb,
lib/hexp/node/attributes.rb,
lib/hexp/node/css_selection.rb

Overview

Transparently use Hexp nodes in templates

Defined Under Namespace

Modules: Attributes, Children Classes: CssSelection, Domize, Normalize, PP, Rewriter, Selection

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Children

#add_child, #append, #content, #empty?, #map_children, #text

Methods included from Attributes

#[], #add_class, #attr, #class?, #class_list, #has_attr?, #merge_attrs, #remove_attr, #remove_class, #set_attrs

Constructor Details

#initialize(*args) ⇒ Hexp::Node

Normalize the arguments

Examples:

Hexp::Node.new(:p, {'class' => 'foo'}, [[:b, "Hello, World!"]])

Parameters:

  • args (Array)

    args a Hexp node components



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/hexp/node.rb', line 127

def initialize(*args)
  tag_ok   = args[0].instance_of?(Symbol)
  raise "The tag of node should be a Symbol" unless tag_ok

  attrs_ok = args[1].instance_of?(Hash) &&
             args[1].all? {|k,v| k.instance_of?(String) && v.instance_of?(String) }

  if attrs_ok && args[2].instance_of?(List)
    concord_init(args[0], args[1], args[2])
  elsif attrs_ok && args[2].instance_of?(Array)
    concord_init(args[0], args[1], List.new(args[2]))
  else
    concord_init(*Normalize.new(args).call)
  end.freeze
end

Class Method Details

.[](*args) ⇒ Hexp::Node

Main entry point for creating literal hexps

At the moment this just redirects to #new, and since Hexp::Node is aliased to H this provides a shorthand for the contructor,

Note that while the H[] form is part of the public API and expected to remain, it’s implementation might change. In particular H might become a class or module in its own right, so it is recommended to only use this method in its H[] form.

Examples:

H[:span, {attr: 'value'}].

Parameters:

  • args (Array)

    args a Hexp node components

Returns:



111
112
113
# File 'lib/hexp/node.rb', line 111

def self.[](*args)
  new(*args)
end

.inspect_nameString

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns the class name for use in creating inspection strings

This will return “H” if H == Hexp::Node, or “Hexp::Node” otherwise.

Returns:

  • (String)


340
341
342
343
344
345
346
# File 'lib/hexp/node.rb', line 340

def inspect_name
  if defined?(H)
    'H'
  else
    self.name
  end
end

Instance Method Details

#concord_initObject



115
# File 'lib/hexp/node.rb', line 115

alias concord_init initialize

#inspectString

Return a string representation that is close to the literal form

Examples:

H[:p, {class: 'foo'}].inspect #=> "H[:p, {\"class\"=>\"foo\"}]"

Returns:

  • (String)


191
192
193
# File 'lib/hexp/node.rb', line 191

def inspect
  self.class.inspect_name + [tag, attributes, children].compact.reject(&:empty?).inspect
end

#ppString

Pretty print, a multiline representation with indentation

Examples:

H[:p, [[:span], [:div]]].pp # => "H[:p, [\n  H[:span],\n  H[:div]]]"

Returns:

  • (String)


203
204
205
# File 'lib/hexp/node.rb', line 203

def pp
  self.class::PP.new(self).call
end

#process(*processors) ⇒ Hexp::Node

Run a number of processors on this node

This is pure convenience, but it helps to conceptualize the “processor” idea of a component (be it a lambda or other object), that responds to call, and transform a Hexp::Node tree.

Examples:

hexp.process(
  ->(node) { node.replace('.section') {|node| H[:p, class: 'big', node]} },
  ->(node) { node.add_class 'foo' },
  InlineAssets.new
)

Parameters:

  • processors (Array<#call>)

Returns:



303
304
305
# File 'lib/hexp/node.rb', line 303

def process(*processors)
  processors.empty? ? self : processors.first.(self).process(*processors.drop(1))
end

#rewrite(css_selector = nil) {|The| ... } ⇒ Hexp::Node Also known as: replace

Replace nodes in a tree

With a CSS selector string like “form.checkout” you specify the nodes you want to operate on. These will be passed one by one into the block. The block returns the Hexp::Node that will replace the old node, or it can replace an Array of nodes to fill the place of the old node.

Because of this you can add one or more nodes, or remove nodes by returning an empty array.

Examples:

Remove all script tags

tree.replace('script') {|_| [] }

Wrap each <input> tag into a <p> tag

tree.replace('input') do |input|
  H[:p, input]
end

Parameters:

  • css_selector (String) (defaults to: nil)

Yield Parameters:

Returns:



264
265
266
267
# File 'lib/hexp/node.rb', line 264

def rewrite(css_selector = nil, &block)
  return Rewriter.new(self, block) if css_selector.nil?
  CssSelection.new(self, css_selector).rewrite(&block)
end

#select(css_selector = nil) {|| ... } ⇒ Hexp::Selector, Hexp::CssSelector

Select nodes based on a css selector

Parameters:

  • css_selector (String) (defaults to: nil)

Yield Parameters:

Returns:



278
279
280
281
282
283
284
# File 'lib/hexp/node.rb', line 278

def select(css_selector = nil, &block)
  if css_selector
    CssSelection.new(self, css_selector).each(&block)
  else
    Selection.new(self, block)
  end
end

#set_tag(tag) ⇒ Hexp::Node

Return a new node, with a different tag

Examples:

H[:div, class: 'foo'].set_tag(:bar)
# => H[:bar, class: 'foo']

Parameters:

  • tag (#to_sym)

    The new tag

Returns:



233
234
235
# File 'lib/hexp/node.rb', line 233

def set_tag(tag)
  H[tag.to_sym, attributes, children]
end

#tag?(tag) ⇒ Boolean

Returns:

  • (Boolean)


219
220
221
# File 'lib/hexp/node.rb', line 219

def tag?(tag)
  self.tag == tag
end

#text?FalseClass

Is this a text node? Returns false

Examples:

H[:p].text? #=> false

Returns:

  • (FalseClass)


215
216
217
# File 'lib/hexp/node.rb', line 215

def text?
  false
end

#to_dom(options = {}) ⇒ Nokogiri::HTML::Document

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Convert this node into a Nokogiri Document

Examples:

H[:p].to_dom
#=> #<Nokogiri::HTML::Document name="document"
      children=[#<Nokogiri::XML::DTD name="html">,
      #<Nokogiri::XML::Element name="p">]>

Returns:

  • (Nokogiri::HTML::Document)


179
180
181
# File 'lib/hexp/node.rb', line 179

def to_dom(options = {})
  Domize.new(self, options).call
end

#to_hexpHexp::Node

Standard hexp coercion protocol, return self

Examples:

H[:p].to_hexp #=> H[:p]

Returns:



151
152
153
# File 'lib/hexp/node.rb', line 151

def to_hexp
  self
end

#to_html(options = {}) ⇒ String

Serialize this node to HTML

Examples:

H[:html, [ H[:body, ["hello, world"] ] ]] .to_html
# => "<html><body>hello, world</body></html>"

Returns:

  • (String)


164
165
166
# File 'lib/hexp/node.rb', line 164

def to_html(options = {})
  Unparser.new(options).call(self)
end

#to_sObject



7
8
9
# File 'lib/hexp-rails.rb', line 7

def to_s
  to_html.html_safe
end