Class: Broadway::Site
- Inherits:
-
Object
- Object
- Broadway::Site
- Defined in:
- lib/broadway/site.rb
Instance Attribute Summary collapse
-
#categories ⇒ Object
Returns the value of attribute categories.
-
#config ⇒ Object
Returns the value of attribute config.
-
#dest ⇒ Object
Returns the value of attribute dest.
-
#exclude ⇒ Object
Returns the value of attribute exclude.
-
#layouts ⇒ Object
Returns the value of attribute layouts.
-
#lsi ⇒ Object
Returns the value of attribute lsi.
-
#pages ⇒ Object
Returns the value of attribute pages.
-
#permalink_style ⇒ Object
Returns the value of attribute permalink_style.
-
#posts ⇒ Object
Returns the value of attribute posts.
-
#pygments ⇒ Object
Returns the value of attribute pygments.
-
#source ⇒ Object
Returns the value of attribute source.
-
#static_files ⇒ Object
Returns the value of attribute static_files.
-
#tags ⇒ Object
Returns the value of attribute tags.
-
#tree ⇒ Object
Returns the value of attribute tree.
Class Method Summary collapse
Instance Method Summary collapse
- #build ⇒ Object
-
#filtered?(path) ⇒ Boolean
Filter out any files/directories that are hidden or backup files (start with “.” or “#” or end with “~”), or contain site content (start with “_”), or are excluded in the site configuration, unless they are web server files such as ‘.htaccess’.
- #find(type, method, value) ⇒ Object
- #first(type, method, value) ⇒ Object
- #generate ⇒ Object
-
#initialize(config) ⇒ Site
constructor
Initialize the site
config
is a Hash containing site configurations details. - #inspect ⇒ Object
- #merge_extra_config!(config) ⇒ Object
- #new_page(path, options = {}) ⇒ Object
- #new_post(path, options = {}) ⇒ Object
- #new_tree(path) ⇒ Object
- #node_list(elem, &proc) ⇒ Object
- #page_count ⇒ Object
- #page_from_xml(content) ⇒ Object
- #parse_tree(parent) ⇒ Object
-
#post_attr_hash(post_attr) ⇒ Object
Constructs a hash map of Posts indexed by the specified Post attribute.
- #post_count ⇒ Object
- #post_from_xml(content) ⇒ Object
-
#process ⇒ Object
third Do the actual work of processing the site and generating the real deal.
- #read ⇒ Object
-
#read_directories(dir = '') ⇒ Object
Reads the directories and finds posts, pages and static files that will become part of the valid site according to the rules in
filter_entries
. -
#read_layouts(dir = '') ⇒ Object
Read all the files in <source>/<dir>/_layouts and create a new Layout object with each one.
-
#render ⇒ Object
While in Jekyll this method renders the content explicitly, I’m using Sinatra, partly because I like having the flexibility of using their get/post methods, and partly because I don’t have the time/desire to try to hack jekyll to use haml.
-
#reset ⇒ Object
first.
-
#setup ⇒ Object
second this just sets configuration variables on the dependencies, if necessary.
-
#site_payload ⇒ Object
The Hash payload containing site-wide data.
- #textile(content) ⇒ Object
-
#write ⇒ Object
Write static files, pages and posts.
Constructor Details
#initialize(config) ⇒ Site
Initialize the site
+config+ is a Hash containing site configurations details
Returns <Site>
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/broadway/site.rb', line 15 def initialize(config) merge_extra_config!(config) config.recursive_symbolize_keys! self.config = config.clone self.source = config[:source] self.dest = config[:destination] self.lsi = config[:lsi] self.pygments = config[:pygments] self.permalink_style = config[:permalink].to_sym self.exclude = config[:exclude] || [] self.tree = [] self.reset self.setup end |
Instance Attribute Details
#categories ⇒ Object
Returns the value of attribute categories.
4 5 6 |
# File 'lib/broadway/site.rb', line 4 def categories @categories end |
#config ⇒ Object
Returns the value of attribute config.
4 5 6 |
# File 'lib/broadway/site.rb', line 4 def config @config end |
#dest ⇒ Object
Returns the value of attribute dest.
4 5 6 |
# File 'lib/broadway/site.rb', line 4 def dest @dest end |
#exclude ⇒ Object
Returns the value of attribute exclude.
4 5 6 |
# File 'lib/broadway/site.rb', line 4 def exclude @exclude end |
#layouts ⇒ Object
Returns the value of attribute layouts.
4 5 6 |
# File 'lib/broadway/site.rb', line 4 def layouts @layouts end |
#lsi ⇒ Object
Returns the value of attribute lsi.
4 5 6 |
# File 'lib/broadway/site.rb', line 4 def lsi @lsi end |
#pages ⇒ Object
Returns the value of attribute pages.
4 5 6 |
# File 'lib/broadway/site.rb', line 4 def pages @pages end |
#permalink_style ⇒ Object
Returns the value of attribute permalink_style.
4 5 6 |
# File 'lib/broadway/site.rb', line 4 def permalink_style @permalink_style end |
#posts ⇒ Object
Returns the value of attribute posts.
4 5 6 |
# File 'lib/broadway/site.rb', line 4 def posts @posts end |
#pygments ⇒ Object
Returns the value of attribute pygments.
4 5 6 |
# File 'lib/broadway/site.rb', line 4 def pygments @pygments end |
#source ⇒ Object
Returns the value of attribute source.
4 5 6 |
# File 'lib/broadway/site.rb', line 4 def source @source end |
#static_files ⇒ Object
Returns the value of attribute static_files.
4 5 6 |
# File 'lib/broadway/site.rb', line 4 def static_files @static_files end |
#tags ⇒ Object
Returns the value of attribute tags.
4 5 6 |
# File 'lib/broadway/site.rb', line 4 def @tags end |
#tree ⇒ Object
Returns the value of attribute tree.
4 5 6 |
# File 'lib/broadway/site.rb', line 4 def tree @tree end |
Class Method Details
.generate ⇒ Object
7 8 9 |
# File 'lib/broadway/site.rb', line 7 def self.generate end |
Instance Method Details
#build ⇒ Object
149 150 151 152 153 154 |
# File 'lib/broadway/site.rb', line 149 def build puts "Building site: #{config[:source]} -> #{config[:destination]}" self.reset self.read puts "Successfully built site, nothing was written." end |
#filtered?(path) ⇒ Boolean
Filter out any files/directories that are hidden or backup files (start with “.” or “#” or end with “~”), or contain site content (start with “_”), or are excluded in the site configuration, unless they are web server files such as ‘.htaccess’
351 352 353 354 355 356 |
# File 'lib/broadway/site.rb', line 351 def filtered?(path) return true if File.directory?(path) file = File.basename(path) return true if ['.htaccess'].include?(file) ['.', '_', '#'].include?(file[0..0]) || file[-1..-1] == '~' || self.exclude.include?(file) end |
#find(type, method, value) ⇒ Object
358 359 360 361 362 363 364 365 366 |
# File 'lib/broadway/site.rb', line 358 def find(type, method, value) self.send(type.to_s.pluralize).select do |content| if content.respond_to?(method) content.send(method) == value else content.send(method.to_s.pluralize).include?(value) end end end |
#first(type, method, value) ⇒ Object
368 369 370 |
# File 'lib/broadway/site.rb', line 368 def first(type, method, value) find(type, method, value).first end |
#generate ⇒ Object
156 157 158 159 160 161 |
# File 'lib/broadway/site.rb', line 156 def generate puts "Generating site: #{config[:source]} -> #{config[:destination]}" self.render self.write puts "Successfully generated site: #{config[:source]} -> #{config[:destination]}" end |
#inspect ⇒ Object
394 395 396 |
# File 'lib/broadway/site.rb', line 394 def inspect "#<Broadway:Site @page_count=#{self.page_count.to_s} @post_count=#{self.post_count.to_s}>" end |
#merge_extra_config!(config) ⇒ Object
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/broadway/site.rb', line 34 def merge_extra_config!(config) locale = File.join("locales", "#{config[:language]}.yml") if File.exists?(locale) config.merge!(YAML.load_file(locale)) end config_dir = "config" return unless File.exists?(config_dir) Dir.glob("#{config_dir}/**/*").each do |file| next if File.directory?(file) path = file.gsub(/config\//, "").split(".")[0..-2].join("") ext = File.extname(file) if ext =~ /yml/ data = YAML.load_file(file) elsif ext =~ /xml/ data = parse_children Nokogiri::XML(IO.read(file)).children[0] else data = IO.read(file) end next unless data name = path.split("/").first if path =~ /\// config[name] ||= {} target = config[name] name = path.split("/").last else target = config end if target.has_key?(name) target[name].merge!(data) else target[name] = data end end end |
#new_page(path, options = {}) ⇒ Object
236 237 238 239 240 241 |
# File 'lib/broadway/site.rb', line 236 def new_page(path, = {}) return if path.nil? || path.empty? page = Page.new(.merge(:site => self, :path => path, :process => false)) self.pages << page page end |
#new_post(path, options = {}) ⇒ Object
243 244 245 246 247 248 |
# File 'lib/broadway/site.rb', line 243 def new_post(path, = {}) return if path.nil? || path.empty? post = Post.new(.merge(:site => self, :path => path, :process => false)) self.posts << post post end |
#new_tree(path) ⇒ Object
250 251 252 |
# File 'lib/broadway/site.rb', line 250 def new_tree(path) self.tree.concat parse_tree(Nokogiri::XML(IO.read(path)).root) end |
#node_list(elem, &proc) ⇒ Object
270 271 272 273 274 |
# File 'lib/broadway/site.rb', line 270 def node_list(elem, &proc) return [] unless elem.class == Nokogiri::XML::Element str = proc.call(elem) [str] + elem.children.inject([]){|a,c| a+node_list(c,&proc)}.map{|e| "#{str}/#{e}"} end |
#page_count ⇒ Object
386 387 388 |
# File 'lib/broadway/site.rb', line 386 def page_count self.pages ? self.pages.length : 0 end |
#page_from_xml(content) ⇒ Object
290 291 292 293 294 295 296 297 298 299 300 301 302 |
# File 'lib/broadway/site.rb', line 290 def page_from_xml(content) # page # 1. If a "src" is defined, then we should have already created the post # 2. If no "src", then content is specified inline (or there is no content yet) page = find_page_by_path(content["src"]) || find_page_by_url(content["url"]) path = (content["src"] || content["url"] || "").gsub(/^\//, "") page ||= new_page(path) return unless page %w(title image excerpt menu_title tooltip show_children content).each do |key| page.data[key] = content[key] if content.has_attribute?(key) end page end |
#parse_tree(parent) ⇒ Object
254 255 256 257 258 259 260 261 262 263 264 265 266 267 |
# File 'lib/broadway/site.rb', line 254 def parse_tree(parent) result = [] return result if parent.nil? || parent.children.nil? || parent.children.empty? parent.children.each do |child| next unless child.elem? content = child.children.empty? ? post_from_xml(child) : page_from_xml(child) next unless content if content.respond_to?(:children) content.children.concat parse_tree(child) end result << content end result end |
#post_attr_hash(post_attr) ⇒ Object
Constructs a hash map of Posts indexed by the specified Post attribute
Returns => [<Post>]
325 326 327 328 329 330 331 332 |
# File 'lib/broadway/site.rb', line 325 def post_attr_hash(post_attr) # Build a hash map based on the specified post attribute ( post attr => array of posts ) # then sort each array in reverse order hash = Hash.new { |hash, key| hash[key] = Array.new } self.posts.each { |p| p.send(post_attr.to_sym).each { |t| hash[t] << p } } hash.values.map { |sortme| sortme.sort! { |a, b| b <=> a} } return hash end |
#post_count ⇒ Object
390 391 392 |
# File 'lib/broadway/site.rb', line 390 def post_count self.posts ? self.posts.length : 0 end |
#post_from_xml(content) ⇒ Object
276 277 278 279 280 281 282 283 284 285 286 287 288 |
# File 'lib/broadway/site.rb', line 276 def post_from_xml(content) # post # 1. If a "src" is defined, then we should have already created the post # 2. If no "src", then content is specified inline (or there is no content yet) post = find_post_by_path(content["src"]) || find_post_by_url(content["url"]) path = (content["src"] || content["url"] || "").gsub(/^\//, "") post ||= new_post(path) return unless post %w(title image excerpt menu_title tooltip show_children content).each do |key| post.data[key] = content[key] if content.has_attribute?(key) end post end |
#process ⇒ Object
third Do the actual work of processing the site and generating the real deal. Now has 4 phases; reset, read, render, write. This allows rendering to have full site payload available.
Returns nothing
144 145 146 147 |
# File 'lib/broadway/site.rb', line 144 def process build generate end |
#read ⇒ Object
163 164 165 166 |
# File 'lib/broadway/site.rb', line 163 def read self.read_layouts # existing implementation did this at top level only so preserved that self.read_directories end |
#read_directories(dir = '') ⇒ Object
Reads the directories and finds posts, pages and static files that will become part of the valid site according to the rules in filter_entries
.
The +dir+ String is a relative path used to call this method
recursively as it descends through directories
Returns nothing
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 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 |
# File 'lib/broadway/site.rb', line 189 def read_directories(dir = '') base = File.join(self.source, dir).gsub(/\/$/, "") lists = [] # RULES: # Pages are only index.textile files, or static .html files (TODO) # Posts are leaf nodes (name.textile files) # Categories are the directory name split plus anything extra defined # Pages and Posts can also be obtained via index.xml files Dir.glob("#{base}/**/*").each do |path| # removes junk, leaves us with .xml, .textile, .html next if filtered?(path) name = File.basename(path).split(".").first ext = File.extname(path).gsub(".", "") if name == "index" if ext != "xml" new_page(path) end elsif %w(textile markdown).include?(ext) new_post(path) else self.static_files << StaticFile.new(:site => self, :path => path) end end # lists are xml files we've collect, but we want to make sure we've # created all the posts we need to beforehand list = File.join(config[:source], "index.xml") lists << list if File.exists?(list) lists.each do |path| new_tree(path) end # finally, we have set all the initial variables on the # pages and posts we need, now we can process them to find # the content and generate the urls self.pages.each do |page| page.process page.categories.each { |c| self.categories[c] << page } page..each { |c| self.[c] << page } end self.posts.each do |post| post.process post.categories.each { |c| self.categories[c] << post } post..each { |c| self.[c] << post } end end |
#read_layouts(dir = '') ⇒ Object
Read all the files in <source>/<dir>/_layouts and create a new Layout object with each one.
Returns nothing
172 173 174 175 176 177 178 179 180 181 |
# File 'lib/broadway/site.rb', line 172 def read_layouts(dir = '') base = File.join(self.source, dir, config[:layouts]) return unless File.exists?(base) entries = [] Dir.chdir(base) { entries = filter_entries(Dir['*.*']) } entries.each do |f| name = f.split(".")[0..-2].join(".") self.layouts[name] = Layout.new(self, base, f) end end |
#render ⇒ Object
While in Jekyll this method renders the content explicitly, I’m using Sinatra, partly because I like having the flexibility of using their get/post methods, and partly because I don’t have the time/desire to try to hack jekyll to use haml. I’d rather just start over
309 310 311 |
# File 'lib/broadway/site.rb', line 309 def render Runner.new(self).run end |
#reset ⇒ Object
first
70 71 72 73 74 75 76 77 |
# File 'lib/broadway/site.rb', line 70 def reset self.layouts = {} self.posts = [] self.pages = [] self.static_files = [] self.categories = Hash.new { |hash, key| hash[key] = [] } self. = Hash.new { |hash, key| hash[key] = [] } end |
#setup ⇒ Object
second this just sets configuration variables on the dependencies, if necessary
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 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/broadway/site.rb', line 81 def setup # Check to see if LSI is enabled. require 'classifier' if self.lsi # Set the Markdown interpreter (and Maruku self.config, if necessary) case self.config[:markdown] when 'rdiscount' begin require 'rdiscount' def markdown(content) RDiscount.new(content).to_html end rescue LoadError puts 'You must have the rdiscount gem installed first' end when 'maruku' begin require 'maruku' def markdown(content) Maruku.new(content).to_html end if self.config[:maruku][:use_divs] require 'maruku/ext/div' puts 'Maruku: Using extended syntax for div elements.' end if self.config[:maruku][:use_tex] require 'maruku/ext/math' puts "Maruku: Using LaTeX extension. Images in `#{self.config[:maruku][:png_dir]}`." # Switch off MathML output MaRuKu::Globals[:html_math_output_mathml] = false MaRuKu::Globals[:html_math_engine] = 'none' # Turn on math to PNG support with blahtex # Resulting PNGs stored in `images/latex` MaRuKu::Globals[:html_math_output_png] = true MaRuKu::Globals[:html_png_engine] = self.config[:maruku][:png_engine] MaRuKu::Globals[:html_png_dir] = self.config[:maruku][:png_dir] MaRuKu::Globals[:html_png_url] = self.config[:maruku][:png_url] end rescue LoadError puts "The maruku gem is required for markdown support!" end else raise "Invalid Markdown processor: '#{self.config[:markdown]}' -- did you mean 'maruku' or 'rdiscount'?" end end |
#site_payload ⇒ Object
The Hash payload containing site-wide data
Returns => {“time” => <Time>,
"posts" => [<Post>],
"categories" => [<Post>]
339 340 341 342 343 344 345 |
# File 'lib/broadway/site.rb', line 339 def site_payload {"site" => self.config.merge({ "time" => Time.now, "posts" => self.posts.sort { |a,b| b <=> a }, "categories" => post_attr_hash('categories'), "tags" => post_attr_hash('tags')})} end |
#textile(content) ⇒ Object
134 135 136 |
# File 'lib/broadway/site.rb', line 134 def textile(content) RedCloth.new(content).to_html end |
#write ⇒ Object
Write static files, pages and posts
Returns nothing
316 317 318 319 320 |
# File 'lib/broadway/site.rb', line 316 def write self.static_files.each do |sf| sf.write(self.dest) end end |