scharfie-bones 0.1.5 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+
4
+ task :default => :test
5
+
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << "lib"
8
+ t.libs << "test"
9
+ t.test_files = FileList['test/test*.rb']
10
+ t.verbose = true
11
+ end
data/bin/bones CHANGED
@@ -1,7 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
- # $:.unshift(File.dirname(__FILE__) + '/../')
3
- require 'fileutils'
4
-
2
+ require File.join(File.dirname(__FILE__), '../lib/boot')
5
3
  path = ARGV.shift
6
4
 
7
5
  if path.nil?
@@ -13,10 +11,4 @@ end
13
11
  path = File.expand_path(path)
14
12
  FileUtils.mkdir(path) unless File.directory?(path)
15
13
 
16
- # Set the root to the path
17
- ROOT = path
18
-
19
- require 'boot.rb'
20
- require 'init.rb'
21
-
22
- BonesInitializer.run
14
+ Bones::Initializer.run(path)
data/bones.gemspec CHANGED
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "bones"
3
- s.version = "0.1.5"
4
- s.date = "2009-02-04"
3
+ s.version = "0.2.0"
4
+ s.date = "2009-02-05"
5
5
  s.authors = ["Chris Scharf", "Ryan Heath"]
6
6
  s.email = "scharfie@gmail.com"
7
7
 
@@ -12,26 +12,59 @@ Gem::Specification.new do |s|
12
12
  s.has_rdoc = false
13
13
 
14
14
  s.require_paths = ['lib']
15
- s.default_executable = 'bones'
16
15
  s.executables = ['bones']
16
+ s.default_executable = 'bones'
17
17
 
18
18
  s.files = [
19
- 'README',
20
- 'lib/Rakefile',
19
+ 'bin',
21
20
  'bin/bones',
22
- 'lib/bones.rb',
21
+ 'bones.gemspec',
22
+ 'lib/bones',
23
+ 'lib/bones/cache.rb',
24
+ 'lib/bones/initializer.rb',
23
25
  'lib/bones/release.rb',
26
+ 'lib/bones/template.rb',
27
+ 'lib/bones/versioned_release.rb',
28
+ 'lib/bones.rb',
24
29
  'lib/boot.rb',
25
- 'lib/cache.rb',
26
30
  'lib/extensions.rb',
27
31
  'lib/helpers',
28
32
  'lib/helpers/core_helper.rb',
29
- 'lib/init.rb',
30
33
  'lib/pages/directory.html.erb',
31
34
  'lib/pages/intro.html.erb',
35
+ 'lib/Rakefile',
32
36
  'lib/server.rb',
37
+ 'lib/tasks',
33
38
  'lib/tasks/bones.rb',
34
- 'bones.gemspec'
39
+ 'Rakefile',
40
+ 'README',
41
+ 'test',
42
+ 'test/example_site',
43
+ 'test/example_site/helpers',
44
+ 'test/example_site/helpers/custom_helper.rb',
45
+ 'test/example_site/layouts',
46
+ 'test/example_site/layouts/example_layout.html.erb',
47
+ 'test/example_site/pages',
48
+ 'test/example_site/pages/about.html.erb',
49
+ 'test/example_site/pages/index.html.erb',
50
+ 'test/example_site/pages/partials',
51
+ 'test/example_site/pages/partials/_footer.html.erb',
52
+ 'test/example_site/pages/things',
53
+ 'test/example_site/pages/things/a.html.erb',
54
+ 'test/example_site/public',
55
+ 'test/example_site/public/images',
56
+ 'test/example_site/public/images/.gitignore',
57
+ 'test/example_site/public/javascripts',
58
+ 'test/example_site/public/javascripts/.gitignore',
59
+ 'test/example_site/public/stylesheets',
60
+ 'test/example_site/public/stylesheets/.gitignore',
61
+ 'test/example_site/public/videos',
62
+ 'test/example_site/public/videos/.gitignore',
63
+ 'test/test_bones.rb',
64
+ 'test/test_cache.rb',
65
+ 'test/test_template.rb',
66
+ 'test/test_example_site.rb',
67
+ 'test/test_helper.rb'
35
68
  ]
36
69
 
37
70
  # Dependencies
data/lib/Rakefile CHANGED
@@ -1,3 +1,14 @@
1
- require 'rubygems'
2
- require 'bones'
1
+ # Bones
2
+ bones_boot = File.join(File.dirname(__FILE__), 'bones', 'boot.rb')
3
+
4
+ if File.file?(bones_boot)
5
+ require bones_boot
6
+ else
7
+ require 'rubygems'
8
+ require 'bones'
9
+ end
10
+
11
+ Bones.root = File.expand_path('.')
12
+
13
+ require 'rake'
3
14
  require 'tasks/bones'
@@ -1,9 +1,3 @@
1
- #!/usr/bin/env ruby
2
- require File.join(File.dirname(__FILE__), 'boot')
3
- require 'fileutils'
4
- require 'optparse'
5
- require 'ostruct'
6
-
7
1
  class Bones
8
2
  class Cache
9
3
  class Options
@@ -21,10 +15,13 @@ class Bones
21
15
  method = "#{k}=".to_sym
