Class: Undies::Template

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

Constant Summary collapse

ESCAPE_HTML =

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

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

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

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

/^_(.+)$/

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ Template

end Rip from Rack v1.3.0 =====================================



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/undies/template.rb', line 39

def initialize(*args)
  output = if args.last.kind_of?(Output)
    args.pop
  else
    raise ArgumentError, "please provide an Output object"
  end
  data = args.last.kind_of?(::Hash) ? args.pop : {}
  source = args.last.kind_of?(Source) ? args.pop : Source.new(Proc.new {})

  # setup the source stack and output objects
  @_undies_source_stack = SourceStack.new(source)

  # apply data to template scope
  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} }}

  # save off the output obj for streaming
  @_undies_output = output

  # yield to recursivley render the source stack
  self.__yield

  # flush any remaining output to the stream
  self.class.flush(self)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

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



103
104
105
106
107
108
109
# File 'lib/undies/template.rb', line 103

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

Class Method Details

.escape_html(string) ⇒ Object

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



34
35
36
# File 'lib/undies/template.rb', line 34

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

.flush(template) ⇒ Object



18
19
20
# File 'lib/undies/template.rb', line 18

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

.output(template) ⇒ Object

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



14
15
16
# File 'lib/undies/template.rb', line 14

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



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

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

#__(data = "") ⇒ Object

Add a text node with the data un-escaped



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

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

#___(data = "") ⇒ Object

Add a text node with the data un-escaped, forcing pp output



93
94
95
# File 'lib/undies/template.rb', line 93

def ___(data="")
  @_undies_output.node(Node.new(data.to_s, :force_pp => true))
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



82
83
84
# File 'lib/undies/template.rb', line 82

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



70
71
72
73
74
75
76
77
# File 'lib/undies/template.rb', line 70

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



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

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

#respond_to?(*args) ⇒ Boolean

Returns:

  • (Boolean)


110
111
112
113
114
115
116
# File 'lib/undies/template.rb', line 110

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