Class: Undies::Template

Inherits:
Object
  • Object
show all
Defined in:
lib/undies/template.rb

Constant Summary collapse

ELEM_METH_REGEX =

Element proxy methods (‘_<element>”) ========================

/^_(.+)$/
ESCAPE_HTML =

Ripped from Rack v1.3.0 ======================================

> ripped b/c I don’t want a dependency on Rack for just this

{
  "&" => "&amp;",
  "<" => "&lt;",
  ">" => "&gt;",
  "'" => "&#x27;",
  '"' => "&quot;",
  "/" => "&#x2F;"
}
ESCAPE_HTML_PATTERN =
Regexp.union(*ESCAPE_HTML.keys)

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(source, data, output) ⇒ Template

Returns a new instance of Template.

Raises:

  • (ArgumentError)


15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/undies/template.rb', line 15

def initialize(source, data, output)
  # setup the source stack and output objects
  raise ArgumentError, "please provide a Source object" if !source.kind_of?(Source)
  @_undies_source_stack = SourceStack.new(source)
  raise ArgumentError, "please provide an Output object" if !output.kind_of?(Output)
  @_undies_output = output

  # apply data to template scope
  raise ArgumentError if !data.kind_of?(::Hash)
  if (data.keys.map(&:to_s) & self.public_methods.map(&:to_s)).size > 0
    raise ArgumentError, "data conflicts with template public methods."
  end
  metaclass = class << self; self; end
  data.each {|key, value| metaclass.class_eval { define_method(key){value} }}

  # yield to recursivley render the source stack
  self.__yield

  # flush any remaining output to the stream
  @_undies_output.flush
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

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



67
68
69
70
71
72
73
# File 'lib/undies/template.rb', line 67

def method_missing(meth, *args, &block)
  if meth.to_s =~ ELEM_METH_REGEX
    element($1, *args, &block)
  else
    super
  end
end

Class Method Details

.output(template) ⇒ Object

have as many methods to the class level as possilbe to keep from polluting the public instance methods, the instance scope, and to maximize the effectiveness of the Template#method_missing logic



11
12
13
# File 'lib/undies/template.rb', line 11

def self.output(template)
  template.instance_variable_get("@_undies_output")
end

Instance Method Details

#_(data = "") ⇒ Object

Add a text node (data escaped) to the nodes of the current node



56
# File 'lib/undies/template.rb', line 56

def _(data=""); self.__ self.escape_html(data.to_s); end

#__(data = "") ⇒ Object

Add a text node with the data un-escaped



59
# File 'lib/undies/template.rb', line 59

def __(data=""); @_undies_output.node(data.to_s); end

#__partial(source, data) ⇒ Object

call this to render partial source embedded in a template partial source is rendered with its own scope/data but shares its parent template’s output object



51
52
53
# File 'lib/undies/template.rb', line 51

def __partial(source, data)
  Undies::Template.new(source, data, @_undies_output)
end

#__yieldObject

call this to render template source use this method in layouts to insert a layout’s content source



39
40
41
42
43
44
45
46
# File 'lib/undies/template.rb', line 39

def __yield
  return if @_undies_source_stack.nil? || (source = @_undies_source_stack.pop).nil?
  if source.file?
    instance_eval(source.data, source.source, 1)
  else
    instance_eval(&source.data)
  end
end

#element(*args, &block) ⇒ Object Also known as: tag

Add an element to the nodes of the current node



62
# File 'lib/undies/template.rb', line 62

def element(*args, &block); @_undies_output.element(*args, &block); end

#escape_html(string) ⇒ Object

Escape ampersands, brackets and quotes to their HTML/XML entities.



95
96
97
# File 'lib/undies/template.rb', line 95

def escape_html(string)
  string.to_s.gsub(ESCAPE_HTML_PATTERN){|c| ESCAPE_HTML[c] }
end

#respond_to?(*args) ⇒ Boolean

Returns:

  • (Boolean)


74
75
76
77
78
79
80
# File 'lib/undies/template.rb', line 74

def respond_to?(*args)
  if args.first.to_s =~ ELEM_METH_REGEX
    true
  else
    super
  end
end