Class: Arrow::Template::IncludeDirective

Inherits:
Directive show all
Includes:
Parser::Patterns
Defined in:
lib/arrow/template/include.rb

Overview

The Arrow::Template::IncludeDirective class, a derivative of Arrow::Template::Directive. This is the class which defines the behaviour of the ‘include’ template directive.

Syntax

  <!-- Include a subtemplate directly -->
  <?include subtemplate.tmpl ?>

  <!-- Include a subtemplate as a callable sub-entity -->
  <?include subtemplate.tmpl as sub ?>

Example

If ‘subtemplate.tmpl’ contains:

  <?attr foo?>

and the main template contains:

  <?include subtemplate.tmpl?>
  <?include subtemplate.tmpl as sub?>

and the code (template is the Template object) looks like:

  template.foo = "argle"
  template.sub.foo = "bargle"

the template will render as:

  argle
  bargle

Authors

  • Michael Granger

Please see the file LICENSE in the top-level directory for licensing details.

Constant Summary

SVNRev =

SVN Revision

%q$Rev$
SVNId =

SVN Id

%q$Id$

Constants included from Parser::Patterns

ALTERNATION, ARGDEFAULT, ARGUMENT, CAPTURE, COMMA, DBLQSTRING, DOT, EQUALS, IDENTIFIER, INFIX, LBRACKET, NUMBER, PATHNAME, QUOTEDSTRING, RBRACKET, REBINDOP, REGEXP, SLASHQSTRING, SYMBOL, TAGCLOSE, TAGMIDDLE, TAGOPEN, TICKQSTRING, VARIABLE, WHITESPACE

Constants inherited from Directive

SVNId, SVNRev

Constants inherited from Node

SVNId, SVNRev

Constants included from Arrow::HTMLUtilities

ARRAY_HTML_CONTAINER, HASH_HTML_CONTAINER, HASH_PAIR_HTML, IMMEDIATE_OBJECT_HTML_CONTAINER, IVAR_HTML_FRAGMENT, OBJECT_HTML_CONTAINER, THREAD_DUMP_KEY

Instance Attribute Summary

Instance Method Summary

Methods inherited from Directive

create, derivativeDirs, #inspect

Methods inherited from Node

#css_class, #inspect, #is_rendering_node?, #to_a, #to_s

Methods included from Arrow::HTMLUtilities

#escape_html, #make_html_for_object, #make_object_html_wrapper

Methods inherited from Arrow::Object

deprecate_class_method, deprecate_method, inherited

Methods included from Arrow::Loggable

#log

Constructor Details

- (IncludeDirective) initialize(type, parser, state)

Initialize a new IncludeDirective object.



54
55
56
57
58
59
60
61
# File 'lib/arrow/template/include.rb', line 54

def initialize( type, parser, state ) # :notnew:
  @nodes      = nil
  @identifier   = nil
  @subtemplate  = nil

  state[:includeStack] ||= []
  super
end

Instance Attribute Details

- (Object) identifier Also known as: name

The identifier associated with an include that has an ‘as ’ part.



70
71
72
# File 'lib/arrow/template/include.rb', line 70

def identifier
  @identifier
end

- (Object) subtemplate

The template object associated with an include that has an ‘as ’ part.



76
77
78
# File 'lib/arrow/template/include.rb', line 76

def subtemplate
  @subtemplate
end

Instance Method Details

- (Object) add_to_template(template)

Add the nodes that were included to the given template object.



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/arrow/template/include.rb', line 80

def add_to_template( template )
  #self.log.debug "Installing an include's subnodes"

  if @identifier
    template.install_node( self )
    template.send( "#{@identifier}=", @subtemplate )
    targetTemplate = @subtemplate
  else
    targetTemplate = template
  end

  @nodes.each do |node|
    targetTemplate.install_node( node )
  end
end

- (Object) parse_directive_contents(parser, state) (protected)

Parse the contents of the directive, loading the specified file into the scanner, if possible.



151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/arrow/template/include.rb', line 151

def parse_directive_contents( parser, state )
  filename = parser.scan_for_pathname( state ) or
    raise Arrow::ParseError, "No filename found for 'include'"
  filename.untaint

  state.scanner.skip( WHITESPACE )
  if state.scanner.scan( /\bas\b/i )
    @identifier = parser.scan_for_identifier( state )
  end

  # Try to do the include. Handle errors ourselves since this happens
  # during parse time.
  begin
    #self.log.debug "Include stack is: ", state[:includeStack]

    # Catch circular includes
    if state[:includeStack].include?( filename )
      raise Arrow::TemplateError, "Circular include: %s -> %s" %
        [ state[:includeStack].join(" -> "), filename ]

    # Parse the included file into nodes, passing the state from
    # the current parse into the subparse.
    else
      initialData = state.data.dup
      initialData[:includeStack].push filename
      
      load_path = state.template._load_path
      #self.log.debug "Load path from including template is: %p" %
      # load_path
      path = Arrow::Template.find_file( filename, load_path )
      content = File.read( path )
      content.untaint

      #self.log.debug "initialData is: %p" % initialData
      @nodes = parser.parse( content, state.template, initialData )
      initialData[:includeStack].pop
    end

  # Some errors just turn into comment nodes
  # :TODO: Make this configurable somehow?
  rescue Arrow::TemplateError, IOError => err
    msg = "#{err.class.name}: Include #{filename}: #{err.message}"
    @nodes = [ Arrow::Template::CommentNode.new(msg) ]
  end

  # If the directive has an "as <id>" part, create the subtemplate
  # that will be associated with that identifier.
  if @identifier
    @subtemplate = Arrow::Template.new( @nodes, state.template._config )
  end

  return true
end

- (Object) render(template, scope)

Render the include.



98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/arrow/template/include.rb', line 98

def render( template, scope )
  rary = super

  # Render the included nodes
  if @subtemplate
    #self.log.debug "Rendering an include's subtemplate"
    rary.push( *(@subtemplate.render) )
  else
    #self.log.debug "Rendering an include's subnodes"
    rary.push( *(template.render( @nodes, scope )) )
  end

  return rary
end

- (Object) to_html

Return an HTML fragment that can be used to represent the node symbolically in a web-based introspection interface.



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/arrow/template/include.rb', line 116

def to_html
  nodeclass = self.css_class

  if @subtemplate
    subtree = @subtemplate._syntax_tree
    html = ''
    html << %q{<strong>#%s</strong> } % @identifier
    html <<
      %q{<div class="node-subtemplate %s-node-subtemplate">
      <div class="node-subtemplate-head %s-node-subtemplate-head"
      >Subtemplate</div>%s</div>} % [
        nodeclass, nodeclass,
        subtree.collect {|node| node.to_html}.join(''),
      ]

    super { html }
  else
    super {
      %q{<div class="node-subtree %s-node-subtree">
      <div class="node-subtree-head %s-node-subtree-head"
      >Subnodes</div>%s</div>} % [
        nodeclass, nodeclass,
        @nodes.collect {|node| node.to_html}.join
      ]
    }
  end
end