Class: Hexp::Builder
- Inherits:
- BasicObject
- Includes:
- Hexp
- Defined in:
- lib/hexp/builder.rb
Overview
Build Hexps using the builder pattern
Defined Under Namespace
Classes: NodeBuilder
Constant Summary
Constant Summary
Constants included from Hexp
Instance Method Summary (collapse)
-
- (Hexp::Builder) <<(*args)
Add Hexp objects to the current tag.
-
- (NilClass) _process(&block)
private
Call the block, with a specific value of 'self'.
-
- (Builder) initialize(tag = nil, *args, &block)
constructor
private
Construct a new builder, and start building.
-
- (String) inspect
Return a debugging representation.
-
- (NilClass) tag!(tag, *args, &block)
(also: #method_missing)
Add a tag (HTML element).
-
- (Hexp::Builder) text!(text)
Add a text node to the tree.
-
- (Hexp::Node) to_hexp
Implement the standard Hexp coercion protocol.
Methods included from Hexp
Array, build, deep_freeze, included, parse
Constructor Details
- (Builder) initialize(tag = nil, *args, &block)
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.
Construct a new builder, and start building
The recommended way to call this is through `Hexp.build`.
19 20 21 22 23 24 25 26 |
# File 'lib/hexp/builder.rb', line 19 def initialize(tag = nil, *args, &block) @stack = [] if tag tag!(tag, *args, &block) else _process(&block) if block end end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
- (NilClass) method_missing
Add a tag (HTML element)
Typically this is called implicitly through method missing, but in case of name clashes or dynamically generated tags you can call this directly.
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/hexp/builder.rb', line 72 def tag!(tag, *args, &block) text, attributes = nil, {} args.each do |arg| case arg when ::Hash attributes.merge!(arg) when ::String text ||= '' text << arg end end @stack << [tag, attributes, text ? [text] : []] if block _process(&block) end if @stack.length > 1 node = @stack.pop @stack.last[2] << node NodeBuilder.new(node, self) else NodeBuilder.new(@stack.last, self) end end |
Instance Method Details
- (Hexp::Builder) <<(*args)
Add Hexp objects to the current tag
Any Hexp::Node or other object implementing to_hexp can be added with this operator. Multiple objects can be specified in one call.
Nokogiri and Builder allow inserting of strings containing HTML through this operator. Since this would violate the core philosophy of Hexp, and open the door for XSS vulnerabilities, we do not support that usage.
If you really want to insert HTML that is already in serialized form, consider parsing it to Hexps first
117 118 119 120 121 122 123 124 125 126 |
# File 'lib/hexp/builder.rb', line 117 def <<(*args) args.each do |arg| if arg.respond_to?(:to_hexp) @stack.last[2] << arg self else ::Kernel.raise ::Hexp::FormatError, "Inserting literal HTML into a builder with << is deliberately not supported by Hexp" end end end |
- (NilClass) _process(&block)
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.
Call the block, with a specific value of 'self'
If the block takes an argument, then we pass ourselves (the builder) to the block, and call it as a closure. This way 'self' refers to the calling object, and it can reference its own methods and ivars.
If the block does not take an argument, then we evaluate it in the context of ourselves (the builder), so unqualified method calls are seen as builder calls.
159 160 161 162 163 164 165 |
# File 'lib/hexp/builder.rb', line 159 def _process(&block) if block.arity == 1 block.call(self) else self.instance_eval(&block) end end |
- (String) inspect
Return a debugging representation
Hexp is intended for HTML, so it shouldn't be a problem that this is an actual method. It really helps for debugging or when playing around in irb. If you really want an `<inspect>` tag, use `tag!(:inspect)`.
219 220 221 |
# File 'lib/hexp/builder.rb', line 219 def inspect "#<Hexp::Builder #{@stack.empty? ? '[]' : to_hexp.inspect}>" end |
- (NilClass) tag!(tag, *args, &block) Also known as: method_missing
Add a tag (HTML element)
Typically this is called implicitly through method missing, but in case of name clashes or dynamically generated tags you can call this directly.
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/hexp/builder.rb', line 48 def tag!(tag, *args, &block) text, attributes = nil, {} args.each do |arg| case arg when ::Hash attributes.merge!(arg) when ::String text ||= '' text << arg end end @stack << [tag, attributes, text ? [text] : []] if block _process(&block) end if @stack.length > 1 node = @stack.pop @stack.last[2] << node NodeBuilder.new(node, self) else NodeBuilder.new(@stack.last, self) end end |
- (Hexp::Builder) text!(text)
Add a text node to the tree
87 88 89 90 91 |
# File 'lib/hexp/builder.rb', line 87 def text!(text) _raise_if_empty! "Hexp::Builder needs a root element to add text elements to" @stack.last[2] << text.to_s self end |
- (Hexp::Node) to_hexp
Implement the standard Hexp coercion protocol
By implementing this a Builder is interchangeable for a regular node, so you can use it inside other nodes transparently. But you can call this method if you really, really just want the plain Node
140 141 142 143 |
# File 'lib/hexp/builder.rb', line 140 def to_hexp _raise_if_empty! ::Hexp::Node[*@stack.last] end |