22
16
  send(method, v) if respond_to?(method)
23
17
  end
18
+
19
+ self
24
20
  end
25
21
 
26
22
  # Process arguments
27
23
  def self.process(args)
24
+ args = [] if args.blank?
28
25
  options = new
29
26
 
30
27
  OptionParser.new do |o|
@@ -72,7 +69,7 @@ class Bones
72
69
  end
73
70
 
74
71
  def default_destination
75
- File.expand_path(ROOT / 'public')
72
+ File.expand_path(Bones.root / 'public')
76
73
  end
77
74
 
78
75
  # Returns true if the versions enabled
@@ -94,7 +91,14 @@ class Bones
94
91
  attr_accessor :options
95
92
 
96
93
  def initialize(options=nil)
97
- self.options = Options === options ? options : Options.process(options)
94
+ self.options = case options
95
+ when Hash
96
+ Options.new.merge(options)
97
+ when Options
98
+ options
99
+ else
100
+ Options.process(options)
101
+ end
98
102
  end
99
103
 
100
104
  def self.run(options=nil)
@@ -105,7 +109,7 @@ class Bones
105
109
  version = options.versioned? ? options.release.versioned_directory_name : nil
106
110
 
107
111
  # Process each page
108
- Dir.chdir(ROOT) do
112
+ Dir.chdir(Bones.root) do
109
113
  puts "** Note: No files/directories will be modified (noop flag)" if options.noop
110
114
  puts "** Writing to: #{options.destination}"
111
115
  puts "** Using base: #{options.base}" unless options.base.blank?
@@ -115,14 +119,9 @@ class Bones
115
119
  pages.each_with_index do |page, index|
116
120
  print "\r %-70s (%4d/%4d)" % [[version, page].compact.join('/') + '.html', index + 1, total]
117
121
  $stdout.flush
118
- template = Bones::Template.new(page)
119
- template.request = generate_mock_request(:path_info => page)
120
- result = template.compile
121
- result.gsub!(/(href|src|action|url)(="|\()([-A-Za-z0-9_\.\/]+)([^:]*?)("|\))/) do |match|
122
- property, url, params = $1, normalize_url(original_url = $3, options.base), $4
123
- property =~ /url/ ? 'url(%s%s)' % [url, params] : '%s="%s%s"' % [property, url, params]
124
- end
125
- path = options.destination / page + '.html'
122
+
123
+ result = process_page(page)
124
+ path = options.destination / page + '.html'
126
125
 
127
126
  unless options.noop
128
127
  FileUtils.mkdir_p(File.dirname(path))
@@ -136,15 +135,24 @@ class Bones
136
135
  puts "** Copying public files"
137
136
  options.release.copy_public_directories unless options.noop
138
137
  end
139
-
140
- # puts "** Cached to: #{options.destination}"
141
- # puts "** Using base: #{options.base}" unless options.base.blank?
142
- # puts "** Note: No files/directories were modified (noop flag)" if options.noop
143
138
  end
144
139
 
145
140
  puts "** Done."
146
141
  end
147
142
 
143
+ def process_page(page)
144
+ template = Bones::Template.new(page)
145
+ template.request = generate_mock_request(:path_info => page)
146
+ process_template(template.compile)
147
+ end
148
+
149
+ def process_template(result)
150
+ result.gsub(/(href|src|action|url)(="|\()([-A-Za-z0-9_\.\/]+)([^:]*?)("|\))/) do |match|
151
+ property, url, params = $1, normalize_url(original_url = $3), $4
152
+ property =~ /url/ ? 'url(%s%s)' % [url, params] : '%s="%s%s"' % [property, url, params]
153
+ end
154
+ end
155
+
148
156
  # Fixes the given URL path to begin at given base.
149
157
  # In addition, the .html extension will be added if
150
158
  # the path is a page.
@@ -152,7 +160,7 @@ class Bones
152
160
  # For example, if the base is /some_folder,
153
161
  # normalize_url('/page_path', '/some_folder')
154
162
  # # => /some_folder/page_path.html
155
- def normalize_url(path, base='')
163
+ def normalize_url(path)
156
164
  @known_pairs ||= {}
157
165
  @public_directories_regex ||= Regexp.new(public_directories.join('|'))
158
166
 
@@ -161,16 +169,18 @@ class Bones
161
169
  else
162
170
  value = case
163
171
  when path =~ /^(\w{3,}:\/\/|mailto)/
172
+ # don't do anything to this type of URL
164
173
  return path
165
174
  when path =~ @public_directories_regex
166
175
  path
167
176
  when File.directory?('pages' / path)
168
177
  path
169
178
  else
170
- path + '.html'
179
+ # don't add .html if there's already an extension
180
+ path =~ /\..+/ ? path : path + '.html'
171
181
  end
172
-
173
- @known_pairs[path] = base / value
182
+
183
+ @known_pairs[path] = options.base / value
174
184
  end
175
185
  end
176
186
 
