tipsy 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. data/.gitignore +1 -0
  2. data/Gemfile +6 -11
  3. data/README.md +24 -1
  4. data/Rakefile +13 -9
  5. data/bin/tipsy +4 -2
  6. data/lib/templates/server/htaccess.erb +14 -0
  7. data/lib/templates/site/Gemfile +19 -0
  8. data/lib/templates/site/assets/stylesheets/_config.css.scss +1 -0
  9. data/lib/templates/site/assets/stylesheets/screen.css.scss +1 -0
  10. data/lib/templates/site/config.rb +52 -0
  11. data/lib/templates/site/deploy.yml +27 -0
  12. data/lib/templates/site/layouts/default.html.erb +41 -0
  13. data/lib/templates/site/views/index.html.erb +2 -0
  14. data/lib/tipsy/compressors/{css.rb → css_compressor.rb} +0 -0
  15. data/lib/tipsy/compressors/javascript_compressor.rb +44 -0
  16. data/lib/tipsy/configuration.rb +9 -0
  17. data/lib/tipsy/handler/all.rb +4 -0
  18. data/lib/tipsy/handler/asset.rb +93 -0
  19. data/lib/tipsy/handler/erb.rb +42 -0
  20. data/lib/tipsy/handler/php.rb +36 -0
  21. data/lib/tipsy/{sass/template.rb → handler/sass/importer.rb} +15 -53
  22. data/lib/tipsy/handler/sass/resolver.rb +30 -0
  23. data/lib/tipsy/handler/sass.rb +36 -0
  24. data/lib/tipsy/handler/static.rb +30 -0
  25. data/lib/tipsy/helpers/asset_paths.rb +29 -1
  26. data/lib/tipsy/helpers/asset_tags.rb +1 -1
  27. data/lib/tipsy/helpers/capture.rb +12 -41
  28. data/lib/tipsy/helpers/rendering.rb +46 -0
  29. data/lib/tipsy/helpers/sass.rb +17 -6
  30. data/lib/tipsy/helpers/tag.rb +6 -9
  31. data/lib/tipsy/helpers.rb +13 -16
  32. data/lib/tipsy/runner.rb +82 -0
  33. data/lib/tipsy/runners/compiler.rb +189 -0
  34. data/lib/tipsy/runners/deployer.rb +7 -0
  35. data/lib/tipsy/runners/generator.rb +24 -0
  36. data/lib/tipsy/server.rb +56 -114
  37. data/lib/tipsy/site.rb +88 -0
  38. data/lib/tipsy/utils/logger.rb +47 -0
  39. data/lib/tipsy/utils/system.rb +115 -0
  40. data/lib/tipsy/utils/system_test.rb +103 -0
  41. data/lib/tipsy/version.rb +1 -1
  42. data/lib/tipsy/view/base.rb +55 -0
  43. data/lib/tipsy/view/context.rb +28 -0
  44. data/lib/tipsy/view/path.rb +44 -0
  45. data/lib/tipsy/view.rb +14 -68
  46. data/lib/tipsy.rb +30 -67
  47. data/{lib/tipsy/project/assets/javascripts/site.js → test/fixtures/capture.html.erb} +0 -0
  48. data/test/helpers/tag_test.rb +22 -0
  49. data/{lib/tipsy/project/assets/stylesheets/screen.css.scss → test/root/compiled/fake.txt} +0 -0
  50. data/test/root/{test/assets/javascripts/test.js → compiled/sub-path/fake.txt} +0 -0
  51. data/test/root/{development/assets/javascripts/test.js → compiled/sub-path-with-skip/fake.txt} +0 -0
  52. data/test/root/layouts/default.html.erb +0 -0
  53. data/test/root/views/index.html.erb +0 -0
  54. data/test/root/views/page.html.erb +0 -0
  55. data/test/root/views/sub/page.html.erb +0 -0
  56. data/test/root/views/sub/tertiary/index.html.erb +0 -0
  57. data/test/runner/compiler_test.rb +49 -0
  58. data/test/test_helper.rb +160 -21
  59. data/test/unit/site_test.rb +23 -0
  60. data/test/unit/tipsy_test.rb +13 -0
  61. data/test/unit/utils/system_test.rb +26 -0
  62. data/test/view/base_test.rb +34 -0
  63. data/test/view/path_test.rb +34 -0
  64. data/tipsy.gemspec +10 -7
  65. metadata +113 -84
  66. data/lib/tipsy/application.rb +0 -86
  67. data/lib/tipsy/builder.rb +0 -26
  68. data/lib/tipsy/builders/base.rb +0 -64
  69. data/lib/tipsy/builders/export.rb +0 -16
  70. data/lib/tipsy/builders/project.rb +0 -40
  71. data/lib/tipsy/builders/remote.rb +0 -14
  72. data/lib/tipsy/compressors/javascript.rb +0 -25
  73. data/lib/tipsy/logger.rb +0 -62
  74. data/lib/tipsy/project/Gemfile +0 -8
  75. data/lib/tipsy/project/config.erb +0 -19
  76. data/lib/tipsy/project/helpers/site_helper.rb +0 -4
  77. data/lib/tipsy/project/views/_layout.html.erb +0 -16
  78. data/test/fixtures/about.html +0 -1
  79. data/test/fixtures/contact.html +0 -1
  80. data/test/fixtures/index.html +0 -1
  81. data/test/functional/page_test.rb +0 -33
  82. data/test/root/.gitignore +0 -7
  83. data/test/root/development/assets/stylesheets/screen.css.scss +0 -3
  84. data/test/root/development/config.rb +0 -6
  85. data/test/root/development/views/_layout.html.erb +0 -20
  86. data/test/root/development/views/index.html.erb +0 -3
  87. data/test/root/test/assets/stylesheets/screen.css.scss +0 -3
  88. data/test/root/test/config.rb +0 -6
  89. data/test/root/test/views/_layout.html.erb +0 -1
  90. data/test/root/test/views/about/index.html +0 -1
  91. data/test/root/test/views/contact.html +0 -1
  92. data/test/root/test/views/index.html.erb +0 -1
  93. data/test/unit/helpers/asset_paths_test.rb +0 -14
  94. data/test/unit/helpers_test.rb +0 -22
  95. data/test/unit/server_test.rb +0 -1
