scharfie-bones 0.1.5 → 0.2.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/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