@@ -0,0 +1,74 @@
1
+ class Bones
2
+ class Initializer
3
+ def self.relative_path(path)
4
+ path.gsub(Bones.root + '/', '')
5
+ end
6
+
7
+ def self.ensure_file(path, &block)
8
+ return if File.exist?(path)
9
+ puts "** Writing #{relative_path(path)}"
10
+ File.open(path, 'w', &block)
11
+ end
12
+
13
+ def self.ensure_directory(path)
14
+ return nil if File.directory?(path)
15
+ puts "** Directory #{relative_path(path)}"
16
+ FileUtils.mkdir_p(path)
17
+ return true
18
+ end
19
+
20
+ def self.run(root=nil)
21
+ Bones.root = root
22
+
23
+ puts "** Initializing"
24
+ puts "** Directory: #{Bones.root}"
25
+
26
+ ensure_directory(Bones.root / 'public' / 'javascripts')
27
+ ensure_directory(Bones.root / 'public' / 'stylesheets')
28
+ pages_new = ensure_directory(Bones.root / 'pages')
29
+ ensure_directory(Bones.root / 'layouts')
30
+ ensure_directory(Bones.root / 'helpers')
31
+
32
+ if pages_new
33
+ ensure_file(Bones.root / 'pages' / 'index.html.erb') do |f|
34
+ f.write File.read(Bones.system_path / 'pages' / 'intro.html.erb')
35
+ end
36
+ end
37
+
38
+ ensure_file(Bones.root / 'layouts' / 'application.html.erb') do |f|
39
+ f.write <<-HTML
40
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
41
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
42
+ <html>
43
+ <head>
44
+ <meta http-equiv="Content-type" content="text/html; charset=utf-8">
45
+ <title>Welcome to bones</title>
46
+ <%= stylesheet_link_tag 'styles' %>
47
+ <%= javascript_include_tag %>
48
+ </head>
49
+ <body>
50
+ <h1>Welcome to <strong>bones</strong></h1>
51
+ <%= @content_for_layout %>
52
+ </body>
53
+ </html>
54
+ HTML
55
+ end
56
+
57
+ ensure_file(Bones.root / 'public' / 'stylesheets' / 'styles.css')
58
+
59
+ ensure_file(Bones.root / 'Rakefile') do |f|
60
+ puts "** Adding Rakefile to parent directory"
61
+ f.write File.read(Bones.system_path / 'Rakefile')
62
+ end
63
+
64
+ puts <<-HELP if __FILE__ == $0
65
+
66
+ All set! Now just run:
67
+ rake server
68
+
69
+ The app will run on port 3000
70
+
71
+ HELP
72
+ end
73
+ end
74
+ end
data/lib/bones/release.rb CHANGED
@@ -15,61 +15,14 @@ class Bones
15
15
  end
16
16
 
17
17
  def original_destination
18
- @original_destination || (ROOT / 'public')
18
+ @original_destination || (Bones.root / 'public')
19
19
  end
20
20
 
21
21
  # Copies all public directories to the new release directory
22
22
  def copy_public_directories
23
23
  public_directories.each do |src|
24
- FileUtils.copy_entry ROOT / 'public' / src, destination / src
24
+ FileUtils.copy_entry Bones.root / 'public' / src, destination / src
25
25
  end
26
26
  end
27
27
  end
28
-
29
- # Class used to encapsulate the logic needed to
30
- # maintain mockup versions
31
- class VersionedRelease < Release
32
- # Pre-fix used for versioned directories
33
- DIR_PREFIX = 'v'
34
-
35
- def initialize(original_destination, release_destination = nil)
36
- super
37
- @release_destination = get_versioned_destination
38
- end
39
-
40
- # Returns the versioned directories within the 'public' folder
41
- # $> Bones::Versioned.directories
42
- # $> => ["/v1", "/v2", ... "/vN"]
43
- def self.directories(base=nil)
44
- base ||= ROOT / 'public'
45
- FileUtils.mkdir_p(base) unless File.directory?(base)
46
- Dir.chdir(base) do
47
- Dir.glob("#{DIR_PREFIX}**").inject([]) do |dirs, dir|
48
- dirs << '/' + File.basename(dir)
49
- end
50
- end
51
- end
52
-
53
- # Public accessor of version
54
- def version
55
- next_version
56
- end
57
-
58
- # Returns directory name of versioned path
59
- # For example, 'v1'
60
- def versioned_directory_name
61
- DIR_PREFIX + next_version
62
- end
63
-
64
- private
65
- # increments to the next version based on existing versions
66
- def next_version
67
- (self.class.directories(original_destination).size + 1).to_s
68
- end
69
-
70
- # constructs the next version path
71
- def get_versioned_destination
72
- original_destination / versioned_directory_name
73
- end
74
- end
75
28
  end
