Class: Zenweb::Site

Inherits:
Object
  • Object
show all
Includes:
Rake::DSL
Defined in:
lib/zenweb/site.rb

Overview

Holder for the entire website. Everything gets driven from here.

TODO: describe expected filesystem layout and dependency mgmt.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeSite

:nodoc:



48
49
50
51
52
# File 'lib/zenweb/site.rb', line 48

def initialize # :nodoc:
  @layouts = {}
  @pages = {}
  @configs = Hash.new { |h,k| h[k] = Config.new self, k }
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(msg, *_args) ⇒ Object

Proxy object for the config. Returns a config item at msg.



143
144
145
146
# File 'lib/zenweb/site.rb', line 143

def method_missing msg, *_args
  k = msg.to_s
  config.key?(k) ? config[k] : warn("#{self.inspect} does not define #{k}")
end

Instance Attribute Details

#configsObject (readonly)

Returns all configs found via #scan



26
27
28
# File 'lib/zenweb/site.rb', line 26

def configs
  @configs
end

#layoutsObject (readonly)

Returns all known layouts found via #scan



31
32
33
# File 'lib/zenweb/site.rb', line 31

def layouts
  @layouts
end

#pagesObject (readonly)

Returns all pages found via #scan



21
22
23
# File 'lib/zenweb/site.rb', line 21

def pages
  @pages
end

Class Method Details

.binary_filesObject



222
223
224
# File 'lib/zenweb/site.rb', line 222

def self.binary_files
  @binary_files ||= %w[png jpg gif eot svg ttf woff2? ico pdf m4a t?gz]
end

.load_pluginsObject

