Class: Proton::Page

Inherits:
Object
  • Object
show all
Extended by:
Cacheable
Defined in:
lib/proton/page.rb

Overview

page.write(‘~/foo.html’)

Direct Known Subclasses

Layout

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Cacheable

cache, cache_method, disable!, enable!, enabled?

Constructor Details

#initialize(file, project = Proton.project) ⇒ Page

Returns a new instance of Page.

Raises:



131
132
133
134
135
# File 'lib/proton/page.rb', line 131

def initialize(file, project=Proton.project)
  @file = File.expand_path(file)  if file.is_a?(String)
  @project = project
  raise Error  if project.nil?
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

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



360
361
362
363
# File 'lib/proton/page.rb', line 360

def method_missing(meth, *args, &blk)
  super  unless meta.instance_variable_get(:@table).keys.include?(meth.to_sym)
  meta.send(meth)
end

Instance Attribute Details

#fileObject (readonly)

Attribute: file (Proton::Page) The full path of the source file.

## Example

page.filepath          #=> "/index.haml"
page.file              #=> "/home/rsc/project/index.haml"

## See also

- {Proton::Page.filepath}


92
93
94
# File 'lib/proton/page.rb', line 92

def file
  @file
end

#projectObject (readonly)

Attribute: project (Proton::Page) A reference to the project.



80
81
82
# File 'lib/proton/page.rb', line 80

def project
  @project
end

Class Method Details

.[](id, project = Proton.project) ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/proton/page.rb', line 94

def self.[](id, project=Proton.project)
  Cacheable.cache(:lookup, id, project.root) do
    site_path = root_path(project)
    return nil  if site_path.nil?

    site = lambda { |*x| File.join site_path, *(x.compact) }
    try  = lambda { |_id| p = new(_id, project); p if p.exists? }

    # For paths like '/' or '/hello/'
    nonfile = File.basename(id).gsub('/','').empty?

    # Account for:
    #   ~/mysite/site/about/us.html.haml
    #   about/us.html.haml => ~/mysite/site/about/us.html.haml
    #   about/us.html      => ~/mysite/site/about/us.html.*
    #   about/us.html      => ~/mysite/site/about/us.*
    #   about/us           => ~/mysite/site/about/us/index.*
    #
    page   = try[id]
    page ||= try[site[id]]
    unless nonfile
      page ||= try[Dir[site["#{id}.*"]].first]
      page ||= try[Dir[site["#{id.to_s.sub(/\.[^\.]*/,'')}.*"]].first]
    end
    page ||= try[Dir[site[id, "index.*"]].first]

    # Subclass
    if page && page.tilt? && page.meta[:type]
      klass = Page.get_type(page.meta[:type])
      raise Error, "#{page.filepath}: Class for type '#{page.meta[:type]}' not found"  unless klass
      page = klass.new(id, project)
    end

    page
  end
end

.get_type(type) ⇒ Object

Method: get_type (Proton::Page) Returns a page subtype.

## Example

Page.get_type('post') => Proton::Page::Post


252
253
254
255
256
257
# File 'lib/proton/page.rb', line 252

def self.get_type(type)
  type  = type.to_s
  klass = type[0..0].upcase + type[1..-1].downcase
  klass = klass.to_sym
  self.const_get(klass)  if self.const_defined?(klass)
end

Instance Method Details

#<=>(other) ⇒ Object



187
188
189
190
191
# File 'lib/proton/page.rb', line 187

def <=>(other)
  result   = self.position <=> other.position
  result ||= self.position.to_s <=> other.position.to_s
  result
end

#==(other) ⇒ Object



485
486
487
# File 'lib/proton/page.rb', line 485

def ==(other)
  self.path == other.path
end

Attribute: breadcrumbs (Proton::Page) Returns an array of the page’s ancestors, including itself.

## Example

Proton::Page['/about/company/contact.html'].breadcrumbs

May look like:

[ Page, Page, Page ]


425
426
427
# File 'lib/proton/page.rb', line 425

def breadcrumbs
  Set.new(parent? ? (parent.breadcrumbs + [self]) : [self])
end

#childrenObject

Method: children (Proton::Page) Returns a Set of the page’s subpages.



390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
# File 'lib/proton/page.rb', line 390

def children
  files = if index?
    # about/index.html => about/*
    File.expand_path('../*', @file)
  else
    # products.html => products/*
    base = File.basename(@file, '.*')
    File.expand_path("../#{base}/*", @file)
  end

  Set.new Dir[files].
    reject { |f| f == @file || project.ignored_files.include?(f) }.
    map { |f| self.class[f, project] }.
    compact.sort
end

#content(locals = {}, tilt_options = {}, &blk) ⇒ Object



269
270
271
272
# File 'lib/proton/page.rb', line 269

