Class: Nokolexbor::Builder

Inherits:
Object
  • Object
show all
Defined in:
lib/nokolexbor/builder.rb

Overview

A DSL for programmatically building HTML documents.

No-arg block (instance_eval style) – tag names are called bare:

Nokolexbor do
body do
  h1 'Hello world'
  p 'This little p'
  ul do
    li 'Go to market'
    li 'Go to bed'
  end
end
end

Block-parameter style – tag names are called on the builder argument:

Nokolexbor::Builder.new do |b|
b.body do
  b.h1 'Hello world'
end
end

Building into an existing node:

Nokolexbor::Builder.with(existing_node) do
span 'injected'
end

Defined Under Namespace

Classes: NodeBuilder

Constant Summary collapse

OBJECT_INSTANCE_METHODS =

Methods defined on plain Object that should never be forwarded to @context as HTML element creation fallbacks.

Object.instance_methods.to_set.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(root = nil, &block) ⇒ Builder

Returns a new instance of Builder.

Parameters:

  • root (Node, nil) (defaults to: nil)

    When given, new nodes are appended under root and root.document is used as the owning document. When omitted a fresh Document and a DocumentFragment container are created.



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/nokolexbor/builder.rb', line 57

def initialize(root = nil, &block)
  if root
    @doc    = root.document
    @parent = root
  else
    @doc    = Document.new
    @parent = DocumentFragment.new(@doc)
  end

  @context = nil
  @arity   = nil

  return unless block

  @arity = block.arity
  if @arity <= 0
    # Capture outer self so that outer methods / ivars remain accessible
    # via method_missing delegation while the builder acts as self.
    @context = eval("self", block.binding)
    instance_eval(&block)
  else
    yield self
  end
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object

:nodoc:



116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/nokolexbor/builder.rb', line 116

def method_missing(method, *args, &block) # :nodoc:
  # Only delegate to the outer context for methods the user defined there.
  # Standard Object / Kernel methods (like :p, :pp, :puts …) must not be
  # forwarded to @context because all objects respond to them, which would
  # bypass element creation entirely.
  if @context && !OBJECT_INSTANCE_METHODS.include?(method) && @context.respond_to?(method)
    @context.send(method, *args, &block)
  else
    node = @doc.create_element(method.to_s.sub(/[_!]$/, ""), *args)
    insert(node, &block)
  end
end

Instance Attribute Details

#arityObject

Arity of the outermost block (drives instance_eval vs yield dispatch)



43
44
45
# File 'lib/nokolexbor/builder.rb', line 43

def arity
  @arity
end

#contextObject

A context object for use when the block has no arguments



46
47
48
# File 'lib/nokolexbor/builder.rb', line 46

def context
  @context
end

#docObject

The Document used to create new nodes



37
38
39
# File 'lib/nokolexbor/builder.rb', line 37

def doc
  @doc
end

#parentObject

The node that currently receives new children



40
41
42
# File 'lib/nokolexbor/builder.rb', line 40

def parent
  @parent
end

Class Method Details

.with(root, &block) ⇒ Object

Build into an existing root node.



49
50
51
# File 'lib/nokolexbor/builder.rb', line 49

def self.with(root, &block)
  new(root, &block)
end

Instance Method Details

#<<(string) ⇒ Object

Append raw HTML (parsed into nodes) under the current parent.



98
99
100
# File 'lib/nokolexbor/builder.rb', line 98

def <<(string)
  @doc.fragment(string).children.each { |x| insert(x) }
end

#cdata(string) ⇒ Object

Insert a CDATA node containing string.



88
89
90
# File 'lib/nokolexbor/builder.rb', line 88

def cdata(string)
  insert(@doc.create_cdata(string))
end

#comment(string) ⇒ Object

Insert a Comment node containing string.



93
94
95
# File 'lib/nokolexbor/builder.rb', line 93

def comment(string)
  insert(@doc.create_comment(string))
end

#p(*args, &block) ⇒ Object

Ruby's Kernel#p, Kernel#pp, etc. are defined on Object and therefore on Builder itself. They must be overridden so they fall through to method_missing and create the corresponding HTML element instead of printing values to stdout.



112
113
114
# File 'lib/nokolexbor/builder.rb', line 112

def p(*args, &block) # :nodoc:
  method_missing(:p, *args, &block)
end

#respond_to_missing?(method, include_private = false) ⇒ Boolean

:nodoc:

Returns:

  • (Boolean)


129
130
131
# File 'lib/nokolexbor/builder.rb', line 129

def respond_to_missing?(method, include_private = false) # :nodoc:
  (@context && !OBJECT_INSTANCE_METHODS.include?(method) && @context.respond_to?(method)) || super
end

#text(string) ⇒ Object

Insert a Text node containing string.



83
84
85
# File 'lib/nokolexbor/builder.rb', line 83

def text(string)
  insert(@doc.create_text_node(string))
end

#to_htmlObject Also known as: to_s

Serialize the built content to an HTML string.



103
104
105
# File 'lib/nokolexbor/builder.rb', line 103

def to_html
  @parent.to_html
end