massimo 0.3.9
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +25 -0
- data/LICENSE +20 -0
- data/README.md +108 -0
- data/Rakefile +62 -0
- data/VERSION +1 -0
- data/bin/massimo +6 -0
- data/lib/massimo/command.rb +242 -0
- data/lib/massimo/helpers.rb +26 -0
- data/lib/massimo/javascript.rb +38 -0
- data/lib/massimo/page.rb +113 -0
- data/lib/massimo/resource.rb +52 -0
- data/lib/massimo/site.rb +186 -0
- data/lib/massimo/stylesheet.rb +46 -0
- data/lib/massimo/templates.rb +20 -0
- data/lib/massimo/view.rb +30 -0
- data/lib/massimo.rb +38 -0
- data/massimo.gemspec +130 -0
- data/test/assertions.rb +8 -0
- data/test/helper.rb +54 -0
- data/test/source/config.yml +4 -0
- data/test/source/helpers/test_helper.rb +5 -0
- data/test/source/javascripts/_plugin.js +1 -0
- data/test/source/javascripts/application.js +3 -0
- data/test/source/javascripts/lib.js +1 -0
- data/test/source/lib/site.rb +5 -0
- data/test/source/pages/_skipped_page.haml +0 -0
- data/test/source/pages/about_us.erb +5 -0
- data/test/source/pages/erb.erb +5 -0
- data/test/source/pages/erb_with_layout.erb +4 -0
- data/test/source/pages/feed.haml +6 -0
- data/test/source/pages/haml.haml +5 -0
- data/test/source/pages/html.html +4 -0
- data/test/source/pages/index.erb +4 -0
- data/test/source/pages/markdown.markdown +5 -0
- data/test/source/pages/posts/first-post.haml +1 -0
- data/test/source/pages/with_extension.haml +4 -0
- data/test/source/pages/with_meta_data.haml +7 -0
- data/test/source/pages/with_title.haml +4 -0
- data/test/source/pages/with_url.haml +4 -0
- data/test/source/pages/without_extension.haml +0 -0
- data/test/source/pages/without_meta_data.haml +1 -0
- data/test/source/pages/without_title.haml +1 -0
- data/test/source/pages/without_url.haml +1 -0
- data/test/source/stylesheets/_base.sass +2 -0
- data/test/source/stylesheets/application.sass +4 -0
- data/test/source/stylesheets/basic.css +3 -0
- data/test/source/stylesheets/less_file.less +5 -0
- data/test/source/views/layouts/application.haml +2 -0
- data/test/source/views/with_helper.haml +1 -0
- data/test/source/views/with_locals.haml +1 -0
- data/test/source/views/without_locals.haml +1 -0
- data/test/test_javascript.rb +30 -0
- data/test/test_page.rb +136 -0
- data/test/test_resource.rb +27 -0
- data/test/test_site.rb +126 -0
- data/test/test_stylesheet.rb +40 -0
- data/test/test_view.rb +46 -0
- metadata +191 -0
data/.document
ADDED
data/.gitignore
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
## MAC OS
|
2
|
+
.DS_Store
|
3
|
+
|
4
|
+
## TEXTMATE
|
5
|
+
*.tmproj
|
6
|
+
tmtags
|
7
|
+
.eprj
|
8
|
+
|
9
|
+
## EMACS
|
10
|
+
*~
|
11
|
+
\#*
|
12
|
+
.\#*
|
13
|
+
|
14
|
+
## VIM
|
15
|
+
*.swp
|
16
|
+
|
17
|
+
## PROJECT::GENERAL
|
18
|
+
coverage
|
19
|
+
rdoc
|
20
|
+
pkg
|
21
|
+
doc
|
22
|
+
.yardoc
|
23
|
+
.sass-cache
|
24
|
+
|
25
|
+
## PROJECT::SPECIFIC
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Peter Browne
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
# Massimo
|
2
|
+
|
3
|
+
Massimo is a full static website generator. While making [Rails](http://rubyonrails.org/) websites I became dependent on [Haml](http://haml-lang.com/), [Sass](http://sass-lang.com/), and other useful gems. I wanted to use that workflow to rapidly make simple, static websites. Massimo's code is inspired by other website generators like [Jekyll](http://github.com/mojombo/jekyll) and [Webby](http://webby.rubyforge.org/). It's features include:
|
4
|
+
|
5
|
+
* It renders templates and views using [Tilt](http://github.com/rtomayko/tilt)
|
6
|
+
* It uses familiar helper methods from [Sinatra::More](http://github.com/nesquena/sinatra_more)
|
7
|
+
* It supports custom helper methods like [Rails](http://rubyonrails.org/) and [Sinatra](http://www.sinatrarb.com/)
|
8
|
+
* It concats javascripts using [Sprockets](http://getsprockets.org/)
|
9
|
+
and then minifies them using [JSMin](http://github.com/rgrove/jsmin)
|
10
|
+
* It renders stylesheets using either [Sass](http://sass-lang.com/) or [Less](http://lesscss.org/)
|
11
|
+
|
12
|
+
|
13
|
+
## Basic Usage
|
14
|
+
|
15
|
+
1. Setup the structure of the Site
|
16
|
+
2. Create some pages
|
17
|
+
3. Run you Site locally to see how it looks
|
18
|
+
4. Deploy your Site
|
19
|
+
|
20
|
+
### Structure
|
21
|
+
|
22
|
+
A basic Massimo Site looks something like this, though each directory's path can be customized:
|
23
|
+
|
24
|
+
.
|
25
|
+
|-- config.yml
|
26
|
+
|
|
27
|
+
|-- helpers
|
28
|
+
| `-- my_helpers.rb
|
29
|
+
|
|
30
|
+
|-- javascripts
|
31
|
+
| |-- _plugin.js
|
32
|
+
| `-- application.js
|
33
|
+
|
|
34
|
+
|-- lib
|
35
|
+
| `-- post.rb
|
36
|
+
|
|
37
|
+
|-- pages
|
38
|
+
| |-- index.haml
|
39
|
+
| |-- contact.haml
|
40
|
+
| `-- about-us.haml
|
41
|
+
|
|
42
|
+
|-- stylesheets
|
43
|
+
| |-- _base.sass
|
44
|
+
| `-- application.sass
|
45
|
+
|
|
46
|
+
|-- views
|
47
|
+
| |-- partial.haml
|
48
|
+
| `-- layouts
|
49
|
+
| `-- applcation.haml
|
50
|
+
|
|
51
|
+
`-- public
|
52
|
+
|
53
|
+
#### config.yml
|
54
|
+
|
55
|
+
This where you setup the options for the Site.
|
56
|
+
|
57
|
+
#### helpers
|
58
|
+
|
59
|
+
This is where you put helper modules (like Rails). This modules will automatically be available in your pages and views.
|
60
|
+
|
61
|
+
#### javascripts
|
62
|
+
|
63
|
+
This is where you put the working copies of your javascripts. They will be concatenated, minified, and moved to your output directory when the site is processed.
|
64
|
+
|
65
|
+
#### lib
|
66
|
+
|
67
|
+
This is where you put additional libraries. You can customize the default Massimo classes or add your own here. This is where you would add additional Tilt Templates.
|
68
|
+
|
69
|
+
#### pages
|
70
|
+
|
71
|
+
These are the actual pages (content) of your site. Anything here that is registered by a Tilt Template will be transformed into HTML and moved to the appropriate place in the output directory.
|
72
|
+
|
73
|
+
#### stylesheets
|
74
|
+
|
75
|
+
This is where you put the working copies of your stylesheets. If they are Sass or Less documents, they will be transformed into CSS documents then moved to your output directory.
|
76
|
+
|
77
|
+
#### views
|
78
|
+
|
79
|
+
This is where you put partials and layouts (like Rails). You can render partials from your pages by calling `render("partial_name")`.
|
80
|
+
|
81
|
+
### Running Massimo
|
82
|
+
|
83
|
+
Usually this is done through the massimo executable, which is installed with the gem. In order to get a server up and running with your Massimo site, run `massimo --server` and then browse to http://localhost:1984/. Or you could simply run `massimo --watch` to watch for changes and regenerate the site.
|
84
|
+
|
85
|
+
|
86
|
+
## YAML Front Matter
|
87
|
+
|
88
|
+
Pages can contain YAML front matter blocks for either predefined configuration options or custom variables. The front matter must be the first thing in the file and takes the form of:
|
89
|
+
|
90
|
+
---
|
91
|
+
title: Using YAML Front Matter
|
92
|
+
layout: false
|
93
|
+
---
|
94
|
+
|
95
|
+
## Note on Patches/Pull Requests
|
96
|
+
|
97
|
+
* Fork the project.
|
98
|
+
* Make your feature addition or bug fix.
|
99
|
+
* Add tests for it. This is important so I don't break it in a
|
100
|
+
future version unintentionally.
|
101
|
+
* Commit, do not mess with Rakefile, VERSION, or history.
|
102
|
+
(if you want to have your own version, that is fine but
|
103
|
+
bump version in a commit by itself I can ignore when I pull)
|
104
|
+
* Send me a pull request. Bonus points for topic branches.
|
105
|
+
|
106
|
+
## Copyright
|
107
|
+
|
108
|
+
Copyright (c) 2009 [Peter Browne](http://peterbrowne.net). See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "rake"
|
3
|
+
|
4
|
+
begin
|
5
|
+
require "jeweler"
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "massimo"
|
8
|
+
gem.summary = %{Massimo is a static website builder.}
|
9
|
+
gem.description = %{Massimo builds HTML, Javascript, and CSS Files from your source.}
|
10
|
+
gem.email = "peter@peterbrowne.net"
|
11
|
+
gem.homepage = "http://github.com/peterbrowne/massimo"
|
12
|
+
gem.authors = [ "Peter Browne" ]
|
13
|
+
gem.add_development_dependency "shoulda", ">= 2.10.2"
|
14
|
+
gem.add_development_dependency "yard", ">= 0.5.2"
|
15
|
+
gem.add_dependency "activesupport", ">= 2.3.5"
|
16
|
+
gem.add_dependency "sinatra_more", ">= 0.3.26"
|
17
|
+
gem.add_dependency "directory_watcher", ">= 1.3.1"
|
18
|
+
gem.add_dependency "sprockets", ">= 1.0.2"
|
19
|
+
gem.add_dependency "jsmin", ">= 1.0.1"
|
20
|
+
end
|
21
|
+
Jeweler::GemcutterTasks.new
|
22
|
+
rescue LoadError
|
23
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rake/testtask"
|
27
|
+
Rake::TestTask.new(:test) do |test|
|
28
|
+
test.libs << "lib" << "test"
|
29
|
+
test.pattern = "test/**/test_*.rb"
|
30
|
+
test.verbose = true
|
31
|
+
end
|
32
|
+
|
33
|
+
begin
|
34
|
+
require "rcov/rcovtask"
|
35
|
+
Rcov::RcovTask.new do |test|
|
36
|
+
test.libs << "test"
|
37
|
+
test.pattern = "test/**/test_*.rb"
|
38
|
+
test.verbose = true
|
39
|
+
end
|
40
|
+
rescue LoadError
|
41
|
+
task :rcov do
|
42
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
task :test => :check_dependencies
|
47
|
+
|
48
|
+
task :default => :test
|
49
|
+
|
50
|
+
desc "Open an irb session preloaded with this library"
|
51
|
+
task :console do
|
52
|
+
sh "irb -rubygems -I lib -r massimo.rb"
|
53
|
+
end
|
54
|
+
|
55
|
+
begin
|
56
|
+
require "yard"
|
57
|
+
YARD::Rake::YardocTask.new
|
58
|
+
rescue LoadError
|
59
|
+
task :yardoc do
|
60
|
+
abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
|
61
|
+
end
|
62
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.3.9
|
data/bin/massimo
ADDED
@@ -0,0 +1,242 @@
|
|
1
|
+
require "optparse"
|
2
|
+
require "active_support"
|
3
|
+
require "yaml"
|
4
|
+
begin require "growl"; rescue ::LoadError; end
|
5
|
+
|
6
|
+
module Massimo
|
7
|
+
class Command
|
8
|
+
attr_accessor :args, :options, :site, :source, :output
|
9
|
+
|
10
|
+
# Default options. Overriden by values in config.yml or command-line opts.
|
11
|
+
DEFAULT_OPTIONS = {
|
12
|
+
:config_path => ::File.join(".", "config.yml")
|
13
|
+
}.freeze
|
14
|
+
|
15
|
+
#
|
16
|
+
def initialize(args)
|
17
|
+
# Parse the command line arguments
|
18
|
+
self.args = args
|
19
|
+
self.options = DEFAULT_OPTIONS.dup
|
20
|
+
self.parse!
|
21
|
+
|
22
|
+
# Load the options from the config file
|
23
|
+
config = ::YAML.load_file(self.options[:config_path]) if ::File.exist?(self.options[:config_path])
|
24
|
+
self.options.merge!(config.symbolize_keys) if config.is_a?(::Hash)
|
25
|
+
|
26
|
+
# Initialize the Site
|
27
|
+
self.site = ::Massimo::Site(self.options)
|
28
|
+
self.options = self.site.options
|
29
|
+
self.source = self.options[:source]
|
30
|
+
self.output = self.options[:output]
|
31
|
+
|
32
|
+
# Setup Backtrace Cleaner
|
33
|
+
@cleaner = ::ActiveSupport::BacktraceCleaner.new
|
34
|
+
@cleaner.add_silencer { |line| line =~ /^(\/|\\)/ } # Remove full File path traces
|
35
|
+
end
|
36
|
+
|
37
|
+
# Run the script, based on the command line options.
|
38
|
+
def run!
|
39
|
+
if generate?
|
40
|
+
generate_layout!
|
41
|
+
elsif watch?
|
42
|
+
watch_source!
|
43
|
+
else
|
44
|
+
process_site!
|
45
|
+
end
|
46
|
+
run_server! if server?
|
47
|
+
return 0
|
48
|
+
rescue ::Interrupt
|
49
|
+
message "Massimo is done watching you.", :newline => true
|
50
|
+
return 0
|
51
|
+
rescue ::Exception => e
|
52
|
+
report_error(e)
|
53
|
+
return 1
|
54
|
+
end
|
55
|
+
|
56
|
+
protected
|
57
|
+
|
58
|
+
# Generate the default layout of the site.
|
59
|
+
def generate_layout!
|
60
|
+
require "fileutils"
|
61
|
+
message "Massimo is generating the default site layout"
|
62
|
+
[ site.source_dir, site.all_source_dirs, site.output_dir ].flatten.each do |dir|
|
63
|
+
full_dir = ::File.expand_path(dir)
|
64
|
+
if ::File.exists?(full_dir)
|
65
|
+
puts indent_body("exists: #{full_dir}")
|
66
|
+
else
|
67
|
+
::FileUtils.mkdir_p(full_dir)
|
68
|
+
puts indent_body("created: #{full_dir}")
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Watch the source for changes.
|
74
|
+
def watch_source!
|
75
|
+
require "directory_watcher"
|
76
|
+
|
77
|
+
message %{Massimo is watching "#{source}" for changes. Press Ctrl-C to Stop.}
|
78
|
+
|
79
|
+
watcher = ::DirectoryWatcher.new(
|
80
|
+
".",
|
81
|
+
:interval => 1,
|
82
|
+
:glob => site.all_source_dirs.collect { |dir| ::File.join(dir, *%w{** *}) }
|
83
|
+
)
|
84
|
+
|
85
|
+
watcher.add_observer do |*args|
|
86
|
+
begin
|
87
|
+
site.process!
|
88
|
+
time = ::Time.now.strftime("%H:%M")
|
89
|
+
change = args.size == 1 ? "1 file" : "#{args.size} files"
|
90
|
+
message "Massimo has rebuilt your site. #{change} changed. (#{time})"
|
91
|
+
rescue ::Exception => e
|
92
|
+
report_error(e)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
watcher.start
|
97
|
+
|
98
|
+
unless server?
|
99
|
+
loop { sleep 1000 }
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# Process the site.
|
104
|
+
def process_site!
|
105
|
+
site.process!
|
106
|
+
message %{Massimo has built your site in "#{site.options[:output]}"}
|
107
|
+
end
|
108
|
+
|
109
|
+
#
|
110
|
+
def run_server!
|
111
|
+
require "webrick"
|
112
|
+
|
113
|
+
# Make sure the output dir exists
|
114
|
+
::FileUtils.mkdir_p(output)
|
115
|
+
|
116
|
+
server = ::WEBrick::HTTPServer.new(
|
117
|
+
:Port => options[:server_port],
|
118
|
+
:DocumentRoot => output
|
119
|
+
)
|
120
|
+
|
121
|
+
trap(:INT) do
|
122
|
+
server.shutdown
|
123
|
+
message "Massimo is shutting down the server.", :newline => true
|
124
|
+
return 0
|
125
|
+
end
|
126
|
+
|
127
|
+
server.start
|
128
|
+
message "Massimo is serving up your site at http://localhost:#{options[:server_port]}/"
|
129
|
+
end
|
130
|
+
|
131
|
+
# Determine if we should watch the source directory for changes.
|
132
|
+
def watch?
|
133
|
+
options[:watch] == true
|
134
|
+
end
|
135
|
+
|
136
|
+
# Determine if we should generate the default layout of the site.
|
137
|
+
def generate?
|
138
|
+
options[:generate] == true
|
139
|
+
end
|
140
|
+
|
141
|
+
# Determine if the server should be started.
|
142
|
+
def server?
|
143
|
+
options[:server] == true
|
144
|
+
end
|
145
|
+
|
146
|
+
#
|
147
|
+
def message(string, options = {})
|
148
|
+
options.reverse_merge!(:growl => true)
|
149
|
+
puts "\n" if options[:newline]
|
150
|
+
puts "== #{string}"
|
151
|
+
::Growl.notify(string, :title => "Massimo") if options[:growl] && defined?(::Growl)
|
152
|
+
end
|
153
|
+
|
154
|
+
# Report the given error. This could eventually log the backtrace.
|
155
|
+
def report_error(error = nil)
|
156
|
+
error ||= $!
|
157
|
+
|
158
|
+
# Show full backtrace if verbose
|
159
|
+
backtrace = if options[:verbose]
|
160
|
+
error.backtrace
|
161
|
+
else
|
162
|
+
@cleaner.clean(error.backtrace)
|
163
|
+
end
|
164
|
+
|
165
|
+
# show the message
|
166
|
+
message "Massimo Error:", :newline => true, :growl => false
|
167
|
+
puts indent_body(error.message)
|
168
|
+
puts indent_body(backtrace)
|
169
|
+
puts "\n"
|
170
|
+
|
171
|
+
# Format the message differently for growl
|
172
|
+
::Growl.notify(error.message, :title => "Massimo Error") if defined?(::Growl)
|
173
|
+
end
|
174
|
+
|
175
|
+
# Returns the string with each line indented.
|
176
|
+
def indent_body(string)
|
177
|
+
string.collect { |line| " #{line}" }
|
178
|
+
end
|
179
|
+
|
180
|
+
# Parse the options
|
181
|
+
def parse!
|
182
|
+
opts = ::OptionParser.new do |opts|
|
183
|
+
opts.banner = <<-HELP
|
184
|
+
Massimo is a static website builder.
|
185
|
+
|
186
|
+
Basic Command Line Usage:
|
187
|
+
massimo # . -> ./public
|
188
|
+
massimo <path to write generated site> # . -> <path>
|
189
|
+
massimo <path to source> <path to write generated site> # <path> -> <path>
|
190
|
+
|
191
|
+
Configuration is read from "<source>/config.yml" but can be overriden
|
192
|
+
using the following options:
|
193
|
+
|
194
|
+
HELP
|
195
|
+
|
196
|
+
opts.on("--config [PATH]", "The path to the config file.") do |path|
|
197
|
+
options[:config_path] = path
|
198
|
+
end
|
199
|
+
|
200
|
+
opts.on("--generate", "Generate the default layout of the site.") do
|
201
|
+
options[:generate] = true
|
202
|
+
end
|
203
|
+
|
204
|
+
opts.on("--watch", "Auto-regenerate the site as files are changed.") do
|
205
|
+
options[:watch] = true
|
206
|
+
end
|
207
|
+
|
208
|
+
opts.on("--server", "Start web server with default port.") do |port|
|
209
|
+
options[:server] = true
|
210
|
+
end
|
211
|
+
|
212
|
+
opts.on("--port [PORT]", "Select the port to start the web server on. Defaults to 1984") do |port|
|
213
|
+
options[:server_port] = port
|
214
|
+
end
|
215
|
+
|
216
|
+
opts.on("--verbose", "-v", "Show full backtrace on errors. Defaults to false.") do
|
217
|
+
options[:verbose] = true
|
218
|
+
end
|
219
|
+
|
220
|
+
opts.on("--version", "-V", "Display current version") do
|
221
|
+
puts "Massimo #{::Massimo::VERSION}"
|
222
|
+
exit 0
|
223
|
+
end
|
224
|
+
end
|
225
|
+
opts.parse!
|
226
|
+
|
227
|
+
# Get source and destintation from command line
|
228
|
+
case args.size
|
229
|
+
when 0
|
230
|
+
when 1
|
231
|
+
options[:source] = args[0]
|
232
|
+
when 2
|
233
|
+
options[:source] = args[0]
|
234
|
+
options[:output] = args[1]
|
235
|
+
else
|
236
|
+
puts %{Invalid options. Run "massimo --help" for assistance.}
|
237
|
+
exit 1
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
end
|
242
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Massimo
|
2
|
+
class Helpers
|
3
|
+
if defined? ::SinatraMore
|
4
|
+
include ::SinatraMore::OutputHelpers
|
5
|
+
include ::SinatraMore::TagHelpers
|
6
|
+
include ::SinatraMore::AssetTagHelpers
|
7
|
+
include ::SinatraMore::FormHelpers
|
8
|
+
include ::SinatraMore::FormatHelpers
|
9
|
+
end
|
10
|
+
|
11
|
+
#
|
12
|
+
def initialize(modules = nil)
|
13
|
+
self.extend(*modules) unless modules.nil? || modules.empty?
|
14
|
+
end
|
15
|
+
|
16
|
+
# Gets the site instance
|
17
|
+
def site
|
18
|
+
::Massimo::Site()
|
19
|
+
end
|
20
|
+
|
21
|
+
#
|
22
|
+
def render(name, locals = {}, &block)
|
23
|
+
self.site.render_view(name, locals, &block)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Massimo
|
2
|
+
class Javascript < Resource
|
3
|
+
# Concat the Javascript using Sprockets, then minify using JSmin
|
4
|
+
def render
|
5
|
+
secretary = ::Sprockets::Secretary.new(
|
6
|
+
:assert_root => self.site.output_dir,
|
7
|
+
:source_files => [ @source_path.to_s ]
|
8
|
+
)
|
9
|
+
# install assets if necessary
|
10
|
+
secretary.install_assets
|
11
|
+
|
12
|
+
if self.site.production? or self.site.options[:minify]
|
13
|
+
# minify the concatenated javascript
|
14
|
+
::JSMin.minify(secretary.concatenation.to_s)
|
15
|
+
else
|
16
|
+
secretary.concatenation.to_s
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Writes the rendered js to the output file.
|
21
|
+
def process!
|
22
|
+
# Make the full path to the directory of the output file
|
23
|
+
::FileUtils.mkdir_p(self.output_path.dirname)
|
24
|
+
# write the filtered data to the output file
|
25
|
+
self.output_path.open("w") do |file|
|
26
|
+
file.write self.render
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
protected
|
31
|
+
|
32
|
+
# Determine the output file path
|
33
|
+
def output_path
|
34
|
+
@output_path ||= ::Pathname.new(@source_path.to_s.
|
35
|
+
sub(self.site.source_dir, self.site.output_dir)) # move to output dir
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/massimo/page.rb
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
module Massimo
|
2
|
+
class Page < View
|
3
|
+
META_SEP = %r/\A---\s*(?:\r\n|\n)?\z/ # :nodoc:
|
4
|
+
|
5
|
+
# Creates a new page associated with the given file path.
|
6
|
+
def initialize(source_path)
|
7
|
+
@source_path = ::Pathname.new(source_path)
|
8
|
+
@meta_data = {
|
9
|
+
:title => @source_path.basename.to_s.gsub(@source_path.extname, "").titleize,
|
10
|
+
:extension => ".html",
|
11
|
+
:url => @source_path.to_s.gsub(self.site.pages_dir, "").gsub(@source_path.extname, "").dasherize,
|
12
|
+
:layout => "application"
|
13
|
+
}
|
14
|
+
# read and parse the source file
|
15
|
+
self.read_source!
|
16
|
+
end
|
17
|
+
|
18
|
+
# Override render to wrap the result in the layout
|
19
|
+
def render(with_layout = true)
|
20
|
+
if with_layout && layout = self.find_layout
|
21
|
+
layout.render(:page => self) { self.render(false) }
|
22
|
+
else
|
23
|
+
super()
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Writes the filtered data to the output file.
|
28
|
+
def process!
|
29
|
+
refresh_layout
|
30
|
+
path = self.output_path
|
31
|
+
# Make the full path to the directory of the output file
|
32
|
+
::FileUtils.mkdir_p(path.dirname)
|
33
|
+
# write the filtered data to the output file
|
34
|
+
path.open("w") do |file|
|
35
|
+
file.write self.render(self.layout?)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Override to_s so that the layout can include the page with <%= page %>
|
40
|
+
def to_s
|
41
|
+
self.render(false)
|
42
|
+
end
|
43
|
+
|
44
|
+
protected
|
45
|
+
|
46
|
+
# Reads the source page file, and populates the meta_data and
|
47
|
+
# body attributes.
|
48
|
+
def read_source!
|
49
|
+
# read the source file and setup some values for the loop
|
50
|
+
source = super()
|
51
|
+
@line = nil
|
52
|
+
front_matter = false
|
53
|
+
meta_data = ""
|
54
|
+
body = ""
|
55
|
+
|
56
|
+
# Loop through source to get meta data
|
57
|
+
# and the correct line number for the body
|
58
|
+
source.each_with_index do |line, line_num|
|
59
|
+
if line =~ META_SEP
|
60
|
+
front_matter = !front_matter
|
61
|
+
else
|
62
|
+
if front_matter
|
63
|
+
meta_data << line
|
64
|
+
else
|
65
|
+
@line ||= line_num
|
66
|
+
body << line
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# finally get the meta_data as a hash and set the body
|
72
|
+
meta_data = ::YAML.load(meta_data)
|
73
|
+
@meta_data.merge!(meta_data.symbolize_keys) if meta_data
|
74
|
+
@body = body
|
75
|
+
end
|
76
|
+
|
77
|
+
# Determine the output file path
|
78
|
+
def output_path
|
79
|
+
path = self.site.output_dir(self.url)
|
80
|
+
path << if index? or not html?
|
81
|
+
self.extension unless path.match(/#{self.extension}$/)
|
82
|
+
else
|
83
|
+
"/index.html" unless path.match(/\/index\.html$/)
|
84
|
+
end
|
85
|
+
::Pathname.new(path)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Determines if this is an index page
|
89
|
+
def index?
|
90
|
+
@source_path.basename.to_s =~ /^index/
|
91
|
+
end
|
92
|
+
|
93
|
+
# Determines if this an HTML page.
|
94
|
+
def html?
|
95
|
+
self.extension =~ /(html|php)$/
|
96
|
+
end
|
97
|
+
|
98
|
+
# The next time `find_layout` is called, the layout will be reloaded.
|
99
|
+
def refresh_layout
|
100
|
+
@layout_view = nil
|
101
|
+
end
|
102
|
+
|
103
|
+
# Determines if there's a layout associated with this page.
|
104
|
+
def layout?
|
105
|
+
self.layout != false && !self.find_layout.nil?
|
106
|
+
end
|
107
|
+
|
108
|
+
# Finds the Layout View if it exists
|
109
|
+
def find_layout
|
110
|
+
@layout_view ||= self.site.find_view("layouts/#{self.layout}") unless self.layout == false
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|