tipsy 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/Gemfile +9 -0
  2. data/README.md +2 -2
  3. data/Rakefile +10 -0
  4. data/bin/tipsy +16 -5
  5. data/lib/tipsy.rb +26 -14
  6. data/lib/tipsy/application.rb +14 -16
  7. data/lib/tipsy/builder.rb +17 -4
  8. data/lib/tipsy/builders/base.rb +64 -0
  9. data/lib/tipsy/builders/export.rb +16 -0
  10. data/lib/tipsy/builders/project.rb +40 -0
  11. data/lib/tipsy/builders/remote.rb +14 -0
  12. data/lib/tipsy/compressors/css.rb +11 -0
  13. data/lib/tipsy/compressors/javascript.rb +25 -0
  14. data/lib/tipsy/helpers.rb +24 -1
  15. data/lib/tipsy/helpers/asset_paths.rb +19 -0
  16. data/lib/tipsy/helpers/asset_tags.rb +32 -0
  17. data/lib/tipsy/helpers/capture.rb +33 -0
  18. data/lib/tipsy/helpers/sass.rb +40 -0
  19. data/lib/tipsy/helpers/tag.rb +12 -0
  20. data/lib/tipsy/logger.rb +54 -3
  21. data/lib/tipsy/project/Gemfile +8 -0
  22. data/lib/tipsy/project/config.erb +5 -2
  23. data/lib/tipsy/sass/template.rb +137 -0
  24. data/lib/tipsy/server.rb +50 -7
  25. data/lib/tipsy/version.rb +1 -1
  26. data/lib/tipsy/view.rb +24 -10
  27. data/test/fixtures/about.html +1 -0
  28. data/test/fixtures/contact.html +1 -0
  29. data/test/fixtures/index.html +1 -0
  30. data/test/functional/page_test.rb +33 -0
  31. data/test/root/{assets → development/assets}/javascripts/test.js +0 -0
  32. data/test/root/{assets → development/assets}/stylesheets/screen.css.scss +0 -0
  33. data/test/root/{config.rb → development/config.rb} +0 -0
  34. data/test/root/{views → development/views}/_layout.html.erb +0 -0
  35. data/test/root/{views → development/views}/index.html.erb +0 -0
  36. data/test/root/test/assets/javascripts/test.js +0 -0
  37. data/test/root/test/assets/stylesheets/screen.css.scss +3 -0
  38. data/test/root/test/config.rb +6 -0
  39. data/test/root/test/views/_layout.html.erb +1 -0
  40. data/test/root/test/views/about/index.html +1 -0
  41. data/test/root/test/views/contact.html +1 -0
  42. data/test/root/test/views/index.html.erb +1 -0
  43. data/test/test_helper.rb +33 -0
  44. data/test/unit/helpers/asset_paths_test.rb +14 -0
  45. data/test/unit/helpers_test.rb +22 -0
  46. data/test/unit/server_test.rb +1 -0
  47. data/tipsy.gemspec +5 -4
  48. metadata +83 -35
  49. data/config.ru +0 -26
  50. data/lib/tipsy/generator.rb +0 -53
@@ -0,0 +1,32 @@
1
+ module Tipsy
2
+ module Helpers
3
+ module AssetTags
4
+
5
+ def image_tag(src, html_attrs = {})
6
+ html_attrs.stringify_keys!
7
+ html_attrs.reverse_merge!('alt' => File.basename(src))
8
+ tag(:img, html_attrs.merge('src' => asset_path(src)))
9
+ end
10
+
11
+ def javascript_include_tag(*files)
12
+ html_attrs = files.extract_options!
13
+ html_attrs.stringify_keys!
14
+ files.map{ |file|
15
+ content_tag('script', '', {'src' => asset_path(path_with_ext(file, 'js'))}.merge!(html_attrs))
16
+ }.join("\n")
17
+ end
18
+
19
+ def stylesheet_link_tag(*files)
20
+ html_attrs = files.extract_options!
21
+ html_attrs.reverse_merge!({
22
+ :media => "screen"
23
+ }).stringify_keys!
24
+
25
+ files.map{ |file|
26
+ content_tag('link', '', { 'href' => asset_path(path_with_ext(file, 'css')), 'rel' => "stylesheet" }.merge!(html_attrs))
27
+ }.join("\n")
28
+ end
29
+
30
+ end
31
+ end
32
+ end
@@ -17,6 +17,39 @@ module Tipsy
17
17
  @_output_buffer = orig_buffer
