Class: Nanoc2::PageRep

Inherits:
Object
  • Object
show all
Defined in:
lib/nanoc2/base/page_rep.rb

Overview

A Nanoc2::PageRep is a single representation (rep) of a page (Nanoc2::Page). A page can have multiple representations. A representation has its own attributes and its own output file. A single page can therefore have multiple output files, each run through a different set of filters with a different layout.

A page representation is observable. The following events will be notified:

  • :compilation_started

  • :compilation_ended

  • :filtering_started

  • :filtering_ended

The compilation-related events have one parameters (the page representation); the filtering-related events have two (the page representation, and a symbol containing the filter class name).

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(page, attributes, name) ⇒ PageRep

Creates a new page representation for the given page and with the given attributes.

page

The page (Nanoc2::Page) to which the new representation will belong.

attributes

A hash containing the new page representation’s attributes. This hash must have been run through Hash#clean before using it here.

name

The unique name for the new page representation.



42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/nanoc2/base/page_rep.rb', line 42

def initialize(page, attributes, name)
  # Set primary attributes
  @page           = page
  @attributes     = attributes
  @name           = name

  # Get page content from page
  @content        = { :pre => nil, :post => nil }

  # Reset flags
  @compiled       = false
  @modified       = false
  @created        = false
end

Instance Attribute Details

#attributesObject

A hash containing this page representation’s attributes.



26
27
28
# File 'lib/nanoc2/base/page_rep.rb', line 26

def attributes
  @attributes
end

#nameObject (readonly)

This page representation’s unique name.



29
30
31
# File 'lib/nanoc2/base/page_rep.rb', line 29

def name
  @name
end

#pageObject (readonly)

The page (Nanoc2::Page) to which this representation belongs.



23
24
25
# File 'lib/nanoc2/base/page_rep.rb', line 23

def page
  @page
end

Instance Method Details

#attribute_named(name) ⇒ Object

Returns the attribute with the given name. This method will look in several places for the requested attribute:

  1. This page representation’s attributes;

  2. The attributes of this page representation’s page;

  3. The page defaults’ representation corresponding to this page representation;

  4. The page defaults in general;

  5. The hardcoded page defaults, if everything else fails.



134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/nanoc2/base/page_rep.rb', line 134

def attribute_named(name)
  # Check in here
  return @attributes[name] if @attributes.has_key?(name)

  # Check in page
  return @page.attributes[name] if @page.attributes.has_key?(name)

  # Check in page defaults' page rep
  page_default_reps = @page.site.page_defaults.attributes[:reps] || {}
  page_default_rep  = page_default_reps[@name] || {}
  return page_default_rep[name] if page_default_rep.has_key?(name)

  # Check in site defaults (global)
  page_defaults_attrs = @page.site.page_defaults.attributes
  return page_defaults_attrs[name] if page_defaults_attrs.has_key?(name)

  # Check in hardcoded defaults
  return Nanoc2::Page::DEFAULTS[name]
end

#compile(also_layout, even_when_not_outdated, from_scratch) ⇒ Object

Compiles the page representation and writes the result to the disk. This method should not be called directly; please use Nanoc2::Compiler#run instead, and pass this page representation’s page as its first argument.

The page representation will only be compiled if it wasn’t compiled before yet. To force recompilation of the page rep, forgetting any progress, set from_scratch to true.

also_layout

true if the page rep should also be laid out and post-filtered, false if the page rep should only be pre-filtered.

even_when_not_outdated

true if the page rep should be compiled even if it is not outdated, false if not.

from_scratch

true if all compilation stages (pre-filter, layout, post-filter) should be performed again even if they have already been performed, false otherwise.



195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
# File 'lib/nanoc2/base/page_rep.rb', line 195

