stache 0.2.2 → 0.9.0

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 (41) hide show
  1. data/CHANGELOG.md +10 -0
  2. data/README.md +32 -7
  3. data/lib/stache.rb +1 -3
  4. data/lib/stache/asset_helper.rb +15 -22
  5. data/lib/stache/config.rb +11 -9
  6. data/lib/stache/handlebars.rb +7 -0
  7. data/lib/stache/handlebars/handler.rb +80 -0
  8. data/lib/stache/handlebars/view.rb +14 -0
  9. data/lib/stache/mustache.rb +7 -0
  10. data/lib/stache/mustache/handler.rb +70 -0
  11. data/lib/stache/mustache/view.rb +37 -0
  12. data/lib/stache/version.rb +1 -1
  13. data/spec/controllers/handlebars_controller_spec.rb +35 -0
  14. data/spec/controllers/stache_controller_spec.rb +17 -5
  15. data/spec/dummy/app/assets/stylesheets/test.css +3 -0
  16. data/spec/dummy/app/controllers/handlebars_controller.rb +18 -0
  17. data/spec/dummy/app/controllers/stache_controller.rb +8 -3
  18. data/spec/dummy/app/helpers/application_helper.rb +4 -0
  19. data/spec/dummy/app/views/handlebars/_eaten_by_a.html.hbs +1 -0
  20. data/spec/dummy/app/views/handlebars/index.html.hbs +1 -0
  21. data/spec/dummy/app/views/handlebars/with_helpers.html.hbs +3 -0
  22. data/spec/dummy/app/views/handlebars/with_partials.html.hbs +3 -0
  23. data/spec/dummy/app/views/stache/with_asset_helpers.html.mustache +4 -0
  24. data/spec/dummy/config/application.rb +3 -0
  25. data/spec/dummy/config/initializers/stache.rb +2 -0
  26. data/spec/dummy/config/routes.rb +5 -53
  27. data/spec/dummy/lib/with_asset_helpers.rb +11 -0
  28. data/spec/spec_helper.rb +1 -1
  29. data/spec/stache/asset_helper_spec.rb +41 -39
  30. data/spec/stache/config_spec.rb +4 -6
  31. data/spec/stache/handlebars/handlebars_spec.rb +37 -0
  32. data/spec/stache/handlebars/profile_autoload.rb +6 -0
  33. data/spec/stache/handlebars/view_spec.rb +11 -0
  34. data/spec/stache/{handler_spec.rb → mustache/handler_spec.rb} +8 -8
  35. data/spec/stache/{profile_autoload.rb → mustache/profile_autoload.rb} +1 -1
  36. data/spec/stache/mustache/view_spec.rb +11 -0
  37. data/stache.gemspec +3 -5
  38. metadata +50 -22
  39. data/lib/stache/handler.rb +0 -68
  40. data/lib/stache/view.rb +0 -38
  41. data/spec/stache/view_spec.rb +0 -9
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ describe HandlebarsController do
4
+ render_views
5
+
6
+ before do
7
+ Stache.template_base_path = ::Rails.root.join('app', 'views')
8
+ end
9
+
10
+ it "can get to index and render a Handlebars" do
11
+ get :index
12
+ assert_response 200
13
+
14
+ response.should render_template 'index'
15
+ response.body.should =~ /Hello, Matt!/
16
+ end
17
+
18
+ it "correctly renders partials" do
19
+ get :with_partials
20
+ assert_response 200
21
+
22
+ response.body.should =~ /Grue/
23
+ # puts response.body
24
+ end
25
+
26
+ it "correctly uses helpers" do
27
+ get :with_helpers
28
+ assert_response 200
29
+
30
+ response.body.should =~ /Here's an image_path=\/assets\/image\.png/
31
+ response.body.should =~ /Here's a capitalized string: Lowercase/
32
+ end
33
+
34
+
35
+ end
@@ -2,7 +2,11 @@ require 'spec_helper'
2
2
 
3
3
  describe StacheController do