@@ -0,0 +1,118 @@
1
+ class Bones
2
+ # Template - loads template file based on
3
+ # request path information and compiles
4
+ # it using ERB
5
+ class Template
6
+ attr_accessor :path
7
+ attr_accessor :layout
8
+ attr_accessor :options
9
+ attr_accessor :request
10
+
11
+ # Returns array of all helper files that should
12
+ # be included
13
+ def self.helpers_to_include
14
+ files = [
15
+ Dir.glob(Bones.system_path / 'helpers/*_helper.rb'),
16
+ Dir.glob(Bones.root / 'helpers/*_helper.rb')
17
+ ].flatten
18
+ end
19
+
20
+ # Load all available helpers
21
+ def self.include_helpers
22
+ helpers_to_include.each do |filename|
23
+ klass = File.basename(filename, '.rb').camelize
24
+ force_load klass => filename
25
+ include klass.constantize
26
+ end
27
+ end
28
+
29
+ # Load the helpers
30
+ include_helpers if Bones.booted?
31
+
32
+ # Initialize template with path and optional layout
33
+ def initialize(path, layout=-1, options={})
34
+ @path = path.gsub(/\.html|\.html\.erb/, '')
35
+ @layout = layout == -1 ? 'application' : layout
36
+ @options = options
37
+
38
+ self.class.include_helpers
39
+ end
40
+
41
+ def inspect
42
+ '#<Bones::Template @path="%s" @layout="%s">' % [path, layout]
43
+ end
44
+
45
+ # Full path to template file
46
+ def filename
47
+ if self.path =~ /raw$/
48
+ layout false
49
+ Bones.system_path / 'pages' / 'directory.html.erb'
50
+ else
51
+ path = Bones.pages_path / @path
52
+ path /= 'index' if File.directory?(path) or path.ends_with?('/')
53
+ path += '.html.erb'
54
+ end
55
+ end
56
+
57
+ # Returns array of pages
58
+ def pages
59
+ Bones.pages
60
+ end
61
+
62
+ # Full path to layout file
63
+ def layout_filename
64
+ Bones.layouts_path / layout.to_s + '.html.erb'
65
+ end
66
+
67
+ # Gets/sets layout
68
+ # If no argument is passed, the layout is returned;
69
+ # otherwise, sets the layout
70
+ # (use false or nil to turn off the layout)
71
+ def layout(arg=-1)
72
+ @layout = arg unless arg == -1
73
+ @layout
74
+ end
75
+
76
+ # Compiles the template (along with the layout
77
+ # if necessary)
78
+ def compile
79
+ src = ERB.new(File.read(filename)).src
80
+ src = (local_assigns_source || '') + (src || '')
81
+ @content_for_layout = eval(src) # erb.result(binding)
82
+
83
+ if layout && File.file?(layout_filename)
84
+ erb = ERB.new(File.read(layout_filename))
85
+ erb.result(binding)
86
+ else
87
+ @content_for_layout
88
+ end
89
+ end
90
+
91
+ # Generates source for local variable assignments
92
+ def local_assigns_source
93
+ src = []
94
+ (options[:locals] || {}).each do |key, value|
95
+ src << "#{key} = #{value.inspect};\n"
96
+ end
97
+ src.join
98
+ end
99
+
100
+ # Short-hand for compiling a template
101
+ def self.compile(*args)
102
+ Template.new(*args).compile
103
+ end
104
+
105
+ # Renders partial template - an underscore
106
+ # is automatically added to the passed name,
107
+ # so <%= partial 'footer' %> will render
108
+ # the '_footer.html.erb' template.
109
+ def partial(name, options={})
110
+ path = name.to_s.split('/')
111
+ path[-1] = '_' + path.last unless path.last.starts_with?('_')
112
+ name = path.join('/')
113
+ template = Template.new(name, false, options)
114
+ template.request = request
115
+ template.compile
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,49 @@
1
+ class Bones
2
+ # Class used to encapsulate the logic needed to
3
+ # maintain mockup versions
4
+ class VersionedRelease < Release
5
+ # Pre-fix used for versioned directories
6
+ DIR_PREFIX = 'v'
7
+
8
+ def initialize(original_destination, release_destination = nil)
9
+ super
10
+ @release_destination = get_versioned_destination
11
+ end
12
+
13
+ # Returns the versioned directories within the 'public' folder
14
+ # $> Bones::Versioned.directories
15
+ # $> => ["/v1", "/v2", ... "/vN"]
16
+ def self.directories(base=nil)
17
+ base ||= Bones.root / 'public'
18
+ FileUtils.mkdir_p(base) unless File.directory?(base)
19
+ Dir.chdir(base) do
20
+ Dir.glob("#{DIR_PREFIX}**").inject([]) do |dirs, dir|
21
+ dirs << '/' + File.basename(dir) if dir =~ /^#{DIR_PREFIX}\d+$/
22
+ dirs
23
+ end.compact
24
+ end
25
+ end
26
+
27
+ # Public accessor of version
28
+ def version
29
+ next_version
30
+ end
31
+
32
+ # Returns directory name of versioned path
33
+ # For example, 'v1'
34
+ def versioned_directory_name
35
+ DIR_PREFIX + next_version
36
+ end
37
+
38
+ private
39
+ # increments to the next version based on existing versions
40
+ def next_version
41
+ (self.class.directories(original_destination).size + 1).to_s
42
+ end
43
+
44
+ # constructs the next version path
45
+ def get_versioned_destination
46
+ original_destination / versioned_directory_name
47
+ end
48
+ end
49
+ end
data/lib/bones.rb CHANGED
@@ -3,11 +3,46 @@
3
3
  # do the dirty work.
4
4
  class Bones
5
5
  class << self
