massimo 0.4.6 → 0.5.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/VERSION +1 -1
- data/bin/massimo +5 -3
- data/lib/massimo/cli.rb +101 -0
- data/lib/massimo/config.rb +56 -0
- data/lib/massimo/helpers.rb +12 -19
- data/lib/massimo/javascript.rb +18 -19
- data/lib/massimo/page.rb +63 -70
- data/lib/massimo/resource.rb +92 -0
- data/lib/massimo/server.rb +27 -0
- data/lib/massimo/site.rb +64 -101
- data/lib/massimo/stylesheet.rb +13 -35
- data/lib/massimo/view.rb +5 -32
- data/lib/massimo/watcher.rb +52 -0
- data/lib/massimo.rb +22 -31
- metadata +172 -117
- data/.document +0 -5
- data/.gitignore +0 -25
- data/Gemfile +0 -13
- data/Rakefile +0 -62
- data/lib/massimo/command.rb +0 -243
- data/lib/massimo/resource/base.rb +0 -74
- data/lib/massimo/resource/collection.rb +0 -56
- data/lib/massimo/resource/processing.rb +0 -67
- data/lib/massimo/templates.rb +0 -22
- data/massimo.gemspec +0 -135
- data/test/assertions.rb +0 -8
- data/test/helper.rb +0 -64
- data/test/source/config.yml +0 -4
- data/test/source/helpers/test_helper.rb +0 -5
- data/test/source/javascripts/_plugin.js +0 -1
- data/test/source/javascripts/application.js +0 -3
- data/test/source/javascripts/lib.js +0 -1
- data/test/source/lib/site.rb +0 -5
- data/test/source/pages/_skipped_page.haml +0 -0
- data/test/source/pages/about_us.erb +0 -5
- data/test/source/pages/erb.erb +0 -5
- data/test/source/pages/erb_with_layout.erb +0 -4
- data/test/source/pages/feed.haml +0 -6
- data/test/source/pages/haml.haml +0 -5
- data/test/source/pages/html.html +0 -4
- data/test/source/pages/index.erb +0 -4
- data/test/source/pages/markdown.markdown +0 -5
- data/test/source/pages/posts/first-post.haml +0 -1
- data/test/source/pages/with_extension.haml +0 -4
- data/test/source/pages/with_meta_data.haml +0 -7
- data/test/source/pages/with_title.haml +0 -4
- data/test/source/pages/with_url.haml +0 -4
- data/test/source/pages/without_extension.haml +0 -0
- data/test/source/pages/without_meta_data.haml +0 -1
- data/test/source/pages/without_title.haml +0 -1
- data/test/source/pages/without_url.haml +0 -1
- data/test/source/stylesheets/_base.sass +0 -2
- data/test/source/stylesheets/application.sass +0 -4
- data/test/source/stylesheets/basic.css +0 -3
- data/test/source/stylesheets/less_file.less +0 -5
- data/test/source/views/layouts/application.haml +0 -2
- data/test/source/views/with_helper.haml +0 -1
- data/test/source/views/with_locals.haml +0 -1
- data/test/source/views/without_locals.haml +0 -1
- data/test/test_helpers.rb +0 -25
- data/test/test_javascript.rb +0 -30
- data/test/test_page.rb +0 -142
- data/test/test_resource.rb +0 -70
- data/test/test_site.rb +0 -125
- data/test/test_stylesheet.rb +0 -40
- data/test/test_view.rb +0 -50
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.5.0
|
data/bin/massimo
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
4
|
-
require File.expand_path("../../lib/massimo/command", __FILE__)
|
3
|
+
$:.unshift File.expand_path('../../lib', __FILE__)
|
5
4
|
|
6
|
-
|
5
|
+
require 'massimo'
|
6
|
+
require 'massimo/cli'
|
7
|
+
|
8
|
+
Massimo::CLI.start
|
data/lib/massimo/cli.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'ostruct'
|
3
|
+
require 'thor'
|
4
|
+
|
5
|
+
module Massimo
|
6
|
+
class CLI < Thor
|
7
|
+
include Thor::Actions
|
8
|
+
|
9
|
+
default_task :build
|
10
|
+
class_option 'config', :desc => 'Path to the config file', :aliases => '-c'
|
11
|
+
class_option 'source_path', :desc => 'Path to the source dir', :aliases => '-s'
|
12
|
+
class_option 'output_path', :desc => 'Path to the output dir', :aliases => '-o'
|
13
|
+
|
14
|
+
desc 'build', 'Builds the site'
|
15
|
+
def build
|
16
|
+
site.process
|
17
|
+
say 'massimo has built your site'
|
18
|
+
end
|
19
|
+
map 'b' => :build
|
20
|
+
|
21
|
+
desc 'watch', 'Watches your files for changes and rebuilds'
|
22
|
+
def watch
|
23
|
+
begin
|
24
|
+
say 'massimo is watching your files for changes'
|
25
|
+
Massimo::Watcher.start(site)
|
26
|
+
rescue Interrupt
|
27
|
+
exit
|
28
|
+
end
|
29
|
+
end
|
30
|
+
map 'w' => :watch
|
31
|
+
|
32
|
+
desc 'server [PORT]', 'Runs a local web server and processes the site on save'
|
33
|
+
def server(port = 3000)
|
34
|
+
say "massimo is serving your site at http://localhost:#{port}"
|
35
|
+
Massimo::Server.start(site, port.to_i)
|
36
|
+
end
|
37
|
+
map 's' => :server
|
38
|
+
|
39
|
+
desc 'generate SITE_OR_RESOURCE [FILE]', 'Generates a new site. Optionally generates a resource file.'
|
40
|
+
method_option 'page_ext',
|
41
|
+
:desc => 'The extension used for generated Pages and Views',
|
42
|
+
:default => 'haml',
|
43
|
+
:aliases => '--page'
|
44
|
+
method_option 'javascript_ext',
|
45
|
+
:desc => 'The extension used for generated Javascripts',
|
46
|
+
:default => 'js',
|
47
|
+
:aliases => '--js'
|
48
|
+
method_option 'stylesheet_ext',
|
49
|
+
:desc => 'The extension used for generated Stylesheets',
|
50
|
+
:default => 'sass',
|
51
|
+
:aliases => '--css'
|
52
|
+
def generate(site_or_resource, file = nil)
|
53
|
+
require 'active_support/inflector'
|
54
|
+
|
55
|
+
if file
|
56
|
+
create_file File.join(site.config.path_for(resource.pluralize), file)
|
57
|
+
else
|
58
|
+
empty_directory site_or_resource
|
59
|
+
inside site_or_resource do
|
60
|
+
site.resources.each do |resource|
|
61
|
+
empty_directory(resource.path)
|
62
|
+
end
|
63
|
+
create_file File.join(Massimo::Page.path, "index.#{options[:page_ext]}")
|
64
|
+
create_file File.join(Massimo::Javascript.path, "main.#{options[:javascript_ext]}")
|
65
|
+
create_file File.join(Massimo::Stylesheet.path, "main.#{options[:stylesheet_ext]}")
|
66
|
+
create_file File.join(Massimo::View.path, "layouts/main.#{options[:page_ext]}")
|
67
|
+
empty_directory site.config.output_path
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
map 'g' => :generate
|
72
|
+
|
73
|
+
desc 'version', 'Displays current version'
|
74
|
+
def version
|
75
|
+
say Massimo::VERSION
|
76
|
+
end
|
77
|
+
map %w( -v --version ) => :version
|
78
|
+
|
79
|
+
protected
|
80
|
+
|
81
|
+
def site
|
82
|
+
@site ||= begin
|
83
|
+
site = Massimo::Site.new config_file(:yml)
|
84
|
+
if config_rb = config_file(:rb)
|
85
|
+
site.instance_eval File.read(config_rb)
|
86
|
+
end
|
87
|
+
site.config.source_path = options[:source_path] if options[:source_path]
|
88
|
+
site.config.output_path = options[:output_path] if options[:output_path]
|
89
|
+
site
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def config_file(ext)
|
94
|
+
if options[:config] && File.extname(options[:config]) == ".#{ext}"
|
95
|
+
options[:config]
|
96
|
+
elsif File.exist?("config.#{ext}")
|
97
|
+
"config.#{ext}"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'active_support/core_ext/hash/keys'
|
2
|
+
require 'ostruct'
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module Massimo
|
6
|
+
class Config < OpenStruct
|
7
|
+
DEFAULT_OPTIONS = {
|
8
|
+
:source_path => '.',
|
9
|
+
:output_path => 'public',
|
10
|
+
:resources_path => '.',
|
11
|
+
:resources_url => '/',
|
12
|
+
:javascripts_url => '/javascripts',
|
13
|
+
:stylesheets_url => '/stylesheets',
|
14
|
+
:resources_url => '/'
|
15
|
+
}.freeze
|
16
|
+
|
17
|
+
def initialize(options = nil)
|
18
|
+
hash = DEFAULT_OPTIONS.dup
|
19
|
+
|
20
|
+
options = YAML.load_file(options) if options.is_a?(String)
|
21
|
+
hash.merge!(options.symbolize_keys) if options.is_a?(Hash)
|
22
|
+
|
23
|
+
super hash
|
24
|
+
end
|
25
|
+
|
26
|
+
def source_path
|
27
|
+
File.expand_path(super)
|
28
|
+
end
|
29
|
+
|
30
|
+
def output_path
|
31
|
+
File.expand_path(super)
|
32
|
+
end
|
33
|
+
|
34
|
+
def path_for(resource_name)
|
35
|
+
path_method = "#{resource_name}_path"
|
36
|
+
if resource_path = (respond_to?(path_method) and send(path_method))
|
37
|
+
File.expand_path(resource_path)
|
38
|
+
else
|
39
|
+
File.join(source_path, resource_name.to_s)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def url_for(resource_name)
|
44
|
+
url_method = "#{resource_name}_url"
|
45
|
+
if resource_url = (respond_to?(url_method) and send(url_method))
|
46
|
+
resource_url
|
47
|
+
else
|
48
|
+
resources_url
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def files_in(resource_name, extension = '*')
|
53
|
+
Dir.glob(File.join(path_for(resource_name), "**/*.#{extension}"))
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/massimo/helpers.rb
CHANGED
@@ -1,28 +1,21 @@
|
|
1
|
-
|
1
|
+
require 'rack/utils' # needed for sinatra_more...
|
2
|
+
require 'sinatra_more/markup_plugin'
|
2
3
|
|
3
4
|
module Massimo
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
include SinatraMore::FormatHelpers
|
11
|
-
end
|
12
|
-
|
13
|
-
#
|
14
|
-
def initialize(modules = nil)
|
15
|
-
extend(*modules) unless modules.nil? || modules.empty?
|
16
|
-
end
|
5
|
+
module Helpers
|
6
|
+
include SinatraMore::OutputHelpers
|
7
|
+
include SinatraMore::TagHelpers
|
8
|
+
include SinatraMore::AssetTagHelpers
|
9
|
+
include SinatraMore::FormHelpers
|
10
|
+
include SinatraMore::FormatHelpers
|
17
11
|
|
18
|
-
# Gets the site instance
|
19
12
|
def site
|
20
|
-
Massimo
|
13
|
+
Massimo.site
|
21
14
|
end
|
22
15
|
|
23
|
-
|
24
|
-
|
25
|
-
|
16
|
+
def render(view_name, locals = {})
|
17
|
+
view = Massimo::View.find(view_name)
|
18
|
+
view && view.render(locals)
|
26
19
|
end
|
27
20
|
end
|
28
21
|
end
|
data/lib/massimo/javascript.rb
CHANGED
@@ -1,24 +1,23 @@
|
|
1
|
-
require "jsmin"
|
2
|
-
require "sprockets"
|
3
|
-
require "massimo/resource/base"
|
4
|
-
|
5
1
|
module Massimo
|
6
|
-
class Javascript < Massimo::Resource
|
7
|
-
processable!
|
8
|
-
|
9
|
-
# Concat the Javascript using Sprockets, then minify using JSmin
|
2
|
+
class Javascript < Massimo::Resource
|
10
3
|
def render
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
4
|
+
case source_path.extname.to_s
|
5
|
+
when '.coffee'
|
6
|
+
require 'coffee-script' unless defined?(CoffeeScript)
|
7
|
+
CoffeeScript.compile(content)
|
8
|
+
else
|
9
|
+
require 'sprockets' unless defined?(Sprockets)
|
10
|
+
secretary = Sprockets::Secretary.new(
|
11
|
+
:assert_root => Massimo.config.output_path,
|
12
|
+
:source_files => [ source_path.to_s ]
|
13
|
+
)
|
14
|
+
secretary.install_assets
|
15
|
+
secretary.concatenation.to_s
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def extension
|
20
|
+
@extension ||= '.js'
|
22
21
|
end
|
23
22
|
end
|
24
23
|
end
|
data/lib/massimo/page.rb
CHANGED
@@ -1,97 +1,90 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
1
|
+
require 'active_support/core_ext/hash/keys'
|
2
|
+
require 'active_support/inflector'
|
3
|
+
require 'tilt'
|
4
|
+
require 'yaml'
|
5
|
+
|
6
|
+
Tilt.register 'html', Tilt::StringTemplate
|
5
7
|
|
6
8
|
module Massimo
|
7
|
-
class Page <
|
8
|
-
|
9
|
+
class Page < Resource
|
10
|
+
def render
|
11
|
+
template = Tilt.new(source_path.basename.to_s, @line || 1) { content }
|
12
|
+
meta_data = @meta_data.merge(self.class.resource_name.singularize.to_sym => self)
|
13
|
+
output = template.render(Massimo.site.template_scope, meta_data)
|
14
|
+
if found_layout = Massimo::View.find("layouts/#{layout}")
|
15
|
+
output = found_layout.render(:page => self) { output }
|
16
|
+
end
|
17
|
+
output
|
18
|
+
end
|
9
19
|
|
10
|
-
|
20
|
+
def title
|
21
|
+
@meta_data[:title] ||= source_path.basename.to_s.chomp(source_path.extname.to_s).titleize
|
22
|
+
end
|
11
23
|
|
12
|
-
|
13
|
-
|
14
|
-
super(source_path, {
|
15
|
-
:title => File.basename(source_path).gsub(File.extname(source_path), "").titleize,
|
16
|
-
:extension => ".html",
|
17
|
-
:url => source_path.gsub(self.class.dir, "").gsub(File.extname(source_path), "").dasherize,
|
18
|
-
:layout => "application"
|
19
|
-
})
|
24
|
+
def extension
|
25
|
+
@meta_data[:extension] ||= '.html'
|
20
26
|
end
|
21
27
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
28
|
+
def url
|
29
|
+
@meta_data[:url] ||= begin
|
30
|
+
url = super
|
31
|
+
url.chomp!('index.html')
|
32
|
+
url.sub!(/\.html$/, '/')
|
33
|
+
url
|
27
34
|
end
|
28
|
-
output
|
29
35
|
end
|
30
36
|
|
31
|
-
|
32
|
-
|
33
|
-
|
37
|
+
def layout
|
38
|
+
@meta_data[:layout] = 'main' if @meta_data[:layout].nil?
|
39
|
+
@meta_data[:layout]
|
40
|
+
end
|
41
|
+
|
42
|
+
def output_path
|
43
|
+
@output_path ||= begin
|
44
|
+
output_path = super.to_s
|
45
|
+
output_path << "index.html" if output_path =~ /\/$/
|
46
|
+
Pathname.new output_path
|
47
|
+
end
|
34
48
|
end
|
35
49
|
|
36
50
|
protected
|
37
51
|
|
38
|
-
|
39
|
-
# `@body` attributes.
|
40
|
-
def read_source!
|
41
|
-
# read the source file and setup some values for the loop
|
42
|
-
source = super()
|
52
|
+
def read_source
|
43
53
|
@line = nil
|
54
|
+
@content = ''
|
44
55
|
front_matter = false
|
45
|
-
meta_data =
|
46
|
-
body = ""
|
56
|
+
meta_data = ''
|
47
57
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
front_matter = !front_matter
|
53
|
-
else
|
54
|
-
if front_matter
|
55
|
-
meta_data << line
|
58
|
+
source_path.open do |file|
|
59
|
+
file.each do |line|
|
60
|
+
if line =~ /\A---\s*\Z/
|
61
|
+
front_matter = !front_matter
|
56
62
|
else
|
57
|
-
|
58
|
-
|
63
|
+
if front_matter
|
64
|
+
meta_data << line
|
65
|
+
else
|
66
|
+
@line ||= file.lineno
|
67
|
+
@content << line
|
68
|
+
end
|
59
69
|
end
|
60
70
|
end
|
61
71
|
end
|
62
72
|
|
63
|
-
|
64
|
-
meta_data = YAML.load(meta_data)
|
65
|
-
@meta_data.merge!(meta_data.symbolize_keys) if meta_data
|
66
|
-
@body = body
|
73
|
+
@meta_data = (YAML.load(meta_data) || {}).symbolize_keys
|
67
74
|
end
|
68
75
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
76
|
+
def method_missing(method, *args, &block)
|
77
|
+
if args.length == 0
|
78
|
+
read_source
|
79
|
+
method_name = method.to_s
|
80
|
+
if method_name.chomp! '?'
|
81
|
+
!!@meta_data[method_name.to_sym]
|
82
|
+
else
|
83
|
+
@meta_data[method_name.to_sym]
|
84
|
+
end
|
85
|
+
else
|
86
|
+
super
|
79
87
|
end
|
80
88
|
end
|
81
|
-
|
82
|
-
# Determines if this is an index page
|
83
|
-
def index?
|
84
|
-
@source_path.basename.to_s =~ /^index/
|
85
|
-
end
|
86
|
-
|
87
|
-
# Determines if this an HTML page.
|
88
|
-
def html?
|
89
|
-
extension =~ /(html|php)$/
|
90
|
-
end
|
91
|
-
|
92
|
-
# Finds the Layout View if it exists
|
93
|
-
def find_layout
|
94
|
-
site.find_view("layouts/#{layout}") unless layout == false
|
95
|
-
end
|
96
89
|
end
|
97
90
|
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'active_support/inflector'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'pathname'
|
4
|
+
|
5
|
+
module Massimo
|
6
|
+
class Resource
|
7
|
+
class << self
|
8
|
+
def resource_name
|
9
|
+
self.name.underscore.sub(/.*\//, '').pluralize
|
10
|
+
end
|
11
|
+
|
12
|
+
def path
|
13
|
+
Massimo.config.path_for resource_name
|
14
|
+
end
|
15
|
+
|
16
|
+
def url
|
17
|
+
Massimo.config.url_for resource_name
|
18
|
+
end
|
19
|
+
|
20
|
+
def find(name)
|
21
|
+
resource_path = Dir.glob(File.join(path, "#{name}.*")).first
|
22
|
+
resource_path && self.new(resource_path)
|
23
|
+
end
|
24
|
+
|
25
|
+
def all
|
26
|
+
files = Massimo.config.files_in resource_name
|
27
|
+
files.reject! { |file| File.basename(file) =~ /^_/ }
|
28
|
+
files.map { |file| self.new(file) }
|
29
|
+
end
|
30
|
+
|
31
|
+
def processable?
|
32
|
+
true
|
33
|
+
end
|
34
|
+
|
35
|
+
protected
|
36
|
+
|
37
|
+
def unprocessable
|
38
|
+
def self.processable?; false; end
|
39
|
+
define_method(:process) { false }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
attr_reader :source_path, :content
|
44
|
+
|
45
|
+
def initialize(source)
|
46
|
+
@source_path = source.is_a?(Pathname) ? source.expand_path : Pathname.new(source).expand_path
|
47
|
+
read_source
|
48
|
+
end
|
49
|
+
|
50
|
+
def filename
|
51
|
+
@filename ||= source_path.basename.to_s
|
52
|
+
end
|
53
|
+
|
54
|
+
def extension
|
55
|
+
@extension ||= source_path.extname
|
56
|
+
end
|
57
|
+
|
58
|
+
def url
|
59
|
+
@url ||= begin
|
60
|
+
url = source_path.to_s.sub(/^#{Regexp.escape(self.class.path)}/, '')
|
61
|
+
url = url.sub(/\.[^\.]+$/, extension)
|
62
|
+
url = File.join(self.class.url, url) unless url.include? self.class.url
|
63
|
+
url = url.dasherize
|
64
|
+
url
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# The path to the output file.
|
69
|
+
def output_path
|
70
|
+
@output_path ||= Pathname.new File.join(Massimo.config.output_path, url)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Runs the content through any necessary filters, templates, etc.
|
74
|
+
def render
|
75
|
+
content
|
76
|
+
end
|
77
|
+
|
78
|
+
# Writes the rendered content to the output file.
|
79
|
+
def process
|
80
|
+
FileUtils.mkdir_p(output_path.dirname)
|
81
|
+
output_path.open('w') do |f|
|
82
|
+
f.write render
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
protected
|
87
|
+
|
88
|
+
def read_source
|
89
|
+
@content = source_path.read
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rack'
|
2
|
+
|
3
|
+
module Massimo
|
4
|
+
class Server
|
5
|
+
class << self
|
6
|
+
def start(site, port = 3000)
|
7
|
+
app = Rack::Builder.new do
|
8
|
+
use Rack::ShowExceptions
|
9
|
+
run Massimo::Server.new(site)
|
10
|
+
end
|
11
|
+
Rack::Handler::WEBrick.run(app, :Port => port)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(site)
|
16
|
+
@site = site
|
17
|
+
@file_server = Rack::File.new(site.config.output_path)
|
18
|
+
@watcher = Massimo::Watcher.new(site)
|
19
|
+
end
|
20
|
+
|
21
|
+
def call(env)
|
22
|
+
@watcher.process
|
23
|
+
env['PATH_INFO'] << 'index.html' if env['PATH_INFO'] =~ /\/$/
|
24
|
+
@file_server.call(env)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|