Class: Usmu::Template::Layout

Inherits:
StaticFile show all
Defined in:
lib/usmu/template/layout.rb

Overview

Class to represent files templated with a Tilt library. Most of the custom rendering logic is contained here.

Direct Known Subclasses

Include, Page

Instance Attribute Summary collapse

Attributes inherited from StaticFile

#mtime, #name

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from StaticFile

#==, #inspect

Methods included from Helpers::Indexer

included

Constructor Details

#initialize(configuration, name, metadata, type = nil, content = nil) ⇒ Layout

Returns a new instance of Layout.

Parameters:

  • configuration (Usmu::Configuration)

    The configuration for the website we're generating.

  • name (String)

    The name of the file in the source directory.

  • metadata (Hash)

    The metadata for the file.

  • type (String) (defaults to: nil)

    The type of template to use with the file. Used for testing purposes.

  • content (String) (defaults to: nil)

    The content of the file. Used for testing purposes.



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/usmu/template/layout.rb', line 23

def initialize(configuration, name, , type = nil, content = nil)
  super(configuration, name, , type, content)

  if type.nil?
    type = name.split('.').last
    unless ::Tilt.default_mapping[type]
      raise "Templates of type '#{type}' aren't currently supported by Tilt. " +
            'Do you have the required gem installed?'
    end
  end
  @type = type
  path = File.join("#{content_path}", "#{name[0, name.length - type.length - 1]}")

  if content.nil?
    content = File.read("#{path}.#{type}")
  end
  @content = content

  @parent = Layout.find_layout(configuration, self.['layout'])

  # Don't use the parent if it would result in weirdness
  unless @parent.nil?
    @parent = nil unless
        output_extension == @parent.output_extension || output_extension.nil? || @parent.output_extension.nil?
  end
end

Instance Attribute Details

#content_pathstring (readonly, protected)

Returns the base path to the files used by this class.

This folder should be the parent folder for the file named by the name attribute.

Returns:

  • (string)

    the base path to the files used by this class.

See Also:



213
214
215
# File 'lib/usmu/template/layout.rb', line 213

def content_path
  @configuration.layouts_path
end

#helpersUsmu::Template::Helpers (readonly, protected)

Returns the Helpers class to use as a scope for templates.

Returns:



219
220
221
# File 'lib/usmu/template/layout.rb', line 219

def helpers
  @helpers ||= Usmu::Template::Helpers.new(@configuration, self)
end

#input_pathString (readonly)

Returns the full path to the file in the source directory.

Returns:

  • (String)

    the full path to the file in the source directory



91
92
93
# File 'lib/usmu/template/layout.rb', line 91

def input_path
  File.join(content_path, @name)
end

#metadataHash (readonly)

Returns the metadata associated with this layout.

This will include any metadata from parent templates and default metadata

Returns:

  • (Hash)

    the metadata associated with this layout.



56
57
58
59
60
61
62
# File 'lib/usmu/template/layout.rb', line 56

def 
  if @parent.nil?
    @configuration['default meta', default: {}].dup.deep_merge!(@metadata)
  else
    @parent..deep_merge!(@metadata)
  end
end

#output_extensionString (readonly)

Returns the extension to use with the output file.

Returns:

  • (String)

    the extension to use with the output file.



97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/usmu/template/layout.rb', line 97

def output_extension
  case @type
    when 'erb', 'rhtml', 'erubis', 'liquid'
      nil
    when 'coffee'
      'js'
    when 'less', 'sass', 'scss'
      'css'
    else
      'html'
  end
end

#output_filenameString (readonly)

Returns the filename to use for the output directory with any modifications to the input filename required.

Returns:

  • (String)

    the filename to use in the output directory.



114
115
116
117
118
119
120
# File 'lib/usmu/template/layout.rb', line 114

def output_filename
  if output_extension
    @name[0..@name.rindex('.')] + output_extension
  else
    @name[0..@name.rindex('.') - 1]
  end
end

#parentUsmu::Template::Layout (readonly, protected)

Returns The template acting as a wrapper for this template, if any.

Returns:



168
169
170
# File 'lib/usmu/template/layout.rb', line 168

def parent
  @parent
end

#provider_nameString (readonly, protected)

Returns the Tilt template engine's name for this layout.

This is used to determine which settings to use from the configuration file.

Returns:

  • (String)

    the Tilt template engine's name for this layout



189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/usmu/template/layout.rb', line 189

def provider_name
  provider = Tilt.default_mapping.lazy_map[@type].select {|x| x[0] == template_class.name }.first
  if provider
    # Use the require path to choose out a name.
    provider[1].split('/').last
  else
    # Approximate using class name if we can't track down a require path.
    provider = template_class.name.split('::').last
    if provider.end_with? 'Template'
      provider[0..-9].downcase
    else
      provider.downcase
    end
  end
end

#template_classTilt::Template (readonly, protected)

Returns the Tilt template engine for this layout.

Returns:

  • (Tilt::Template)

    the Tilt template engine for this layout



179
180
181
# File 'lib/usmu/template/layout.rb', line 179

def template_class
  @template_class ||= ::Tilt.default_mapping[@type]
end

#typeString (readonly)

Returns the type of file this is. This is used to determine which template engine to use.

