broadway 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.textile +300 -0
- data/Rakefile +80 -0
- data/lib/broadway.rb +7 -0
- data/lib/broadway/api.rb +51 -0
- data/lib/broadway/asset.rb +17 -0
- data/lib/broadway/base.rb +121 -0
- data/lib/broadway/convertible.rb +89 -0
- data/lib/broadway/core_ext.rb +93 -0
- data/lib/broadway/helpers.rb +7 -0
- data/lib/broadway/helpers/collection_helper.rb +152 -0
- data/lib/broadway/helpers/partial_helper.rb +31 -0
- data/lib/broadway/helpers/text_helper.rb +78 -0
- data/lib/broadway/main.rb +64 -0
- data/lib/broadway/page.rb +133 -0
- data/lib/broadway/post.rb +196 -0
- data/lib/broadway/resource.rb +5 -0
- data/lib/broadway/runner.rb +49 -0
- data/lib/broadway/site.rb +398 -0
- data/lib/broadway/static_file.rb +32 -0
- metadata +119 -0
data/README.textile
ADDED
@@ -0,0 +1,300 @@
|
|
1
|
+
h1. Broadway
|
2
|
+
|
3
|
+
TODO: Tests. I've just extracted this out of a project and now I'll write tests.
|
4
|
+
|
5
|
+
"html2haml":http://html2haml.heroku.com/
|
6
|
+
|
7
|
+
"JAVASCRIPT <script src=":http://github.com/HenrikJoreteg/jquery-magic-labels/raw/master/jquery.magiclabels.min.js
|
8
|
+
|
9
|
+
This is the source for my blog. I develop the themes in Sinatra, and convert them into Jekyll for posts. I'm only doing this until _someone_ gives Jekyll some HAML support so I can use it with Github... Or I find that it's really not that good of an investment to use Github Pages.
|
10
|
+
|
11
|
+
h2. The Goal
|
12
|
+
|
13
|
+
The goal of this project is to make it easy to manage 20 public software projects at once. This way, anyone developing their thing on github can easily post new examples and documentation as they develop their project, without anything out of their ordinary workflow.
|
14
|
+
|
15
|
+
h2. Sinatra, HAML, JQuery, Textile
|
16
|
+
|
17
|
+
"About this Blog":http://blog.peepcode.com/tutorials/2010/about-this-blog
|
18
|
+
|
19
|
+
h2. Jekyll and Sinatra
|
20
|
+
|
21
|
+
I use Jekyll for the static page generation (spits out all the pages, essentially pre-compiling everything into raw HTML). I don't use Jekyll because it uses Liquid. Liquid might be nice for someone who doesn't want to learn programming but would like to have fun with a few variables, and reuse some code. But for a programmer who takes pride in efficiency, clean code, and being DRY, HAML and full Ruby access is much better; it gives me freedom to _do_. I can:
|
22
|
+
|
23
|
+
# Format the HTML perfectly (using HAML with Textmate)
|
24
|
+
# Have Ruby hooks to conditionally link in elements throughout (getting rid of YAML headers)
|
25
|
+
# Use Ruby to dynamically process other URLs
|
26
|
+
# Extend the application to do other things like file uploading, all the while
|
27
|
+
# Keeping everything DRY and clean.
|
28
|
+
|
29
|
+
You can use @_posts@ without any layout! And they can be raw HTML files!
|
30
|
+
|
31
|
+
h3. Notes
|
32
|
+
|
33
|
+
* Any folder starting with an underscore is private in terms of browser access
|
34
|
+
|
35
|
+
h2. Directory Structure
|
36
|
+
|
37
|
+
<pre>
|
38
|
+
.
|
39
|
+
|-- _config.yml
|
40
|
+
|-- _layouts
|
41
|
+
|-- _posts (generated output)
|
42
|
+
|-- _site (github's place)
|
43
|
+
|-- _source (sinatra application for development)
|
44
|
+
| |-- files (blog files to-be published)
|
45
|
+
| |-- posts (blog files)
|
46
|
+
| |-- lib (sinatra helpers)
|
47
|
+
| `-- public (sinatra public directory)
|
48
|
+
|-- shared (javascripts, css, media, etc.)
|
49
|
+
|-- index.html
|
50
|
+
|-- robots.txt (what google should ignore)
|
51
|
+
`-- sitemap.xml (google's sitemap from jekyll)
|
52
|
+
</pre>
|
53
|
+
|
54
|
+
h2. Configuration
|
55
|
+
|
56
|
+
h3. Default Configuration
|
57
|
+
|
58
|
+
<pre>
|
59
|
+
permalink:
|
60
|
+
if post's name is "entry": /path/to (index.haml)
|
61
|
+
if post's name is "something-else": /path/to/something-else
|
62
|
+
those are "directory" styled permalinks
|
63
|
+
title: Path - To - Index
|
64
|
+
keywords: nil
|
65
|
+
description: nil
|
66
|
+
</pre>
|
67
|
+
|
68
|
+
h4. Permalink Styles
|
69
|
+
|
70
|
+
directory: /path/to/index or /path/to/title
|
71
|
+
date: /year/month/day/title
|
72
|
+
category: /root/child/childer/title
|
73
|
+
|
74
|
+
If directories have underscores, they are subtracted from the path:
|
75
|
+
|
76
|
+
/path/to/_some_way_of_organizing_my_posts/my-post.textile
|
77
|
+
=> /path/to/my-post
|
78
|
+
|
79
|
+
Preference:
|
80
|
+
|
81
|
+
# If directory contains all of [index.haml, entry.textile], it will render index.haml
|
82
|
+
# If directory contains all of [entry.textile], it will render entry.textile
|
83
|
+
|
84
|
+
h2. The Rendering Process
|
85
|
+
|
86
|
+
# Startup Sinatra
|
87
|
+
# Generate URLs from Post metadata, or, by default, directory to index.html or index.haml. Also collect all tags and categories in the application
|
88
|
+
# Now we have all: urls, tags, categories. But we haven't read all of the files into memory which can be a problem
|
89
|
+
# Go to a URL via Sinatra, render HAML
|
90
|
+
# Read post for that URL into memory
|
91
|
+
# Save HAML to HTML file
|
92
|
+
|
93
|
+
h2. Themes
|
94
|
+
|
95
|
+
When you make a request to a url, it renders out the template from the public/themes directory, but your content goes in public/posts. In public/posts, you can add HAML/HTML files to customize the base of the them (via 'yield'), but you don't need to. Instead, you just create your posts and they will be given a url. The default layout for anything in your public/posts directory is the root directory it's in. That's because you're likely to initially structure your posts according to the theme's RESTful page structure. But if you specify a <code>layout</code> in the header of your file, it will use that from the theme.
|
96
|
+
|
97
|
+
ln -s ~/viatropos/shared/themes ~/viatropos/_source/public/shared
|
98
|
+
|
99
|
+
h2. Posts
|
100
|
+
|
101
|
+
There are 3 types of posts:
|
102
|
+
|
103
|
+
# Blog Posts
|
104
|
+
# Index Posts
|
105
|
+
# Regular Posts
|
106
|
+
|
107
|
+
Blog posts are dated, so they must be prefixed with a date (2010-03-11-my-blog-post.textile). Index posts describe the default page and metadata, and they must be named "index" (index.textile). Regular posts are posts that don't care about date (such as wiki posts or just simple pages for a portfolio site), and they are named however (my-service-page.textile). Each post has metadata defined in a YAML header. The metadata can be wired explicitly to a themes implementation because, eventually, we'll all come to some sort of consensus on what should and shouldn't be included in the page metadata definition.
|
108
|
+
|
109
|
+
h2. View Variables
|
110
|
+
|
111
|
+
Inside your view you have access to quite a lot of variables:
|
112
|
+
|
113
|
+
# @metadata@: Hash of all the config variables defined for your header metadata.
|
114
|
+
# @config@: Hash of global config values
|
115
|
+
# @params@: Hash of values passed in through the URL
|
116
|
+
# @site@: site object, which has these properties
|
117
|
+
## @posts@: array of posts
|
118
|
+
## @categories@: array of categories @{:name => post}@
|
119
|
+
## @pages@: array of pages (TBD)
|
120
|
+
# @post@: Post object, if applicable
|
121
|
+
## @data@: Hash of metadata specific to this post (symbolized keys)
|
122
|
+
## @title@: Post title
|
123
|
+
## @url@: Relative URL to Post
|
124
|
+
## @date@: Date post was created
|
125
|
+
## @published@: Whether or not it's been officially published
|
126
|
+
## @tags@
|
127
|
+
## @categories@
|
128
|
+
|
129
|
+
ALL HASH KEYS ARE SYMBOLS, NOT STRINGS!
|
130
|
+
|
131
|
+
h2. Layouts
|
132
|
+
|
133
|
+
There are quite a few layouts available in each project:
|
134
|
+
|
135
|
+
# Overview
|
136
|
+
# Blog
|
137
|
+
# Post w/ column
|
138
|
+
# Post w/o column
|
139
|
+
# Portfolio: two column grid
|
140
|
+
# Portfolio: three column grid
|
141
|
+
# Testimonials
|
142
|
+
# two column list
|
143
|
+
# Contact
|
144
|
+
|
145
|
+
h2. TODO
|
146
|
+
|
147
|
+
# CycleHelper for easier haml repeaters
|
148
|
+
|
149
|
+
h2. Theme Development
|
150
|
+
|
151
|
+
"html2haml":http://html2haml.heroku.com/
|
152
|
+
|
153
|
+
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
|
154
|
+
|
155
|
+
<pre>
|
156
|
+
.
|
157
|
+
|-- index.haml # home page (layout.haml is somewhere else entirely)
|
158
|
+
|-- about
|
159
|
+
|-- blog
|
160
|
+
|-- features
|
161
|
+
|-- demos
|
162
|
+
|-- download
|
163
|
+
|-- support
|
164
|
+
|-- community
|
165
|
+
|-- shared
|
166
|
+
| |-- stylesheets
|
167
|
+
| |-- javascripts
|
168
|
+
| |-- images
|
169
|
+
| `-- partials
|
170
|
+
| |-- _head.haml
|
171
|
+
| `-- _header.haml
|
172
|
+
</pre>
|
173
|
+
|
174
|
+
There are two ways the posts/pages can be constructed:
|
175
|
+
|
176
|
+
# They have a date prefixing their name
|
177
|
+
# They are in an XML file
|
178
|
+
|
179
|
+
Dates specify an order, so do XML files. In the end, we have an xml file for each root directory that lists all of the posts in a tree. Whether they were from being in the "_posts" directory or because they were in an XML file, it doesn't matter.
|
180
|
+
|
181
|
+
If the content of the post doesn't need more than a few lines, you can specify it in XML (each item in XML is converted to a Post). Saves on space.
|
182
|
+
|
183
|
+
The end result is that we have 1 xml file for each category of posts, which can be imported into Flex.
|
184
|
+
|
185
|
+
h2. Posts vs. Pages
|
186
|
+
|
187
|
+
Posts are pages that can be mass produced, such as wiki pages, blog entries, and forum posts. They may have these extra defined properties:
|
188
|
+
|
189
|
+
# date
|
190
|
+
# categories
|
191
|
+
# tags
|
192
|
+
|
193
|
+
However, Pages can also have categories and tags and dates, but they are not used the same way as posts.
|
194
|
+
|
195
|
+
A major difference between pages and posts however is that Posts cannot be nested; Pages can be nested.
|
196
|
+
|
197
|
+
h3. So how do we define the difference between Pages and Posts in Broadway?
|
198
|
+
|
199
|
+
# Posts and Pages can be written with a date in their name: 2010-03-30-my-post.textile.
|
200
|
+
# Directories determine _some_ of the categories of Posts and Pages (you can define additional ones)
|
201
|
+
# Posts are basically subclasses of Page, which we can define in two ways:
|
202
|
+
## Placing Posts into the __posts_ directory
|
203
|
+
## Adding a @category@ to a Page called "post"
|
204
|
+
# Related Posts have the same layout, while related pages may have completely different layouts
|
205
|
+
|
206
|
+
So what we do is say, _all Posts are leaf items_. If a file is called @index.textile@, however, it is considered a Page for the corresponding directory. Thus, the following directory structure:
|
207
|
+
|
208
|
+
|-- overview
|
209
|
+
| |-- index.textile
|
210
|
+
| |-- screenshots.textile
|
211
|
+
| |-- performance.textile
|
212
|
+
|
213
|
+
...corresponds to this XML structure:
|
214
|
+
|
215
|
+
<pre><code>
|
216
|
+
<page url="/overview">
|
217
|
+
<post url="/overview/screenshots"/>
|
218
|
+
<post url="/overview/performance"/>
|
219
|
+
</page>
|
220
|
+
</code></pre>
|
221
|
+
|
222
|
+
...which corresponds to these ruby objects
|
223
|
+
|
224
|
+
<pre><code>
|
225
|
+
page = Page.new(:url => "/overview")
|
226
|
+
page.posts << Post.new(:url => "/overview/screenshots")
|
227
|
+
page.posts << Post.new(:url => "/overview/performance")
|
228
|
+
</pre></code>
|
229
|
+
|
230
|
+
Posts can have dates, categories, and tags, while pages can only have categories and tags.
|
231
|
+
|
232
|
+
h2. Post Properties
|
233
|
+
|
234
|
+
# title
|
235
|
+
# url
|
236
|
+
# has_one: image
|
237
|
+
# tooltip
|
238
|
+
# content
|
239
|
+
# description
|
240
|
+
# categories (directory)
|
241
|
+
# tags
|
242
|
+
# slug (identifier)
|
243
|
+
# published
|
244
|
+
# author
|
245
|
+
# comments
|
246
|
+
# attachments
|
247
|
+
|
248
|
+
h2. Attachment Properties
|
249
|
+
|
250
|
+
id - Integer
|
251
|
+
url - String
|
252
|
+
slug - String
|
253
|
+
title - String
|
254
|
+
description - String
|
255
|
+
caption - String
|
256
|
+
parent - Integer
|
257
|
+
mime_type - String
|
258
|
+
images - Object
|
259
|
+
|
260
|
+
- Go through public directory
|
261
|
+
- look for .xml and .textile/.markdown/.html
|
262
|
+
- Can go arbitrary levels deep
|
263
|
+
- Pages are for each directory
|
264
|
+
- if no page, then it will render an error page
|
265
|
+
- if index.haml, it will render that
|
266
|
+
- Posts are organized by category, which map directly to their directory
|
267
|
+
- Posts also have tags
|
268
|
+
- Themes can sort posts based on categories
|
269
|
+
- There is a global list of tags and categories
|
270
|
+
- Posts unique id is the slug
|
271
|
+
- posts can't be nested
|
272
|
+
- pages can't be nested, but the urls can be
|
273
|
+
- there are config files for random variables
|
274
|
+
- posts are stored into xml files by page (root level)
|
275
|
+
- posts can have 1 image, plus any random content in the post
|
276
|
+
- snippets are config items, which can be textile/markdown/html
|
277
|
+
|
278
|
+
If there is an index.xml in a folder, it is appended to the child matching that url node in the root index.xml file
|
279
|
+
- Content is either in XML, or in the index.textile file of a folder, or the name of the url dot textile.
|
280
|
+
- overview/index.textile
|
281
|
+
- overview.textile
|
282
|
+
- The Post (textile file) or XML node can specify the layout:
|
283
|
+
- <item layout="guides".../>
|
284
|
+
- layout: guides
|
285
|
+
If no layout is specified, it will check for these files:
|
286
|
+
- path/to/post/index.haml
|
287
|
+
- theme/path/index.haml
|
288
|
+
- error
|
289
|
+
|
290
|
+
h2. Defining Posts and Pages
|
291
|
+
|
292
|
+
Posts can be created in two ways: XML or text
|
293
|
+
|
294
|
+
h3. Posts from Text (HTML, Textile, Markdown)
|
295
|
+
|
296
|
+
Post objects are built out of the path to the file
|
297
|
+
|
298
|
+
h3. Posts from XML
|
299
|
+
|
300
|
+
Post objects are built out of everything in the XML. If the XML node is referencing a file outside of itself, then it falls into the first category.
|
data/Rakefile
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require "rake/rdoctask"
|
3
|
+
require 'rake/gempackagetask'
|
4
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), 'lib', 'broadway', 'base')
|
5
|
+
|
6
|
+
def files(path, from = __FILE__, &block)
|
7
|
+
Dir.glob(File.join(File.dirname(from), path)) {|file| yield file}
|
8
|
+
end
|
9
|
+
|
10
|
+
APP_ROOT = defined?(RAILS_ROOT) ? RAILS_ROOT : File.dirname(__FILE__)
|
11
|
+
RAILS_ROOT = File.dirname(__FILE__)
|
12
|
+
|
13
|
+
# http://docs.rubygems.org/read/chapter/20
|
14
|
+
spec = Gem::Specification.new do |s|
|
15
|
+
s.name = "broadway"
|
16
|
+
s.author = "Lance Pollard"
|
17
|
+
s.version = Broadway::VERSION
|
18
|
+
s.date = "Mon Mar 22 20:12:47 -0700 2010"
|
19
|
+
s.summary = "More than Syncing Rails Apps with the Google Data API"
|
20
|
+
s.homepage = "http://github.com/viatropos/broadway"
|
21
|
+
s.email = "lancejpollard@gmail.com"
|
22
|
+
s.description = "Broadway: A New Way of Googling"
|
23
|
+
s.has_rdoc = true
|
24
|
+
s.rubyforge_project = "broadway"
|
25
|
+
s.platform = Gem::Platform::RUBY
|
26
|
+
s.files = %w(README.textile Rakefile) +
|
27
|
+
Dir["{broadway,lib,spec}/**/*"] -
|
28
|
+
Dir["spec/tmp"]
|
29
|
+
s.extra_rdoc_files = %w(README.textile)
|
30
|
+
s.require_path = "lib"
|
31
|
+
s.add_dependency("nokogiri")
|
32
|
+
s.add_dependency("activesupport", ">= 2.3.5")
|
33
|
+
s.add_dependency("activerecord", ">= 2.3.5")
|
34
|
+
end
|
35
|
+
|
36
|
+
desc "Create .gemspec file (useful for github)"
|
37
|
+
task :gemspec do
|
38
|
+
File.open("#{spec.name}.gemspec", "w") do |f|
|
39
|
+
f.puts spec.to_ruby
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
desc "Build the gem into the current directory"
|
44
|
+
task :gem => :gemspec do
|
45
|
+
`gem build #{spec.name}.gemspec`
|
46
|
+
end
|
47
|
+
|
48
|
+
desc "Print a list of the files to be put into the gem"
|
49
|
+
task :manifest => :clean do
|
50
|
+
File.open("Manifest", "w") do |f|
|
51
|
+
spec.files.each do |file|
|
52
|
+
f.puts file
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
58
|
+
pkg.gem_spec = spec
|
59
|
+
end
|
60
|
+
|
61
|
+
desc "Install the gem locally"
|
62
|
+
task :install => [:package] do
|
63
|
+
sh %{sudo gem install pkg/broadway-#{Broadway::VERSION} --no-ri --no-rdoc}
|
64
|
+
end
|
65
|
+
|
66
|
+
desc "Generate the rdoc"
|
67
|
+
Rake::RDocTask.new do |rdoc|
|
68
|
+
files = ["README.textile", "lib/**/*.rb"]
|
69
|
+
rdoc.rdoc_files.add(files)
|
70
|
+
rdoc.main = "README.textile"
|
71
|
+
rdoc.title = "Broadway: A New Way of Googling"
|
72
|
+
end
|
73
|
+
|
74
|
+
desc "Run the rspec"
|
75
|
+
task :default => :spec
|
76
|
+
|
77
|
+
desc "Run Broadway Benchmarks"
|
78
|
+
task :benchmark do
|
79
|
+
files("spec/benchmarks/*") {|file| system("ruby #{file}") }
|
80
|
+
end
|
data/lib/broadway.rb
ADDED
data/lib/broadway/api.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
module Broadway
|
2
|
+
module API
|
3
|
+
|
4
|
+
def Post.to_xml(site)
|
5
|
+
xml = Nokogiri::XML::Builder.new { |xml|
|
6
|
+
xml.send("posts", :type => "array") {
|
7
|
+
site.posts.each do |post|
|
8
|
+
xml.post {
|
9
|
+
xml.title post.data["title"]
|
10
|
+
xml.url post.url
|
11
|
+
xml.categories post.categories.join(",")
|
12
|
+
xml.date(:type => "date") {
|
13
|
+
xml.text post.date.to_s
|
14
|
+
}
|
15
|
+
xml.slug post.slug
|
16
|
+
xml.published(:type => "boolean") {
|
17
|
+
xml.text post.published.to_s
|
18
|
+
}
|
19
|
+
xml.tags post.tags.join(",")
|
20
|
+
}
|
21
|
+
end
|
22
|
+
}
|
23
|
+
}
|
24
|
+
xml.to_xml
|
25
|
+
end
|
26
|
+
|
27
|
+
def Page.to_xml(site)
|
28
|
+
xml = Nokogiri::XML::Builder.new { |xml|
|
29
|
+
xml.send("pages", :type => "array") {
|
30
|
+
site.pages.each do |post|
|
31
|
+
xml.page {
|
32
|
+
xml.title post.data["title"]
|
33
|
+
xml.url post.url
|
34
|
+
xml.categories post.categories.join(",")
|
35
|
+
xml.date(:type => "date") {
|
36
|
+
xml.text post.date.to_s
|
37
|
+
}
|
38
|
+
xml.slug post.slug
|
39
|
+
xml.published(:type => "boolean") {
|
40
|
+
xml.text post.published.to_s
|
41
|
+
}
|
42
|
+
xml.tags post.tags.join(",")
|
43
|
+
}
|
44
|
+
end
|
45
|
+
}
|
46
|
+
}
|
47
|
+
xml.to_xml
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Broadway
|
2
|
+
|
3
|
+
class Asset
|
4
|
+
attr_accessor :url, :title, :tooltip, :thumb
|
5
|
+
|
6
|
+
def initialize(options = {})
|
7
|
+
options.each do |k,v|
|
8
|
+
self.send "#{k}=", v
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def inspect
|
13
|
+
"#<Broadway:Asset @url=#{self.url.inspect} @title=#{self.title.inspect}>"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|