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.
- data/README.markdown +155 -0
- data/lib/broadway.rb +64 -4
- data/lib/broadway/{core_ext.rb → ext.rb} +40 -6
- data/lib/broadway/filters/erb.rb +10 -0
- data/lib/broadway/filters/haml.rb +10 -0
- data/lib/broadway/filters/liquid.rb +14 -0
- data/lib/broadway/filters/markdown.rb +10 -0
- data/lib/broadway/filters/textile.rb +11 -0
- data/lib/broadway/migrators/blogger.rb +7 -0
- data/lib/broadway/migrators/wordpress.rb +7 -0
- data/lib/broadway/mixins/assetable.rb +48 -0
- data/lib/broadway/mixins/configurable.rb +32 -0
- data/lib/broadway/mixins/convertible.rb +25 -0
- data/lib/broadway/mixins/hierarchical.rb +61 -0
- data/lib/broadway/mixins/layoutable.rb +18 -0
- data/lib/broadway/mixins/pageable.rb +5 -0
- data/lib/broadway/mixins/processable.rb +44 -0
- data/lib/broadway/mixins/publishable.rb +36 -0
- data/lib/broadway/mixins/readable.rb +73 -0
- data/lib/broadway/mixins/resourceful.rb +27 -0
- data/lib/broadway/mixins/sluggable.rb +36 -0
- data/lib/broadway/mixins/sortable.rb +24 -0
- data/lib/broadway/mixins/taggable.rb +46 -0
- data/lib/broadway/mixins/themeable.rb +39 -0
- data/lib/broadway/processors/link.rb +45 -0
- data/lib/broadway/processors/post.rb +117 -0
- data/lib/broadway/processors/site.rb +77 -0
- data/lib/broadway/processors/tree.rb +121 -0
- data/lib/broadway/resources/asset.rb +28 -0
- data/lib/broadway/resources/configuration.rb +114 -0
- data/lib/broadway/resources/file.rb +88 -0
- data/lib/broadway/resources/layout.rb +28 -0
- data/lib/broadway/resources/link.rb +16 -0
- data/lib/broadway/resources/post.rb +63 -0
- data/lib/broadway/resources/site.rb +164 -0
- data/lib/broadway/resources/slug.rb +69 -0
- data/lib/broadway/sinatra/app.rb +21 -0
- data/lib/broadway/sinatra/helpers/collection_helper.rb +2 -1
- data/lib/broadway/sinatra/helpers/partial_helper.rb +5 -5
- data/lib/broadway/sinatra/helpers/text_helper.rb +5 -11
- data/lib/broadway/sinatra/processor.rb +84 -0
- data/lib/broadway/tasks.rb +1 -0
- data/lib/broadway/tasks/default.rake +85 -0
- metadata +46 -41
- data/README.textile +0 -306
- data/Rakefile +0 -85
- data/lib/broadway/api.rb +0 -51
- data/lib/broadway/asset.rb +0 -17
- data/lib/broadway/base.rb +0 -120
- data/lib/broadway/convertible.rb +0 -91
- data/lib/broadway/page.rb +0 -71
- data/lib/broadway/post.rb +0 -112
- data/lib/broadway/rails.rb +0 -3
- data/lib/broadway/resource.rb +0 -128
- data/lib/broadway/runner.rb +0 -62
- data/lib/broadway/sinatra.rb +0 -5
- data/lib/broadway/sinatra/base.rb +0 -90
- data/lib/broadway/sinatra/helpers.rb +0 -7
- data/lib/broadway/site.rb +0 -421
- data/lib/broadway/static_file.rb +0 -32
data/README.markdown
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
<h1>
|
2
|
+
<span>Broadway</span>
|
3
|
+
<span><img src="http://viatropos.github.com/broadway/favicon.png"/></span>
|
4
|
+
</h1>
|
5
|
+
|
6
|
+
Pluggable, portable, framework-friendly static site generator. Setting the Stage for the Ruby CMS.
|
7
|
+
|
8
|
+
## Usage
|
9
|
+
|
10
|
+
### Install
|
11
|
+
|
12
|
+
sudo gem install broadway
|
13
|
+
|
14
|
+
#### Test
|
15
|
+
|
16
|
+
rake test
|
17
|
+
|
18
|
+
### Structure
|
19
|
+
|
20
|
+
Everything uses relative paths from the site root.
|
21
|
+
|
22
|
+
.
|
23
|
+
|-- _config.yml
|
24
|
+
|-- _layouts
|
25
|
+
|-- _posts (generated output)
|
26
|
+
|-- _site (github's place)
|
27
|
+
|-- _source (sinatra application for development)
|
28
|
+
| |-- files (blog files to-be published)
|
29
|
+
| |-- posts (blog files)
|
30
|
+
| |-- lib (sinatra helpers)
|
31
|
+
| `-- public (sinatra public directory)
|
32
|
+
|-- shared (javascripts, css, media, etc.)
|
33
|
+
|-- index.html
|
34
|
+
|-- robots.txt (what google should ignore)
|
35
|
+
`-- sitemap.xml (google's sitemap from jekyll)
|
36
|
+
|
37
|
+
### Run
|
38
|
+
|
39
|
+
If you want to use this entirely as a web server, run this at your source root:
|
40
|
+
|
41
|
+
broadway
|
42
|
+
|
43
|
+
If you want to use it inside of Sinatra or Rails, create the site manually:
|
44
|
+
|
45
|
+
site = Broadway.build!
|
46
|
+
|
47
|
+
### Models
|
48
|
+
|
49
|
+
Broadway uses Site, Post, Asset, File, Link, Slug, and Configuration to solve pretty much everything for creating a fully featured site using just Textmate.
|
50
|
+
|
51
|
+
#### The Site
|
52
|
+
|
53
|
+
The `Site` is basically the static database.
|
54
|
+
|
55
|
+
- It holds a reference to all of your other models.
|
56
|
+
- It reads a `_config.yml` file from a directory.
|
57
|
+
- Creates `File` objects out of the directory tree.
|
58
|
+
- Converts `Files` into `Posts` with slugs, tags, categories, and dates if they fit the profile.
|
59
|
+
- Finds `Assets` from within `Posts`.
|
60
|
+
- And uses a DSL to build menus out of `Links`.
|
61
|
+
|
62
|
+
##### Api
|
63
|
+
|
64
|
+
site = Broadway::Site.new
|
65
|
+
# dynamic finders
|
66
|
+
site.(models) #=> array of all models
|
67
|
+
site.find_(model)_by_(property)(value) #=> first model matching property value
|
68
|
+
site.find_(models)_by_(property)(value) #=> all models matching property value
|
69
|
+
site.find_(model)(attributes) #=> first model matching attributes
|
70
|
+
site.find_(models)(attributes) #=> all models matching attributes
|
71
|
+
site.(model)_roots #=> all hierarchical models without a parent
|
72
|
+
|
73
|
+
#### The Post
|
74
|
+
|
75
|
+
The `Post` works just like the other static site generators, it is the content input.
|
76
|
+
|
77
|
+
- It has `metadata` (YAML header) which defines (nested) key-value attributes.
|
78
|
+
- It has a `Slug` based on the folder structure, title, date, and is customizable.
|
79
|
+
- It has `tags` defined by `metadata`, which can be scoped (e.g tags by "skill" vs. "favorite")
|
80
|
+
- It has `categories` based on the folder structure.
|
81
|
+
- It has a `kind`, specifying how the post should be treated (currently `post` or `page`).
|
82
|
+
- It has `children` if it is a `page`.
|
83
|
+
- It has `Assets` defined by `metadata`, if desired.
|
84
|
+
- It has a `date` if a) its title was formatted like `yyyy-mm-dd-title.extension`, or b) metadata has defined a `date` attribute.
|
85
|
+
|
86
|
+
##### Api
|
87
|
+
|
88
|
+
post = site.posts.first #=> e.g...
|
89
|
+
post.tags #=> ["ruby", "sinatra", "rails"]
|
90
|
+
post.categories #=> ["path", "to", "post"]
|
91
|
+
post.assets #=> array of Asset objects, if defined
|
92
|
+
post.file #=> associate file object, where all calculations are based
|
93
|
+
post.slug #=> slug calculation object
|
94
|
+
post.path #=> "/path/to/post"
|
95
|
+
post.url #=> "http://site.com/path/to/post"
|
96
|
+
post.kind #=> "page" or "post" (or whatever you define)
|
97
|
+
post.children #=> array of Post objects, if it's a "page"
|
98
|
+
post.title
|
99
|
+
post.data #=> access to everything in the yaml header
|
100
|
+
|
101
|
+
### The Configuration
|
102
|
+
|
103
|
+
The `Configuration` object is defined from `_config.yml` in the Broadway Site root.
|
104
|
+
|
105
|
+
- Nested YAML properties
|
106
|
+
- Can be used to store arbitrary data, such as site seo stuff, author, etc.
|
107
|
+
- Accessed in views via `c("path.to.attribute")`.
|
108
|
+
|
109
|
+
## Context
|
110
|
+
|
111
|
+
There are plenty of static site generators out there: [Jekyll](http://github.com/mojombo/jekyll), [Webby](http://github.com/TwP/webby), [Nanoc](http://github.com/ddfreyne/nanoc), [StaticMatic](http://github.com/staticmatic/staticmatic), [Middleman](http://github.com/tdreyno/middleman), [Mercury](http://github.com/jackhq/mercury), [Frank](http://github.com/blahed/frank), [DynamicMatic](http://github.com/nex3/dynamicmatic), [WebGen](http://github.com/gettalong/webgen), [Pekky](http://github.com/lukesutton/pekky), [Awestruct](http://github.com/bobmcwhirter/awestruct), [Massimo](http://github.com/petebrowne/massimo)... The problem with them is that they are completely separate frameworks from Sinatra and Rails. They're not meant to be used with either of those. It's a lot of work to integrate them.
|
112
|
+
|
113
|
+
Broadway makes Rails and Sinatra static-compatible.
|
114
|
+
|
115
|
+
Why integrate static sites with Rails and Sinatra?
|
116
|
+
|
117
|
+
1. So you can write posts in Textmate.
|
118
|
+
2. So you can organize your documents and still write complex app code around them.
|
119
|
+
3. So you can use all the helpers the frameworks have built in.
|
120
|
+
4. So you can use Haml and Sass.
|
121
|
+
5. So you can make pretty blogs and still think like a programmer.
|
122
|
+
6. So you can host it on Github Pages if you want.
|
123
|
+
|
124
|
+
## Tools
|
125
|
+
|
126
|
+
- [SeeSaw](http://meetseesaw.com): Convert HTML to HAML, Textile/Markdown to HTML, and lots of other conversions. Useful for converting html you find on sites to Haml for learning.
|
127
|
+
- [Sinatra, HAML, JQuery, Textile (cool blog)](http://blog.peepcode.com/tutorials/2010/about-this-blog). Random site I thought was cool.
|
128
|
+
- [Tilt](http://github.com/rtomayko/tilt)
|
129
|
+
|
130
|
+
## Sinatra on Broadway
|
131
|
+
|
132
|
+
Here is a [Sinatra + Broadway Example App](http://github.com/viatropos/broadway).
|
133
|
+
|
134
|
+
Below is a description on how you might setup a Sinatra app to be themeable and run via markdown files. TODO.
|
135
|
+
|
136
|
+
### Themes
|
137
|
+
|
138
|
+
Create a folder called shared/themes/my-theme-name. In there, create folders for html, touch, and flash. In the html folder, you need the following
|
139
|
+
|
140
|
+
.
|
141
|
+
|-- index.haml # home page (layout.haml is somewhere else entirely)
|
142
|
+
|-- about
|
143
|
+
|-- blog
|
144
|
+
|-- features
|
145
|
+
|-- demos
|
146
|
+
|-- download
|
147
|
+
|-- support
|
148
|
+
|-- community
|
149
|
+
|-- shared
|
150
|
+
| |-- stylesheets
|
151
|
+
| |-- javascripts
|
152
|
+
| |-- images
|
153
|
+
| `-- partials
|
154
|
+
| |-- _head.haml
|
155
|
+
| `-- _header.haml
|
data/lib/broadway.rb
CHANGED
@@ -1,6 +1,66 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require "rubygems"
|
2
|
+
require "active_support"
|
3
|
+
require "active_support/core_ext"
|
4
|
+
require "fileutils"
|
5
|
+
require "time"
|
6
|
+
require "yaml"
|
7
|
+
require "cgi"
|
3
8
|
|
4
|
-
|
9
|
+
# settings
|
10
|
+
# require 'cockpit'
|
11
|
+
this = File.dirname(__FILE__) + "/broadway"
|
12
|
+
require "#{this}/ext"
|
13
|
+
requirements = %w(builders processors mixins resources).map { |dir| Dir["#{this}/#{dir}/*"] }
|
5
14
|
|
6
|
-
|
15
|
+
if defined?(::Sinatra)
|
16
|
+
requirements << Dir["#{this}/sinatra/**/*"]
|
17
|
+
end
|
18
|
+
|
19
|
+
requirements.flatten.each { |file| require file if File.extname(file) == ".rb" }
|
20
|
+
|
21
|
+
module Broadway
|
22
|
+
class << self
|
23
|
+
attr_accessor :site, :generator
|
24
|
+
|
25
|
+
def build(options = {})
|
26
|
+
process(:build, options)
|
27
|
+
end
|
28
|
+
|
29
|
+
def generator(&block)
|
30
|
+
@generator = block if block_given?
|
31
|
+
@generator
|
32
|
+
end
|
33
|
+
|
34
|
+
def generate(options = {}, &block)
|
35
|
+
block = generator unless block_given?
|
36
|
+
process(:generate, options, &block)
|
37
|
+
end
|
38
|
+
|
39
|
+
def process(method, options = {}, &block)
|
40
|
+
self.site ||= Broadway::Site.new(options)
|
41
|
+
self.site.send(method, &block)
|
42
|
+
self.site
|
43
|
+
end
|
44
|
+
|
45
|
+
def menu!(site, name, &block)
|
46
|
+
Broadway::Processor::Link.menu!(site, name, &block)
|
47
|
+
end
|
48
|
+
|
49
|
+
# path to views
|
50
|
+
def views
|
51
|
+
site.views_path
|
52
|
+
end
|
53
|
+
|
54
|
+
def public
|
55
|
+
site.public_path
|
56
|
+
end
|
57
|
+
|
58
|
+
def index
|
59
|
+
site.index_path
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def Broadway(*args, &block)
|
65
|
+
Broadway.define!(*args, &block)
|
66
|
+
end
|
@@ -1,27 +1,45 @@
|
|
1
1
|
class Hash
|
2
|
-
def
|
2
|
+
def recursively_symbolize_keys!
|
3
3
|
self.symbolize_keys!
|
4
4
|
self.values.each do |v|
|
5
5
|
if v.is_a? Hash
|
6
|
-
v.
|
6
|
+
v.recursively_symbolize_keys!
|
7
7
|
elsif v.is_a? Array
|
8
|
-
v.
|
8
|
+
v.recursively_symbolize_keys!
|
9
9
|
end
|
10
10
|
end
|
11
11
|
self
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
+
class String
|
16
|
+
def taggify(separator = "-", quoted = false)
|
17
|
+
result = self.dup.downcase.strip.gsub(/[^a-z0-9\.]/, separator).squeeze(separator)
|
18
|
+
result = "\"#{result}\"" if quoted && !(result =~ /\s+/).nil?
|
19
|
+
result
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
15
23
|
class Array
|
16
|
-
def
|
24
|
+
def recursively_symbolize_keys!
|
17
25
|
self.each do |item|
|
18
26
|
if item.is_a? Hash
|
19
|
-
item.
|
27
|
+
item.recursively_symbolize_keys!
|
20
28
|
elsif item.is_a? Array
|
21
|
-
item.
|
29
|
+
item.recursively_symbolize_keys!
|
22
30
|
end
|
23
31
|
end
|
24
32
|
end
|
33
|
+
|
34
|
+
# separator = ", ",
|
35
|
+
# max = 10_000
|
36
|
+
# quote = true|false
|
37
|
+
def taggify(space = " ", separator = ", ", max = 10_000)
|
38
|
+
quoted = !(separator =~ /\s+/).nil?
|
39
|
+
chop(separator, max) do |word|
|
40
|
+
word.taggify(space, quoted)
|
41
|
+
end.join(separator)
|
42
|
+
end
|
25
43
|
|
26
44
|
# http://snippets.dzone.com/posts/show/3486
|
27
45
|
def chunk(pieces)
|
@@ -39,6 +57,22 @@ class Array
|
|
39
57
|
end
|
40
58
|
end
|
41
59
|
|
60
|
+
class String
|
61
|
+
def nested_parameterize(sep = '-')
|
62
|
+
parameterized_string = self.dup
|
63
|
+
# Turn unwanted chars into the seperator
|
64
|
+
parameterized_string = parameterized_string.gsub(/'/, "").gsub(/[^a-z0-9\-_\+\/]+/i, sep)
|
65
|
+
unless sep.blank?
|
66
|
+
re_sep = Regexp.escape(sep)
|
67
|
+
# No more than one of the separator in a row.
|
68
|
+
parameterized_string.gsub!(/#{re_sep}{2,}/, sep)
|
69
|
+
# Remove leading/trailing separator.
|
70
|
+
parameterized_string.gsub!(/^#{re_sep}|#{re_sep}$/i, '')
|
71
|
+
end
|
72
|
+
parameterized_string.downcase
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
42
76
|
class Hash
|
43
77
|
# Merges self with another hash, recursively.
|
44
78
|
#
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Broadway
|
2
|
+
class Liquid
|
3
|
+
|
4
|
+
class << self
|
5
|
+
def transform(payload, layouts)
|
6
|
+
info = { :filters => [], :registers => { :site => self.site } }
|
7
|
+
# render and transform content (this becomes the final content of the object)
|
8
|
+
payload["content_type"] = self.content_type
|
9
|
+
self.output = Liquid::Template.parse(self.content).render(payload, info)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Broadway
|
2
|
+
module Assetable
|
3
|
+
def self.included(base)
|
4
|
+
base.send :include, InstanceMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
module InstanceMethods
|
8
|
+
def asset_types
|
9
|
+
%w(image video audio asset)
|
10
|
+
end
|
11
|
+
|
12
|
+
def assets
|
13
|
+
unless @assets
|
14
|
+
@assets = []
|
15
|
+
if self.data.has_key?("asset")
|
16
|
+
@assets << ::Broadway::Asset.new(self, "asset", data["asset"])
|
17
|
+
elsif self.data.has_key?("assets")
|
18
|
+
self.data["assets"].each do |name, asset|
|
19
|
+
@assets << ::Broadway::Asset.new(self, name, asset)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
@assets
|
25
|
+
end
|
26
|
+
|
27
|
+
def asset
|
28
|
+
assets.first
|
29
|
+
end
|
30
|
+
|
31
|
+
def num_assets
|
32
|
+
assets.length
|
33
|
+
end
|
34
|
+
|
35
|
+
def find_asset_by_name(name)
|
36
|
+
assets.detect { |asset| asset.name == name }
|
37
|
+
end
|
38
|
+
|
39
|
+
def method_missing(meth, *args, &block)
|
40
|
+
if asset_types.detect { |type| meth.to_s =~ /(\w+)_#{type}/ }
|
41
|
+
find_asset_by_name($1.to_s)
|
42
|
+
else
|
43
|
+
super(meth, *args, &block)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Broadway
|
2
|
+
module Configurable
|
3
|
+
def self.included(base)
|
4
|
+
base.send :include, InstanceMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
module InstanceMethods
|
8
|
+
attr_accessor :data
|
9
|
+
|
10
|
+
# should only read the beginning of the file
|
11
|
+
def configure
|
12
|
+
self.content = file.read
|
13
|
+
|
14
|
+
if self.content =~ /^(---\s*\n.*?\n?)^(---\s*$\n?)/m
|
15
|
+
self.content = self.content[($1.size + $2.size)..-1]
|
16
|
+
|
17
|
+
self.data.merge!(YAML.load($1))
|
18
|
+
end
|
19
|
+
|
20
|
+
self.data ||= {}
|
21
|
+
end
|
22
|
+
|
23
|
+
def method_missing(meth, *args, &block)
|
24
|
+
if self.data && self.data.has_key?(meth.to_s)
|
25
|
+
self.data[meth.to_s]
|
26
|
+
else
|
27
|
+
super(meth, *args, &block)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|