tipsy 0.0.1 → 0.0.2

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