Returns:

  • (String)

    the type of file this is. This is used to determine which template engine to use.



16
17
18
# File 'lib/usmu/template/layout.rb', line 16

def type
  @type
end

Class Method Details

.find_layout(configuration, name) ⇒ Usmu::Layout

Static method to create a layout for a given configuration by it's name if it exists. This differs from #initialise in that it allows different types of values to be supplied as the name and will not fail if name is nil

Parameters:

  • configuration (Usmu::Configuration)

    The configuration to use for the search

  • name (String)

    If name is a string then search for a template with that name. Name here should not include file extension, eg. body not body.slim. If name is not a string then it will be returned verbatim. This means that name is nilable and can also be passed in as an Usmu::Template::Layout already for testing purposes.

Returns:

  • (Usmu::Layout)


132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/usmu/template/layout.rb', line 132

def self.find_layout(configuration, name)
  return nil if name.nil?

  if @layout_history[configuration][name]
    @log.debug(
        'Layout loop detected. Current loaded layouts: ' +
        @layout_history[configuration].inspect
    )
    return nil
  else
    @log.debug("Loading layout '#{name}'")
    @layout_history[configuration][name] = true
  end

  ret = search_layout(configuration, name)

  @layout_history[configuration][name] = nil
  return ret
end

.is_valid_file?(folder_type, name) ⇒ Boolean

Tests if a given file is a valid Tilt template based on the filename.

Parameters:

  • folder_type (String)

    One of "source" or "layout" depending on where the template is in the source tree. Not used by Usmu::Template::Layout directly but intended to be available for future API.

  • name (String)

    The filename to be tested.

Returns:

  • (Boolean)


159
160
161
162
# File 'lib/usmu/template/layout.rb', line 159

def self.is_valid_file?(folder_type, name)
  type = name.split('.').last
  ::Tilt.default_mapping[type] ? true : false
end

.search_layout(configuration, name) ⇒ Usmu::Template::Layout (private)

Returns:

See Also:

  • #find_layout


264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
# File 'lib/usmu/template/layout.rb', line 264

def self.search_layout(configuration, name)
  if name === 'none' || name.nil?
    return nil
  elsif name.class.name == 'String'
    layouts_path = configuration.layouts_path
    Dir["#{layouts_path}/#{name}.*"].each do |f|
      filename = File.basename(f)
      if filename != "#{name}.meta.yml"
        path = f[(layouts_path.length + 1)..f.length]
        return new(configuration, path, configuration..(path))
      end
    end
  else
    return name
  end
end

Instance Method Details

#[]=(index, value) ⇒ void (protected)

Allows for protected level direct access to the metadata store.

See Also:



173
174
175
# File 'lib/usmu/template/layout.rb', line 173

def []=(index, value)
  @metadata[index] = value
end

#add_template_defaults(overrides, engine) ⇒ Hash (protected)

Adds defaults for the given generator engine

Parameters:

  • overrides (Hash)

    A hash of options provided by the user

  • engine (String)

    The name of the rendering engine

Returns:

  • (Hash)

    Template options to pass into the engine



228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
# File 'lib/usmu/template/layout.rb', line 228

def add_template_defaults(overrides, engine)
  case engine
    when 'redcarpet'
      if overrides.delete :pygments
        begin
          require 'pygments'
          overrides[:renderer] = Class.new(::Redcarpet::Render::HTML) do
            def block_code(code, language)
              Pygments.highlight(code, lexer: language)
            end
          end
        rescue LoadError
          @log.warn('Unable to load pygments.rb gem.')
        end
        overrides
      end
    when 'sass'
      {
          :load_paths => [@configuration.source_path + '/' + File.dirname(@name)]
      }.deep_merge!(overrides)
    else
      overrides
  end
end

#get_variables(variables) ⇒ Hash (private)

Utility function which collates variables to pass to the template engine.

Returns:

  • (Hash)


258
259
260
# File 'lib/usmu/template/layout.rb', line 258

def get_variables(variables)
  {'site' => @configuration}.deep_merge!().deep_merge!(variables)
end

#render(variables = {}) ⇒ String

Renders the file with any templating language required and returns the result

Parameters:

  • variables (Hash) (defaults to: {})

    Variables to be used in the template.

Returns:

  • (String)

    The rendered file.



68
69
70
71
72
73
74
75
76
77
78
# File 'lib/usmu/template/layout.rb', line 68

def render(variables = {})
  content = render_content(variables)
  has_cr = content.index("\r")
  content += (has_cr ? "\r\n" : "\n") if content[-1] != "\n"

  if @parent.nil?
    content
  else
    @parent.render({'content' => content})
  end
end

#render_content(variables = {}) ⇒ String

Renders the internal content of the file with any templating language required and returns the result

Parameters:

  • variables (Hash) (defaults to: {})

    Variables to be used in the template.

Returns:

  • (String)

    The rendered content.



84
85
86
87
# File 'lib/usmu/template/layout.rb', line 84

def render_content(variables = {})
  template_config = add_template_defaults((@configuration[provider_name] || {}).clone, provider_name)
  template_class.new("#{@name}", 1, template_config) { @content }.render(helpers, get_variables(variables))
end