broadway 0.0.3.5 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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