def content(locals={}, tilt_options={}, &blk)
  return markup  unless tilt?
  tilt(tilt_options).render(dup.extend(Helpers), locals, &blk)
end

#default_extObject

Attribute: default_ext (Proton::Page) Returns a default extension for the page based on the page’s MIME type.

## Example

Page['/style.css'].default_ext    #=> 'css'
Page['/index.html'].default_ext   #=> 'html'

## See also

- {Proton::Page::mime_type}


237
238
239
240
241
242
243
244
# File 'lib/proton/page.rb', line 237

def default_ext
  case mime_type
  when 'text/html' then 'html'
  when 'text/css' then 'css'
  when 'text/xml' then 'xml'
  when 'application/javascript' then 'js'
  end
end

#depthObject

Attribute: depth (Proton::Page) Returns how deep the page is in the heirarchy.

## Description

This counts the number of pages from the root page. This means:

* The root page (eg, `/index.html`) has a depth of `1`
* A child page of the root (eg, `/about.html`) has a depth of `2`
* A child of that (eg, `/about/company.html`) has a depth of `3`
* ...and so on


474
475
476
# File 'lib/proton/page.rb', line 474

def depth
  breadcrumbs.size
end

#exists?Boolean

Returns:

  • (Boolean)


259
260
261
# File 'lib/proton/page.rb', line 259

def exists?
  @file and File.file?(@file||'') and valid?
end

#filepathObject

Attribute: filepath (Proton::Page) Returns a short filepath relative to the project path.

## Description

This is different from {Proton::Page.file} as this only returns the
path relative to the project's root instead of an absolute path.

## Example

See {Proton::Page.file} for an example.


160
161
162
163
164
165
# File 'lib/proton/page.rb', line 160

def filepath
  root = project.root
  fpath = file
  fpath = fpath[root.size..-1]  if fpath[0...root.size] == root
  fpath
end

#html?Boolean

Method: html? (Proton::Page) Returns true if the page is an HTML page.

Returns:

  • (Boolean)


196
197
198
# File 'lib/proton/page.rb', line 196

def html?
  mime_type == 'text/html'
end

#index?Boolean

Method: index? (Proton::Page) Returns true if the page is and index page.

Returns:

  • (Boolean)


432
433
434
# File 'lib/proton/page.rb', line 432

def index?
  File.basename(path, '.*') == 'index'
end

#inspectObject



489
490
491
# File 'lib/proton/page.rb', line 489

def inspect
  "<##{self.class.name} #{path.inspect}>"
end

#layoutObject



283
284
285
286
287
# File 'lib/proton/page.rb', line 283

def layout
  layout = meta.layout
  layout ||= default_layout  unless meta.layout == false
  Layout[layout, page]  if layout
end

#layout?Boolean

Returns:

  • (Boolean)


293
294
295
# File 'lib/proton/page.rb', line 293

def layout?
  !! layout
end

#markupObject



356
357
358
# File 'lib/proton/page.rb', line 356

def markup
  parts.last
end

#metaObject

Method: meta (Proton::Page) Returns the metadata for the page.

## Description

This returns an instance of {Proton::Meta}.


303
304
305
# File 'lib/proton/page.rb', line 303

def meta
  @meta ||= Meta.new(parts.first)
end

#mime_typeObject

Attribute: mime_type (Proton::Page) The MIME type for the page, based on what template engine was used.

## Example

Page['/style.css'].mime_type    #=> 'text/css'
Page['/index.html'].mime_type   #=> 'text/html'

## See also

- {Proton::Page::default_ext}


210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/proton/page.rb', line 210

def mime_type
  return nil  unless tilt?

  mime = nil
  mime = tilt_engine.default_mime_type  if tilt_engine.respond_to?(:default_mime_type)

  mime ||= case tilt_engine.name
    when 'Tilt::SassTemplate' then 'text/css'
    when 'Tilt::ScssTemplate' then 'text/css'
    when 'Tilt::LessTemplate' then 'text/css'
    when 'Tilt::CoffeeScriptTemplate' then 'application/javascript'
    when 'Tilt::NokogiriTemplate' then 'text/xml'
    when 'Tilt::BuilderTemplate' then 'text/xml'
    else 'text/html'
  end
end

#nextObject



478
479
480
481
482
483
# File 'lib/proton/page.rb', line 478

def next
  page = self
  while true do
    page.siblings.index(self)
  end
end

#pageObject



289
290
291
# File 'lib/proton/page.rb', line 289

def page
  self
end

#parentObject

Attribute: parent (Proton::Page) Returns the page’s parent page, or nil.

## Usage

page.parent

## Description

This will return the page's parent (also a {Proton::Page} instance), or 
`nil` if it's the page is already the root.


375
376
377
378
379
380
381
382
383
384
385
# File 'lib/proton/page.rb', line 375

