brite 0.5 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY.rdoc +30 -0
- data/LICENSE +199 -17
- data/README.rdoc +61 -0
- data/Syckfile +76 -0
- data/bin/brite +3 -3
- data/bin/brite-server +4 -0
- data/lib/brite.rb +11 -0
- data/lib/brite/command.rb +53 -56
- data/lib/brite/config.rb +94 -18
- data/lib/brite/controller.rb +181 -0
- data/lib/brite/layout.rb +24 -19
- data/lib/brite/meta/data.rb +26 -0
- data/lib/brite/meta/package +8 -0
- data/lib/brite/meta/profile +19 -0
- data/lib/brite/models/model.rb +97 -0
- data/lib/brite/models/page.rb +142 -0
- data/lib/brite/models/post.rb +9 -0
- data/lib/brite/models/site.rb +46 -0
- data/lib/brite/rackup.rb +6 -0
- data/lib/brite/server.rb +144 -0
- data/lib/plugins/sow/brite/awesome/Sowfile +11 -0
- data/lib/plugins/sow/brite/awesome/about.page +28 -0
- data/lib/plugins/sow/brite/awesome/assets/custom.less +96 -0
- data/lib/plugins/sow/brite/awesome/assets/fade.png +0 -0
- data/lib/plugins/sow/brite/awesome/assets/highlight.css +96 -0
- data/lib/plugins/sow/brite/awesome/assets/highlight.js +1 -0
- data/lib/plugins/sow/brite/awesome/assets/jquery.js +19 -0
- data/lib/plugins/sow/brite/awesome/assets/jquery.tabs.js +1 -0
- data/lib/plugins/sow/brite/awesome/assets/reset.css +57 -0
- data/lib/plugins/sow/brite/awesome/assets/ruby.png +0 -0
- data/lib/plugins/sow/brite/awesome/brite.yaml +3 -0
- data/lib/plugins/sow/brite/awesome/history.page +15 -0
- data/lib/plugins/sow/brite/awesome/index.page +18 -0
- data/lib/plugins/sow/brite/awesome/legal.page +28 -0
- data/lib/plugins/sow/brite/awesome/logs.page +14 -0
- data/lib/plugins/sow/brite/awesome/page.layout +75 -0
- data/lib/plugins/sow/brite/blog1/.rsync-filter +12 -0
- data/lib/plugins/sow/brite/blog1/2011/01/sample.html +293 -0
- data/lib/plugins/sow/brite/blog1/2011/01/sample.post +44 -0
- data/lib/plugins/sow/brite/blog1/Sowfile +10 -0
- data/lib/plugins/sow/brite/blog1/assets/images/bg.jpg +0 -0
- data/lib/plugins/sow/brite/blog1/assets/images/icon.jpg +0 -0
- data/lib/plugins/sow/brite/blog1/assets/styles/class.css +15 -0
- data/lib/plugins/sow/brite/blog1/assets/styles/id.css +85 -0
- data/lib/plugins/sow/brite/blog1/assets/styles/misc.css +0 -0
- data/lib/plugins/sow/brite/blog1/assets/styles/print.css +76 -0
- data/lib/plugins/sow/brite/blog1/assets/styles/reset.css +77 -0
- data/lib/plugins/sow/brite/blog1/assets/styles/tag.css +68 -0
- data/lib/plugins/sow/brite/blog1/brite.yml +3 -0
- data/lib/plugins/sow/brite/blog1/index.page +23 -0
- data/lib/plugins/sow/brite/blog1/page.layout +88 -0
- data/lib/plugins/sow/brite/blog1/post.layout +25 -0
- data/meta/data.rb +26 -0
- data/meta/package +8 -0
- data/meta/profile +19 -0
- metadata +86 -47
- data/HISTORY +0 -16
- data/MANIFEST +0 -28
- data/README +0 -42
- data/lib/brite/page.rb +0 -235
- data/lib/brite/part.rb +0 -31
- data/lib/brite/post.rb +0 -37
- data/lib/brite/site.rb +0 -137
- data/lib/brite/template.rb +0 -215
- data/meta/authors +0 -1
- data/meta/contact +0 -1
- data/meta/copyright +0 -1
- data/meta/description +0 -4
- data/meta/homepage +0 -1
- data/meta/license +0 -1
- data/meta/name +0 -1
- data/meta/repository +0 -1
- data/meta/requires +0 -1
- data/meta/ruby +0 -2
- data/meta/subtitle +0 -1
- data/meta/suite +0 -1
- data/meta/summary +0 -1
- data/meta/title +0 -1
- data/meta/version +0 -1
data/lib/brite/config.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'yaml'
|
1
2
|
require 'ostruct'
|
2
3
|
|
3
4
|
module Brite
|
@@ -5,26 +6,101 @@ module Brite
|
|
5
6
|
# Configuration
|
6
7
|
class Config
|
7
8
|
|
8
|
-
#
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
9
|
+
# Configuration file name glob.
|
10
|
+
CONFIG_FILE = '{.brite,brite.yml,brite.yaml}'
|
11
|
+
|
12
|
+
# Default URL, which is just for testing purposes.
|
13
|
+
DEFAULT_URL = 'http://0.0.0.0:4321'
|
14
|
+
|
15
|
+
# Default stencil.
|
16
|
+
DEFAULT_STENCIL = 'rhtml' #'liquid' # 'rhtml'
|
17
|
+
|
18
|
+
# Default format.
|
19
|
+
DEFAULT_FORMAT = nil #html
|
20
|
+
|
21
|
+
# Default page layout file name (less `.layout` extension).
|
22
|
+
DEFAULT_PAGE_LAYOUT = 'page'
|
23
|
+
|
24
|
+
# Default post layout file name (less `.layout` extension).
|
25
|
+
DEFAULT_POST_LAYOUT = 'post'
|
26
|
+
|
27
|
+
# Location of brite files.
|
28
|
+
attr :location
|
29
|
+
|
30
|
+
# Site's absolute URL. Where possible links are relative,
|
31
|
+
# but it is not alwasy possible. So a URL should *ALWAYS*
|
32
|
+
# be provided for the site.
|
33
|
+
#--
|
34
|
+
# TODO: Allow +url+ to be set via the command line when generating the site.
|
35
|
+
#++
|
36
|
+
attr_accessor :url
|
37
|
+
|
38
|
+
# Defaut section template engine.
|
39
|
+
attr_accessor :stencil
|
40
|
+
|
41
|
+
# Default section markup format.
|
42
|
+
attr_accessor :format
|
43
|
+
|
44
|
+
# Default page layout file name (less extension).
|
45
|
+
attr_accessor :page_layout
|
46
|
+
|
47
|
+
# Default post layout file name (less extension).
|
48
|
+
attr_accessor :post_layout
|
49
|
+
|
50
|
+
# New instance of Config.
|
51
|
+
def initialize(location=nil)
|
52
|
+
@location = location || Dir.pwd
|
53
|
+
|
54
|
+
@url = DEFAULT_URL
|
55
|
+
@stencil = DEFAULT_STENCIL
|
56
|
+
@format = DEFAULT_FORMAT
|
57
|
+
|
58
|
+
@page_layout = DEFAULT_PAGE_LAYOUT
|
59
|
+
@post_layout = DEFAULT_POST_LAYOUT
|
60
|
+
|
61
|
+
configure
|
62
|
+
end
|
63
|
+
|
64
|
+
# Load configuration file.
|
65
|
+
def configure
|
66
|
+
if file = Dir[File.join(location, CONFIG_FILE)].first
|
67
|
+
data = YAML.load(File.new(file))
|
68
|
+
data.each do |k,v|
|
69
|
+
__send__("#{k}=", v)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
#def initialize_defaults
|
75
|
+
# if file = Dir['{.,}config/defaults{,.yml,.yaml}'].first
|
76
|
+
# custom_defaults = YAML.load(File.new(file))
|
77
|
+
# else
|
78
|
+
# custom_defaults = {}
|
79
|
+
# end
|
80
|
+
# @defaults = OpenStruct.new(DEFAULTS.merge(custom_defaults))
|
81
|
+
#end
|
82
|
+
|
83
|
+
# FIXME: Is this used? What about page vs pagelayout?
|
84
|
+
#def defaults
|
85
|
+
# @defaults ||= OpenStruct.new(
|
86
|
+
# :stencil => stencil,
|
87
|
+
# :format => format,
|
88
|
+
# :pagelayout => page,
|
89
|
+
# :postlayout => post
|
90
|
+
# )
|
91
|
+
#end
|
92
|
+
|
93
|
+
# Use Gemdo.
|
94
|
+
def gemdo=(set)
|
95
|
+
return unless set
|
96
|
+
require 'gemdo'
|
97
|
+
Brite::Context.class_eval do
|
98
|
+
def project
|
99
|
+
@project ||= Gemdo::Project.new
|
100
|
+
end
|
24
101
|
end
|
25
|
-
@defaults = OpenStruct.new(DEFAULTS.merge(custom_defaults))
|
26
102
|
end
|
103
|
+
|
27
104
|
end
|
28
105
|
|
29
106
|
end
|
30
|
-
|
@@ -0,0 +1,181 @@
|
|
1
|
+
require 'neapolitan'
|
2
|
+
require 'brite/config'
|
3
|
+
require 'brite/layout'
|
4
|
+
require 'brite/models/site'
|
5
|
+
require 'brite/models/page'
|
6
|
+
require 'brite/models/post'
|
7
|
+
|
8
|
+
module Brite
|
9
|
+
|
10
|
+
# The Controller class is the primary Brite class, handling
|
11
|
+
# the generation of site files.
|
12
|
+
class Controller
|
13
|
+
|
14
|
+
# New Controller.
|
15
|
+
def initialize(options={})
|
16
|
+
@location = options[:location] || Dir.pwd
|
17
|
+
@output = options[:output]
|
18
|
+
@url = options[:url]
|
19
|
+
@dryrun = options[:dryrun]
|
20
|
+
@trace = options[:trace]
|
21
|
+
|
22
|
+
@layouts = []
|
23
|
+
|
24
|
+
initialize_site
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns an instance of Site.
|
28
|
+
def initialize_site
|
29
|
+
@site = Site.new(:url=>url)
|
30
|
+
|
31
|
+
Dir.chdir(location) do
|
32
|
+
files = Dir['**/*']
|
33
|
+
files.each do |file|
|
34
|
+
name = File.basename(file)
|
35
|
+
ext = File.extname(file)
|
36
|
+
case ext
|
37
|
+
when '.layout'
|
38
|
+
layouts << Layout.new(self, file)
|
39
|
+
when '.page' #*%w{.markdown .rdoc .textile .whtml}
|
40
|
+
@site.pages << initialize_page(file)
|
41
|
+
when '.post'
|
42
|
+
@site.posts << initialize_post(file)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
@site.posts.sort!{ |a,b| b.date <=> a.date }
|
47
|
+
@site
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns an instance of Page.
|
51
|
+
#++
|
52
|
+
# TODO: Limit Neapolitan to Markup formats only.
|
53
|
+
#--
|
54
|
+
def initialize_page(file)
|
55
|
+
template = Neapolitan.file(file, :stencil=>config.stencil)
|
56
|
+
settings = template.header
|
57
|
+
|
58
|
+
settings[:site] = site
|
59
|
+
settings[:file] = file
|
60
|
+
|
61
|
+
Page.new(settings){ |page| render(template, page) }
|
62
|
+
end
|
63
|
+
|
64
|
+
# Returns an instance of Post.
|
65
|
+
def initialize_post(file)
|
66
|
+
template = Neapolitan.file(file, :stencil=>config.stencil)
|
67
|
+
settings = template.header
|
68
|
+
|
69
|
+
settings[:site] = site
|
70
|
+
settings[:file] = file
|
71
|
+
|
72
|
+
Post.new(settings){ |post| render(template, post) }
|
73
|
+
end
|
74
|
+
|
75
|
+
# Returns an instance of Site.
|
76
|
+
attr :site
|
77
|
+
|
78
|
+
#
|
79
|
+
attr :location
|
80
|
+
|
81
|
+
#
|
82
|
+
attr :output
|
83
|
+
|
84
|
+
# Is `dryrun` mode on?
|
85
|
+
def dryrun?
|
86
|
+
@dryrun
|
87
|
+
end
|
88
|
+
|
89
|
+
# Is `trace` mode on?
|
90
|
+
def trace?
|
91
|
+
@trace
|
92
|
+
end
|
93
|
+
|
94
|
+
# Returns an Array of Layouts.
|
95
|
+
def layouts
|
96
|
+
@layouts
|
97
|
+
end
|
98
|
+
|
99
|
+
# Access to configuration file data.
|
100
|
+
def config
|
101
|
+
@config ||= Config.new(location)
|
102
|
+
end
|
103
|
+
|
104
|
+
# URL of site as set in initializer or configuration file.
|
105
|
+
def url
|
106
|
+
@url ||= config.url
|
107
|
+
end
|
108
|
+
|
109
|
+
#
|
110
|
+
def render(template, model) #scope=nil, &body)
|
111
|
+
#if scope
|
112
|
+
# scope.merge!(attributes)
|
113
|
+
#else
|
114
|
+
# scope = to_scope
|
115
|
+
#end
|
116
|
+
|
117
|
+
render = template.render(model) #, &body)
|
118
|
+
|
119
|
+
model.summary = render.summary # TODO: make part of neapolitan?
|
120
|
+
|
121
|
+
result = render.to_s
|
122
|
+
|
123
|
+
if model.layout
|
124
|
+
layout = lookup_layout(model.layout)
|
125
|
+
raise "No such layout -- #{layout}" unless layout
|
126
|
+
result = layout.render(model){ result }
|
127
|
+
end
|
128
|
+
|
129
|
+
result.to_s.strip
|
130
|
+
end
|
131
|
+
|
132
|
+
# Lookup layout by name.
|
133
|
+
def lookup_layout(name)
|
134
|
+
layouts.find{ |layout| name == layout.name }
|
135
|
+
end
|
136
|
+
|
137
|
+
# Build site.
|
138
|
+
def build
|
139
|
+
if trace?
|
140
|
+
puts "Layouts: " + layouts.map{ |layout| layout.name }.join(", ")
|
141
|
+
puts "Pages: " + pages.map{ |page| page.file }.join(", ")
|
142
|
+
puts "Posts: " + posts.map{ |post| post.file }.join(", ")
|
143
|
+
puts
|
144
|
+
end
|
145
|
+
Dir.chdir(location) do
|
146
|
+
site.posts.each do |post|
|
147
|
+
save(post)
|
148
|
+
end
|
149
|
+
site.pages.each do |page|
|
150
|
+
save(page)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
puts "#{site.pages.size + site.posts.size} Files: #{site.pages.size} Pages, #{site.posts.size} Posts"
|
154
|
+
end
|
155
|
+
|
156
|
+
# Save page/post redering to disk.
|
157
|
+
def save(model)
|
158
|
+
file = output ? File.join(output, model.output) : model.output
|
159
|
+
text = model.to_s
|
160
|
+
|
161
|
+
if File.exist?(file)
|
162
|
+
current = File.read(file)
|
163
|
+
else
|
164
|
+
current = nil
|
165
|
+
end
|
166
|
+
|
167
|
+
if current != text or $FORCE
|
168
|
+
if dryrun?
|
169
|
+
puts " dry run: #{file}"
|
170
|
+
else
|
171
|
+
puts " write: #{file}"
|
172
|
+
File.open(file, 'w'){ |f| f << text }
|
173
|
+
end
|
174
|
+
else
|
175
|
+
puts " unchanged: #{file}"
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
end
|
180
|
+
|
181
|
+
end
|
data/lib/brite/layout.rb
CHANGED
@@ -1,34 +1,39 @@
|
|
1
1
|
module Brite
|
2
2
|
|
3
3
|
# Layout class
|
4
|
-
class Layout
|
5
|
-
undef_method :save
|
6
|
-
|
7
|
-
#def to_contextual_attributes
|
8
|
-
# { 'site'=>site.to_h }
|
9
|
-
#end
|
4
|
+
class Layout
|
10
5
|
|
11
6
|
#
|
12
|
-
def
|
13
|
-
|
14
|
-
|
7
|
+
def initialize(controller, file)
|
8
|
+
@controller = controller
|
9
|
+
@file = file
|
10
|
+
@name = file.chomp('.layout')
|
11
|
+
@path = File.expand_path(file)
|
12
|
+
end
|
13
|
+
|
14
|
+
attr :controller
|
15
|
+
|
16
|
+
attr :file
|
15
17
|
|
16
|
-
|
18
|
+
attr :path
|
17
19
|
|
18
|
-
|
20
|
+
attr :name
|
19
21
|
|
20
|
-
|
22
|
+
# TODO: merge in layout header
|
23
|
+
def render(model, &content)
|
24
|
+
template = Neapolitan.file(path, :stencil=>controller.config.stencil)
|
25
|
+
|
26
|
+
result = template.render(model, &content).to_s
|
27
|
+
|
28
|
+
layout = template.header['layout']
|
21
29
|
|
22
30
|
if layout
|
23
|
-
|
31
|
+
layout = controller.lookup_layout(layout)
|
32
|
+
raise "No such layout -- #{layout}" unless layout
|
33
|
+
result = layout.render(model){ result }
|
24
34
|
end
|
25
35
|
|
26
|
-
|
27
|
-
end
|
28
|
-
|
29
|
-
# Layouts have no default layout.
|
30
|
-
def default_layout
|
31
|
-
nil
|
36
|
+
result.to_s
|
32
37
|
end
|
33
38
|
|
34
39
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Brite
|
2
|
+
|
3
|
+
def self.package
|
4
|
+
@package ||= (
|
5
|
+
require 'yaml'
|
6
|
+
YAML.load(File.new(File.dirname(__FILE__) + '/package'))
|
7
|
+
)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.profile
|
11
|
+
@profile ||= (
|
12
|
+
require 'yaml'
|
13
|
+
YAML.load(File.new(File.dirname(__FILE__) + '/profile'))
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.const_missing(name)
|
18
|
+
key = name.to_s.downcase
|
19
|
+
package[key] || profile[key] || super(name)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
# becuase Ruby 1.8~ gets in the way
|
25
|
+
Object.__send__(:remove_const, :VERSION) if Object.const_defined?(:VERSION)
|
26
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
---
|
2
|
+
title : Brite
|
3
|
+
subtitle : Light Up Your Site
|
4
|
+
summary : Super Simple Static Site Generation
|
5
|
+
copyright: Copyright (c) 2006,2009 Thomas Sawyer
|
6
|
+
license : Apache v2.0
|
7
|
+
suite : proutils
|
8
|
+
contact : http://googlegroups.com/group/proutils
|
9
|
+
authors : Thomas Sawyer
|
10
|
+
|
11
|
+
description:
|
12
|
+
Brite is a remarkably easy to use, light-weight website
|
13
|
+
generator. It supports a variety of backend rendering engines
|
14
|
+
including rhtml via eruby, textile via redcloth, markdown
|
15
|
+
via rdiscount, with others on the way.
|
16
|
+
|
17
|
+
resources:
|
18
|
+
homepage: http://proutils.github.com/brite
|
19
|
+
repository: git://github.com/proutils/brite.git
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module Brite
|
2
|
+
|
3
|
+
#
|
4
|
+
class Model
|
5
|
+
|
6
|
+
# Designate a field to be omitted from rendering context.
|
7
|
+
def self.omit_field(name)
|
8
|
+
omit_fields << (RUBY_VERSION >= "1.9" ? name.to_sym : name.to_s)
|
9
|
+
end
|
10
|
+
|
11
|
+
# Returns an Array of omitted fields for this class.
|
12
|
+
def self.omit_fields
|
13
|
+
@omit_fields ||= []
|
14
|
+
end
|
15
|
+
|
16
|
+
#
|
17
|
+
def self.attr_accessor(name, &default)
|
18
|
+
name = name.to_sym
|
19
|
+
if default
|
20
|
+
define_method(name) do
|
21
|
+
value = instance_variable_get("@#{name}") || instance_eval(&default)
|
22
|
+
(class << self; self; end).class_eval do
|
23
|
+
define_method(name){ value }
|
24
|
+
end
|
25
|
+
value
|
26
|
+
end
|
27
|
+
else
|
28
|
+
attr_reader(name)
|
29
|
+
end
|
30
|
+
attr_writer(name)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Define a singleton method for given key-value pair.
|
34
|
+
def []=(k,v)
|
35
|
+
(class << self; self; end).class_eval do
|
36
|
+
define_method(k){v}
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns a Binding for this instance.
|
41
|
+
def to_binding(&block)
|
42
|
+
binding
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns a Hash of rendering fields.
|
46
|
+
def to_h
|
47
|
+
hash = {}
|
48
|
+
fields = rendering_fields
|
49
|
+
fields.each do |field|
|
50
|
+
hash[field.to_s] = __send__(field)
|
51
|
+
end
|
52
|
+
#extra.each do |k,v|
|
53
|
+
# hash[k.to_s] == v
|
54
|
+
#end
|
55
|
+
hash
|
56
|
+
end
|
57
|
+
|
58
|
+
# In case Liquid template is used.
|
59
|
+
def to_liquid
|
60
|
+
to_h
|
61
|
+
end
|
62
|
+
|
63
|
+
# Returns an Array of attribute/method names to be visible to the page
|
64
|
+
# rendering.
|
65
|
+
def rendering_fields
|
66
|
+
list = public_methods
|
67
|
+
list -= Model.public_instance_methods
|
68
|
+
list -= omit_fields
|
69
|
+
list.select do |name|
|
70
|
+
case name.to_s
|
71
|
+
when /\W+/ then false
|
72
|
+
when /^to_/ then false
|
73
|
+
else
|
74
|
+
true
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# Returns an Array of attribute/method names explicitly omitted from
|
80
|
+
# being visible from the rendering.
|
81
|
+
def omit_fields
|
82
|
+
list = []
|
83
|
+
self.class.ancestors.reverse_each do |ancestor|
|
84
|
+
list.concat(ancestor.omit_fields) if ancestor.respond_to?(:omit_fields)
|
85
|
+
end
|
86
|
+
list
|
87
|
+
end
|
88
|
+
|
89
|
+
#
|
90
|
+
def singleton_class
|
91
|
+
(class << self; self; end)
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|