6
- attr_accessor :base
6
+ attr_accessor :base, :root
7
+ attr_accessor :system_path, :pages_path, :layouts_path
8
+ attr_accessor :booted
7
9
 
8
10
  def base
9
11
  @base || ''
10
12
  end
13
+
14
+ # Path to the root of the bones project
15
+ # Defaults to current directory
16
+ def root
17
+ @root ||= File.expand_path(File.dirname(__FILE__) + '/../../')
18
+ end
19
+
20
+ # Path to the bones system files
21
+ # Defaults to the directory containing this file
22
+ def system_path
23
+ @system_path ||= File.expand_path(File.dirname(__FILE__))
24
+ end
25
+
26
+ # Path to the directory containing the page templates
27
+ # [root]/pages
28
+ def pages_path
29
+ @pages_path || root / 'pages'
30
+ end
31
+
32
+ # Path to the directory containing the layout templates
33
+ # [root]/layouts
34
+ def layouts_path
35
+ @layouts_path || root / 'layouts'
36
+ end
37
+
38
+ def booted?
39
+ @booted
40
+ end
41
+ end
42
+
43
+ # Resets root, pages, and layouts paths and the base setting
44
+ def self.reset
45
+ @pages_path = @layouts_path = @root = @base = nil
11
46
  end
12
47
 
13
48
  # Process incoming request (for real this time!)
@@ -29,124 +64,10 @@ class Bones
29
64
 
30
65
  # Returns array of all pages (excluding partials)
31
66
  def self.pages
32
- Dir.chdir(PAGES) do
67
+ Dir.chdir(Bones.pages_path) do
33
68
  Dir.glob('**/*.html.erb').map do |f|
34
69
  f.starts_with?('_') ? nil : f.gsub('.html.erb', '')
35
70
  end.compact
36
71
  end
37
72
  end
38
-
39
- # Template - loads template file based on
40
- # request path information and compiles
41
- # it using ERB
42
- class Template
43
- attr_accessor :path
44
- attr_accessor :layout
45
- attr_accessor :options
46
- attr_accessor :request
47
-
48
- # Load all available helpers
49
- def self.include_helpers
50
- files = [
51
- Dir.glob(SYSTEM / 'helpers/*_helper.rb'),
52
- Dir.glob(ROOT / 'helpers/*_helper.rb')
53
- ].flatten
54
-
55
- # Include each helper
56
- files.each do |filename|
57
- klass = File.basename(filename, '.rb').camelize
58
- force_load klass => filename
59
- include klass.constantize
60
- end
61
- end
62
-
63
- # Load the helpers
64
- include_helpers if Object.const_defined?(:SYSTEM)
65
-
66
- # Initialize template with path and optional layout
67
- def initialize(path, layout=-1, options={})
68
- @path = path.gsub(/\.html|\.html\.erb/, '')
69
- @layout = layout == -1 ? 'application' : layout
70
- @options = options
71
-
72
- self.class.include_helpers
73
- end
74
-
75
- def inspect
76
- '#<Bones::Template @path="%s" @layout="%s">' % [path, layout]
77
- end
78
-
79
- # Full path to template file
80
- def filename
81
- if @path =~ /raw$/
82
- layout false
83
- path = SYSTEM / 'pages' / 'directory.html.erb'
84
- else
85
- path = PAGES / @path
86
- path /= 'index' if File.directory?(path) or path.ends_with?('/')
87
- path += '.html.erb'
88
- end
89
- end
90
-
91
- # Returns array of pages
92
- def pages
93
- Bones.pages
94
- end
95
-
96
- # Full path to layout file
97
- def layout_filename
98
- path = LAYOUTS / layout.to_s + '.html.erb'
99
- end
100
-
101
- # Gets/sets layout
102
- # If no argument is passed, the layout is returned;
103
- # otherwise, sets the layout
104
- # (use false or nil to turn off the layout)
105
- def layout(arg=-1)
106
- @layout = arg unless arg == -1
107
- @layout
108
- end
109
-
110
- # Compiles the template (along with the layout
111
- # if necessary)
112
- def compile
113
- src = ERB.new(File.read(filename)).src
114
- src = (local_assigns_source || '') + (src || '')
115
- @content_for_layout = eval(src) # erb.result(binding)
116
-
117
- if layout
118
- erb = ERB.new(File.read(layout_filename))
119
- erb.result(binding)
120
- else
121
- @content_for_layout
122
- end
123
- end
124
-
125
- # Generates source for local variable assignments
126
- def local_assigns_source
127
- src = []
128
- (options[:locals] || {}).each do |key, value|
129
- src << "#{key} = #{value.inspect};\n"
130
- end
131
- src.join
132
- end
133
-
134
- # Short-hand for compiling a template
135
- def self.compile(*args)
136
- Template.new(*args).compile
137
- end
138
-
139
- # Renders partial template - an underscore
140
- # is automatically added to the passed name,
141
- # so <%= partial 'footer' %> will render
142
- # the '_footer.html.erb' template.
143
- def partial(name, options={})
144
- path = name.to_s.split('/')
145
- path[-1] = '_' + path.last unless path.last.starts_with?('_')
146
- name = path.join('/')
147
- template = Template.new(name, false, options)
148
- template.request = request
149
- template.compile
150
- end
151
- end
152
73
  end
