broadway 0.0.3.5 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. data/README.markdown +155 -0
  2. data/lib/broadway.rb +64 -4
  3. data/lib/broadway/{core_ext.rb → ext.rb} +40 -6
  4. data/lib/broadway/filters/erb.rb +10 -0
  5. data/lib/broadway/filters/haml.rb +10 -0
  6. data/lib/broadway/filters/liquid.rb +14 -0
  7. data/lib/broadway/filters/markdown.rb +10 -0
  8. data/lib/broadway/filters/textile.rb +11 -0
  9. data/lib/broadway/migrators/blogger.rb +7 -0
  10. data/lib/broadway/migrators/wordpress.rb +7 -0
  11. data/lib/broadway/mixins/assetable.rb +48 -0
  12. data/lib/broadway/mixins/configurable.rb +32 -0
  13. data/lib/broadway/mixins/convertible.rb +25 -0
  14. data/lib/broadway/mixins/hierarchical.rb +61 -0
  15. data/lib/broadway/mixins/layoutable.rb +18 -0
  16. data/lib/broadway/mixins/pageable.rb +5 -0
  17. data/lib/broadway/mixins/processable.rb +44 -0
  18. data/lib/broadway/mixins/publishable.rb +36 -0
  19. data/lib/broadway/mixins/readable.rb +73 -0
  20. data/lib/broadway/mixins/resourceful.rb +27 -0
  21. data/lib/broadway/mixins/sluggable.rb +36 -0
  22. data/lib/broadway/mixins/sortable.rb +24 -0
  23. data/lib/broadway/mixins/taggable.rb +46 -0
  24. data/lib/broadway/mixins/themeable.rb +39 -0
  25. data/lib/broadway/processors/link.rb +45 -0
  26. data/lib/broadway/processors/post.rb +117 -0
  27. data/lib/broadway/processors/site.rb +77 -0
  28. data/lib/broadway/processors/tree.rb +121 -0
  29. data/lib/broadway/resources/asset.rb +28 -0
  30. data/lib/broadway/resources/configuration.rb +114 -0
  31. data/lib/broadway/resources/file.rb +88 -0
  32. data/lib/broadway/resources/layout.rb +28 -0
  33. data/lib/broadway/resources/link.rb +16 -0
  34. data/lib/broadway/resources/post.rb +63 -0
  35. data/lib/broadway/resources/site.rb +164 -0
  36. data/lib/broadway/resources/slug.rb +69 -0
  37. data/lib/broadway/sinatra/app.rb +21 -0
  38. data/lib/broadway/sinatra/helpers/collection_helper.rb +2 -1
  39. data/lib/broadway/sinatra/helpers/partial_helper.rb +5 -5
  40. data/lib/broadway/sinatra/helpers/text_helper.rb +5 -11
  41. data/lib/broadway/sinatra/processor.rb +84 -0
  42. data/lib/broadway/tasks.rb +1 -0
  43. data/lib/broadway/tasks/default.rake +85 -0
  44. metadata +46 -41
  45. data/README.textile +0 -306
  46. data/Rakefile +0 -85
  47. data/lib/broadway/api.rb +0 -51
  48. data/lib/broadway/asset.rb +0 -17
  49. data/lib/broadway/base.rb +0 -120
  50. data/lib/broadway/convertible.rb +0 -91
  51. data/lib/broadway/page.rb +0 -71
  52. data/lib/broadway/post.rb +0 -112
  53. data/lib/broadway/rails.rb +0 -3
  54. data/lib/broadway/resource.rb +0 -128
  55. data/lib/broadway/runner.rb +0 -62
  56. data/lib/broadway/sinatra.rb +0 -5
  57. data/lib/broadway/sinatra/base.rb +0 -90
  58. data/lib/broadway/sinatra/helpers.rb +0 -7
  59. data/lib/broadway/site.rb +0 -421
  60. data/lib/broadway/static_file.rb +0 -32
