scharfie-bones 0.1.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/README +38 -0
- data/bin/bones +22 -0
- data/bones.gemspec +37 -0
- data/lib/Rakefile +3 -0
- data/lib/bones.rb +193 -0
- data/lib/boot.rb +34 -0
- data/lib/cache.rb +105 -0
- data/lib/extensions.rb +26 -0
- data/lib/helpers/core_helper.rb +140 -0
- data/lib/init.rb +70 -0
- data/lib/pages/directory.html.erb +5 -0
- data/lib/pages/intro.html.erb +28 -0
- data/lib/server.rb +42 -0
- data/lib/tasks/bones.rb +28 -0
- metadata +85 -0
data/README
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
Bones, the simple HTML mockup framework.
|
2
|
+
|
3
|
+
What it does:
|
4
|
+
|
5
|
+
- Provides a simple framework for creating views
|
6
|
+
without worrying about controllers
|
7
|
+
- Allows the building of a complete static website
|
8
|
+
out of views, partials, and layouts which can
|
9
|
+
then be combined into full HTML pages for deployment
|
10
|
+
onto ANY webserver.
|
11
|
+
|
12
|
+
Requirements:
|
13
|
+
|
14
|
+
- ActiveSupport
|
15
|
+
- rack
|
16
|
+
|
17
|
+
Starting it up:
|
18
|
+
|
19
|
+
- Install
|
20
|
+
sudo gem install scharfie-bones -s http://gems.github.com
|
21
|
+
|
22
|
+
- Generate:
|
23
|
+
bones my_bones_app
|
24
|
+
cd my_bones_app
|
25
|
+
|
26
|
+
- Serve
|
27
|
+
rake server
|
28
|
+
|
29
|
+
- Browse:
|
30
|
+
http://localhost:3000
|
31
|
+
|
32
|
+
Flatten your views into .html files:
|
33
|
+
|
34
|
+
- Cache with our without versioning
|
35
|
+
rake cache:simple # without versioning
|
36
|
+
rake cache:versioned # with versioning
|
37
|
+
|
38
|
+
Then upload the entire public/ directory to your server.
|
data/bin/bones
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# $:.unshift(File.dirname(__FILE__) + '/../')
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
path = ARGV.shift
|
6
|
+
|
7
|
+
if path.nil?
|
8
|
+
puts "Please supply a path to create a bones application."
|
9
|
+
exit
|
10
|
+
end
|
11
|
+
|
12
|
+
# Ensure given path exists
|
13
|
+
path = File.expand_path(path)
|
14
|
+
FileUtils.mkdir(path) unless File.directory?(path)
|
15
|
+
|
16
|
+
# Set the root to the path
|
17
|
+
ROOT = path
|
18
|
+
|
19
|
+
require 'boot.rb'
|
20
|
+
require 'init.rb'
|
21
|
+
|
22
|
+
BonesInitializer.run
|
data/bones.gemspec
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "bones"
|
3
|
+
s.version = "0.1.0"
|
4
|
+
s.date = "2008-08-22"
|
5
|
+
|
6
|
+
s.summary = "Simple HTML mockup framework for designers using ERB"
|
7
|
+
s.description = "Simple HTML mockup framework for designers using ERB"
|
8
|
+
s.email = "scharfie@gmail.com"
|
9
|
+
s.homepage = "http://github.com/scharfie/bones"
|
10
|
+
s.has_rdoc = false
|
11
|
+
s.authors = ["Chris Scharf", "Ryan Heath"]
|
12
|
+
|
13
|
+
s.require_paths = ['lib']
|
14
|
+
s.default_executable = 'bones'
|
15
|
+
s.executables = ['bones']
|
16
|
+
|
17
|
+
s.files = [
|
18
|
+
'README',
|
19
|
+
'bin/bones',
|
20
|
+
'lib/bones.rb',
|
21
|
+
'lib/boot.rb',
|
22
|
+
'lib/cache.rb',
|
23
|
+
'lib/extensions.rb',
|
24
|
+
'lib/helpers',
|
25
|
+
'lib/helpers/core_helper.rb',
|
26
|
+
'lib/init.rb',
|
27
|
+
'lib/pages/directory.html.erb',
|
28
|
+
'lib/pages/intro.html.erb',
|
29
|
+
'lib/Rakefile',
|
30
|
+
'lib/server.rb',
|
31
|
+
'lib/tasks/bones.rb',
|
32
|
+
'bones.gemspec'
|
33
|
+
]
|
34
|
+
|
35
|
+
s.add_dependency("rack", [">= 0.3.0"])
|
36
|
+
s.add_dependency("activesupport", [">= 2.1.0"])
|
37
|
+
end
|
data/lib/Rakefile
ADDED
data/lib/bones.rb
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
# Bones - the _real_ request handler,
|
2
|
+
# which BonesProxy loads and calls upon to
|
3
|
+
# do the dirty work.
|
4
|
+
class Bones
|
5
|
+
# Process incoming request (for real this time!)
|
6
|
+
def call(env)
|
7
|
+
# Grab the request
|
8
|
+
request = Rack::Request.new(env)
|
9
|
+
|
10
|
+
# Create a new template for the given path
|
11
|
+
# and compile it
|
12
|
+
template = Template.new(request.path_info)
|
13
|
+
output = template.compile
|
14
|
+
|
15
|
+
# Build a rack response
|
16
|
+
Rack::Response.new.finish do |response|
|
17
|
+
response.write output
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Returns array of all pages (excluding partials)
|
22
|
+
def self.pages
|
23
|
+
Dir.chdir(PAGES) do
|
24
|
+
Dir.glob('**/*.html.erb').map do |f|
|
25
|
+
f.starts_with?('_') ? nil : f.gsub('.html.erb', '')
|
26
|
+
end.compact
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Template - loads template file based on
|
31
|
+
# request path information and compiles
|
32
|
+
# it using ERB
|
33
|
+
class Template
|
34
|
+
attr_accessor :path
|
35
|
+
attr_accessor :layout
|
36
|
+
attr_accessor :options
|
37
|
+
|
38
|
+
# Load all available helpers
|
39
|
+
def self.include_helpers
|
40
|
+
files = [
|
41
|
+
Dir.glob(SYSTEM / 'helpers/*_helper.rb'),
|
42
|
+
Dir.glob(ROOT / 'helpers/*_helper.rb')
|
43
|
+
].flatten
|
44
|
+
|
45
|
+
# Include each helper
|
46
|
+
files.each do |filename|
|
47
|
+
klass = File.basename(filename, '.rb').camelize
|
48
|
+
force_load klass => filename
|
49
|
+
include klass.constantize
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Load the helpers
|
54
|
+
include_helpers if Object.const_defined?(:SYSTEM)
|
55
|
+
|
56
|
+
# Initialize template with path and optional layout
|
57
|
+
def initialize(path, layout=-1, options={})
|
58
|
+
@path = path.gsub(/\.html|\.html\.erb/, '')
|
59
|
+
@layout = layout == -1 ? 'application' : layout
|
60
|
+
@options = options
|
61
|
+
end
|
62
|
+
|
63
|
+
# Full path to template file
|
64
|
+
def filename
|
65
|
+
if @path =~ /raw$/
|
66
|
+
layout false
|
67
|
+
path = SYSTEM / 'pages' / 'directory.html.erb'
|
68
|
+
else
|
69
|
+
path = PAGES / @path
|
70
|
+
path /= 'index' if File.directory?(path) or path.ends_with?('/')
|
71
|
+
path += '.html.erb'
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Returns array of pages
|
76
|
+
def pages
|
77
|
+
Bones.pages
|
78
|
+
end
|
79
|
+
|
80
|
+
# Full path to layout file
|
81
|
+
def layout_filename
|
82
|
+
path = LAYOUTS / layout.to_s + '.html.erb'
|
83
|
+
end
|
84
|
+
|
85
|
+
# Gets/sets layout
|
86
|
+
# If no argument is passed, the layout is returned;
|
87
|
+
# otherwise, sets the layout
|
88
|
+
# (use false or nil to turn off the layout)
|
89
|
+
def layout(arg=-1)
|
90
|
+
@layout = arg unless arg == -1
|
91
|
+
@layout
|
92
|
+
end
|
93
|
+
|
94
|
+
# Compiles the template (along with the layout
|
95
|
+
# if necessary)
|
96
|
+
def compile
|
97
|
+
src = ERB.new(File.read(filename)).src
|
98
|
+
src = (local_assigns_source || '') + (src || '')
|
99
|
+
@content_for_layout = eval(src) # erb.result(binding)
|
100
|
+
|
101
|
+
if layout
|
102
|
+
erb = ERB.new(File.read(layout_filename))
|
103
|
+
erb.result(binding)
|
104
|
+
else
|
105
|
+
@content_for_layout
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# Generates source for local variable assignments
|
110
|
+
def local_assigns_source
|
111
|
+
src = []
|
112
|
+
(options[:locals] || {}).each do |key, value|
|
113
|
+
src << "#{key} = #{value.inspect};\n"
|
114
|
+
end
|
115
|
+
src.join
|
116
|
+
end
|
117
|
+
|
118
|
+
# Short-hand for compiling a template
|
119
|
+
def self.compile(*args)
|
120
|
+
Template.new(*args).compile
|
121
|
+
end
|
122
|
+
|
123
|
+
# Renders partial template - an underscore
|
124
|
+
# is automatically added to the passed name,
|
125
|
+
# so <%= partial 'footer' %> will render
|
126
|
+
# the '_footer.html.erb' template.
|
127
|
+
def partial(name, options={})
|
128
|
+
path = name.to_s.split('/')
|
129
|
+
path[-1] = '_' + path.last unless path.last.starts_with?('_')
|
130
|
+
name = path.join('/')
|
131
|
+
Template.compile(name, false, options)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
# Class used to encapsulate the logic needed to
|
136
|
+
# maintain mockup versions
|
137
|
+
class Versioned
|
138
|
+
# Pre-fix used for versioned directories
|
139
|
+
DIR_PREFIX = 'v'
|
140
|
+
|
141
|
+
# Start with the original destination
|
142
|
+
def initialize(original_destination)
|
143
|
+
@original_destination = original_destination
|
144
|
+
@versioned_destination = nil
|
145
|
+
end
|
146
|
+
|
147
|
+
# Returns the new destination, which depends on
|
148
|
+
# the existing amount of 'versions'
|
149
|
+
def destination
|
150
|
+
@versioned_destination ||= get_versioned_destination
|
151
|
+
end
|
152
|
+
|
153
|
+
# Transfers all public directories to the new 'versioned'
|
154
|
+
# directory, so each version can contain it's own mockup
|
155
|
+
# (note: only copies asset directories - ignores "v1", "v2", etc)
|
156
|
+
def copy_public_directories
|
157
|
+
public_directories.each do |src|
|
158
|
+
FileUtils.copy_entry ROOT / 'public' / src, destination / src
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
# Returns the versioned directories within the 'public' folder
|
163
|
+
# $> Bones::Versioned.directories
|
164
|
+
# $> => ["/v1", "/v2", ... "/vN"]
|
165
|
+
def self.directories
|
166
|
+
Dir.glob(ROOT / 'public' / "#{DIR_PREFIX}**").inject([]) do |dirs, dir|
|
167
|
+
dirs << '/' + dir.gsub(/^\/.+\//, '')
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
# Public accessor of version
|
172
|
+
def version
|
173
|
+
next_version
|
174
|
+
end
|
175
|
+
|
176
|
+
# Returns directory name of versioned path
|
177
|
+
# For example, 'v1'
|
178
|
+
def versioned_directory_name
|
179
|
+
DIR_PREFIX + next_version
|
180
|
+
end
|
181
|
+
|
182
|
+
private
|
183
|
+
# increments to the next version based on existing versions
|
184
|
+
def next_version
|
185
|
+
(self.class.directories.size + 1).to_s
|
186
|
+
end
|
187
|
+
|
188
|
+
# constructs the next version path
|
189
|
+
def get_versioned_destination
|
190
|
+
@original_destination /= versioned_directory_name
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
data/lib/boot.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
SYSTEM = File.dirname(__FILE__)
|
2
|
+
ROOT = File.expand_path('.') unless Object.const_defined?(:ROOT)
|
3
|
+
PAGES = File.join(ROOT, 'pages')
|
4
|
+
LAYOUTS = File.join(ROOT, 'layouts')
|
5
|
+
|
6
|
+
$:.unshift(SYSTEM)
|
7
|
+
$:.unshift(File.join(ROOT, 'lib'))
|
8
|
+
|
9
|
+
require 'rubygems'
|
10
|
+
require 'yaml'
|
11
|
+
require 'rack'
|
12
|
+
require 'rack/request'
|
13
|
+
require 'rack/response'
|
14
|
+
require 'activesupport'
|
15
|
+
require 'extensions'
|
16
|
+
require 'erb'
|
17
|
+
require 'bones'
|
18
|
+
|
19
|
+
def directories(base)
|
20
|
+
Dir.chdir(base) do
|
21
|
+
Dir.entries(base).map do |e|
|
22
|
+
next if e =~ /^\.+$/
|
23
|
+
File.directory?(base / e) ? '/' + e : nil
|
24
|
+
end.compact
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def page_directories
|
29
|
+
directories(ROOT / 'pages')
|
30
|
+
end
|
31
|
+
|
32
|
+
def public_directories
|
33
|
+
directories(ROOT / 'public') - page_directories - Bones::Versioned.directories
|
34
|
+
end
|
data/lib/cache.rb
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
require File.join(File.dirname(__FILE__), 'boot')
|
3
|
+
require 'fileutils'
|
4
|
+
require 'bones'
|
5
|
+
require 'optparse'
|
6
|
+
require 'ostruct'
|
7
|
+
|
8
|
+
# Argument processor
|
9
|
+
class CacheOptions < OpenStruct
|
10
|
+
# Default options
|
11
|
+
def self.default_options
|
12
|
+
returning new do |o|
|
13
|
+
o.destination = ROOT / 'public' # Set original destination
|
14
|
+
o.versioned = false # No versions by default
|
15
|
+
o.base = '' # Base URL is empty
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Process arguments
|
20
|
+
def self.process(args)
|
21
|
+
options = default_options
|
22
|
+
|
23
|
+
OptionParser.new do |o|
|
24
|
+
o.on('--versioned', '--versions', "Enable versioning") do
|
25
|
+
options.versioned = Bones::Versioned.new(options.destination)
|
26
|
+
end
|
27
|
+
|
28
|
+
o.on('--base PATH', "Change the base URL path") do |path|
|
29
|
+
options.base = path
|
30
|
+
end
|
31
|
+
|
32
|
+
o.on_tail("-h", "--help", "Show this message") do
|
33
|
+
puts o
|
34
|
+
exit
|
35
|
+
end
|
36
|
+
end.parse!(args)
|
37
|
+
|
38
|
+
options
|
39
|
+
end
|
40
|
+
|
41
|
+
# Returns true if the versions enabled
|
42
|
+
def versioned?
|
43
|
+
versioned != false
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns destination
|
47
|
+
def destination
|
48
|
+
versioned? ? versioned.destination : super
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Process arguments
|
53
|
+
options = CacheOptions.process(ARGV)
|
54
|
+
|
55
|
+
# Fixes the given URL path to begin at given base.
|
56
|
+
# In addition, the .html extension will be added if
|
57
|
+
# the path is a page.
|
58
|
+
#
|
59
|
+
# For example, if the base is /some_folder,
|
60
|
+
# normalize_url('/page_path', '/some_folder')
|
61
|
+
# # => /some_folder/page_path.html
|
62
|
+
def normalize_url(path, base='')
|
63
|
+
@known_pairs ||= {}
|
64
|
+
@public_directories_regex ||= Regexp.new(public_directories.join('|'))
|
65
|
+
|
66
|
+
if v = @known_pairs[path]
|
67
|
+
return v
|
68
|
+
else
|
69
|
+
value = case
|
70
|
+
when path =~ @public_directories_regex
|
71
|
+
path
|
72
|
+
when File.directory?('pages' / path)
|
73
|
+
path
|
74
|
+
else
|
75
|
+
path + '.html'
|
76
|
+
end
|
77
|
+
|
78
|
+
@known_pairs[path] = base / value
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
version = options.versioned? ? options.versioned.versioned_directory_name : nil
|
83
|
+
|
84
|
+
# Process each page
|
85
|
+
Dir.chdir(ROOT) do
|
86
|
+
Bones.pages.each do |page|
|
87
|
+
puts "** Generating #{[version, page].compact.join('/')}.html"
|
88
|
+
result = Bones::Template.compile(page)
|
89
|
+
result.gsub!(/(href|src|action)="([-A-Za-z0-9_\.\/]+)(.*?)"/) do |match|
|
90
|
+
property, url, params = $1, normalize_url(original_url = $2, options.base), $3
|
91
|
+
'%s="%s%s"' % [property, url, params]
|
92
|
+
end
|
93
|
+
|
94
|
+
path = options.destination / page + '.html'
|
95
|
+
FileUtils.mkdir_p(File.dirname(path))
|
96
|
+
File.open(path, 'w') { |f| f.write(result) }
|
97
|
+
end
|
98
|
+
|
99
|
+
if options.versioned?
|
100
|
+
puts "** Copying public files"
|
101
|
+
options.versioned.copy_public_directories
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
puts "** Done."
|
data/lib/extensions.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
class String
|
2
|
+
# Join strings using /
|
3
|
+
# (i.e. "system" / "pages" -> "system/pages")
|
4
|
+
def /(other)
|
5
|
+
File.join(self, other)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
# Loads filename, removing the associated
|
10
|
+
# class if defined
|
11
|
+
#
|
12
|
+
# Arguments:
|
13
|
+
# hash of 'Class' => 'filename' pairs
|
14
|
+
#
|
15
|
+
# Example:
|
16
|
+
#
|
17
|
+
# force_load 'Application' => 'application.rb'
|
18
|
+
#
|
19
|
+
# will remove the Application class if found,
|
20
|
+
# and then load the application.rb file
|
21
|
+
def force_load(map={})
|
22
|
+
map.each do |klass, filename|
|
23
|
+
Class.remove_class(klass) if Object.const_defined?(klass)
|
24
|
+
load filename
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
module CoreHelper
|
2
|
+
module HTML
|
3
|
+
# Creates a tag with content and properties
|
4
|
+
# Example:
|
5
|
+
# content_tag(:div, "Hello", :id => 'greeting')
|
6
|
+
# -- generates --
|
7
|
+
# <div id="greeting">Hello</div>
|
8
|
+
def content_tag(name, *arguments, &block)
|
9
|
+
name = name.to_s
|
10
|
+
options = Hash === arguments.last ? arguments.pop : {}
|
11
|
+
properties = html_options_from_hash(options)
|
12
|
+
|
13
|
+
result = ["<#{name}"]
|
14
|
+
result << ' ' + properties unless properties.empty?
|
15
|
+
|
16
|
+
if short_tag_names.include?(name)
|
17
|
+
result << ' />'
|
18
|
+
else
|
19
|
+
result << '>'
|
20
|
+
result << arguments.join
|
21
|
+
result << capture(&block) if block_given?
|
22
|
+
result << "</#{name}>"
|
23
|
+
end
|
24
|
+
|
25
|
+
result = result.join('')
|
26
|
+
concat(result, block.binding) if block_given?
|
27
|
+
result
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns array of tag names that can be
|
31
|
+
# closed with /> instead of </tagname>
|
32
|
+
def short_tag_names
|
33
|
+
%w(input br link hr img)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Converts hash of options into a string of HTML
|
37
|
+
# property="value" pairs
|
38
|
+
def html_options_from_hash(options={})
|
39
|
+
options.map do |key, value|
|
40
|
+
%Q{#{key}="#{value}"}
|
41
|
+
end.sort.join(' ')
|
42
|
+
end
|
43
|
+
|
44
|
+
# Creates link tag to stylesheet(s)
|
45
|
+
# (options are support as the last argument)
|
46
|
+
def stylesheet_link_tag(*sources)
|
47
|
+
return nil if sources.empty?
|
48
|
+
options = Hash === sources.last ? sources.pop : {}
|
49
|
+
result = sources.map { |e| stylesheet_tag(e, options) }
|
50
|
+
result.join("\n")
|
51
|
+
end
|
52
|
+
|
53
|
+
# Creates a stylesheet link tag
|
54
|
+
def stylesheet_tag(name, options={})
|
55
|
+
name += '.css' unless name =~ /\./
|
56
|
+
options.reverse_merge! :href => "/stylesheets/#{name}",
|
57
|
+
:rel => 'stylesheet', :type => 'text/css'
|
58
|
+
|
59
|
+
content_tag :link, options
|
60
|
+
end
|
61
|
+
|
62
|
+
# Creates script tag to javascript(s)
|
63
|
+
# (options are support as the last argument)
|
64
|
+
def javascript_include_tag(*sources)
|
65
|
+
return nil if sources.empty?
|
66
|
+
options = Hash === sources.last ? sources.pop : {}
|
67
|
+
sources.collect { |e| javascript_tag(e, options) }.join("\n")
|
68
|
+
end
|
69
|
+
|
70
|
+
# Creates a javascript script tag
|
71
|
+
def javascript_tag(name, options={})
|
72
|
+
name += '.js' unless name =~ /\./
|
73
|
+
options.merge! :src => "/javascripts/#{name}",
|
74
|
+
:type => 'text/javascript'
|
75
|
+
|
76
|
+
content_tag :script, options
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
module Capture
|
81
|
+
def content_for(name, content = nil, &block)
|
82
|
+
existing_content_for = instance_variable_get("@content_for_#{name}").to_s
|
83
|
+
new_content_for = existing_content_for + (block_given? ? capture(&block) : content)
|
84
|
+
instance_variable_set("@content_for_#{name}", new_content_for)
|
85
|
+
end
|
86
|
+
|
87
|
+
def capture(*args, &block)
|
88
|
+
# execute the block
|
89
|
+
begin
|
90
|
+
buffer = eval('_erbout', block.binding)
|
91
|
+
rescue
|
92
|
+
buffer = nil
|
93
|
+
end
|
94
|
+
|
95
|
+
if buffer.nil?
|
96
|
+
capture_block(*args, &block).to_s
|
97
|
+
else
|
98
|
+
capture_erb_with_buffer(buffer, *args, &block).to_s
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def capture_block(*args, &block)
|
103
|
+
block.call(*args)
|
104
|
+
end
|
105
|
+
|
106
|
+
def capture_erb(*args, &block)
|
107
|
+
buffer = eval('_erbout', block.binding)
|
108
|
+
capture_erb_with_buffer(buffer, *args, &block)
|
109
|
+
end
|
110
|
+
|
111
|
+
def capture_erb_with_buffer(buffer, *args, &block)
|
112
|
+
pos = buffer.length
|
113
|
+
block.call(*args)
|
114
|
+
|
115
|
+
# extract the block
|
116
|
+
data = buffer[pos..-1]
|
117
|
+
|
118
|
+
# replace it in the original with empty string
|
119
|
+
buffer[pos..-1] = ''
|
120
|
+
|
121
|
+
data
|
122
|
+
end
|
123
|
+
|
124
|
+
def concat(string, binding)
|
125
|
+
eval('_erbout', binding) << string
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
include HTML
|
130
|
+
include Capture
|
131
|
+
|
132
|
+
# Simple helper for setting title
|
133
|
+
# Call from a page template with an argument
|
134
|
+
# to set the title; call from the layout with
|
135
|
+
# no argument to get the title
|
136
|
+
def title(value=-1)
|
137
|
+
return @content_for_title if value == -1
|
138
|
+
@content_for_title = value
|
139
|
+
end
|
140
|
+
end
|
data/lib/init.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'boot') if __FILE__ == $0
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
class BonesInitializer
|
5
|
+
def self.ensure_file(path, &block)
|
6
|
+
return if File.exist?(path)
|
7
|
+
puts "** Writing #{path}"
|
8
|
+
File.open(path, 'w', &block)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.ensure_directory(path)
|
12
|
+
return nil if File.directory?(path)
|
13
|
+
puts "** Creating directory #{path}"
|
14
|
+
FileUtils.mkdir_p(path)
|
15
|
+
return true
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.run
|
19
|
+
puts "** Initializing"
|
20
|
+
|
21
|
+
ensure_directory(ROOT / 'public' / 'javascripts')
|
22
|
+
ensure_directory(ROOT / 'public' / 'stylesheets')
|
23
|
+
pages_new = ensure_directory(ROOT / 'pages')
|
24
|
+
ensure_directory(ROOT / 'layouts')
|
25
|
+
ensure_directory(ROOT / 'helpers')
|
26
|
+
|
27
|
+
if pages_new
|
28
|
+
ensure_file(ROOT / 'pages' / 'index.html.erb') do |f|
|
29
|
+
f.write File.read(SYSTEM / 'pages' / 'intro.html.erb')
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
ensure_file(ROOT / 'layouts' / 'application.html.erb') do |f|
|
34
|
+
f.write <<-HTML
|
35
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
36
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
37
|
+
<html>
|
38
|
+
<head>
|
39
|
+
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
40
|
+
<title>Welcome to bones</title>
|
41
|
+
<%= stylesheet_link_tag 'styles' %>
|
42
|
+
<%= javascript_include_tag %>
|
43
|
+
</head>
|
44
|
+
<body>
|
45
|
+
<h1>Welcome to <strong>bones</strong></h1>
|
46
|
+
<%= @content_for_layout %>
|
47
|
+
</body>
|
48
|
+
</html>
|
49
|
+
HTML
|
50
|
+
end
|
51
|
+
|
52
|
+
ensure_file(ROOT / 'public' / 'stylesheets' / 'styles.css')
|
53
|
+
|
54
|
+
puts "** Adding Rakefile to parent directory"
|
55
|
+
ensure_file(ROOT / 'Rakefile') do |f|
|
56
|
+
f.write File.read(SYSTEM / 'Rakefile')
|
57
|
+
end
|
58
|
+
|
59
|
+
puts <<-HELP if __FILE__ == $0
|
60
|
+
|
61
|
+
All set! Now just run:
|
62
|
+
ruby bones/server.rb
|
63
|
+
|
64
|
+
The app will run on port 3000
|
65
|
+
|
66
|
+
HELP
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
BonesInitializer.run if __FILE__ == $0
|
@@ -0,0 +1,28 @@
|
|
1
|
+
<% layout false %>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
5
|
+
<title>Welcome to bones</title>
|
6
|
+
<%= stylesheet_link_tag 'styles' %>
|
7
|
+
<%= javascript_include_tag %>
|
8
|
+
</head>
|
9
|
+
<h1>Welcome to <strong>bones</strong></h1>
|
10
|
+
<pre>
|
11
|
+
Getting started:
|
12
|
+
|
13
|
+
- Create some files in /pages (i.e. index.html.erb)
|
14
|
+
- Create some directories in /pages if you want as well
|
15
|
+
and drop .html.erb files in them as well
|
16
|
+
- Check out /raw to see all the pages in the system
|
17
|
+
|
18
|
+
Other things you can do:
|
19
|
+
|
20
|
+
- Create partials in /pages (i.e. _footer.html.erb)
|
21
|
+
- Drop anything you want in /public
|
22
|
+
(/stylesheets and /javascripts are created for you)
|
23
|
+
- Customize the layout (/layouts/application.html.erb)
|
24
|
+
- Create your own layout:
|
25
|
+
- Drop the file in /layouts (i.e. /layouts/custom.html.erb)
|
26
|
+
- Use the layout from a page (i.e. <%= layout 'custom' %>)
|
27
|
+
</pre>
|
28
|
+
</html>
|
data/lib/server.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require File.join(File.dirname(__FILE__), 'boot')
|
3
|
+
require 'init'
|
4
|
+
|
5
|
+
# BonesProxy is simply a proxy class handler
|
6
|
+
# to the actual Bones class - the reason for
|
7
|
+
# this is to allow live changes to Bones
|
8
|
+
# and helpers, etc. The proxy reloads on every
|
9
|
+
# request
|
10
|
+
class BonesProxy
|
11
|
+
# Process incoming request
|
12
|
+
def call(env)
|
13
|
+
reload!
|
14
|
+
Bones.new.call(env)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Reloads the application
|
18
|
+
def reload!
|
19
|
+
force_load 'Bones' => 'bones.rb'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class BonesServer
|
24
|
+
def self.run
|
25
|
+
app = Rack::Builder.new do
|
26
|
+
use Rack::CommonLogger
|
27
|
+
use Rack::ShowExceptions
|
28
|
+
use Rack::Reloader
|
29
|
+
use Rack::Static, :urls => public_directories, :root => ROOT / 'public'
|
30
|
+
run BonesProxy.new
|
31
|
+
end
|
32
|
+
|
33
|
+
port = ARGV.shift || 3000
|
34
|
+
puts "** Starting bones server on http://0.0.0.0:#{port}"
|
35
|
+
puts "** Public directories: #{public_directories.to_sentence}"
|
36
|
+
Rack::Handler::Mongrel.run app, :Port => port do |server|
|
37
|
+
puts "** Use CTRL-C to stop."
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
BonesServer.run if __FILE__ == $0
|
data/lib/tasks/bones.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
desc "Start bones server"
|
2
|
+
task :server do
|
3
|
+
ARGV.shift
|
4
|
+
load File.join(File.dirname(__FILE__), '..', 'server.rb')
|
5
|
+
BonesServer.run
|
6
|
+
end
|
7
|
+
|
8
|
+
namespace :cache do
|
9
|
+
desc "Cache page templates for redistribution (non-versioned)"
|
10
|
+
task :simple do
|
11
|
+
ARGV.shift
|
12
|
+
load File.join(File.dirname(__FILE__), '..', 'cache.rb')
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "Cache page templatets for redistribution (versioned)"
|
16
|
+
task :versioned do
|
17
|
+
ARGV.shift
|
18
|
+
file = File.join(File.dirname(__FILE__), '..', 'cache.rb')
|
19
|
+
system "ruby #{file} '--versioned'"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
task :clean do
|
24
|
+
# TODO
|
25
|
+
# ARGV.shift
|
26
|
+
# ARGV.unshift '--clean'
|
27
|
+
# load File.join(File.dirname(__FILE__), 'cache.rb')
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: scharfie-bones
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Chris Scharf
|
8
|
+
- Ryan Heath
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2008-08-22 00:00:00 -07:00
|
14
|
+
default_executable: bones
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: rack
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.3.0
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: activesupport
|
27
|
+
version_requirement:
|
28
|
+
version_requirements: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 2.1.0
|
33
|
+
version:
|
34
|
+
description: Simple HTML mockup framework for designers using ERB
|
35
|
+
email: scharfie@gmail.com
|
36
|
+
executables:
|
37
|
+
- bones
|
38
|
+
extensions: []
|
39
|
+
|
40
|
+
extra_rdoc_files: []
|
41
|
+
|
42
|
+
files:
|
43
|
+
- README
|
44
|
+
- bin/bones
|
45
|
+
- lib/bones.rb
|
46
|
+
- lib/boot.rb
|
47
|
+
- lib/cache.rb
|
48
|
+
- lib/extensions.rb
|
49
|
+
- lib/helpers
|
50
|
+
- lib/helpers/core_helper.rb
|
51
|
+
- lib/init.rb
|
52
|
+
- lib/pages/directory.html.erb
|
53
|
+
- lib/pages/intro.html.erb
|
54
|
+
- lib/Rakefile
|
55
|
+
- lib/server.rb
|
56
|
+
- lib/tasks/bones.rb
|
57
|
+
- bones.gemspec
|
58
|
+
has_rdoc: false
|
59
|
+
homepage: http://github.com/scharfie/bones
|
60
|
+
post_install_message:
|
61
|
+
rdoc_options: []
|
62
|
+
|
63
|
+
require_paths:
|
64
|
+
- lib
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: "0"
|
70
|
+
version:
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: "0"
|
76
|
+
version:
|
77
|
+
requirements: []
|
78
|
+
|
79
|
+
rubyforge_project:
|
80
|
+
rubygems_version: 1.2.0
|
81
|
+
signing_key:
|
82
|
+
specification_version: 2
|
83
|
+
summary: Simple HTML mockup framework for designers using ERB
|
84
|
+
test_files: []
|
85
|
+
|