4
4
  render_views
5
-
5
+
6
+ before do
7
+ Stache.template_base_path = ::Rails.root.join('app', 'views')
8
+ end
9
+
6
10
  it "can get to index and render a Mustache" do
7
11
  get :index
8
12
  assert_response 200
@@ -10,14 +14,22 @@ describe StacheController do
10
14
  response.should render_template 'index' # view
11
15
  response.body.should =~ /Hello, Matt!/
12
16
  end
13
-
17
+
14
18
  it "correctly renders partials" do
15
19
  get :with_partials
16
20
  assert_response 200
17
-
21
+
18
22
  response.body.should =~ /Grue/
19
23
  # puts response.body
20
24
  end
21
-
22
-
25
+
26
+ it "correctly uses the asset helpers" do
27
+ get :with_asset_helpers
28
+ assert_response 200
29
+
30
+ response.body.should =~ /Here's an image_path=\/assets\/image\.png/
31
+ response.body.should =~ /link href="\/assets\/test\.css"/
32
+ end
33
+
34
+
23
35
  end
@@ -0,0 +1,3 @@
1
+ body {
2
+ margin: 0;
3
+ }
@@ -0,0 +1,18 @@
1
+ class HandlebarsController < ApplicationController
2
+
3
+ def index
4
+ @user = params[:user] || "Matt"
5
+ # index.html.hbs
6
+ end
7
+
8
+ def with_partials
9
+ @user = params[:user] || "Matt"
10
+ @thing = "Grue"
11
+ end
12
+
13
+ def with_helpers
14
+ @image = "image.png"
15
+ @some_text = "lowercase"
16
+ end
17
+
18
+ end
@@ -1,13 +1,18 @@
1
1
  class StacheController < ApplicationController
2
-
2
+
3
3
  def index
4
4
  @user = params[:user] || "Matt"
5
5
  # index.html.mustache
6
6
  end
7
-
7
+
8
8
  def with_partials
9
9
  @user = params[:user] || "Matt"
10
10
  @thing = "Grue"
11
11
  end
12
-
12
+
13
+ def with_asset_helpers
14
+ require 'with_asset_helpers'
15
+ # with_asset_helpers.html.mustache
16
+ end
17
+
13
18
  end
@@ -1,2 +1,6 @@
1
1
  module ApplicationHelper
2
+
3
+ def capitalize string
4
+ string.capitalize if string
5
+ end
2
6
  end
@@ -0,0 +1 @@
1
+ <b>{{thing}}</b>
@@ -0,0 +1 @@
1
+ Hello, {{user}}!
@@ -0,0 +1,3 @@
1
+ Here's an image_path={{image_path image}}
2
+
3
+ Here's a capitalized string: {{capitalize some_text}}
@@ -0,0 +1,3 @@
1
+ Unfortunately, {{user}} was eaten by a:
2
+
3
+ {{> eaten_by_a }}
@@ -0,0 +1,4 @@
1
+ Here's an image_path={{my_image}}
2
+
3
+ Here's a stylesheet link tag:
4
+ {{{my_styles}}}
@@ -5,6 +5,7 @@ require "active_model/railtie"
5
5
  require "action_controller/railtie"
6
6
  require "action_view/railtie"
7
7
  require "action_mailer/railtie"
8
+ require "sprockets/railtie"
8
9
 
9
10
  Bundler.require
10
11
 
@@ -40,5 +41,7 @@ module Dummy
40
41
 
41
42
  # Configure sensitive parameters which will be filtered from the log file.
42
43
  config.filter_parameters += [:password]
44
+
45
+ config.assets.enabled = true
43
46
  end
44
47
  end
@@ -1,3 +1,5 @@
1
1
  Stache.configure do |config|
2
2
  config.template_base_path = Rails.root.join('app', 'views')
3
+ config.use :mustache
4
+ config.use :handlebars
3
5
  end
@@ -1,61 +1,13 @@
1
1
  Dummy::Application.routes.draw do