def compile(also_layout, even_when_not_outdated, from_scratch)
  # Don't compile if already compiled
  return if @content[also_layout ? :post : :pre] and !from_scratch

  # Skip unless outdated
  unless outdated? or even_when_not_outdated
    if also_layout
      Nanoc2::NotificationCenter.post(:compilation_started, self)
      Nanoc2::NotificationCenter.post(:compilation_ended,   self)
    end
    return
  end

  # Reset flags
  @compiled = false
  @modified = false
  @created  = false

  # Forget progress if requested
  @content = { :pre => nil, :post => nil } if from_scratch

  # Check for recursive call
  if @page.site.compiler.stack.include?(self)
    @page.site.compiler.stack.push(self)
    raise Nanoc2::Errors::RecursiveCompilationError.new
  end

  # Start
  @page.site.compiler.stack.push(self)
  Nanoc2::NotificationCenter.post(:compilation_started, self) if also_layout

  # Pre-filter if necesary
  if @content[:pre].nil?
    do_filter(:pre)
  end

  # Post-filter if necessary
  if @content[:post].nil? and also_layout
    do_layout
    do_filter(:post)

    # Update status
    @compiled = true
    unless attribute_named(:skip_output)
      @created  = !File.file?(self.disk_path)
      @modified = @created ? true : File.read(self.disk_path) != @content[:post]
    end

    # Write if necessary
    write unless attribute_named(:skip_output)
  end

  # Stop
  Nanoc2::NotificationCenter.post(:compilation_ended, self) if also_layout
  @page.site.compiler.stack.pop
end

#compiled?Boolean

Returns true if this page rep has been compiled, false otherwise.

Returns:

  • (Boolean)


75
76
77
# File 'lib/nanoc2/base/page_rep.rb', line 75

def compiled?
  @compiled
end

#content(stage = :pre) ⇒ Object

Returns the page representation content at the given stage.

stage

The stage at which the content should be fetched. Can be either :pre or :post. To get the raw, uncompiled content, use Nanoc2::Page#content.



159
160
161
162
163
# File 'lib/nanoc2/base/page_rep.rb', line 159

def content(stage=:pre)
  compile(stage == :post, true, false)

  @content[stage]
end

#created?Boolean

Returns true if this page rep’s output file was created during the last compilation session, or false if the output file did already exist.

Returns:

  • (Boolean)


64
65
66
# File 'lib/nanoc2/base/page_rep.rb', line 64

def created?
  @created
end

#disk_pathObject

Returns the path to the output file, including the path to the output directory specified in the site configuration, and including the filename and extension.



113
114
115
# File 'lib/nanoc2/base/page_rep.rb', line 113

def disk_path
  @disk_path ||= @page.site.router.disk_path_for(self)
end

#layoutObject

Returns the layout used for this page representation.



166
167
168
169
170
171
172
173
174
175
# File 'lib/nanoc2/base/page_rep.rb', line 166

def layout
  # Check whether layout is present
  return nil if attribute_named(:layout).nil?

  # Find layout
  @layout ||= @page.site.layouts.find { |l| l.path == attribute_named(:layout).cleaned_path }
  raise Nanoc2::Errors::UnknownLayoutError.new(attribute_named(:layout)) if @layout.nil?

  @layout
end

#modified?Boolean

Returns true if this page rep’s output file was modified during the last compilation session, or false if the output file wasn’t changed.

Returns:

  • (Boolean)


70
71
72
# File 'lib/nanoc2/base/page_rep.rb', line 70

def modified?
  @modified
end

#outdated?Boolean

Returns true if this page rep’s output file is outdated and must be regenerated, false otherwise.

Returns:

  • (Boolean)


81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/nanoc2/base/page_rep.rb', line 81

def outdated?
  # Outdated if we don't know
  return true if @page.mtime.nil?

  # Outdated if compiled file doesn't exist
  return true if !File.file?(disk_path)

  # Get compiled mtime
  compiled_mtime = File.stat(disk_path).mtime

  # Outdated if file too old
  return true if @page.mtime > compiled_mtime

  # Outdated if layouts outdated
  return true if @page.site.layouts.any? do |l|
    l.mtime.nil? or l.mtime > compiled_mtime
  end

  # Outdated if page defaults outdated
  return true if @page.site.page_defaults.mtime.nil?
  return true if @page.site.page_defaults.mtime > compiled_mtime

  # Outdated if code outdated
  return true if @page.site.code.mtime.nil?
  return true if @page.site.code.mtime > compiled_mtime

  return false
end

#to_proxyObject

Returns a proxy (Nanoc2::PageRepProxy) for this page representation.



58
59
60
# File 'lib/nanoc2/base/page_rep.rb', line 58

def to_proxy
  @proxy ||= PageRepProxy.new(self)
end

#web_pathObject

Returns the path to the output file as it would be used in a web browser: starting with a slash (representing the web root), and only including the filename and extension if they cannot be ignored (i.e. they are not in the site configuration’s list of index files).



121
122
123
# File 'lib/nanoc2/base/page_rep.rb', line 121

def web_path
  @web_path ||= @page.site.router.web_path_for(self)
end