Loads all files matching “zenweb/plugins/*.rb”.



36
37
38
39
40
41
42
43
44
# File 'lib/zenweb/site.rb', line 36

def self.load_plugins
  seen = {}
  Gem.find_files("zenweb/plugins/*.rb").each do |path|
    file = File.basename path
    next if seen[file]
    seen[file] = true
    require path
  end
end

.text_filesObject



226
227
228
# File 'lib/zenweb/site.rb', line 226

def self.text_files
  @text_files ||= %w[txt html css js]
end

Instance Method Details

#categoriesObject

Returns a magic hash that groups up all the pages by category (directory). The hash has extra accessor methods on it to make grabbing what you want a bit cleaner. eg:

site.categories.blog # => [Page[blog/...], ...]


61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/zenweb/site.rb', line 61

def categories
  @categories ||=
    begin
      h = Hash.new { |h2,k| h2[k] = [] }

      def h.method_missing msg, *args
        if self.has_key? msg.to_s then
          self[msg.to_s]
        else
          super
        end
      end

      time_prune
      fix_subpages

      pages.each do |url, page|
        dir = url.split(/\//).first
        next unless File.directory? dir and dir !~ /^_/
        next if url =~ /index.html/ or url !~ /html/
        h[dir] << page
      end

      h.keys.each do |dir|
        h[dir] = h[dir].sort_by { |p| [-p.date.to_i, p.title ] }
      end

      h
    end
end

#configObject

Return the top level config.



95
96
97
# File 'lib/zenweb/site.rb', line 95

def config
  configs["_config.yml"]
end

#fix_subpagesObject

:nodoc:



238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
# File 'lib/zenweb/site.rb', line 238

def fix_subpages # :nodoc:
  # TODO: push most of this down to page
  parents = {}

  @pages.values.select(&:index?).each do |p|
    parents[p.url] = p
  end

  @pages.values.each do |p|
    path = p.parent_url

    parent = nil
    begin
      path = File.join File.dirname(path), "index.html"
      parent = parents[path]
      path = File.dirname path
    end until parent or path == "/"

    next unless parent and parent != p and p.url =~ /html$/

    p.parent.subpages.delete p if p.parent
    p.parent = parent
    parent.subpages << p
  end

  @pages.values.each do |p|
    unless p.subpages.empty? then
      sorted = p.subpages.sort_by(&:clean_url).uniq
      p.subpages.replace sorted
    end
  end
end

#generateObject

Generates the website by invoking the ‘site’ task.



102
103
104
# File 'lib/zenweb/site.rb', line 102

def generate
  task(:site).invoke
end

#html_page_map(&map) ⇒ Object

Return a list of all pages my applying map to all html_pages and cleaning up the results.



110
111
112
# File 'lib/zenweb/site.rb', line 110

def html_page_map &map
  html_pages.map(&map).flatten.uniq.compact
end

#html_pagesObject

Returns a list of all known html pages.



117
118
119
# File 'lib/zenweb/site.rb', line 117

def html_pages
  self.pages.values.select { |p| p.url_path =~ /\.html/ }
end

#inspectObject

:nodoc:



121
122
123
# File 'lib/zenweb/site.rb', line 121

def inspect # :nodoc:
  "Site[#{pages.size} pages, #{configs.size} configs]"
end

#layout(name) ⇒ Object

Returns a layout named name.



128
129
130
# File 'lib/zenweb/site.rb', line 128

def layout name
  name and (@layouts[name] or raise "unknown layout #{name.inspect}")
end

Return a list of HTML links after applying map to all html pages and cleaning the results.



136
137
138
# File 'lib/zenweb/site.rb', line 136

def link_list &map
  html_page_map(&map).map(&:link_html)
end

#pages_by_dateObject

Returns all pages (with titles) sorted by date.



151
152
153
154
155
# File 'lib/zenweb/site.rb', line 151

def pages_by_date
  # page.config["title"] avoids the warning
  html_pages.select {|page| page.config["title"] }.
    sort_by { |page| [-page.date.to_i, page.title] }
end

#pages_by_urlObject

Returns a hash mapping page url to page.



160
161
162
163
164
165
166
167
168
169
# File 'lib/zenweb/site.rb', line 160

def pages_by_url
  unless defined? @pages_by_url then
    h = {}
    pages.each do |_,p|
      h[p.url] = p
    end
    @pages_by_url = h
  end
  @pages_by_url
end

#scanObject

Scans the directory tree and finds all relevant pages, configs, layouts, etc.

TODO: talk about expected directory structure and extra naming enhancements.



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
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/zenweb/site.rb', line 178

def scan
  excludes = %w[~ Rakefile] + Array(config["exclude"])

  top = Dir["*"] - excludes
  files = top.select { |path| File.file? path }
  files += Dir["{#{top.join(",")}}/**/*"].reject { |f| not File.file? f }
  files.reject! { |f| f.include? "/_" }

  renderers_re = Page.renderers_re

  files.each do |path|
    case path
    when /(?:#{excludes.join '|'})$/
      # ignore
    when /^_layout/ then
      name = File.basename(path).sub(/\..+$/, '')
      @layouts[name] = Page.new self, path
    when /^_/ then
      next
    when /\.yml$/ then
      @configs[path] = Config.new self, path
    when /\.(?:#{self.class.binary_files.join("|")})$/ then
      @pages[path] = Page.new self, path, self.config
    when /\.(?:#{self.class.text_files.join("|")})$/, renderers_re then
      @pages[path] = Page.new self, path
    else
      warn "unknown file type: #{path}" if Rake.application.options.trace
    end
  end

  $website = self # HACK
  task(:virtual_pages).invoke

  time_prune

  fix_subpages
end

#stale?Boolean

Returns:

  • (Boolean)


234
235
236
# File 'lib/zenweb/site.rb', line 234

def stale?
  not stale_pages.empty?
end

#stale_pagesObject



230
231
232
# File 'lib/zenweb/site.rb', line 230

def stale_pages
  pages.values.find_all(&:stale?)
end

#time_pruneObject



216
217
218
219
220
# File 'lib/zenweb/site.rb', line 216

def time_prune
  t = Time.now
  @pages.reject! { |path, page| page.date && page.date > t } unless
    ENV["ALL"]
end

#wireObject

Wire up all the configs and pages. Invokes :extra_wirings to allow you to add extra manual dependencies.



275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
# File 'lib/zenweb/site.rb', line 275

def wire
  directory ".site"
  task :site => ".site"

  configs.each do |path, config|
    config.wire
  end

  pages.each do |path, page|
    page.wire
  end

  $website = self # HACK
  task(:extra_wirings).invoke
end