2
2
  get 'stache', :to => 'stache#index', :as => 'stache'
3
-
4
- get 'stache/with_partials', :to => 'stache#with_partials'
5
- # The priority is based upon order of creation:
6
- # first created -> highest priority.
7
-
8
- # Sample of regular route:
9
- # match 'products/:id' => 'catalog#view'
10
- # Keep in mind you can assign values other than :controller and :action
11
-
12
- # Sample of named route:
13
- # match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase
14
- # This route can be invoked with purchase_url(:id => product.id)
15
-
16
- # Sample resource route (maps HTTP verbs to controller actions automatically):
17
- # resources :products
18
3
 
19
- # Sample resource route with options:
20
- # resources :products do
21
- # member do
22
- # get 'short'
23
- # post 'toggle'
24
- # end
25
- #
26
- # collection do
27
- # get 'sold'
28
- # end
29
- # end
30
-
31
- # Sample resource route with sub-resources:
32
- # resources :products do
33
- # resources :comments, :sales
34
- # resource :seller
35
- # end
36
-
37
- # Sample resource route with more complex sub-resources
38
- # resources :products do
39
- # resources :comments
40
- # resources :sales do
41
- # get 'recent', :on => :collection
42
- # end
43
- # end
4
+ get 'stache/with_partials', :to => 'stache#with_partials'
44
5
 
45
- # Sample resource route within a namespace:
46
- # namespace :admin do
47
- # # Directs /admin/products/* to Admin::ProductsController
48
- # # (app/controllers/admin/products_controller.rb)
49
- # resources :products
50
- # end
6
+ get 'stache/with_asset_helpers', :to => 'stache#with_asset_helpers'
51
7
 
52
- # You can have the root of your site routed with "root"
53
- # just remember to delete public/index.html.
54
- # root :to => "welcome#index"
8
+ get 'handlebars', :to => 'handlebars#index', :as => 'handlebars'
55
9
 
56
- # See how all your routes lay out with "rake routes"
10
+ get 'handlebars/with_partials', :to => 'handlebars#with_partials'
57
11
 
58
- # This is a legacy wild controller route that's not recommended for RESTful applications.
59
- # Note: This route will make all actions in every controller accessible via GET requests.
60
- # match ':controller(/:action(/:id(.:format)))'
12
+ get 'handlebars/with_helpers', :to => 'handlebars#with_helpers'
61
13
  end
@@ -0,0 +1,11 @@
1
+ class Stache::WithAssetHelpers < Stache::Mustache::View
2
+
3
+ def my_image
4
+ @my_image ||= image_path("image.png")
5
+ end
6
+
7
+ def my_styles
8
+ @my_styles ||= stylesheet_link_tag("test")
9
+ end
10
+
11
+ end
data/spec/spec_helper.rb CHANGED
@@ -29,5 +29,5 @@ require 'rspec/rails'
29
29
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
30
30
 
31
31
  RSpec.configure do |config|
32
-
32
+
33
33
  end
@@ -3,6 +3,31 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
3
3
  class MyViewContext
4
4
  include ActionView::Helpers::TagHelper
5
5
  include Stache::AssetHelper
6
+
7
+ def lookup_context
8
+ @context ||= LookupContext.new
9
+ end
10
+ end
11
+
12
+ class LookupContext
13
+ def find(name, prefixes = [], partial = false, keys = [], options = {})
14
+ raise ActionView::MissingTemplate.new(view_paths || [], name, prefixes, partial, options)
15
+ end
16
+
17
+ def view_paths= new_paths
18
+ @paths = ActionView::PathSet.new(Array.wrap(new_paths))
19
+ end
20
+
21
+ def view_paths
22
+ @paths
23
+ end
24
+ end
25
+
26
+ class TemplateStub
27
+ attr_accessor :source
28
+ def initialize source
29
+ self.source = source
30
+ end
6
31
  end
7
32
 
8
33
  describe Stache::AssetHelper do