data/lib/tipsy/server.rb CHANGED
@@ -1,134 +1,76 @@
1
1
  require 'rack'
2
- require 'sprockets'
3
2
  require 'hike'
4
3
 
5
- module Tipsy
6
-
4
+ module Tipsy
5
+ ##
6
+ # Rack server implementation.
7
+ # Tipsy::Server will run any Rack::Builder compatable format. If thin or mongrel
8
+ # are availble, they will be used first, and in that order, with a fallback to webrick.
9
+ #
7
10
  class Server
11
+ attr_reader :request, :response
8
12
 
9
- attr_reader :request
10
- attr_reader :response
11
-
12
- def self.init!
13
- Rack::Builder.new {
14
- use Rack::CommonLogger
15
- use Rack::ShowStatus
16
- use Rack::ShowExceptions
17
- use Tipsy::StaticFile, :root => Tipsy.options.public_path, :urls => %w[/]
18
- run Rack::Cascade.new([
19
- Rack::URLMap.new({ "/#{File.basename(Tipsy.options.asset_path)}" => Tipsy::AssetHandler.new }),
20
- Tipsy::Server.new
21
- ])
22
- }
13
+ class << self
14
+ ##
15
+ # Run the Rack::Builder application
16
+ # @param [run] Rack::Builder An instance of Rack::Builder
17
+ #
18
+ def run!(app, options)
19
+ begin
20
+ handler = Rack::Handler.get('thin')
21
+ handler.run app, options do |server|
22
+ puts "Running Tipsy with Thin (#{Thin::VERSION::STRING})."
23
+ end
24
+ exit(0)
25
+ rescue LoadError
26
+ begin
27
+ handler = Rack::Handler.get('mongrel')
28
+ handler.run app, options do |server|
29
+ puts "Running Tipsy with Mongrel (#{Mongrel::Const::MONGREL_VERSION})."
30
+ end
31
+ exit(0)
32
+ rescue LoadError
33
+ handler = Rack::Handler.get('webrick')
34
+ handler.run app, server_opts do |server|
35
+ puts "Running Tipsy with Webrick. To use Mongrel or Thin (recommended), add them to your Gemfile"
36
+ trap("INT"){ server.shutdown }
37
+ end
38
+ end
39
+ end
40
+ end
23
41
  end