data/lib/boot.rb CHANGED
@@ -1,21 +1,23 @@
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')
1
+ require 'rubygems'
2
+ require 'activesupport'
5
3
 
6
- $:.unshift(SYSTEM)
7
- $:.unshift(File.join(ROOT, 'lib'))
4
+ require File.join(File.dirname(__FILE__), 'bones.rb')
5
+ require File.join(File.dirname(__FILE__), 'extensions.rb')
6
+
7
+ # Bones.root = BONES_ROOT if Object.const_defined?(:BONES_ROOT)
8
+ ActiveSupport::Dependencies.load_paths.push << Bones.system_path
8
9
 
9
- require 'rubygems'
10
10
  require 'yaml'
11
11
  require 'rack'
12
12
  require 'rack/request'
13
13
  require 'rack/response'
14
- require 'activesupport'
15
- require 'extensions'
14
+
15
+ require 'fileutils'
16
+ require 'optparse'
17
+ require 'ostruct'
16
18
  require 'erb'
17
- require 'bones'
18
- require 'bones/release'
19
+
20
+ Bones.booted = true
19
21
 
20
22
  def directories(base)
21
23
  Dir.chdir(base) do
@@ -23,11 +25,11 @@ def directories(base)
23
25
  next if e =~ /^\.+$/
24
26
  File.directory?(base / e) ? '/' + e : nil
25
27
  end.compact
26
- end
28
+ end
27
29
  end
28
30
 
29
31
  def page_directories
30
- directories(ROOT / 'pages')
32
+ directories(Bones.root / 'pages')
31
33
  end
32
34
 
33
35
  def versioned_directories
@@ -35,5 +37,5 @@ def versioned_directories
35
37
  end
36
38
 
37
39
  def public_directories
38
- directories(ROOT / 'public') - page_directories - versioned_directories
40
+ directories(Bones.root / 'public') - page_directories - versioned_directories
39
41
  end
data/lib/server.rb CHANGED
@@ -1,7 +1,3 @@
1
- #!/usr/bin/env ruby
2
- require File.join(File.dirname(__FILE__), 'boot')
3
- require 'init'
4
-
5
1
  # BonesProxy is simply a proxy class handler
6
2
  # to the actual Bones class - the reason for
7
3
  # this is to allow live changes to Bones
@@ -22,17 +18,20 @@ end
22
18
 
23
19
  class BonesServer
24
20
  def self.run
21
+ statics = public_directories
22
+
25
23
  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
24
+ use Rack::CommonLogger
25
+ use Rack::ShowExceptions
26
+ use Rack::Reloader
27
+ use Rack::Static, :urls => statics, :root => Bones.root / 'public'
28
+ run BonesProxy.new
31
29
  end
32
-
30
+
33
31
  port = ARGV.shift || 3000
34
32
  puts "** Starting bones server on http://0.0.0.0:#{port}"
35
- puts "** Public directories: #{public_directories.to_sentence}"
33
+ puts "** Public directories: #{statics.to_sentence}"
34
+
36
35
  Rack::Handler::Mongrel.run app, :Port => port do |server|
37
36
  puts "** Use CTRL-C to stop."
38
37
  end
data/lib/tasks/bones.rb CHANGED
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), '..', 'cache.rb')
1
+ require File.join(File.dirname(__FILE__), '..', 'boot.rb')
2
2
 
3
3
  task :default => :server
4
4
 