18
18
  end
19
19
 
20
+ def render(options = {})
21
+ options.symbolize_keys!
22
+ assert_valid_keys!(options, :template, :partial, :collection, :locals)
23
+
24
+ if template = options.delete(:template)
25
+ _render_template(template, options)
26
+ elsif template = options.delete(:partial)
27
+ _render_template(template, options, true)
28
+ else
29
+ raise 'Render requires a :template or :partial option.'
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def _render_template(name, options = {}, partial = false)
36
+ to_render = ( partial === true ? "_#{name}" : name )
37
+ to_render = view_trail.find(to_render)
38
+ unless to_render.nil?
39
+ local_vars = options.delete(:locals) || {}
40
+ results = Tilt[to_render].new(to_render, nil)
41
+ return results.render(self, local_vars)
42
+ end
43
+ raise "Missing #{ partial ? 'partial' : 'template' } #{name}."
44
+ end
45
+
46
+ def assert_valid_keys!(hash, *keys)
47
+ left = hash.keys.reject{ |k| keys.include?(k) }
48
+ unless left.empty?
49
+ raise 'Invalid keys for hash: #{left.join(", ")}'
50
+ end
51
+ end
52
+
20
53
  end
21
54
  end
22
55
  end
@@ -0,0 +1,40 @@
1
+ require 'sass'
2
+
3
+ module Tipsy
4
+ module Helpers
5
+ module Sass
6
+
7
+ def asset_path(asset, kind)
8
+ ::Sass::Script::String.new(public_path(asset.value, kind.value), true)
9
+ end
10
+
11
+ def asset_url(asset, kind)
12
+ ::Sass::Script::String.new(%Q{url(#{public_path(asset.value, kind.value)})})
13
+ end
14
+
15
+ [:image, :font, :video, :audio, :javascript, :stylesheet].each do |asset_class|
16
+ class_eval %Q{
17
+ def #{asset_class}_path(asset)
18
+ asset_path(asset, Sass::Script::String.new("#{asset_class}"))
19
+ end
20
+ def #{asset_class}_url(asset)
21
+ asset_url(asset, Sass::Script::String.new("#{asset_class}"))
22
+ end
23
+ }, __FILE__, __LINE__ - 6
24
+ end
25
+
26
+ protected
27
+ def public_path(asset, kind)
28
+ options[:custom][:resolver].public_path(asset, kind.pluralize)
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ module Sass
35
+ module Script
36
+ module Functions
37
+ include Tipsy::Helpers::Sass
38
+ end
39
+ end
40
+ end
@@ -14,6 +14,18 @@ module Tipsy
14
14
  "<#{name}#{make_attributes(html_attrs)}>#{content}</#{name}>"
15
15
  end
16
16
 
17
+ def link_to(text, path, html_attrs = {})
18
+ content_tag(:a, text, html_attrs.merge!('href' => path))
19
+ end
20
+
21
+ def mail_to(addr, text = nil, html_attrs = {})
22
+ unless text || text.is_a?(Hash)
23
+ html_attrs = text if text
24
+ text = addr
25
+ end
26
+ link_to(text, "mailto:#{addr}", html_attrs)
27
+ end
28
+
17
29
  private
18
30
 
19
31
  def make_attributes(hash)
data/lib/tipsy/logger.rb CHANGED
@@ -1,11 +1,62 @@
1
1
  require 'logger'
2
2
 
3
3
  module Tipsy
4
- class Logger < ::Logger
4
+ class Logger
5
5
 
6
- def initialize
7
- super($stdout)
6
+ COLOR_VALUES = {
7
+ :clear => 0,
8
+ :red => 31,
9
+ :green => 32,
10
+ :yellow => 33
11
+ }
12
+
13
+ attr_accessor :cache
14
+ attr_reader :stdout
15
+
16
+ def initialize(o)
17
+ @stdout = o
18
+ @cache = []
8
19
  end
9
20
 
21
+ def append(msg)
22
+ @cache << msg
23
+ end
24
+
25
+ def flush!
26
+ cache.each{ |c| print c }
27
+ end
28
+
29
+ def log_action(name, action)
30
+ print colorize(:green, (name.rjust(12, ' ') << " "), :clear, action)
31
+ end
32
+
33
+ def info(msg)
34
+ print msg
35
+ end
36
+
37
+ def warn(msg)
38
+ print colorize(:yellow, "Warning: ", :clear, msg)
39
+ end
40
+
41
+ def error
42
+ print colorize(:red, "Error: ", :clear, msg)
43
+ end
44
+
45
+ def colorize(*args)
46
+ output = args.inject([]) do |arr, option|
47
+ unless option.is_a?(Symbol) && COLOR_VALUES[option]
48
+ arr << option
49
+ else
50
+ arr << "\e[#{COLOR_VALUES[option]}m"
51
+ end
52
+ arr
53
+ end
54
+ output.push("\e[0m").join("")
55
+ end
56
+
57
+ def print(msg)
58
+ puts msg
59
+ end
60
+
10
61
  end
11
62
  end
@@ -0,0 +1,8 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "rack", "~> 1.2"
4
+ gem "tilt", "~> 1.3"
5
+ gem "i18n", "~> 0.5"
6
+ gem "sass", "~> 3.1"
7
+ gem "activesupport", ">= 3.0"
8
+ gem 'sprockets', '~> 2.0.0.beta.12'
@@ -1,8 +1,11 @@
1
1
  class <%= classname %> < Tipsy::Application
2
2
 
3
3
  # Configure assets to be precompiled
4
- config.assets << "site.js"
5
- config.assets << "screen.css"
4
+ config.assets.precompile << "site.js"
5
+ config.assets.precompile << "screen.css"
6
+
7
+ # Add assets to the load path
8
+ # config.assets.paths << "/some/path"
6
9
 
7
10
  # The path where build files will go when compiled
8
11
  # config.build_path = <%= File.join(root, 'build') %>
@@ -0,0 +1,137 @@
1
+ require 'tilt'
2
+ require 'sass/engine'
3
+ require 'compass'
4
+
5
+ ##
6
+ # Most of this was extracted and modified from the sass-rails plugin, since most of the
7
+ # Sprockets functionality is the same.
8
+ #
9
+ module Tipsy
10
+ module Sass
11
+ class Template < Tilt::ScssTemplate
12
+ self.default_mime_type = 'text/css'
13
+
14
+ class Resolver
15
+ attr_accessor :context
16
+ def initialize(context)
17
+ @context = context
18
+ end
19
+ def resolve(path, content_type = :self)
20
+ options = {}
21
+ options[:content_type] = content_type unless content_type.nil?
22
+ context.resolve(path, options)
23
+ rescue Sprockets::FileNotFound, Sprockets::ContentTypeMismatch
24
+ nil
25
+ end
26
+ def public_path(path, scope)
27
+ context.asset_paths.compute_public_path(path, scope)
28
+ end
29
+ def process(path)
30
+ context.environment[path].to_s
31
+ end
32
+ end
33
+
34
+
35
+ class Importer
36
+
37
+ GLOB = /\*|\[.+\]/
38
+ PARTIAL = /^_/
39
+ HAS_EXTENSION = /\.css(.s[ac]ss)?$/
40
+ SASS_EXTENSIONS = {
41
+ ".css.sass" => :sass,
42
+ ".css.scss" => :scss,
43
+ ".sass" => :sass,
44
+ ".scss" => :scss
45
+ }
46
+
47
+ attr_reader :context
48
+
49
+ def initialize(context)
50
+ @context = context
51
+ @resolver = Resolver.new(context)
52
+ end
53
+
54
+ def sass_file?(filename)
55
+ filename = filename.to_s
56
+ SASS_EXTENSIONS.keys.any?{|ext| filename[ext]}
57
+ end
58
+
59
+ def syntax(filename)
60
+ filename = filename.to_s
61
+ SASS_EXTENSIONS.each {|ext, syntax| return syntax if filename[(ext.size+2)..-1][ext]}
62
+ nil
63
+ end
64
+
65
+ def render_with_engine(data, pathname, options = {})
66
+ ::Sass::Engine.new(data, options.merge(:filename => pathname.to_s, :importer => self, :syntax => syntax(pathname)))
67
+ end
68
+
69
+ def resolve(name, base_pathname = nil)
70
+ name = Pathname.new(name)
71
+ if base_pathname && base_pathname.to_s.size > 0
72
+ root = Pathname.new(context.root_path)
73
+ name = base_pathname.relative_path_from(root).join(name)
74
+ end
75
+ partial_name = name.dirname.join("_#{name.basename}")
76
+ @resolver.resolve(name) || @resolver.resolve(partial_name)
77
+ end
78
+
79
+ def find_relative(name, base, options)
80
+ base_pathname = Pathname.new(base)
81
+ if pathname = resolve(name, base_pathname.dirname)
82
+ context.depend_on(pathname)
83
+ if sass_file?(pathname)
84
+ render_with_engine(pathname.read, pathname)
85
+ else
86
+ render_with_engine(@resolver.process(pathname), pathname)
87
+ end
88
+ else
89
+ nil
90
+ end
91
+ end
92
+
93
+ def find(name, options)
94
+ if pathname = resolve(name)
95
+ context.depend_on(pathname)
96
+ if sass_file?(pathname)
97
+ render_with_engine(pathname.read, pathname)
98
+ else
99
+ render_with_engine(@resolver.process(pathname), pathname)
100
+ end
101
+ else
102
+ nil
103
+ end
104
+ end
105
+
106
+ def mtime(name, options)
107
+ if pathname = resolve_sass_path(name, options)
108
+ pathname.mtime
109
+ end
110
+ end
111
+
112
+ def key(name, options)
113
+ ["Sprockets:" + File.dirname(File.expand_path(name)), File.basename(name)]
114
+ end
115
+
116
+ def resolve_sass_path(name, options = {}, relative = false)
117
+ prefix = ( relative === false ? "" : "./" )
118
+ (context.resolve("#{prefix}#{name}", options) || context.resolve("#{prefix}_#{name}", options))
119
+ end
120
+
121
+ end
122
+
123
+ def prepare
124
+ end
125
+
126
+ def evaluate(scope, locals, &block)
127
+ ::Sass::Engine.new(data, {
128
+ :filename => eval_file,
129
+ :line => line,
130
+ :syntax => :scss,
131
+ :importer => Importer.new(scope)
132
+ }.reverse_merge!(::Compass.sass_engine_options)).render
133
+ end
134
+
135
+ end
136
+ end
137
+ end
data/lib/tipsy/server.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  require 'rack'
2
2
  require 'sprockets'
3
3
  require 'hike'
4
- require 'sass'
5
4
 
6
5
  module Tipsy
7
6
 
@@ -9,6 +8,19 @@ module Tipsy
9
8
 
10
9
  attr_reader :request
11
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
+ }
23
+ end
12
24
 
13
25
  def initialize
14
26
  @last_update = Time.now
@@ -37,14 +49,45 @@ module Tipsy
37
49
 
38
50
  class AssetHandler < Sprockets::Environment
39
51
  def initialize
40
- super(Tipsy.root) do |env|
41
- env.static_root = Tipsy.options.asset_path
42
- end
43
- self.append_path "assets/javascripts"
44
- self.append_path "assets/stylesheets"
45
- self.append_path "assets/images"
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!
46
66
  self
47
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
+
48
91
  end
49
92
 
50
93
  # From the rack/contrib TryStatic class
data/lib/tipsy/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Tipsy
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end