@@ -12,54 +37,31 @@ describe Stache::AssetHelper do
12
37
 
13
38
  describe "#template_include_tag" do
14
39
  it "renders a script tag with the template contents" do
15
- File.stub!(:file?).with(Rails.root.join("app/views/widgets/_oh_herro.html.mustache").to_s).and_return(true)
16
- File.stub!(:open).with(Rails.root.join("app/views/widgets/_oh_herro.html.mustache"), "rb", {:encoding=>"utf-8"}).
17
- and_return(StringIO.new("{{ awyeah }}"))
40
+ helper.lookup_context.should_receive(:find).with('widgets/oh_herro', [], true, [], anything).and_return(TemplateStub.new("{{ awyeah }}"))
18
41
 
19
42
  helper.template_include_tag("widgets/oh_herro").should == "<script id=\"oh_herro_template\" type=\"text/html\">{{ awyeah }}</script>"
20
43
  end
21
- it "uses the template_base_path config setting to locate the template" do
22
- Stache.configure do |c|
23
- c.template_base_path = "/tmp/whee"
24
- end
25
- File.stub!(:file?).with("/tmp/whee/_whooo.html.mustache").and_return(true)
26
- File.stub!(:open).with(Pathname.new("/tmp/whee/_whooo.html.mustache"), "rb", {:encoding=>"utf-8"}).
27
- and_return(StringIO.new("{{ awyeah }}"))
44
+ it "renders a script tag with the template contents and given id" do
45
+ helper.lookup_context.should_receive(:find).with('widgets/oh_herro', [], true, [], anything).and_return(TemplateStub.new("{{ awyeah }}"))
28
46
 
29
- helper.template_include_tag("whooo").should == "<script id=\"whooo_template\" type=\"text/html\">{{ awyeah }}</script>"
47
+ helper.template_include_tag("widgets/oh_herro", :id => 'oh_herro_tmpl').should == "<script id=\"oh_herro_tmpl\" type=\"text/html\">{{ awyeah }}</script>"
30
48
  end
31
- it "raises if it cannot find the template" do
32
- lambda { helper.template_include_tag("arrrgh") }.should raise_error(ActionView::MissingTemplate)
33
- end
34
- end
49
+ it "renders a script tag with the template contents and given options" do
50
+ helper.lookup_context.should_receive(:find).with('widgets/oh_herro', [], true, [], anything).and_return(TemplateStub.new("{{ awyeah }}"))
35
51
 
36
- describe "#locate_template_for" do
37
- it "tries permutations of partial names and default file extension to find the requested file" do
38
- File.should_receive(:file?).with("/tmp/whee/_whooo.html.mustache")
39
- File.should_receive(:file?).with("/tmp/whee/whooo.html.mustache").and_return(true)
40
-
41
- helper.locate_template_for(Pathname.new("/tmp/whee"), "whooo").should == Pathname.new("/tmp/whee/whooo.html.mustache")
52
+ helper.template_include_tag("widgets/oh_herro", :data => {:engine => 'mustache'}).
53
+ should == "<script data-engine=\"mustache\" id=\"oh_herro_template\" type=\"text/html\">{{ awyeah }}</script>"
42
54
  end
55
+ it "will find first by partial and later by non-partial" do
56
+ helper.lookup_context.should_receive(:find).with('widgets/oh_herro', anything, true, anything, anything).and_raise(StandardError.new("noooooo"))
57
+ helper.lookup_context.should_receive(:find).with('widgets/oh_herro', anything, false, anything, anything).and_return(TemplateStub.new("{{ awyeah }}"))
43
58
 
44
- it "tries permutations of partial names and configured file extension to find the requested file" do
45
- Stache.configure do |config|
46
- @current_extension = config.template_extension
47
- config.template_extension = 'mustache'
48
- end
49
-
50
- File.should_receive(:file?).with("/tmp/whee/_whooo.mustache")
51
- File.should_receive(:file?).with("/tmp/whee/whooo.mustache").and_return(true)
52
-
53
- helper.locate_template_for(Pathname.new("/tmp/whee"), "whooo").should == Pathname.new("/tmp/whee/whooo.mustache")
54
-
55
- Stache.configure do |config|
56
- config.template_extension = @current_extension
57
- end
59
+ helper.template_include_tag("widgets/oh_herro").should == "<script id=\"oh_herro_template\" type=\"text/html\">{{ awyeah }}</script>"
58
60
  end