@@ -0,0 +1,5 @@
1
+ module CustomHelper
2
+ def some_custom_helper
3
+ "Some custom helper"
4
+ end
5
+ end
@@ -0,0 +1,2 @@
1
+ Example Layout
2
+ <%= @content_for_layout %>
@@ -0,0 +1,2 @@
1
+ <% layout 'example_layout' %>
2
+ <%= some_custom_helper %>
@@ -0,0 +1,9 @@
1
+ <html>
2
+ <head>
3
+ <link rel="stylesheet" type="text/css" src="/stylesheets/styles.css" />
4
+ </head>
5
+ <body>
6
+ <a href="/things/a">Thing A</a>
7
+ <form action="/comment"></form>
8
+ </body>
9
+ </html>
@@ -0,0 +1 @@
1
+ Footer text
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,16 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ context 'Bones' do
4
+ test "should have proper paths" do
5
+ assert_equal relative_path('../..'), Bones.root
6
+ assert_equal relative_path('../lib'), Bones.system_path
7
+ assert_equal relative_path('../../pages'), Bones.pages_path
8
+ assert_equal relative_path('../../layouts'), Bones.layouts_path
9
+ end
10
+
11
+ test "should allow getting/setting Bones.base" do
12
+ assert_equal '', Bones.base
13
+ Bones.base = '/something'
14
+ assert_equal '/something', Bones.base
15
+ end
16
+ end
@@ -0,0 +1,72 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ context "Bones::Cache with default options" do
4
+ uses_example_site
5
+
6
+ setup do
7
+ @cache = Bones::Cache.new
8
+ @page = @cache.process_page('index')
9
+ end
10
+
11
+ test "should process page correctly" do
12
+ assert_include @page, 'src="/stylesheets/styles.css"'
13
+ assert_include @page, 'action="/comment.html"'
14
+ assert_include @page, 'href="/things/a.html"'
15
+ end
16
+ end
17
+
18
+ context "Bones::Cache with custom base" do
19
+ uses_example_site
20
+
21
+ setup do
22
+ @cache = Bones::Cache.new(:base => '/mysite')
23
+ @page = @cache.process_page('index')
24
+ end
25
+
26
+ test "should process page correctly using custom base" do
27
+ assert_include @page, 'src="/mysite/stylesheets/styles.css"'
28
+ assert_include @page, 'action="/mysite/comment.html"'
29
+ assert_include @page, 'href="/mysite/things/a.html"'
30
+ end
31
+ end
32
+
33
+ context "Bones::Cache URL normalization" do
34
+ uses_example_site
35
+
36
+ setup do
37
+ @cache = Bones::Cache.new(:base => '/mysite')
38
+ end
39
+
40
+ def assert_normalized(expected, actual=nil)
41
+ assert_equal(expected, @cache.normalize_url(actual))
42
+ end
43
+
44
+ def assert_normalized_with_base(url)
45
+ assert_equal @cache.options.base / url, @cache.normalize_url(url)
46
+ end
47
+
48
+ def assert_not_normalized(url)
49
+ assert_equal url, @cache.normalize_url(url)
50
+ end
51
+
52
+ test "should not normalize URLs that have a protocol" do
53
+ assert_not_normalized "mailto:someone@example.com"
54
+ assert_not_normalized "http://www.example.com"
55
+ assert_not_normalized "ftp://ftp.example.com"
56
+ end
57
+
58
+ test "should not add .html to URLs that have an extension" do
59
+ assert_normalized_with_base "/videos/hello.mov"
60
+ assert_normalized_with_base "/articles.rss"
61
+ end
62
+
63
+ test "should not add .html to URLs in a public directory path" do
64
+ assert_normalized_with_base "/stylesheets"
65
+ assert_normalized_with_base "/images/spacer"
66
+ end
67
+
68
+ test "should normalize URLs that match page paths" do
69
+ assert_normalized "/mysite/about.html", "/about"
70
+ assert_normalized "/mysite/things/a.html", "/things/a"
71
+ end
72
+ end
@@ -0,0 +1,16 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ context "Bones Example Site" do
4
+ uses_example_site
5
+
6
+ test "should have proper paths" do
7
+ assert_equal relative_path('./example_site'), Bones.root
8
+ assert_equal relative_path('./example_site/pages'), Bones.pages_path
9
+ assert_equal relative_path('./example_site/layouts'), Bones.layouts_path
10
+ end
11
+
12
+ test "should have pages" do
13
+ assert 3, Bones.pages.length
14
+ assert ['about', 'index', 'things/a'], Bones.pages
15
+ end
16
+ end
@@ -0,0 +1,68 @@
1
+ $:.unshift(File.dirname(__FILE__) + '/../')
2
+ require 'lib/boot'
3
+ require 'test/unit'
4
+
5
+ class String
6
+ def only_alphanumeric
7
+ self.gsub(/[^a-zA-Z0-9]/, '_').squeeze('_')
8
+ end
9
+
10
+ def to_test_method_name
11
+ 'test_' + self.downcase.only_alphanumeric
12
+ end
13
+
14
+ def to_test_class_name
15
+ only_alphanumeric.camelize + 'Test'
16
+ end
17
+ end
18
+
19
+ def context(name, &block)
20
+ Object.const_set(name.to_s.to_test_class_name, Class.new(Test::Unit::TestCase, &block))
21
+ end
22
+
23
+
24
+ class Test::Unit::TestCase
25
+ class << self; attr_accessor :bones_root; end
26
+
27
+ def self.test(name, &block)
28
+ define_method(name.to_test_method_name, &block)
29
+ end
30
+
31
+ def self.setup(&block)
32
+ define_method(:setup, &block)
33
+ end
34
+
35
+ # def self.reset_bones
36
+ # Bones.reset
37
+ # Bones.root = File.expand_path(File.dirname(__FILE__) + '/../../')
38
+ # end
39
+
40
+ def self.uses_example_site
41
+ self.bones_root = File.expand_path(File.dirname(__FILE__) / 'example_site')
42
+ end
43
+
44
+ def run_with_bones_root(*args, &block)
45
+ with_bones_root do
46
+ run_without_bones_root(*args, &block)
47
+ end
48
+ end
49
+
50
+ alias_method_chain :run, :bones_root unless method_defined?(:run_without_bones_root)
51
+
52
+ def with_bones_root(root=nil, &block)
53
+ previous_root, Bones.root = Bones.root, (root || self.class.bones_root)
54
+ yield(block)
55
+ Bones.root = previous_root
56
+ end
57
+
58
+ def relative_path(path)
59
+ File.expand_path(File.dirname(__FILE__) / path)
60
+ end
61
+
62
+ def assert_include(collection, obj, message=nil)
63
+ assert collection.include?(obj), message
64
+ end
65
+ end
66
+
67
+ class TestRequest < OpenStruct
68
+ end
@@ -0,0 +1,69 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ context "Bones Template" do
4
+ uses_example_site
5
+
6
+ setup do
7
+ @template = Bones::Template.new('')
8
+ end
9
+
10
+ test "should return proper filename for top-level files" do
11
+ @template.path = 'about'
12
+ assert_include @template.filename, '/about.html.erb'
13
+ end
14
+
15
+ test "should return proper filename for directories" do
16
+ @template.path = 'things'
17
+ assert_include @template.filename, '/things/index.html.erb'
18
+ end
19
+
20
+ test "should return proper filename for files in directories" do
21
+ @template.path = 'things/a'
22
+ assert_include @template.filename, '/things/a.html.erb'
23
+ end
24
+
25
+ test "should return proper layout filename" do
26
+ @template.layout = 'example_layout'
27
+ assert_equal Bones.layouts_path / 'example_layout.html.erb', @template.layout_filename
28
+ end
29
+
30
+ test "should invoke custom helper" do
31
+ assert_include @template.some_custom_helper, 'Some custom helper'
32
+ end
33
+
34
+ test "should render partial partials/footer" do
35
+ assert_include @template.partial('partials/footer'), 'Footer text'
36
+ end
37
+
38
+ end
39
+
40
+ context "Bones template helpers" do
41
+ uses_example_site
42
+
43
+ def assert_include_helper(helper)
44
+ assert_include Bones::Template.helpers_to_include, helper
45
+ end
46
+
47
+ test "should include system core helper" do
48
+ assert_include_helper Bones.system_path / 'helpers/core_helper.rb'
49
+ end
50
+
51
+ test "should include user custom helper" do
52
+ assert_include_helper Bones.root / 'helpers/custom_helper.rb'
53
+ end
54
+ end
55
+
56
+ context "Bones template 'about'" do
57
+ uses_example_site
58
+
59
+ setup do
60
+ @template = Bones::Template.new('about')
61
+ @template.request = TestRequest.new(:path_info => 'about')
62
+ @response = @template.compile
63
+ end
64
+
65
+ test "should use layout 'example_layout'" do
66
+ assert_equal 'example_layout', @template.layout
67
+ assert_include @response, 'Example Layout'
68
+ end
69
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: scharfie-bones
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Scharf
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2009-02-04 00:00:00 -08:00
13
+ date: 2009-02-05 00:00:00 -08:00
14
14
  default_executable: bones
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -40,22 +40,55 @@ extensions: []
40
40
  extra_rdoc_files: []