24
-
42
+
25
43
  def initialize
26
44
  @last_update = Time.now
27
45
  end
28
46
 
29
47
  def call(env)
30
48
  @request = Request.new(env)
31
- @response = Response.new
32
- path = request.path_info.to_s.sub(/^\//, '')
33
- view = Tipsy::View.new(path, request)
34
- content = view.render
35
- content.nil? ? not_found : finish(content)
36
- end
37
-
38
- private
39
-
40
- def finish(content)
41
- [ 200, { 'Content-Type' => 'text/html' }, [content] ]
42
- end
43
-
44
- def not_found
45
- [ 400, { 'Content-Type' => 'text/html' }, [] ]
46
- end
47
-
48
- end
49
-
50
- class AssetHandler < Sprockets::Environment
51
- def initialize
52
- Sprockets.register_engine '.scss', Tipsy::Sass::Template
53
-
54
- super(Tipsy.root) do |env|
55
- env.static_root = Tipsy.options.asset_path
56
- #env.css_compressor = Tipsy::Compressors::CssCompressor.new
57
- # begin
58
- # require 'uglifier'
59
- # env.js_compressor = Uglifier
60
- # rescue LoadError
61
- # env.js_compressor = Tipsy::Compressors::JavascriptCompressor.new
62
- # end
63
- end
64
- Tipsy.sprockets = self
65
- configure_paths!
66
- self
67
- end
68
-
69
- private
70
-
71
- def configure_paths!
72
- require 'compass'
73
- require 'sass/plugin'
74
-
75
- append_path "assets/javascripts"
76
- append_path "assets/images"
77
- append_path "assets/stylesheets"
78
-
79
- compass_config = ::Compass::Configuration::Data.new("project")
80
- compass_config.project_type = :rails
81
- compass_config.project_path = Tipsy.root
82
- compass_config.extensions_dir = Tipsy.root
83
- compass_config.sass_dir = File.join("assets", "stylesheets")
84
-
85
- ::Sass::Plugin.engine_options.merge!(Compass.sass_engine_options)
86
-
87
- Tipsy.options.assets.paths |= self.paths
88
-
89
- end
90
-
91
- end
92
-
93
- # From the rack/contrib TryStatic class
94
- class StaticFile
95
- attr_reader :app, :try_files, :static
96
-
97
- def initialize(app, options)
98
- @app = app
99
- @try_files = ['', *options.delete(:try)]
100
- @static = ::Rack::Static.new(lambda { [404, {}, []] }, options)
49
+ @response = Response.new
50
+ result = Tipsy::View::Base.new(@request, @response)
51
+ result.render.to_a
101
52
  end
102
53
 
103
- def call(env)
104
- orig_path = env['PATH_INFO']
105
- found = nil
106
- try_files.each do |path|
107
- resp = static.call(env.merge!({'PATH_INFO' => orig_path + path}))
108
- break if 404 != resp[0] && found = resp
109
- end
110
- found or app.call(env.merge!('PATH_INFO' => orig_path))
54
+ ##
55
+ # Subclass Rack::Request to create a rails-like params hash.
56
+ class Request < Rack::Request
57
+ def params
58
+ @params ||= begin
59
+ hash = HashWithIndifferentAccess.new.update(Rack::Utils.parse_nested_query(query_string))
60
+ post_params = form_data? ? Rack::Utils.parse_nested_query(body.read) : {}
61
+ hash.update(post_params) unless post_params.empty?
62
+ hash
63
+ end
64
+ end
111
65
  end
112
- end
113
66
 
114
-
115
- class Request < Rack::Request
116
- # Hash access to params
117
- def params
118
- @params ||= begin
119
- hash = HashWithIndifferentAccess.new.update(Rack::Utils.parse_nested_query(query_string))
120
- post_params = form_data? ? Rack::Utils.parse_nested_query(body.read) : {}
121
- hash.update(post_params) unless post_params.empty?
122
- hash
67
+ ##
68
+ # Ensure proper body output
69
+ class Response < Rack::Response
70
+ def body=(value)
71
+ value.respond_to?(:each) ? super(value) : super([value])
123
72
  end
124
- end
125
- end
126
-
127
- class Response < Rack::Response
128
- def body=(value)
129
- value.respond_to?(:each) ? super(value) : super([value])
130
73
  end
131
74
  end
132
75
 
133
- end
134
-
76
+ end
data/lib/tipsy/site.rb ADDED
@@ -0,0 +1,88 @@
1
+ require 'active_support/configurable'
2
+
3
+ module Tipsy
4
+
5
+ class Site
6
+ include ActiveSupport::Configurable
7
+ config_accessor :asset_path, :compile_to, :css_path, :javascripts_path, :images_path, :fonts_path,
8
+ :public_path, :load_paths, :compile_to, :compile
9
+ ##
10
+ # Site configuration options
11
+ #
12
+ # General:
13
+ # port: The port in which the server should run
14
+ # address: The address on which the server should run
15
+ # public_path: Path to the public files/assets
16
+ #
17
+ # Assets:
18
+ # asset_path: The path in which assets should be preserved
19
+ # assets.paths: Paths in which sprockets will look for assets
20
+ # assets.javascripts_path: Path in which javascript files should be served. Helper methods will use this path
21
+ # assets.images_path: Path in which image assets should be served. Helper methods will use this path
22
+ # assets.css_path: Path in which stylesheets should be served. Helper methods will use this path
23
+ #
24
+ # Compiling:
25
+ # compile_path: The directory in which the site will be compiled
26
+ # compile.preserve: An array of files or directories that will be preserved when the compile folder is rebuilt.
27
+
28
+ config.port = 4000
29
+ config.address = '0.0.0.0'
30
+
31
+ config.public_path = File.join(Tipsy.root, 'public')
32
+ config.load_paths = ::ActiveSupport::OrderedOptions.new( 'assets' => [] )
33
+ config.asset_path = '/assets'
34
+ config.images_path = asset_path
35
+ config.fonts_path = "/fonts"
36
+ config.javascripts_path = asset_path
37
+ config.css_path = asset_path
38
+ config.compile_to = File.join(Tipsy.root, 'compiled')
39
+
40
+ config.compile = ::ActiveSupport::OrderedOptions.new
41
+ config.compile.assets = ['screen.css', 'site.js']
42
+ config.compile.preserve = [".svn", ".gitignore", ".git"]
43
+ config.compile.skip = []
44
+
45
+
46
+ config.compile.enable_rewrite = true
47
+ config.compile.rewrite_mode = :htaccess
48
+
49
+ def self.configure!
50
+ @_callbacks = { :before => [], :after => [] }
51
+ local_config = File.join(Tipsy.root, 'config.rb')
52
+ if File.exists?(local_config)
53
+ class_eval(File.open(local_config).readlines.join("\n"))
54
+ end
55
+
56
+ end
57
+
58
+ ##
59
+ # Callback support
60
+ #
61
+ [:compile].each do |callback|
62
+ class_eval <<-METHOD, __FILE__, __LINE__ + 1
63
+ def self.before_#{callback}(&block)
64
+ if block_given?
65
+ @_callbacks[:before] << block
66
+ else
67
+ @_callbacks[:before].each(&:call)
68
+ end
69
+ end
70
+
71
+ def self.after_#{callback}(&block)
72
+ if block_given?
73
+ @_callbacks[:after] << block
74
+ else
75
+ @_callbacks[:after].each(&:call)
76
+ end
77
+ end
78
+ METHOD
79
+ end
80
+
81
+
82
+ def initialize
83
+ @_callbacks = {}
84
+ end
85
+
86
+ end
87
+
88
+ end
@@ -0,0 +1,47 @@
1
+ module Tipsy
2
+ module Utils
3
+ class Logger
4
+ COLORS = { :clear => 0, :red => 31, :green => 32, :yellow => 33 }
5
+ attr_reader :stdout
6
+
7
+ def initialize(o)
8
+ @stdout = o
9
+ end
10
+
11
+ def print(msg)
12
+ puts msg
13
+ end
14
+
15
+ def action(name, action)
16
+ print colorize(:green, (name.rjust(12, ' ') << " "), :clear, action)
17
+ end
18
+
19
+ def info(msg)
20
+ print msg unless Tipsy.env.eql?("test")
21
+ end
22
+
23
+ def warn(msg)
24
+ print colorize(:yellow, "Warning: ", :clear, msg)
25
+ end
26
+
27
+ def error
28
+ print colorize(:red, "Error: ", :clear, msg)
29
+ end
30
+
31
+ private
32
+
33
+ def colorize(*args)
34
+ output = args.inject([]) do |arr, option|
35
+ unless option.is_a?(Symbol) && COLORS[option]
36
+ arr << option
37
+ else
38
+ arr << "\e[#{COLORS[option]}m"
39
+ end
40
+ arr
41
+ end
42
+ output.push("\e[0m").join("")
43
+ end
44
+
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,115 @@
1
+ require 'find'
2
+ require 'pathname'
3
+ require 'fileutils'
4
+
5
+ module Tipsy
6
+ module Utils
7
+ module System
8
+ extend ActiveSupport::Concern
9
+
10
+ def excludes
11
+ @_excludes ||= ['.svn', '.git', '.gitignore', '.sass-cache', 'config.erb', '.rb', '.DS_Store']
12
+ end
13
+
14
+ def excluded?(file, against = nil)
15
+ against ||= excludes
16
+ return true if file.to_s == '.' || file.to_s == '..' || against.include?(file)
17
+ check = ::Pathname.new(file)
18
+ return true if against.include?(check.basename.to_s)
19
+ !against.detect do |exc|
20
+ (check.basename == exc || check.extname == exc)
21
+ end.nil?
22
+ end
23
+
24
+ ##
25
+ # Copies from one location to another
26
+ #
27
+ def copy_file(source, destination)
28
+ return true if skip_file?(source)
29
+ log_action("create", destination)
30
+ ::FileUtils.cp(source, destination)
31
+ end
32
+
33
+ ##
34
+ # Makes a matching folder in destination from source
35
+ #
36
+ def copy_folder(dirname)
37
+ return true if skip_path?(dirname)
38
+ log_action("create", dirname)
39
+ ::FileUtils.mkdir(dirname)
40
+ end
41
+
42
+ ##
43
+ # Basic alias
44
+ #
45
+ def mkdir_p(path)
46
+ return true if ::File.exists?(path)
47
+ log_action("create", path)
48
+ ::FileUtils.mkdir_p(path)
49
+ end
50
+
51
+ def make_file(path, content)
52
+ ::File.new(path, 'w').puts(content)
53
+ end
54
+
55
+ def rm_rf(path)
56
+ log_action('delete', path)
57
+ ::FileUtils.rm_rf(path)
58
+ end
59
+
60
+ def unlink(file)
61
+ log_action('delete', file)
62
+ ::File.unlink(file)
63
+ end
64
+
65
+ def empty_dir?(path)
66
+ ::Dir.entries(path).reject do |ent|
67
+ ent == "." || ent == ".." || ent == path
68
+ end.empty?
69
+ end
70
+
71
+ ##
72
+ # Iterate through a file tree and process each file and folder.
73
+ #
74
+ def copy_tree(src, dest)
75
+ ::Dir.foreach(src) do |file|
76
+ next if excluded?(file)
77
+ source = ::File.join(src, file)
78
+ destination = ::File.join(dest, file)
79
+
80
+ if ::File.directory?(source)
81
+ copy_folder(destination)
82
+ copy_tree(source, destination)
83
+ else
84
+ copy_file(source, destination)
85
+ end
86
+ end
87
+ end
88
+
89
+ # Override in specific runner as necessary
90
+ # Allows more fine-grained control per directory.
91
+ def skip_path?(dirname)
92
+ false
93
+ end
94
+
95
+ # Override in specific runner as necessary.
96
+ # Allows more fine-grained control per file.
97
+ def skip_file?(filename)
98
+ false
99
+ end
100
+
101
+ ##
102
+ # Collect the entire tree of files and folders and yield to a block
103
+ def enumerate_tree(path, &block)
104
+ ::Find.find(path) do |path|
105
+ yield path
106
+ end
107
+ end
108
+
109
+ def log_action(name, action)
110
+ ::Tipsy.logger.action(name, action)
111
+ end
112
+
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,103 @@
1
+ require 'find'
2
+ require 'pathname'
3
+ require 'fileutils'
4
+
5
+ module Tipsy
6
+ module Utils
7
+ ##
8
+ # Overrides file and directory methods for the test environment
9
+ module SystemTest
10
+ attr_reader :deletions, :creations
11
+
12
+ extend ActiveSupport::Concern
13
+ include System
14
+
15
+ ##
16
+ # Copies from one location to another
17
+ #
18
+ def copy_file(source, destination)
19
+ return true if skip_file?(source)
20
+ set_created(destination)
21
+ end
22
+
23
+ ##
24
+ # Makes a matching folder in destination from source
25
+ #
26
+ def copy_folder(dirname)
27
+ return true if skip_path?(dirname)
28
+ log_action("create", dirname)
29
+ set_created(dirname)
30
+ end
31
+
32
+ ##
33
+ # Basic alias
34
+ #
35
+ def mkdir_p(path)
36
+ return true if ::File.exists?(path)
37
+ log_action("create", path)
38
+ set_created(path)
39
+ end
40
+
41
+ def make_file(path, content)
42
+ set_created(path)
43
+ end
44
+
45
+ def rm_rf(path)
46
+ log_action('delete', path)
47
+ set_deleted(path)
48
+ end
49
+
50
+ def unlink(file)
51
+ log_action('delete', file)
52
+ set_deleted(file)
53
+ end
54
+
55
+ def empty_dir?(path)
56
+ ::Dir.entries(path).reject do |ent|
57
+ ent == "." || ent == ".." || ent == path || was_deleted?(File.join(path, ent))
58
+ end.empty?
59
+ end
60
+
61
+ ##
62
+ # Iterate through a file tree and process each file and folder.
63
+ #
64
+ def copy_tree(src, dest)
65
+ ::Dir.foreach(src) do |file|
66
+ next if excluded?(file)
67
+ source = ::File.join(src, file)
68
+ destination = ::File.join(dest, file)
69
+
70
+ if ::File.directory?(source)
71
+ copy_folder(destination)
72
+ copy_tree(source, destination)
73
+ else
74
+ copy_file(source, destination)
75
+ end
76
+ end
77
+ end
78
+
79
+
80
+ def log_action(name, action)
81
+ end
82
+
83
+ def was_deleted?(path)
84
+ (@deletions ||= []).include?(path)
85
+ end
86
+
87
+ def was_created?(path)
88
+ (@creations ||= []).include?(path)
89
+ end
90
+
91
+ private
92
+
93
+ def set_created(path)
94
+ (@creations ||= []) << path
95
+ end
96
+
97
+ def set_deleted(path)
98
+ (@deletions ||= []) << path
99
+ end
100
+
101
+ end
102
+ end
103
+ end
data/lib/tipsy/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Tipsy
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -0,0 +1,55 @@
1
+ module Tipsy
2
+ module View
3
+ class Base
4
+
5
+ attr_reader :lookup_context, :request, :response, :view_context, :template
6
+
7
+ def initialize(request, response)
8
+ @request = request
9
+ @response = response
10
+ @lookup_context = Tipsy::View::Path.new
11
+ end
12
+
13
+ def render
14
+
15
+ @template = lookup_context.locate_template(current_path)
16
+
17
+ if template.nil?
18
+ return generate_response(nil)
19
+ end
20
+
21
+ @view_context = Tipsy::View::Context.new(request, lookup_context, File.dirname(template), lookup_context)
22
+
23
+ handler = Tilt[template]
24
+ tilt = handler.new(template, nil, :outvar => '@output_buffer')
25
+ result = tilt.render(view_context)
26
+
27
+ unless view_context.layout == false
28
+ layout = lookup_context.locate_layout(view_context.layout)
29
+ raise Tipsy::View::LayoutMissing.new("Missing layout '#{view_context.layout}'") and return if layout.nil?
30
+ wrapped = Tilt[layout].new(layout, nil, :outvar => '@output_buffer')
31
+ result = wrapped.render(view_context) do |*args|
32
+ result
33
+ end
34
+ end
35
+
36
+ generate_response(result)
37
+
38
+ end
39
+
40
+ private
41
+
42
+ def current_path
43
+ @_current_path ||= request.path_info.to_s.sub(/^\//, '')
44
+ end
45
+
46
+ def generate_response(content)
47
+ response.status = ( content.nil? ? 404 : 200)
48
+ response.headers['content-type'] = "text/html"
49
+ response.body = content
50
+ response
51
+ end
52
+
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,28 @@
1
+ module Tipsy
2
+ module View
3
+ ##
4
+ # All views are rendered within a context object. This object handles
5
+ # transitioning data between templates and layouts.
6
+ #
7
+ class Context
8
+ include Tipsy::Helpers
9
+ attr_reader :request, :template, :layout, :virtual_path, :lookup_context
10
+
11
+ def initialize(request, template, path, lookup)
12
+ @request = request
13
+ @layout = 'default'
14
+ @template = template
15
+ @virtual_path = path
16
+ @lookup_context = lookup
17
+ @output_buffer = nil
18
+ end
19
+
20
+ def layout(set = nil)
21
+ @layout = set unless set.nil?
22
+ @layout
23
+ end
24
+
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,44 @@
1
+ require 'hike'
2
+
3
+ module Tipsy
4
+ module View
5
+ class Path < ::Hike::Trail
6
+
7
+ def initialize
8
+ super(Tipsy.root)
9
+ append_path('.')
10
+ append_extensions '.erb','.html', '.json', '.xml'
11
+ end
12
+
13
+ def locate_template(view_path)
14
+ with_temporary_scope('views') do
15
+ @_template ||= (find(view_path) || find(File.join(view_path, "index")))
16
+ end
17
+ end
18
+
19
+ def locate_layout(name)
20
+ with_temporary_scope('layouts') do
21
+ @_layout ||= find(name)
22
+ end
23
+ end
24
+
25
+ def locate_relative(path, name)
26
+ with_temporary_scope("views", path) do
27
+ find(name)
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def with_temporary_scope(*new_scope)
34
+ old_paths = @paths
35
+ new_scope = [Tipsy.root, new_scope].flatten
36
+ append_path(File.join(*new_scope))
37
+ yield
38
+ ensure
39
+ @paths = old_paths
40
+ end
41
+
42
+ end
43
+ end
44
+ end