59
-
60
-
61
- it "returns nil if it cannot find anything" do
62
- helper.locate_template_for(Pathname.new("/tmp/whee"), "whooo").should be_nil
61
+ it "raises if it cannot find the template" do
62
+ lambda { helper.template_include_tag("arrrgh") }.should raise_error(ActionView::MissingTemplate)
63
63
  end
64
64
  end
65
+
66
+
65
67
  end
@@ -5,25 +5,23 @@ describe "Stache::Config" do
5
5
  before do
6
6
  Stache.send(:instance_variable_set, :@template_base_path, nil)
7
7
  end
8
- [:template_base_path, :template_extension, :shared_path].each do |attr|
8
+ [:template_base_path, :shared_path].each do |attr|
9
9
  it "sets up an attribute named #{attr.to_s}" do
10
10
  Stache.should respond_to(attr)
11
11
  Stache.should respond_to("#{attr}=")
12
12
  end
13
-
13
+
14
14
  it "sets up a default value for #{attr}" do
15
15
  Stache.send(attr).should_not be_nil
16
16
  Stache.send(attr).should == if attr == :template_base_path
17
17
  ::Rails.root.join('app', 'templates')
18
- elsif attr == :template_extension
19
- "html.mustache"
20
18
  elsif attr == :shared_path
21
19
  ::Rails.root.join('app', 'templates', 'shared')
22
20
  end
23
21
  end
24
22
  end
25
23
  end
26
-
24
+
27
25
  describe ".configure" do
28
26
  it "yields self to the block as a convienence to future refactoring" do
29
27
  Stache.configure do |config|
@@ -35,5 +33,5 @@ describe "Stache::Config" do
35
33
  end
36
34
  end
37
35
  end
38
-
36
+
39
37
  end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe Stache::Handlebars::Handler do
4
+ before do
5
+ @template = ActionView::Template.new("{{body}}", "hello handlebars", Stache::Handlebars::Handler, { :virtual_path => "hello_world"})
6
+ @handler = Stache::Handlebars::Handler.new
7
+ end
8
+
9
+ describe "#handlebars_class_from_template" do
10
+ it "returns the appropriate handlebars class" do
11
+ class HelloWorld < Stache::Handlebars::View; end
12
+ @handler.handlebars_class_from_template(@template).should == HelloWorld
13
+ Object.send(:remove_const, :HelloWorld)
14
+ end
15
+ it "is clever about folders and such" do
16
+ @template.stub!(:virtual_path).and_return("profiles/index")
17
+ module Profiles; class Index < Stache::Handlebars::View; end; end
18
+ @handler.handlebars_class_from_template(@template).should == Profiles::Index
19
+ Object.send(:remove_const, :Profiles)
20
+ end
21
+ it "retuns Stache::Handlebars::View if it can't find none" do
22
+ @handler.handlebars_class_from_template(@template).should == Stache::Handlebars::View
23
+ end
24
+ it "reraises error if loaded handlebars_class raises a NameError" do
25
+ @template.stub!(:virtual_path).and_return("profiles/index")
26
+ module Profiles; end
27
+ # Emulate autoload behavior so the error gets raised upon const_get
28
+ Profiles.autoload :Index, File.join(File.dirname(__FILE__), "profile_autoload.rb")
29
+
30
+ lambda {
31
+ @handler.handlebars_class_from_template(@template)
32
+ }.should raise_error(NameError, "uninitialized constant Profiles::Index::Foo")
33
+
34
+ Object.send(:remove_const, :Profiles)
35
+ end
36
+ end
37
+ end