41
41
 
42
42
  files:
43
- - README
44
- - lib/Rakefile
43
+ - bin
45
44
  - bin/bones
46
- - lib/bones.rb
45
+ - bones.gemspec
46
+ - lib/bones
47
+ - lib/bones/cache.rb
48
+ - lib/bones/initializer.rb
47
49
  - lib/bones/release.rb
50
+ - lib/bones/template.rb
51
+ - lib/bones/versioned_release.rb
52
+ - lib/bones.rb
48
53
  - lib/boot.rb
49
- - lib/cache.rb
50
54
  - lib/extensions.rb
51
55
  - lib/helpers
52
56
  - lib/helpers/core_helper.rb
53
- - lib/init.rb
54
57
  - lib/pages/directory.html.erb
55
58
  - lib/pages/intro.html.erb
59
+ - lib/Rakefile
56
60
  - lib/server.rb
61
+ - lib/tasks
57
62
  - lib/tasks/bones.rb
58
- - bones.gemspec
63
+ - Rakefile
64
+ - README
65
+ - test
66
+ - test/example_site
67
+ - test/example_site/helpers
68
+ - test/example_site/helpers/custom_helper.rb
69
+ - test/example_site/layouts
70
+ - test/example_site/layouts/example_layout.html.erb
71
+ - test/example_site/pages
72
+ - test/example_site/pages/about.html.erb
73
+ - test/example_site/pages/index.html.erb
74
+ - test/example_site/pages/partials
75
+ - test/example_site/pages/partials/_footer.html.erb
76
+ - test/example_site/pages/things
77
+ - test/example_site/pages/things/a.html.erb
78
+ - test/example_site/public
79
+ - test/example_site/public/images
80
+ - test/example_site/public/images/.gitignore
81
+ - test/example_site/public/javascripts
82
+ - test/example_site/public/javascripts/.gitignore
83
+ - test/example_site/public/stylesheets
84
+ - test/example_site/public/stylesheets/.gitignore
85
+ - test/example_site/public/videos
86
+ - test/example_site/public/videos/.gitignore
87
+ - test/test_bones.rb
88
+ - test/test_cache.rb
89
+ - test/test_template.rb
90
+ - test/test_example_site.rb
91
+ - test/test_helper.rb
59
92
  has_rdoc: false
60
93
  homepage: http://github.com/scharfie/bones
61
94
  post_install_message:
data/lib/init.rb DELETED
@@ -1,70 +0,0 @@
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
- ensure_file(ROOT / 'Rakefile') do |f|
55
- puts "** Adding Rakefile to parent directory"
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