@@ -0,0 +1,45 @@
1
+ module Broadway
2
+ module Definition
3
+ class Link
4
+ attr_accessor :site, :context, :records
5
+
6
+ def initialize(site, context, &block)
7
+ self.site = site
8
+ self.context = context
9
+ self.records = []
10
+ instance_eval(&block)
11
+ end
12
+
13
+ def link(*args, &block)
14
+ options = args.extract_options!
15
+ href = args.shift
16
+ title = args.shift || options[:title] || href.split("/").last.titleize
17
+ record = Broadway::Link.new(site, :href => href, :title => title, :categories => [context.to_s])
18
+ self.records << record
19
+ site.links << record
20
+ if block_given?
21
+ record.children = Broadway::Definition::Link.new(site, context, &block).records
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ module Processor
28
+ class Link
29
+ class << self
30
+ def tree!(site, name, &block)
31
+ Broadway::Definition::Link.new(site, name, &block).records
32
+ end
33
+ alias menu! tree!
34
+ end
35
+
36
+ def initialize(link, site, options = {})
37
+ link.site = site
38
+ link.href = options[:href]
39
+ link.title = options[:title]
40
+ link.categories = options[:categories]
41
+ end
42
+
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,117 @@
1
+ module Broadway
2
+ module Processor
3
+ class Post
4
+ class << self
5
+
6
+ # RULES:
7
+ # Pages are only index.textile files, or static .html files (TODO)
8
+ # Posts are leaf nodes (name.textile files)
9
+ # Categories are the directoryectory name split plus anything extra defined
10
+ # Pages and Posts can also be obtained via index.xml files
11
+ def build(parent, site)
12
+ result = Dir.entries(parent).collect do |path|
13
+ # removes junk, leaves us with .xml, .textile, .html
14
+ next if skip?(path)
15
+ name = File.file_name(path)
16
+ next if name == "index"
17
+ ext = File.file_ext(path)
18
+ file = ::File.join(parent, path)
19
+ if %w(textile markdown html).include?(ext)
20
+ ::Broadway::Post.new(site, :file => file)
21
+ elsif page = Post.page_exists?(file)
22
+ ::Broadway::Post.new(site, :file => page)
23
+ else
24
+ nil
25
+ end
26
+ end.compact
27
+
28
+ result.sort!
29
+
30
+ # finally, we have set all the initial variables on the
31
+ # pages and posts we need, now we can process them to find
32
+ # the content and generate the urls
33
+ result.each do |post|
34
+ site.posts << post
35
+ post.categories.each { |c| site.categories[c] << post }
36
+ post.tags.each { |c| site.tags[c] << post }
37
+ end
38
+
39
+ result
40
+ end
41
+
42
+ def page_exists?(file)
43
+ %w(markdown textile txt).each do |extension|
44
+ page = ::File.join(file, "index.#{extension}")
45
+ return page if ::File.exists?(page)
46
+ end
47
+ nil
48
+ end
49
+
50
+ # Filter out any files/directoryectories that are hidden or backup files (start
51
+ # with "." or "#" or end with "~"), or contain site content (start with "_"),
52
+ # or are excluded in the site settingsuration, unless they are web server
53
+ # files such as '.htaccess'
54
+ def skip?(path)
55
+ #return true if ::File.directory?(path)
56
+ file = ::File.basename(path)
57
+ return true if ['.htaccess'].include?(file)
58
+ ['.', '_', '#'].include?(file[0..0]) || file[-1..-1] == '~'# || self.exclude.include?(file)
59
+ end
60
+
61
+ # sort all pages and posts
62
+ # determined by index.xml file (and later, for dates)
63
+ def sort!
64
+ sort_content(:post, site.posts)
65
+ end
66
+
67
+ def sort_content(type, contents)
68
+ method = type.to_s.pluralize
69
+ unnumbered = site.send(method).select { |content| content.position.nil? }
70
+ start_index = site.send(method).length - unnumbered.length
71
+ unnumbered.each_with_index { |content, index| content.position = start_index + index }
72
+ site.send(method).sort!
73
+ site.send(method)
74
+ end
75
+
76
+ # Constructs a hash map of Posts indexed by the specified Post attribute
77
+ #
78
+ # Returns {post_attr => [<Post>]}
79
+ def post_attr_hash(post_attr)
80
+ # Build a hash map based on the specified post attribute ( post attr => array of posts )
81
+ # then sort each array in reverse order
82
+ hash = Hash.new { |hash, key| hash[key] = Array.new }
83
+ self.posts.each { |p| p.send(post_attr.to_sym).each { |t| hash[t] << p } }
84
+ hash.values.map { |sortme| sortme.sort! { |a, b| b <=> a} }
85
+ return hash
86
+ end
87
+ end
88
+
89
+ def initialize(post, site, options = {})
90
+ post.site = site
91
+ post.file = Broadway::File.new(site, options)
92
+ post.kind = "page" if post.file.slug == "index"
93
+ post.slug = Broadway::Slug.new(post.file.slug, post)
94
+ post.data = post.file.header
95
+ post.title = post.data["title"].blank? ? post.slug.titleize : post.data["title"]
96
+ if post.title.downcase == "index"
97
+ post.title = ::File.basename(post.file.directory).titleize
98
+ end
99
+ unless options[:recursive] == false
100
+ post.children = children(post.file.directory, site) if post.kind == "page"
101
+ end
102
+ end
103
+
104
+ def children(path, site)
105
+ Post.build(path, site) if path
106
+ end
107
+
108
+ def read(attribute = nil)
109
+ post.file.read(attribute)
110
+ end
111
+
112
+ def write(to)
113
+ post.file.write(to)
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,77 @@
1
+ module Broadway
2
+ module Processor
3
+ class Site
4
+ attr_accessor :site, :source, :destination, :lsi, :pygments, :exclude, :lists, :configuration
5
+
6
+ def initialize(site, settings)
7
+ self.site = Broadway.site = site
8
+
9
+ site.configuration = Broadway::Configuration.new(site, settings)
10
+
11
+ self.lists = []
12
+ self.source = settings[:source]
13
+ self.lsi = settings[:lsi]
14
+ self.pygments = settings[:pygments]
15
+ self.exclude = settings[:exclude] || []
16
+
17
+ reset
18
+ end
19
+
20
+ # first
21
+ def reset
22
+ site.posts = []
23
+ site.assets = []
24
+ site.links = []
25
+ site.files = []
26
+ site.categories = Hash.new { |hash, key| hash[key] = [] }
27
+ site.tags = Hash.new { |hash, key| hash[key] = [] }
28
+ end
29
+
30
+ def destination
31
+ settings[:destination]
32
+ end
33
+
34
+ def settings
35
+ site.settings
36
+ end
37
+
38
+ def process
39
+ build
40
+ generate
41
+ end
42
+
43
+ def build
44
+ self.reset
45
+ self.read
46
+ site
47
+ end
48
+
49
+ def generate(&block)
50
+ raise "pass a block to `generate`" unless block_given?
51
+ raise "define a destination for the site to be written to" if destination.blank?
52
+ Broadway::Sinatra::Processor.new(site).run(&block) if defined?(::Sinatra)
53
+ site
54
+ end
55
+
56
+ def read
57
+ roots
58
+ links
59
+ end
60
+
61
+ def roots
62
+ site.roots = Broadway::Processor::Post.build(source, site) if source
63
+ end
64
+
65
+ def links
66
+ #@links ||= Broadway::Processor::Link.build(source, site)
67
+ @links
68
+ end
69
+
70
+ def write
71
+ site.files.each do |file|
72
+ file.write(self.destination)
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,121 @@
1
+ # redefine the hierarchy of posts, or order them
2
+ # DSL for defining initial page hierarchy
3
+ module Broadway
4
+ module Processor
5
+ class Tree
6
+ attr_accessor :root
7
+
8
+ class << self
9
+
10
+ # lists are xml files we've collect, but we want to make sure we've
11
+ # created all the posts we need to beforehand
12
+ # this also sorts everything
13
+ def build(path)
14
+ list = ::File.join(source, "index.xml")
15
+ lists << list if ::File.exists?(list)
16
+ unless lists.blank?
17
+ require 'nokogiri'
18
+ lists.each do |path|
19
+ new_tree(path)
20
+ end
21
+ end
22
+ end
23
+
24
+ def new_tree(path)
25
+ site.tree.concat parse_tree(Nokogiri::XML(IO.read(path)).root)
26
+ end
27
+
28
+ def parse_tree(parent)
29
+ result = []
30
+ return result if parent.nil? || parent.children.nil? || parent.children.empty?
31
+ parent.children.each_with_index do |child, index|
32
+ next unless child.elem?
33
+ post = post_from_xml(child)
34
+ next unless post
35
+ if post.respond_to?(:children)
36
+ post.children.concat parse_tree(child)
37
+ end
38
+ post.position = index
39
+ result << post
40
+ end
41
+ result
42
+ end
43
+
44
+ def post_from_xml(post)
45
+ # post
46
+ # 1. If a "src" is defined, then we should have already created the post
47
+ # 2. If no "src", then post is specified inline (or there is no post yet)
48
+ path = (post["src"] || ::File.join(site.source, post["path"]) || "").gsub(/^\//, "").gsub(/\/$/, "").squeeze("/")
49
+ post = site.find_post_by_path(path)
50
+ unless post
51
+ if ::File.directory?(path)
52
+ page = Dir.entries(path)[2..-1].detect do |file|
53
+ ::File.basename(file).split(".")[0..-2].join(".").downcase == "index"
54
+ end
55
+ if page
56
+ path = ::File.join(path, page)
57
+ post = site.find_post_by_path(path)
58
+ post ||= Broadway::Builder::Post.new_post(path)
59
+ end
60
+ end
61
+ end
62
+
63
+ return unless post
64
+
65
+ %w(title image excerpt menu_title tooltip show_children post layout).each do |key|
66
+ post.data[key] = post[key] if post.has_attribute?(key)
67
+ end
68
+ post
69
+ end
70
+ end
71
+
72
+ def initialize(*args, &block)
73
+ self.root = ::Broadway::Definition::Post.new(*args, &block)
74
+ end
75
+ end
76
+
77
+ module Definition
78
+ class Base
79
+ def initialize(*args, &block)
80
+ options = args.extract_options!
81
+
82
+ options.each do |k, v|
83
+ self.send("#{k}=", v) if self.respond_to?(k)
84
+ end
85
+
86
+ instance_eval(&block) if block_given?
87
+ end
88
+ end
89
+
90
+ class Post
91
+ attr_accessor :title, :path, :tooltip, :show_children
92
+
93
+ def title(value = "")
94
+ @title = value if value
95
+ @title
96
+ end
97
+
98
+ def path(value = "")
99
+ @path = value if value
100
+ @path
101
+ end
102
+
103
+ def tooltip(value = "")
104
+ @tooltip = value if value
105
+ @tooltip
106
+ end
107
+
108
+ def show_children(value = "")
109
+ @show_children = value if value
110
+ @show_children
111
+ end
112
+
113
+ end
114
+
115
+ class Menu
116
+
117
+ end
118
+
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,28 @@
1
+ module Broadway
2
+ class Asset
3
+ attr_accessor :site, :title, :tooltip, :thumb, :width, :height, :resource, :content_type, :name, :path
4
+
5
+ include Comparable
6
+ include Broadway::Resourceful
7
+ include Broadway::Readable
8
+ include Broadway::Sortable
9
+ include Broadway::Taggable
10
+ include Broadway::Configurable
11
+
12
+ def initialize(resource, name, options = {})
13
+ self.resource = resource
14
+ self.name = name
15
+ self.data = options.recursively_symbolize_keys!
16
+ self.path = options.delete(:path)
17
+ options.each do |k,v|
18
+ self.send("#{k}=", v) if self.respond_to?(k)
19
+ end
20
+
21
+ self.title ||= Broadway::File.file_name(self.path).titleize
22
+ end
23
+
24
+ def site
25
+ resource.site
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,114 @@
1
+ module Broadway
2
+ class Configuration
3
+ attr_accessor :settings, :site
4
+ # Default options. Overriden by values in _settings.yml or command-line opts.
5
+ # (Strings rather symbols used for compatability with YAML)
6
+ DEFAULTS = {
7
+ :auto => false,
8
+ :server => false,
9
+ :server_port => 4000,
10
+
11
+ :source => ".",
12
+ :settings => "_config.yml",
13
+ :destination => "_site",
14
+
15
+ :lsi => false,
16
+ :pygments => false,
17
+ :markdown => "rdiscount",
18
+ :permalink => "pretty",
19
+ :url_type => "relative",
20
+ :url => "http://localhost:4567",
21
+ :locales => "locales",
22
+ :language => "en-US",
23
+
24
+ :maruku => {
25
+ :use_tex => false,
26
+ :use_divs => false,
27
+ :png_engine => "blahtex",
28
+ :png_dir => "images/latex",
29
+ :png_url => "/images/latex"
30
+ },
31
+
32
+ :layouts => "_layouts",
33
+ :posts_include => [".textile", ".markdown"],
34
+ :theme_path => "themes",
35
+ :theme_versions => ["main"]
36
+ } unless defined?(Broadway::Configuration::DEFAULTS)
37
+
38
+
39
+ def initialize(site, overrides)
40
+ self.site = site
41
+ self.settings = merge(overrides)
42
+ end
43
+
44
+ def merge(overrides)
45
+ DEFAULTS.deep_merge(read(overrides)).merge(overrides)
46
+ end
47
+
48
+ def get(path)
49
+ result = settings
50
+ path.to_s.split(".").each { |node| result = result[node.to_sym] if result }
51
+ result.nil? ? "" : result
52
+ end
53
+
54
+ def read(overrides)
55
+ overrides = overrides.recursively_symbolize_keys!
56
+ # _settings.yml may override default source location, but until
57
+ # then, we need to know where to look for _settings.yml
58
+ source = overrides[:source] || DEFAULTS[:source]
59
+ settings_file = overrides[:settings] || DEFAULTS[:settings]
60
+ settings_file = ::File.join(source, settings_file) unless ::File.exists?(settings_file)
61
+ # Get configuration from <source>/_config.yml
62
+ begin
63
+ settings = YAML.load_file(settings_file).recursively_symbolize_keys!
64
+ raise "Invalid configuration - #{settings_file}" if !settings.is_a?(Hash)
65
+ #$stdout.puts "Configuration from #{settings_file}"
66
+ rescue => err
67
+ puts err.inspect
68
+ #$stderr.puts "WARNING: Could not read configuration. Using defaults (and options)."
69
+ #$stderr.puts "\t" + err.to_s
70
+ settings = {}
71
+ end
72
+
73
+ settings
74
+ end
75
+
76
+ def merge_extra_settings!(settings)
77
+ locale = ::File.join(settings[:locales], "#{settings[:language]}.yml")
78
+
79
+ settings.merge!(YAML.load_file(locale)) if ::File.exists?(locale)
80
+
81
+ settings_dir = ::File.join(settings[:source], "settings")
82
+ return unless ::File.exists?(settings_dir)
83
+ Dir.glob("#{settings_dir}/**/*").each do |file|
84
+ next if ::File.directory?(file)
85
+ path = file.gsub(/settings\//, "").split(".")[0..-2].join("")
86
+ ext = ::File.extname(file)
87
+ if ext =~ /yml/
88
+ data = YAML.load_file(file)
89
+ elsif ext =~ /xml/
90
+ data = parse_children Nokogiri::XML(IO.read(file)).children[0]
91
+ else
92
+ data = IO.read(file)
93
+ end
94
+ next unless data
95
+ name = path.split("/").first
96
+ if path =~ /\//
97
+ settings[name] ||= {}
98
+ target = settings[name]
99
+ name = path.split("/").last
100
+ else
101
+ target = settings
102
+ end
103
+ if target.has_key?(name)
104
+ target[name].merge!(data)
105
+ else
106
+ target[name] = data
107
+ end
108
+ end
109
+ end
110
+
111
+ def setup
112
+ end
113
+ end
114
+ end