brite 0.5 → 0.6.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/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
|
+
|