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

#name

Class Method Summary collapse

Instance Method Summary collapse

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.



22
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
# File 'lib/usmu/template/layout.rb', line 22

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:



200
201
202
# File 'lib/usmu/template/layout.rb', line 200

def content_path
  @configuration.layouts_path
end

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

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

Returns:



206
207
208
# File 'lib/usmu/template/layout.rb', line 206

def helpers
  @helpers ||= Usmu::Template::Helpers.new(@configuration)
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



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

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.



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

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.



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

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.



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

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:



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

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



188
189
190
# File 'lib/usmu/template/layout.rb', line 188

def provider_name
  Tilt.default_mapping.lazy_map[@type].select {|x| x[0] == template_class.name }.first[1].split('/').last
end

#template_classTilt::Template (readonly, protected)

Returns the Tilt template engine for this layout.

Returns:

  • (Tilt::Template)

    the Tilt template engine for this layout



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

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.



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

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)


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

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)


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

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


237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
# File 'lib/usmu/template/layout.rb', line 237

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) ⇒ void

This is a shortcut to accessing metadata.

See Also:



66
67
68
# File 'lib/usmu/template/layout.rb', line 66

def [](index)
  [index]
end

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

Allows for protected level direct access to the metadata store.

See Also:



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

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



215
216
217
218
219
220
221
222
223
224
# File 'lib/usmu/template/layout.rb', line 215

def add_template_defaults(overrides, engine)
  case engine
    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)


231
232
233
# File 'lib/usmu/template/layout.rb', line 231

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.



74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/usmu/template/layout.rb', line 74

def render(variables = {})
  template_config = add_template_defaults(@configuration[provider_name] || {}, provider_name)
  content = template_class.new("#{@name}", 1, template_config) { @content }.
      render(helpers, get_variables(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