gumdrop 0.2.1
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/License +18 -0
- data/Readme.md +3 -0
- data/bin/gumdrop +11 -0
- data/lib/gumdrop.rb +81 -0
- data/lib/gumdrop/cli.rb +47 -0
- data/lib/gumdrop/content.rb +77 -0
- data/lib/gumdrop/context.rb +133 -0
- data/lib/gumdrop/generator.rb +6 -0
- data/lib/gumdrop/hash_object.rb +22 -0
- data/lib/gumdrop/server.rb +60 -0
- data/lib/gumdrop/template/Gemfile +18 -0
- data/lib/gumdrop/template/Rakefile +32 -0
- data/lib/gumdrop/template/config.ru +13 -0
- data/lib/gumdrop/template/data/config.yml +2 -0
- data/lib/gumdrop/template/lib/view_helpers.rb +7 -0
- data/lib/gumdrop/template/source/favicon.ico +0 -0
- data/lib/gumdrop/template/source/index.html.erb +1 -0
- data/lib/gumdrop/template/source/theme/screen.css.scss +3 -0
- data/lib/gumdrop/template/source/theme/scripts/app.js.coffee +0 -0
- data/lib/gumdrop/template/source/theme/styles/_tools.scss +384 -0
- data/lib/gumdrop/template/source/theme/templates/site.template.erb +25 -0
- data/lib/gumdrop/version.rb +5 -0
- data/lib/gumdrop/view_helpers.rb +26 -0
- metadata +86 -0
data/License
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
Copyright (C) 2011 by Matt McCray
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
data/Readme.md
ADDED
data/bin/gumdrop
ADDED
data/lib/gumdrop.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'tilt'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'active_support/all'
|
4
|
+
|
5
|
+
DEFAULT_OPTIONS= {
|
6
|
+
:cache_data => false,
|
7
|
+
:relative_paths => true,
|
8
|
+
:root => "."
|
9
|
+
}
|
10
|
+
|
11
|
+
module Gumdrop
|
12
|
+
|
13
|
+
class << self
|
14
|
+
|
15
|
+
attr_accessor :root_path, :source_path, :site, :layouts, :generators, :partials, :config
|
16
|
+
|
17
|
+
def run(opts={})
|
18
|
+
# Opts
|
19
|
+
Gumdrop.config.merge! opts
|
20
|
+
|
21
|
+
root= File.expand_path Gumdrop.config.root
|
22
|
+
src= File.join root, 'source'
|
23
|
+
if File.exists? "#{root}/lib/view_helpers.rb"
|
24
|
+
$: << "#{root}/lib"
|
25
|
+
require 'view_helpers'
|
26
|
+
end
|
27
|
+
|
28
|
+
@site= Hash.new {|h,k| h[k]= nil }
|
29
|
+
@layouts= Hash.new {|h,k| h[k]= nil }
|
30
|
+
@generators= Hash.new {|h,k| h[k]= nil }
|
31
|
+
@partials= Hash.new {|h,k| h[k]= nil }
|
32
|
+
@root_path= root.split '/'
|
33
|
+
@source_path= src.split '/'
|
34
|
+
|
35
|
+
# Scan
|
36
|
+
#puts "Running in: #{root}"
|
37
|
+
Dir["#{src}/**/*"].each do |path|
|
38
|
+
unless File.directory? path
|
39
|
+
file_path = (path.split('/') - @root_path).join '/'
|
40
|
+
node= Content.new(file_path)
|
41
|
+
@site[node.to_s]= node
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Layout
|
46
|
+
@site.keys.each do |path|
|
47
|
+
if File.extname(path) == ".template"
|
48
|
+
@layouts[File.basename(path)]= @site.delete(path)
|
49
|
+
elsif File.extname(path) == ".generator"
|
50
|
+
@generators[File.basename(path)]= @site.delete(path)
|
51
|
+
elsif File.basename(path).starts_with?("_")
|
52
|
+
@partials[File.basename(path)[1..-1]]= @site.delete(path)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Render
|
57
|
+
site.keys.each do |path|
|
58
|
+
node= site[path]
|
59
|
+
output_path= "output/#{node.to_s}"
|
60
|
+
FileUtils.mkdir_p File.dirname(output_path)
|
61
|
+
node.renderTo output_path
|
62
|
+
end
|
63
|
+
|
64
|
+
puts "Done."
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
base= File.dirname(__FILE__)
|
71
|
+
|
72
|
+
require "#{base}/gumdrop/hash_object.rb"
|
73
|
+
|
74
|
+
Gumdrop.config= Gumdrop::HashObject.new(DEFAULT_OPTIONS)
|
75
|
+
|
76
|
+
require "#{base}/gumdrop/version.rb"
|
77
|
+
require "#{base}/gumdrop/view_helpers.rb"
|
78
|
+
require "#{base}/gumdrop/context.rb"
|
79
|
+
require "#{base}/gumdrop/content.rb"
|
80
|
+
require "#{base}/gumdrop/server.rb"
|
81
|
+
require "#{base}/gumdrop/generator.rb"
|
data/lib/gumdrop/cli.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
|
2
|
+
require 'trollop'
|
3
|
+
|
4
|
+
opts = Trollop::options do
|
5
|
+
opt :verbose,"Verbose output"
|
6
|
+
opt :debug, "Enable debugging output"
|
7
|
+
opt :quiet, "No output"
|
8
|
+
opt :create, "Create a gumdrop project", :type=>String
|
9
|
+
opt :build, "Build HTML output"
|
10
|
+
opt :server, "Runs development server"
|
11
|
+
opt :port, "Specifies port to run server on", :type=>:int
|
12
|
+
end
|
13
|
+
|
14
|
+
# Trollop::die :volume, "must be non-negative" if opts[:volume] < 0
|
15
|
+
# Trollop::die :file, "must exist" unless File.exist?(opts[:file]) if opts[:file]
|
16
|
+
|
17
|
+
unless opts[:create_given] or opts[:build_given] or opts[:server_given]
|
18
|
+
Trollop::die "You must specify one of --create --build --server"
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
if opts[:create_given]
|
23
|
+
require 'fileutils'
|
24
|
+
here= File.dirname(__FILE__)
|
25
|
+
there= File.expand_path(opts[:create])
|
26
|
+
|
27
|
+
if File.file? there
|
28
|
+
puts "You cannot specify a file as the target!"
|
29
|
+
elsif !File.directory? there
|
30
|
+
FileUtils.mkdir_p there
|
31
|
+
end
|
32
|
+
|
33
|
+
FileUtils.cp_r Dir[File.join(here, "template", "*")], there
|
34
|
+
|
35
|
+
puts "Done."
|
36
|
+
|
37
|
+
elsif opts[:build_given]
|
38
|
+
Gumdrop.run(opts)
|
39
|
+
|
40
|
+
elsif opts[:server_given]
|
41
|
+
Gumdrop::Server.start(opts)
|
42
|
+
|
43
|
+
else
|
44
|
+
require 'pp'
|
45
|
+
puts "Unknown options"
|
46
|
+
pp opts
|
47
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
|
2
|
+
module Gumdrop
|
3
|
+
|
4
|
+
class Content
|
5
|
+
|
6
|
+
attr_accessor :path, :level, :filename, :source_filename, :type, :ext, :uri, :slug, :template
|
7
|
+
|
8
|
+
def initialize(path)
|
9
|
+
@path= path
|
10
|
+
@level= (@path.split('/').length - 2)
|
11
|
+
@source_filename= File.basename path
|
12
|
+
filename_parts= @source_filename.split('.')
|
13
|
+
@filename= filename_parts[0..1].join('.')
|
14
|
+
path_parts= @path.split('/')
|
15
|
+
path_parts.shift
|
16
|
+
path_parts.pop
|
17
|
+
path_parts.push @filename
|
18
|
+
@type= filename_parts.last
|
19
|
+
@ext= File.extname @filename
|
20
|
+
@uri= path_parts.join('/')
|
21
|
+
@slug=@uri.gsub('/', '-').gsub(@ext, '')
|
22
|
+
@template= unless Tilt[path].nil?
|
23
|
+
Tilt.new path
|
24
|
+
else
|
25
|
+
nil
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def render(ignore_layout=false, reset_context=true)
|
30
|
+
if reset_context
|
31
|
+
default_layout= (@ext == '.css' or @ext == '.js' or @ext == '.xml') ? nil : 'site'
|
32
|
+
Context.reset_data 'current_depth'=>@level, 'current_slug'=>@slug, 'page'=>self, 'layout'=>default_layout
|
33
|
+
end
|
34
|
+
content= @template.render(Context)
|
35
|
+
return content if ignore_layout
|
36
|
+
layout= Context.get_template()
|
37
|
+
while !layout.nil?
|
38
|
+
content = layout.template.render(Context, :content=>content)
|
39
|
+
layout= Context.get_template()
|
40
|
+
end
|
41
|
+
content
|
42
|
+
end
|
43
|
+
|
44
|
+
def renderTo(output_path, opts={})
|
45
|
+
return copyTo(output_path, opts) unless useLayout?
|
46
|
+
output= render()
|
47
|
+
File.open output_path, 'w' do |f|
|
48
|
+
puts " Rendering: #{@uri}"
|
49
|
+
f.write output
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def copyTo(output, layout=nil, opts={})
|
54
|
+
do_copy= if File.exists? output
|
55
|
+
!FileUtils.identical? @path, output
|
56
|
+
else
|
57
|
+
true
|
58
|
+
end
|
59
|
+
if do_copy
|
60
|
+
puts " Copying: #{@uri}"
|
61
|
+
FileUtils.cp_r @path, output, opts
|
62
|
+
else
|
63
|
+
puts " (same): #{@uri}"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def useLayout?
|
68
|
+
!@template.nil?
|
69
|
+
end
|
70
|
+
|
71
|
+
def to_s
|
72
|
+
@uri
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
def hashes2ostruct(object)
|
5
|
+
return case object
|
6
|
+
when Hash
|
7
|
+
object = object.clone
|
8
|
+
object.each do |key, value|
|
9
|
+
object[key] = hashes2ostruct(value)
|
10
|
+
end
|
11
|
+
OpenStruct.new(object)
|
12
|
+
when Array
|
13
|
+
object = object.clone
|
14
|
+
object.map! { |i| hashes2ostruct(i) }
|
15
|
+
else
|
16
|
+
object
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module Gumdrop
|
21
|
+
|
22
|
+
class DeferredLoader
|
23
|
+
attr_reader :cache
|
24
|
+
|
25
|
+
# def initialize
|
26
|
+
# puts "@!@"
|
27
|
+
# end
|
28
|
+
|
29
|
+
def method_missing(key, value=nil)
|
30
|
+
@cache= Hash.new {|h,k| h[k]= load_data(k) } if @cache.nil?
|
31
|
+
@cache[key]
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def load_data(key)
|
37
|
+
path=get_filename(key)
|
38
|
+
if File.extname(path) == ".yamldb"
|
39
|
+
docs=[]
|
40
|
+
File.open(path, 'r') do |f|
|
41
|
+
YAML.load_documents(f) do |doc|
|
42
|
+
docs << hashes2ostruct( doc )
|
43
|
+
end
|
44
|
+
end
|
45
|
+
docs
|
46
|
+
else
|
47
|
+
hashes2ostruct( YAML.load_file(path) )
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# TODO: Support './data/collection_name/*.(yaml|json)' data loading?
|
52
|
+
|
53
|
+
def get_filename(path)
|
54
|
+
if File.exists? "data/#{path}.json"
|
55
|
+
"data/#{path}.json"
|
56
|
+
elsif File.exists? "data/#{path}.yml"
|
57
|
+
"data/#{path}.yml"
|
58
|
+
elsif File.exists? "data/#{path}.yaml"
|
59
|
+
"data/#{path}.yaml"
|
60
|
+
elsif File.exists? "data/#{path}.yamldb"
|
61
|
+
"data/#{path}.yamldb"
|
62
|
+
else
|
63
|
+
raise "No data found for #{path}"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
module Context
|
69
|
+
class << self
|
70
|
+
|
71
|
+
include ::Gumdrop::ViewHelpers
|
72
|
+
|
73
|
+
attr_accessor :state
|
74
|
+
attr_reader :data
|
75
|
+
|
76
|
+
def uri(path)
|
77
|
+
if Gumdrop.config.relative_paths
|
78
|
+
"#{'../'*@state['current_depth']}#{path}"
|
79
|
+
else
|
80
|
+
"/#{path}"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def slug
|
85
|
+
@state['current_slug']
|
86
|
+
end
|
87
|
+
|
88
|
+
def get_template
|
89
|
+
layout= @state['layout']
|
90
|
+
@state['layout']= nil
|
91
|
+
unless layout.nil?
|
92
|
+
Gumdrop.layouts["#{layout}.template"]
|
93
|
+
else
|
94
|
+
nil
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def use_template(name)
|
99
|
+
@state['layout']= name
|
100
|
+
end
|
101
|
+
|
102
|
+
def render(path)
|
103
|
+
page= Gumdrop.site[path]
|
104
|
+
unless page.nil?
|
105
|
+
#TODO: nested state for an inline rendered page?
|
106
|
+
old_layout= @state['layout']
|
107
|
+
content= page.render(true, false)
|
108
|
+
old_layout= @state['layout']
|
109
|
+
content
|
110
|
+
else
|
111
|
+
""
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def reset_data(preset={})
|
116
|
+
# TODO: Add a setting for reloading data on every request/page
|
117
|
+
@data= DeferredLoader.new if @data.nil? or !Gumdrop.config.cache_data
|
118
|
+
@state = preset
|
119
|
+
end
|
120
|
+
|
121
|
+
def method_missing(name, value=nil)
|
122
|
+
@state= Hash.new {|h,k| h[k]= nil } if @state.nil?
|
123
|
+
unless value.nil?
|
124
|
+
@state[name]= value
|
125
|
+
else
|
126
|
+
@state[name]
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
|
133
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Gumdrop
|
2
|
+
|
3
|
+
class HashObject < ActiveSupport::HashWithIndifferentAccess
|
4
|
+
|
5
|
+
def method_missing(sym, *args, &block)
|
6
|
+
if self.has_key? sym
|
7
|
+
self[sym]
|
8
|
+
|
9
|
+
elsif sym.to_s.ends_with? '='
|
10
|
+
key= sym.to_s.chop.to_sym
|
11
|
+
self[key]= args[0]
|
12
|
+
|
13
|
+
else
|
14
|
+
# FIXME: Return super() or nil for Model#method_missing?
|
15
|
+
# super sym, *args, &block
|
16
|
+
nil
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Gumdrop
|
2
|
+
|
3
|
+
module Server
|
4
|
+
|
5
|
+
class << self
|
6
|
+
|
7
|
+
def start(opts={})
|
8
|
+
# Opts
|
9
|
+
opts.reverse_merge! :auto_run => true, :cache_data => false
|
10
|
+
Gumdrop.config.merge! opts
|
11
|
+
|
12
|
+
require 'sinatra'
|
13
|
+
|
14
|
+
set :port, Gumdrop.config.port if Gumdrop.config.port
|
15
|
+
|
16
|
+
get '/' do
|
17
|
+
redirect '/index.html'
|
18
|
+
end
|
19
|
+
|
20
|
+
get '/*' do
|
21
|
+
file_path= params[:splat].join('/')
|
22
|
+
matches= Dir["source/#{file_path}*"]
|
23
|
+
if matches.length > 0
|
24
|
+
|
25
|
+
Gumdrop.site = Gumdrop.layouts= Hash.new do |hash, key|
|
26
|
+
templates= Dir["source/**/#{key}*"]
|
27
|
+
if templates.length > 0
|
28
|
+
Content.new( templates[0] )
|
29
|
+
else
|
30
|
+
puts "NOT FOUND: #{key}"
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
content= Content.new matches[0]
|
36
|
+
if content.useLayout?
|
37
|
+
content_type :css if content.ext == '.css' # Meh?
|
38
|
+
content.render
|
39
|
+
else
|
40
|
+
send_file matches[0]
|
41
|
+
end
|
42
|
+
else
|
43
|
+
puts "NOT FOUND: #{file_path}"
|
44
|
+
"#{file_path} Not Found"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
if Gumdrop.config.auto_run
|
49
|
+
Sinatra::Application.run!
|
50
|
+
else
|
51
|
+
Sinatra::Application
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
|
3
|
+
gem "sinatra"
|
4
|
+
gem "active_support"
|
5
|
+
gem "i18n"
|
6
|
+
gem "rake"
|
7
|
+
gem "gumdrop", :git=>"git://github.com/darthapo/gumdrop.git"
|
8
|
+
|
9
|
+
#
|
10
|
+
# Add your dependencies here:
|
11
|
+
|
12
|
+
gem "sass"
|
13
|
+
gem "haml"
|
14
|
+
gem "coffee-script"
|
15
|
+
|
16
|
+
# gem "rdiscount"
|
17
|
+
# gem "less"
|
18
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require "bundler/setup"
|
3
|
+
require 'gumdrop'
|
4
|
+
|
5
|
+
# For the SYNC task
|
6
|
+
USER='user'
|
7
|
+
SERVER='server.com'
|
8
|
+
FOLDER="~/#{SERVER}"
|
9
|
+
|
10
|
+
|
11
|
+
task :default do
|
12
|
+
sh 'rake -T'
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "Build source files into output"
|
16
|
+
task :build do
|
17
|
+
Gumdrop.run()
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
desc "Run development server"
|
22
|
+
task :serve do
|
23
|
+
Gumdrop::Server.start()
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "Syncs with public server using rsync (if configured)"
|
27
|
+
task :sync do
|
28
|
+
cmd= "rsync -avz --delete output/ #{USER}@#{SERVER}:#{FOLDER}"
|
29
|
+
puts "Running:\n#{cmd}\n"
|
30
|
+
system(cmd)
|
31
|
+
puts "Done."
|
32
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
|
11
|
+
require 'gumdrop'
|
12
|
+
|
13
|
+
run Gumdrop::Server.start( :auto_run=>false)
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
<p>Welcome to <%= data.config.title %></p>
|
File without changes
|
@@ -0,0 +1,384 @@
|
|
1
|
+
// Layout Tools v 1.1
|
2
|
+
|
3
|
+
// Sample Usage:
|
4
|
+
// #container {
|
5
|
+
// @include border-radius(5px);
|
6
|
+
// }
|
7
|
+
|
8
|
+
// GRID
|
9
|
+
|
10
|
+
// = The 1Kb Grid = (slightly modified)
|
11
|
+
@mixin grid($columns:12, $column_width:60, $column_margin:20) {
|
12
|
+
.row, section {
|
13
|
+
overflow: hidden;
|
14
|
+
margin: 0 auto;
|
15
|
+
width: #{$columns * $column_width + $columns * $column_margin}px;
|
16
|
+
|
17
|
+
.row {
|
18
|
+
margin: 0 #{$column_margin - $column_margin * 1.5}px;
|
19
|
+
display: inline-block;
|
20
|
+
width: auto;
|
21
|
+
}
|
22
|
+
|
23
|
+
.col {
|
24
|
+
margin: 0 #{$column_margin / 2}px;
|
25
|
+
overflow: hidden;
|
26
|
+
float: left;
|
27
|
+
display: inline;
|
28
|
+
width: #{$column_width * 1 + $column_margin * (1 - 1)}px;
|
29
|
+
|
30
|
+
@for $i from 2 through $columns {
|
31
|
+
&.span-#{$i} {
|
32
|
+
width: #{$column_width * $i + $column_margin * ($i - 1)}px;
|
33
|
+
//&:hover
|
34
|
+
// outline: 1px solid red
|
35
|
+
}
|
36
|
+
}
|
37
|
+
}
|
38
|
+
}
|
39
|
+
}
|
40
|
+
|
41
|
+
// TEST
|
42
|
+
@mixin gridTest($columns:12, $column_width:60, $column_margin:20) {
|
43
|
+
row {
|
44
|
+
display: block;
|
45
|
+
overflow: hidden;
|
46
|
+
margin: 0 auto;
|
47
|
+
width: #{$columns * $column_width + $columns * $column_margin}px;
|
48
|
+
|
49
|
+
row {
|
50
|
+
margin: 0 #{$column_margin - $column_margin * 1.5}px;
|
51
|
+
display: inline-block;
|
52
|
+
width: auto;
|
53
|
+
}
|
54
|
+
|
55
|
+
col {
|
56
|
+
margin: 0 #{$column_margin / 2}px;
|
57
|
+
overflow: hidden;
|
58
|
+
float: left;
|
59
|
+
display: inline;
|
60
|
+
width: #{$column_width * 1 + $column_margin * (1 - 1)}px;
|
61
|
+
}
|
62
|
+
@for $i from 2 through $columns {
|
63
|
+
col#{$i} {
|
64
|
+
margin: 0 #{$column_margin / 2}px;
|
65
|
+
overflow: hidden;
|
66
|
+
float: left;
|
67
|
+
display: inline;
|
68
|
+
width: #{$column_width * $i + $column_margin * ($i - 1)}px;
|
69
|
+
//&:hover
|
70
|
+
// outline: 1px solid red
|
71
|
+
}
|
72
|
+
}
|
73
|
+
}
|
74
|
+
}
|
75
|
+
|
76
|
+
// CSS RESET
|
77
|
+
|
78
|
+
@mixin css-reset($boxmodel:'border-box') {
|
79
|
+
* {
|
80
|
+
@include box-model($boxmodel);
|
81
|
+
}
|
82
|
+
body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,textarea,p,blockquote,th,td {
|
83
|
+
margin:0;
|
84
|
+
padding:0;
|
85
|
+
}
|
86
|
+
article, aside, dialog, figure, footer, header, hgroup, menu, nav, section {
|
87
|
+
display: block;
|
88
|
+
}
|
89
|
+
table {
|
90
|
+
border-collapse:collapse;
|
91
|
+
border-spacing:0;
|
92
|
+
}
|
93
|
+
fieldset,img {
|
94
|
+
border:0;
|
95
|
+
}
|
96
|
+
address,caption,cite,code,dfn,em,strong,th,var {
|
97
|
+
font-style:normal;
|
98
|
+
font-weight:normal;
|
99
|
+
}
|
100
|
+
ol,ul {
|
101
|
+
list-style:none;
|
102
|
+
}
|
103
|
+
caption,th {
|
104
|
+
text-align:left;
|
105
|
+
}
|
106
|
+
h1,h2,h3,h4,h5,h6 {
|
107
|
+
font-size:100%;
|
108
|
+
font-weight:normal;
|
109
|
+
}
|
110
|
+
q:before,q:after {
|
111
|
+
content:'';
|
112
|
+
}
|
113
|
+
abbr,acronym {
|
114
|
+
border:0;
|
115
|
+
}
|
116
|
+
}
|
117
|
+
|
118
|
+
@mixin debug-hover($color:'red') {
|
119
|
+
&:hover {
|
120
|
+
outline: 1px solid $color;
|
121
|
+
}
|
122
|
+
}
|
123
|
+
|
124
|
+
|
125
|
+
// Vertical Background Gradient
|
126
|
+
@mixin vbg-gradient($fc: #FFF, $tc: #FFF) {
|
127
|
+
background: $fc;
|
128
|
+
background: -webkit-gradient(linear, left top, left bottom, from($fc), to($tc));
|
129
|
+
background: -moz-linear-gradient(top, $fc, $tc);
|
130
|
+
}
|
131
|
+
|
132
|
+
// Vertical Background Gradient, 3 color
|
133
|
+
@mixin vbg-gradient3($fc: #FFF, $mc: #FFF, $tc: #FFF) {
|
134
|
+
background: $fc;
|
135
|
+
background: -webkit-gradient(linear, left top, left bottom, from($fc), color-stop(0.5, $mc), to($tc));
|
136
|
+
background: -moz-linear-gradient(top, $fc, $mc, $tc);
|
137
|
+
}
|
138
|
+
|
139
|
+
// Horizontal Background Gradient
|
140
|
+
@mixin hbg-gradient($fc: #FFF, $tc: #FFF) {
|
141
|
+
background: $fc;
|
142
|
+
background: -webkit-gradient(linear, left top, right top, from($fc), to($tc));
|
143
|
+
background: -moz-linear-gradient(left, $fc, $tc);
|
144
|
+
}
|
145
|
+
|
146
|
+
|
147
|
+
// Box Model
|
148
|
+
@mixin box-model($type:'border-box') {
|
149
|
+
box-sizing: $type;
|
150
|
+
-moz-box-sizing: $type;
|
151
|
+
-ms-box-sizing: $type;
|
152
|
+
-webkit-box-sizing: $type;
|
153
|
+
}
|
154
|
+
|
155
|
+
@mixin hbox ($boxAlign:stretch, $boxPack:left) {
|
156
|
+
@include display-box();
|
157
|
+
@include box-orient(horizontal);
|
158
|
+
@include box-align($boxAlign);
|
159
|
+
@include box-pack($boxPack);
|
160
|
+
}
|
161
|
+
|
162
|
+
@mixin vbox ($boxAlign:stretch, $boxPack:left) {
|
163
|
+
@include display-box();
|
164
|
+
@include box-orient(vertical);
|
165
|
+
@include box-align($boxAlign);
|
166
|
+
@include box-pack($boxPack);
|
167
|
+
}
|
168
|
+
|
169
|
+
@mixin display-box () {
|
170
|
+
display: box;
|
171
|
+
display: -webkit-box;
|
172
|
+
display: -moz-box;
|
173
|
+
}
|
174
|
+
|
175
|
+
|
176
|
+
@mixin box-flex ($s: 0) {
|
177
|
+
box-flex: $s;
|
178
|
+
-webkit-box-flex: $s;
|
179
|
+
-moz-box-flex: $s;
|
180
|
+
}
|
181
|
+
|
182
|
+
|
183
|
+
@mixin box-orient($dir:horizontal) {
|
184
|
+
box-orient: $dir;
|
185
|
+
-webkit-box-orient: $dir;
|
186
|
+
-moz-box-orient: $dir;
|
187
|
+
}
|
188
|
+
|
189
|
+
@mixin box-pack($dir:left) {
|
190
|
+
box-pack: $dir;
|
191
|
+
-webkit-box-pack: $dir;
|
192
|
+
-moz-box-pack: $dir;
|
193
|
+
}
|
194
|
+
|
195
|
+
@mixin box-align($dir:stretch) {
|
196
|
+
box-align: $dir;
|
197
|
+
-webkit-box-align: $dir;
|
198
|
+
-moz-box-align: $dir;
|
199
|
+
}
|
200
|
+
|
201
|
+
@mixin box-lines($rows:single) {
|
202
|
+
box-lines: $rows;
|
203
|
+
-webkit-box-lines: $rows;
|
204
|
+
-moz-box-lines: $rows;
|
205
|
+
}
|
206
|
+
|
207
|
+
|
208
|
+
// SHADOWS
|
209
|
+
|
210
|
+
// TEXT shadow
|
211
|
+
@mixin text-shadow($props) {
|
212
|
+
text-shadow: $props;
|
213
|
+
-moz-text-shadow: $props;
|
214
|
+
-webkit-text-shadow: $props; }
|
215
|
+
|
216
|
+
// BOX shadow
|
217
|
+
@mixin box-shadow($props) {
|
218
|
+
box-shadow: $props;
|
219
|
+
-moz-box-shadow: $props;
|
220
|
+
-webkit-box-shadow: $props; }
|
221
|
+
|
222
|
+
@mixin inset-box-shadow ($h: 0px, $v: 0px, $b: 4px, $c: #333) {
|
223
|
+
box-shadow: inset $h $v $b $c;
|
224
|
+
-moz-box-shadow: inset $h $v $b $c;
|
225
|
+
-webkit-box-shadow: inset $h $v $b $c;
|
226
|
+
}
|
227
|
+
|
228
|
+
@mixin border-as-shadow($tlc:#000, $brc:#FFF, $width:1px, $style:solid) {
|
229
|
+
border: {
|
230
|
+
top: $width $style $tlc;
|
231
|
+
left: $width $style $tlc;
|
232
|
+
right: $width $style $brc;
|
233
|
+
bottom: $width $style $brc;
|
234
|
+
};
|
235
|
+
}
|
236
|
+
|
237
|
+
|
238
|
+
// BORDER RADIUS
|
239
|
+
|
240
|
+
// All corners
|
241
|
+
@mixin border-radius($radius) {
|
242
|
+
border-radius: $radius;
|
243
|
+
-moz-border-radius: $radius;
|
244
|
+
-webkit-border-radius: $radius; }
|
245
|
+
|
246
|
+
// Top Right
|
247
|
+
@mixin border-radius-top-right($radius) {
|
248
|
+
@include border-radius-top-right($radius); }
|
249
|
+
|
250
|
+
// Bottom Right
|
251
|
+
@mixin border-radius-bottom-right($radius) {
|
252
|
+
@include border-radius-bottom-right($radius); }
|
253
|
+
|
254
|
+
// Bottom Left
|
255
|
+
@mixin border-radius-bottom-left($radius) {
|
256
|
+
@include border-radius-bottom-left($radius); }
|
257
|
+
|
258
|
+
// Top Left
|
259
|
+
@mixin border-radius-top-left($radius) {
|
260
|
+
@include border-radius-top-left($radius); }
|
261
|
+
|
262
|
+
// Top
|
263
|
+
@mixin border-radius-top($radius) {
|
264
|
+
@include border-radius-top-left($radius);
|
265
|
+
@include border-radius-top-right($radius); }
|
266
|
+
|
267
|
+
// Right
|
268
|
+
@mixin border-radius-right($radius) {
|
269
|
+
@include border-radius-top-right($radius);
|
270
|
+
@include border-radius-bottom-right($radius); }
|
271
|
+
|
272
|
+
// Bottom
|
273
|
+
@mixin border-radius-bottom($radius) {
|
274
|
+
@include border-radius-bottom-right($radius);
|
275
|
+
@include border-radius-bottom-left($radius); }
|
276
|
+
|
277
|
+
// Left
|
278
|
+
@mixin border-radius-left($radius) {
|
279
|
+
@include border-radius-top-left($radius);
|
280
|
+
@include border-radius-bottom-left($radius); }
|
281
|
+
|
282
|
+
// Let's setup the rules so we don't have to repeat ourselves
|
283
|
+
// These are mixins for this mixin and are re-used above
|
284
|
+
@mixin border-radius-top-right($radius) {
|
285
|
+
border-top-right-radius: $radius;
|
286
|
+
-moz-border-radius-topright: $radius;
|
287
|
+
-webkit-border-top-right-radius: $radius; }
|
288
|
+
|
289
|
+
@mixin border-radius-bottom-right($radius) {
|
290
|
+
border-bottom-right-radius: $radius;
|
291
|
+
-moz-border-radius-bottomright: $radius;
|
292
|
+
-webkit-border-bottom-right-radius: $radius; }
|
293
|
+
|
294
|
+
@mixin border-radius-bottom-left($radius) {
|
295
|
+
border-bottom-left-radius: $radius;
|
296
|
+
-moz-border-radius-bottomleft: $radius;
|
297
|
+
-webkit-border-bottom-left-radius: $radius; }
|
298
|
+
|
299
|
+
@mixin border-radius-top-left($radius) {
|
300
|
+
border-top-left-radius: $radius;
|
301
|
+
-moz-border-radius-topleft: $radius;
|
302
|
+
-webkit-border-top-left-radius: $radius; }
|
303
|
+
|
304
|
+
@mixin animate($name, $dur:1s, $easing:ease-in-out, $iter:infinite, $dir:alternate) {
|
305
|
+
-webkit-animation-name: $name;
|
306
|
+
-webkit-animation-duration: $dur;
|
307
|
+
-webkit-animation-direction: $dir;
|
308
|
+
-webkit-animation-iteration-count: $iter;
|
309
|
+
-webkit-animation-timing-function: $easing;
|
310
|
+
}
|
311
|
+
|
312
|
+
@mixin transition($info:all 250 ease-out) {
|
313
|
+
-webkit-transition: $info;
|
314
|
+
-moz-transition: $info;
|
315
|
+
-o-transition: $info;
|
316
|
+
transition: $info;
|
317
|
+
}
|
318
|
+
|
319
|
+
@mixin transform( $s:'rotate(45deg)') {
|
320
|
+
-moz-transform: $s;
|
321
|
+
-webkit-transform: $s;
|
322
|
+
-o-transform: $s;
|
323
|
+
transform: $s;
|
324
|
+
}
|
325
|
+
|
326
|
+
@mixin box-attrs() {
|
327
|
+
*[box-flex="0"] { @include box-flex(0); }
|
328
|
+
*[box-flex="1"] { @include box-flex(1); }
|
329
|
+
*[box-flex="2"] { @include box-flex(2); }
|
330
|
+
*[box-flex="3"] { @include box-flex(3); }
|
331
|
+
*[box-flex="4"] { @include box-flex(4); }
|
332
|
+
*[box-flex="5"] { @include box-flex(5); }
|
333
|
+
*[box-flex="6"] { @include box-flex(6); }
|
334
|
+
*[box-flex="7"] { @include box-flex(7); }
|
335
|
+
*[box-flex="8"] { @include box-flex(8); }
|
336
|
+
*[box-flex="9"] { @include box-flex(9); }
|
337
|
+
*[box-flex="10"] { @include box-flex(10); }
|
338
|
+
|
339
|
+
*[box-align="start"] { @include box-align(start); }
|
340
|
+
*[box-align="center"] { @include box-align(center); }
|
341
|
+
*[box-align="end"] { @include box-align(end); }
|
342
|
+
*[box-align="baseline"] { @include box-align(baseline); }
|
343
|
+
*[box-align="stretch"] { @include box-align(stretch); }
|
344
|
+
|
345
|
+
*[box-pack="start"] { @include box-pack(start); }
|
346
|
+
*[box-pack="center"] { @include box-pack(center); }
|
347
|
+
*[box-pack="end"] { @include box-pack(end); }
|
348
|
+
*[box-pack="justify"] { @include box-pack(justify); }
|
349
|
+
*[box-pack="stretch"] { @include box-pack(justify); }
|
350
|
+
|
351
|
+
*[box-lines="single"] { @include box-lines(single); }
|
352
|
+
*[box-lines="multiple"] { @include box-lines(multiple); }
|
353
|
+
|
354
|
+
*[box-orient="horizontal"] { @include box-orient(horizontal); }
|
355
|
+
*[box-orient="vertical"] { @include box-orient(vertical); }
|
356
|
+
|
357
|
+
}
|
358
|
+
|
359
|
+
// Font stuff
|
360
|
+
|
361
|
+
@mixin web-font($family, $url, $format:'truetype') {
|
362
|
+
@font-face {
|
363
|
+
font-family: $family;
|
364
|
+
src: url($url) format($format);
|
365
|
+
}
|
366
|
+
}
|
367
|
+
|
368
|
+
// Color stuff
|
369
|
+
|
370
|
+
@function strengthen($color, $multiplier: 1, $reversed: $reversed-text) {
|
371
|
+
@if $reversed {
|
372
|
+
@return lighten($color, 20% * $multiplier);
|
373
|
+
} @else {
|
374
|
+
@return darken($color, 20% * $multiplier);
|
375
|
+
}
|
376
|
+
}
|
377
|
+
|
378
|
+
@function soften($color, $multiplier: 1, $reversed: $reversed-text) {
|
379
|
+
@if $reversed {
|
380
|
+
@return darken($color, 20% * $multiplier);
|
381
|
+
} @else {
|
382
|
+
@return lighten($color, 20% * $multiplier);
|
383
|
+
}
|
384
|
+
}
|
@@ -0,0 +1,25 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8" />
|
5
|
+
<title><%= data.config.title %></title>
|
6
|
+
<!--[if lt IE 9]>
|
7
|
+
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
8
|
+
<![endif]-->
|
9
|
+
<script type="text/javascript" src="<%= uri 'theme/scripts/app.js' %>"></script>
|
10
|
+
</head>
|
11
|
+
<body>
|
12
|
+
<header>
|
13
|
+
<h1><%= data.config.title %></h1>
|
14
|
+
<h4><%= data.config.tagline %></h4>
|
15
|
+
</header>
|
16
|
+
<nav></nav>
|
17
|
+
<article>
|
18
|
+
<section>
|
19
|
+
<%= content %>
|
20
|
+
</section>
|
21
|
+
</article>
|
22
|
+
<aside></aside>
|
23
|
+
<footer><%= copyright_years 2009 %></footer>
|
24
|
+
</body>
|
25
|
+
</html>
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Gumdrop
|
2
|
+
|
3
|
+
module ViewHelpers
|
4
|
+
|
5
|
+
# Calculate the years for a copyright
|
6
|
+
def copyright_years(start_year, divider="–")
|
7
|
+
end_year = Date.today.year
|
8
|
+
if start_year == end_year
|
9
|
+
"#{start_year}"
|
10
|
+
else
|
11
|
+
"#{start_year}#{divider}#{end_year}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# Handy for hiding a block of unfinished code
|
16
|
+
def hidden(&block)
|
17
|
+
#no-op
|
18
|
+
end
|
19
|
+
|
20
|
+
def gumdrop_version
|
21
|
+
::Gumdrop::VERSION
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gumdrop
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 2
|
8
|
+
- 1
|
9
|
+
version: 0.2.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Matt McCray
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2011-07-22 00:00:00 -05:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: A simple cms/prototyping tool.
|
22
|
+
email: matt@elucidata.net
|
23
|
+
executables:
|
24
|
+
- gumdrop
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files: []
|
28
|
+
|
29
|
+
files:
|
30
|
+
- bin/gumdrop
|
31
|
+
- lib/gumdrop/cli.rb
|
32
|
+
- lib/gumdrop/content.rb
|
33
|
+
- lib/gumdrop/context.rb
|
34
|
+
- lib/gumdrop/generator.rb
|
35
|
+
- lib/gumdrop/hash_object.rb
|
36
|
+
- lib/gumdrop/server.rb
|
37
|
+
- lib/gumdrop/template/config.ru
|
38
|
+
- lib/gumdrop/template/data/config.yml
|
39
|
+
- lib/gumdrop/template/Gemfile
|
40
|
+
- lib/gumdrop/template/lib/view_helpers.rb
|
41
|
+
- lib/gumdrop/template/Rakefile
|
42
|
+
- lib/gumdrop/template/source/favicon.ico
|
43
|
+
- lib/gumdrop/template/source/index.html.erb
|
44
|
+
- lib/gumdrop/template/source/theme/screen.css.scss
|
45
|
+
- lib/gumdrop/template/source/theme/scripts/app.js.coffee
|
46
|
+
- lib/gumdrop/template/source/theme/styles/_tools.scss
|
47
|
+
- lib/gumdrop/template/source/theme/templates/site.template.erb
|
48
|
+
- lib/gumdrop/version.rb
|
49
|
+
- lib/gumdrop/view_helpers.rb
|
50
|
+
- lib/gumdrop.rb
|
51
|
+
- License
|
52
|
+
- Readme.md
|
53
|
+
has_rdoc: true
|
54
|
+
homepage: https://github.com/darthapo/gumdrop
|
55
|
+
licenses: []
|
56
|
+
|
57
|
+
post_install_message:
|
58
|
+
rdoc_options: []
|
59
|
+
|
60
|
+
require_paths:
|
61
|
+
- lib
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
segments:
|
68
|
+
- 0
|
69
|
+
version: "0"
|
70
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
segments:
|
76
|
+
- 0
|
77
|
+
version: "0"
|
78
|
+
requirements: []
|
79
|
+
|
80
|
+
rubyforge_project: gumdrop
|
81
|
+
rubygems_version: 1.3.7
|
82
|
+
signing_key:
|
83
|
+
specification_version: 3
|
84
|
+
summary: A simple cms/prototyping tool.
|
85
|
+
test_files: []
|
86
|
+
|