tipsy 0.0.2 → 0.0.3

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.
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