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.
- data/.gitignore +1 -0
- data/Gemfile +6 -11
- data/README.md +24 -1
- data/Rakefile +13 -9
- data/bin/tipsy +4 -2
- data/lib/templates/server/htaccess.erb +14 -0
- data/lib/templates/site/Gemfile +19 -0
- data/lib/templates/site/assets/stylesheets/_config.css.scss +1 -0
- data/lib/templates/site/assets/stylesheets/screen.css.scss +1 -0
- data/lib/templates/site/config.rb +52 -0
- data/lib/templates/site/deploy.yml +27 -0
- data/lib/templates/site/layouts/default.html.erb +41 -0
- data/lib/templates/site/views/index.html.erb +2 -0
- data/lib/tipsy/compressors/{css.rb → css_compressor.rb} +0 -0
- data/lib/tipsy/compressors/javascript_compressor.rb +44 -0
- data/lib/tipsy/configuration.rb +9 -0
- data/lib/tipsy/handler/all.rb +4 -0
- data/lib/tipsy/handler/asset.rb +93 -0
- data/lib/tipsy/handler/erb.rb +42 -0
- data/lib/tipsy/handler/php.rb +36 -0
- data/lib/tipsy/{sass/template.rb → handler/sass/importer.rb} +15 -53
- data/lib/tipsy/handler/sass/resolver.rb +30 -0
- data/lib/tipsy/handler/sass.rb +36 -0
- data/lib/tipsy/handler/static.rb +30 -0
- data/lib/tipsy/helpers/asset_paths.rb +29 -1
- data/lib/tipsy/helpers/asset_tags.rb +1 -1
- data/lib/tipsy/helpers/capture.rb +12 -41
- data/lib/tipsy/helpers/rendering.rb +46 -0
- data/lib/tipsy/helpers/sass.rb +17 -6
- data/lib/tipsy/helpers/tag.rb +6 -9
- data/lib/tipsy/helpers.rb +13 -16
- data/lib/tipsy/runner.rb +82 -0
- data/lib/tipsy/runners/compiler.rb +189 -0
- data/lib/tipsy/runners/deployer.rb +7 -0
- data/lib/tipsy/runners/generator.rb +24 -0
- data/lib/tipsy/server.rb +56 -114
- data/lib/tipsy/site.rb +88 -0
- data/lib/tipsy/utils/logger.rb +47 -0
- data/lib/tipsy/utils/system.rb +115 -0
- data/lib/tipsy/utils/system_test.rb +103 -0
- data/lib/tipsy/version.rb +1 -1
- data/lib/tipsy/view/base.rb +55 -0
- data/lib/tipsy/view/context.rb +28 -0
- data/lib/tipsy/view/path.rb +44 -0
- data/lib/tipsy/view.rb +14 -68
- data/lib/tipsy.rb +30 -67
- data/{lib/tipsy/project/assets/javascripts/site.js → test/fixtures/capture.html.erb} +0 -0
- data/test/helpers/tag_test.rb +22 -0
- data/{lib/tipsy/project/assets/stylesheets/screen.css.scss → test/root/compiled/fake.txt} +0 -0
- data/test/root/{test/assets/javascripts/test.js → compiled/sub-path/fake.txt} +0 -0
- data/test/root/{development/assets/javascripts/test.js → compiled/sub-path-with-skip/fake.txt} +0 -0
- data/test/root/layouts/default.html.erb +0 -0
- data/test/root/views/index.html.erb +0 -0
- data/test/root/views/page.html.erb +0 -0
- data/test/root/views/sub/page.html.erb +0 -0
- data/test/root/views/sub/tertiary/index.html.erb +0 -0
- data/test/runner/compiler_test.rb +49 -0
- data/test/test_helper.rb +160 -21
- data/test/unit/site_test.rb +23 -0
- data/test/unit/tipsy_test.rb +13 -0
- data/test/unit/utils/system_test.rb +26 -0
- data/test/view/base_test.rb +34 -0
- data/test/view/path_test.rb +34 -0
- data/tipsy.gemspec +10 -7
- metadata +113 -84
- data/lib/tipsy/application.rb +0 -86
- data/lib/tipsy/builder.rb +0 -26
- data/lib/tipsy/builders/base.rb +0 -64
- data/lib/tipsy/builders/export.rb +0 -16
- data/lib/tipsy/builders/project.rb +0 -40
- data/lib/tipsy/builders/remote.rb +0 -14
- data/lib/tipsy/compressors/javascript.rb +0 -25
- data/lib/tipsy/logger.rb +0 -62
- data/lib/tipsy/project/Gemfile +0 -8
- data/lib/tipsy/project/config.erb +0 -19
- data/lib/tipsy/project/helpers/site_helper.rb +0 -4
- data/lib/tipsy/project/views/_layout.html.erb +0 -16
- data/test/fixtures/about.html +0 -1
- data/test/fixtures/contact.html +0 -1
- data/test/fixtures/index.html +0 -1
- data/test/functional/page_test.rb +0 -33
- data/test/root/.gitignore +0 -7
- data/test/root/development/assets/stylesheets/screen.css.scss +0 -3
- data/test/root/development/config.rb +0 -6
- data/test/root/development/views/_layout.html.erb +0 -20
- data/test/root/development/views/index.html.erb +0 -3
- data/test/root/test/assets/stylesheets/screen.css.scss +0 -3
- data/test/root/test/config.rb +0 -6
- data/test/root/test/views/_layout.html.erb +0 -1
- data/test/root/test/views/about/index.html +0 -1
- data/test/root/test/views/contact.html +0 -1
- data/test/root/test/views/index.html.erb +0 -1
- data/test/unit/helpers/asset_paths_test.rb +0 -14
- data/test/unit/helpers_test.rb +0 -22
- 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
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
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
|
-
|
33
|
-
|
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
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
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
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
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
@@ -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
|