def parent
  parts = path.split('/') # ['', 'about', 'index.html']

  try = lambda { |newpath| p = self.class[newpath, project]; p if p && p.path != path }

  # Absolute root
  return nil  if index? and parts.size <= 2

  parent   = try[parts[0...-1].join('/')]  # ['','about'] => '/about'
  parent ||= try['/']                      # Home
end

#parent?Boolean

Method: parent? (Proton::Page) Returns true if the page has a parent.

## Description

This is the opposite of {Proton::Page::root?}.

## See also

- {Proton::Page::root?}

Returns:

  • (Boolean)


445
446
447
# File 'lib/proton/page.rb', line 445

def parent?
  !parent.nil?
end

#pathObject

Returns the URL path for a page.



138
139
140
141
142
143
144
145
146
147
148
# File 'lib/proton/page.rb', line 138

def path
  path = @file.sub(File.expand_path(root_path), '')

  # if xx.haml (but not xx.html.haml), 
  if tilt?
    path = path.sub(/\.[^\.]*$/, "")
    path += ".#{default_ext}"  unless File.basename(path).include?('.')
  end

  path
end

#positionObject



183
184
185
# File 'lib/proton/page.rb', line 183

def position
  meta[:position] || title
end

#root?Boolean

Method: root? (Proton::Page) Returns true if the page is the home page.

## Description

This is the opposite of {Proton::Page::parent?}.

## See also

- {Proton::Page::parent?}

Returns:

  • (Boolean)


458
459
460
# File 'lib/proton/page.rb', line 458

def root?
  parent.nil?
end

#siblingsObject

Method: siblings (Proton::Page) Returns a Set of pages that share the same parent as the current page.



409
410
411
412
413
414
# File 'lib/proton/page.rb', line 409

def siblings
  pages = (p = parent and p.children)
  return Set.new  unless pages
  return Set.new  unless pages.include?(self)
  Set.new(pages)
end

#tilt(tilt_options = {}) ⇒ Object

Attribute: tilt (Proton::Page) Returns the tilt layout.

This returns an instance of ‘Tilt`.



346
347
348
349
350
351
352
353
354
# File 'lib/proton/page.rb', line 346

def tilt(tilt_options={})
  if tilt?
    parts
    # HAML options and such (like :escape_html)
    options = project.config.tilt_options_for(@file, tilt_options)
    offset = @offset || 1
    Tilt.new(@file, offset, options) { markup }
  end
end

#tilt?Boolean

Method: tilt? (Proton::Page) Checks if the file is supported by tilt.

Returns:

  • (Boolean)


327
328
329
# File 'lib/proton/page.rb', line 327

def tilt?
  !! tilt_engine
end

#tilt_engineObject

Attribute: tilt_engine (Proton::Page) Returns the Tilt engine (eg Tilt::HamlEngine).



333
334
335
# File 'lib/proton/page.rb', line 333

def tilt_engine
  Tilt[@file]
end

#tilt_engine_nameObject



337
338
339
# File 'lib/proton/page.rb', line 337

def tilt_engine_name
  tilt_engine.name.match(/:([^:]*)(?:Template?)$/)[1]
end

#titleObject Also known as: to_s

Attribute: title (Proton::Page) Returns the page title as a string.

## Description

This attribute tries to infer the page's title based on metadata. If the 
`title` key is not in the page's header metadata, then it returns the 
path name instead.

This is also aliased as `to_s`.


177
178
179
# File 'lib/proton/page.rb', line 177

def title
  (meta.title if tilt?) || path
end

#to_html(locals = {}, tilt_options = {}, &blk) ⇒ Object

Method: to_html (Proton::Page) Returns the full HTML document for the page.



277
278
279
280
281
# File 'lib/proton/page.rb', line 277

def to_html(locals={}, tilt_options={}, &blk)
  html = content(locals, tilt_options, &blk)
  html = layout.to_html(locals, tilt_options) { html }  if layout?
  html
end

#valid?Boolean

Ensures that the page is in the right folder.

Returns:

  • (Boolean)


264
265
266
267
# File 'lib/proton/page.rb', line 264

def valid?
  prefix = File.expand_path(root_path)
  prefix == File.expand_path(@file)[0...prefix.size]
end

#write(out = nil) ⇒ Object

Method: write (Proton::Page) Writes to the given output file.

## Description

This is the method used by `proton build`.


313
314
315
316
317
318
319
320
321
322
# File 'lib/proton/page.rb', line 313

def write(out=nil)
  out ||= project.path(:output, path)
  FileUtils.mkdir_p File.dirname(out)

  if tilt?
    File.open(out, 'w') { |f| f.write to_html({}, :build => true) }
  else
    FileUtils.cp file, out
  end
end