musterb 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ /bin
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ -r spec_helper
2
+ --format documentation
3
+ --color
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in musterb.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Tejas Dinkar
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,29 @@
1
+ # Musterb
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'musterb'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install musterb
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,13 @@
1
+ require "musterb/version"
2
+ require "musterb/musterbifier"
3
+ require "musterb/binding_extractor"
4
+ require "musterb/hash_extractor"
5
+ require "musterb/object_extractor"
6
+ require "musterb/evaluator"
7
+
8
+ module Musterb
9
+ def self.to_erb(template)
10
+ musterbifier = Musterbifier.new(template)
11
+ "<% Musterb::Evaluator.new(Musterb::BindingExtractor.new binding).tap do |musterb| %>#{musterbifier.to_erb}<% end %>"
12
+ end
13
+ end
@@ -0,0 +1,15 @@
1
+ class Musterb::BindingExtractor
2
+ def initialize(_binding)
3
+ @binding = _binding
4
+ end
5
+
6
+ def [](symbol)
7
+ @binding.eval <<-EOF
8
+ begin
9
+ #{symbol}
10
+ rescue NameError
11
+ nil
12
+ end
13
+ EOF
14
+ end
15
+ end
@@ -0,0 +1,59 @@
1
+ class Musterb::Evaluator
2
+ def initialize(context)
3
+ @context = context
4
+ end
5
+
6
+ def [](symbol)
7
+ @context[symbol]
8
+ end
9
+
10
+ def block(symbol)
11
+ value = self[symbol]
12
+ return if is_falsy? value
13
+
14
+ case value
15
+ when Hash
16
+ switch_context(value) { |v| yield v }
17
+ when Enumerable
18
+ value.each { |e| switch_context(e) { |v| yield v } }
19
+ else
20
+ switch_context(value) { |v| yield v }
21
+ end
22
+ end
23
+
24
+ def block_unless(symbol)
25
+ yield if is_falsy? self[symbol]
26
+ end
27
+
28
+ private
29
+
30
+ def is_falsy?(value)
31
+ case value
32
+ when Hash
33
+ false
34
+ when Enumerable
35
+ value.empty?
36
+ else
37
+ !value
38
+ end
39
+ end
40
+
41
+ def new_context(value)
42
+ case value
43
+ when Hash
44
+ HashExtractor.new(value, @context)
45
+ else
46
+ ObjectExtractor.new(value, @context)
47
+ end
48
+ end
49
+
50
+ def old_context
51
+ @context.parent
52
+ end
53
+
54
+ def switch_context(value)
55
+ @context = new_context(value)
56
+ yield value
57
+ @context = old_context
58
+ end
59
+ end
@@ -0,0 +1,26 @@
1
+ require 'hashie'
2
+
3
+ class HashExtractor
4
+ attr_reader :parent
5
+
6
+ def initialize(value, parent)
7
+ @value = to_string_access(value)
8
+ @parent = parent
9
+ end
10
+
11
+ def [](symbol)
12
+ if @value.has_key? symbol
13
+ @value[symbol]
14
+ else
15
+ @parent[symbol]
16
+ end
17
+ end
18
+
19
+ private
20
+ def to_string_access(hash)
21
+ hash.dup.tap do |hash|
22
+ hash.extend Hashie::HashExtensions
23
+ hash.hashie_stringify_keys!
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,23 @@
1
+ class Musterb::Musterbifier
2
+ def initialize(template)
3
+ @template = template
4
+ end
5
+
6
+ def to_erb
7
+ @template.gsub(/\{\{(\{?[^\}]*\}?)\}\}/) do |match|
8
+ match = $1
9
+ case match[0]
10
+ when '#'
11
+ "<% musterb.block '#{match[1..-1]}' do %>"
12
+ when '^'
13
+ "<% musterb.block_unless '#{match[1..-1]}' do %>"
14
+ when "/"
15
+ "<% end %>"
16
+ when '{'
17
+ "<%= musterb['#{match[1..-2]}'] %>"
18
+ else
19
+ "<%== musterb['#{match}'] %>"
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,16 @@
1
+ class ObjectExtractor
2
+ attr_reader :parent
3
+
4
+ def initialize(value, parent)
5
+ @value = value
6
+ @parent = parent
7
+ end
8
+
9
+ def [](symbol)
10
+ if @value.respond_to? symbol
11
+ @value.send(symbol)
12
+ else
13
+ @parent[symbol]
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,3 @@
1
+ module Musterb
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'musterb/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "musterb"
8
+ gem.version = Musterb::VERSION
9
+ gem.authors = ["Tejas Dinkar"]
10
+ gem.email = ["tejas@gja.in"]
11
+ gem.description = %q{The ability to compile mustache templates to erubis erb templates so that we can make use of the performance of compiling templates}
12
+ gem.summary = %q{Compile Mustache templates to ERB}
13
+ gem.homepage = ""
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_dependency "erubis"
21
+ gem.add_dependency "hashie"
22
+ gem.add_development_dependency "rspec"
23
+ end
@@ -0,0 +1,12 @@
1
+ describe Musterb::BindingExtractor do
2
+ it "can pull out local variables from the binding" do
3
+ foo = "bar"
4
+ extractor = Musterb::BindingExtractor.new binding
5
+ extractor["foo"].should eq "bar"
6
+ end
7
+
8
+ it "returns nil if the local variable cannot be found" do
9
+ extractor = Musterb::BindingExtractor.new binding
10
+ extractor["foo"].should be_nil
11
+ end
12
+ end
@@ -0,0 +1,91 @@
1
+ describe Musterb::Evaluator do
2
+ it "can pull local variables out from the binding" do
3
+ foo = "bar"
4
+ evaluator = Musterb::Evaluator.new Musterb::BindingExtractor.new(binding)
5
+ evaluator["foo"].should eq "bar"
6
+ end
7
+
8
+ context "block" do
9
+ it "yields to the block if a value is set" do
10
+ foo = "bar"
11
+ evaluator = Musterb::Evaluator.new Musterb::BindingExtractor.new(binding)
12
+ expect { |b| evaluator.block("foo", &b) }.to yield_control
13
+ end
14
+
15
+ it "does not yield to the block if the value is unset" do
16
+ foo = nil
17
+ evaluator = Musterb::Evaluator.new Musterb::BindingExtractor.new(binding)
18
+ expect { |b| evaluator.block("foo", &b) }.not_to yield_control
19
+ end
20
+
21
+ it "yields to the block for every element in the array" do
22
+ foo = [1, 2, 3]
23
+ evaluator = Musterb::Evaluator.new Musterb::BindingExtractor.new(binding)
24
+ expect { |b| evaluator.block("foo", &b) }.to yield_successive_args(1,2,3)
25
+ end
26
+
27
+ it "does not yield to an empty array" do
28
+ foo = []
29
+ evaluator = Musterb::Evaluator.new Musterb::BindingExtractor.new(binding)
30
+ expect { |b| evaluator.block("foo", &b) }.not_to yield_control
31
+ end
32
+
33
+ it "yields to an empty hash" do
34
+ foo = {}
35
+ evaluator = Musterb::Evaluator.new Musterb::BindingExtractor.new(binding)
36
+ expect { |b| evaluator.block("foo", &b) }.to yield_control
37
+ end
38
+ end
39
+
40
+ context "block_unless" do
41
+ it "does not yield to the block if a value is set" do
42
+ foo = "bar"
43
+ evaluator = Musterb::Evaluator.new Musterb::BindingExtractor.new(binding)
44
+ expect { |b| evaluator.block_unless("foo", &b) }.not_to yield_control
45
+ end
46
+
47
+ it "does not yield to the block if the value is unset" do
48
+ foo = nil
49
+ evaluator = Musterb::Evaluator.new Musterb::BindingExtractor.new(binding)
50
+ expect { |b| evaluator.block_unless("foo", &b) }.to yield_control
51
+ end
52
+
53
+ it "yields to the block for every element in the array" do
54
+ foo = [1, 2, 3]
55
+ evaluator = Musterb::Evaluator.new Musterb::BindingExtractor.new(binding)
56
+ expect { |b| evaluator.block_unless("foo", &b) }.not_to yield_control
57
+ end
58
+
59
+ it "does not yield to an empty array" do
60
+ foo = []
61
+ evaluator = Musterb::Evaluator.new Musterb::BindingExtractor.new(binding)
62
+ expect { |b| evaluator.block_unless("foo", &b) }.to yield_control
63
+ end
64
+ end
65
+
66
+ context "switching context" do
67
+ it "switches inside a hash" do
68
+ hash = { "foo" => "bar"}
69
+ evaluator = Musterb::Evaluator.new Musterb::BindingExtractor.new(binding)
70
+ evaluator.block "hash" do
71
+ evaluator['foo'].should eq 'bar'
72
+ end
73
+ end
74
+
75
+ it "resets the context later" do
76
+ hash = { "foo" => "bar"}
77
+ evaluator = Musterb::Evaluator.new Musterb::BindingExtractor.new(binding)
78
+ evaluator.block("hash") {}
79
+ evaluator["hash"].should eq hash
80
+ end
81
+
82
+ it "cascades the context to the parent" do
83
+ foo = "bar"
84
+ hash = { }
85
+ evaluator = Musterb::Evaluator.new Musterb::BindingExtractor.new(binding)
86
+ evaluator.block "hash" do
87
+ evaluator['foo'].should eq 'bar'
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,16 @@
1
+ describe HashExtractor do
2
+ it "can pull values out from a hash" do
3
+ extractor = HashExtractor.new({"foo" => "bar"}, nil)
4
+ extractor["foo"].should eq "bar"
5
+ end
6
+
7
+ it "can pull values out from a symbol" do
8
+ extractor = HashExtractor.new({:foo => "bar"}, nil)
9
+ extractor["foo"].should eq "bar"
10
+ end
11
+
12
+ it "delegates to the parent if there is no match" do
13
+ extractor = HashExtractor.new({}, HashExtractor.new({:foo => "bar"}, nil))
14
+ extractor["foo"].should eq "bar"
15
+ end
16
+ end
@@ -0,0 +1,21 @@
1
+ describe Musterb::Musterbifier do
2
+ it "does not change vanilla strings" do
3
+ Musterb::Musterbifier.new("Hello, world!").to_erb.should eq "Hello, world!"
4
+ end
5
+
6
+ it "replaces mustaches correctly" do
7
+ Musterb::Musterbifier.new("Hello, {{world}}!").to_erb.should eq "Hello, <%== musterb['world'] %>!"
8
+ end
9
+
10
+ it "replaces triple staches correctly" do
11
+ Musterb::Musterbifier.new("Hello, {{{world}}}!").to_erb.should eq "Hello, <%= musterb['world'] %>!"
12
+ end
13
+
14
+ it "replaces blocks correctly" do
15
+ Musterb::Musterbifier.new("{{#cond}}foo{{/cond}}").to_erb.should eq "<% musterb.block 'cond' do %>foo<% end %>"
16
+ end
17
+
18
+ it "replaces carrot correctly" do
19
+ Musterb::Musterbifier.new("{{^cond}}foo{{/cond}}").to_erb.should eq "<% musterb.block_unless 'cond' do %>foo<% end %>"
20
+ end
21
+ end
@@ -0,0 +1,11 @@
1
+ describe ObjectExtractor do
2
+ it "calls methods on the object" do
3
+ extractor = ObjectExtractor.new(2, nil)
4
+ extractor["to_s"].should eq "2"
5
+ end
6
+
7
+ it "delegates to the parent if there it doesn't respnd to something" do
8
+ extractor = ObjectExtractor.new(2, ObjectExtractor.new("string", nil))
9
+ extractor["upcase"].should eq "STRING"
10
+ end
11
+ end
@@ -0,0 +1,27 @@
1
+ require 'erubis'
2
+
3
+ describe Musterb do
4
+ def evaluate(template, _binding)
5
+ erb = Musterb.to_erb(template)
6
+ Erubis::Eruby.new(erb).result(_binding)
7
+ end
8
+
9
+ it "correctly replaces variables" do
10
+ planet = "World"
11
+ evaluate("Hello, {{planet}}!", binding).should eq "Hello, World!"
12
+ end
13
+
14
+ it "correctly evaluates if a variable is set" do
15
+ set_var = "set"
16
+ unset_var = nil
17
+ evaluate("{{#set_var}}foo{{/set_var}}", binding).should eq "foo"
18
+ evaluate("{{#unset_var}}foo{{/unset_var}}", binding).should eq ""
19
+ end
20
+
21
+ it "skips blocks for truthy values" do
22
+ set_var = "set"
23
+ unset_var = nil
24
+ evaluate("{{^set_var}}foo{{/set_var}}", binding).should eq ""
25
+ evaluate("{{^unset_var}}foo{{/unset_var}}", binding).should eq "foo"
26
+ end
27
+ end
@@ -0,0 +1 @@
1
+ require 'musterb'
metadata ADDED
@@ -0,0 +1,150 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: musterb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Tejas Dinkar
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-09-15 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: erubis
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: hashie
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: The ability to compile mustache templates to erubis erb templates so
63
+ that we can make use of the performance of compiling templates
64
+ email:
65
+ - tejas@gja.in
66
+ executables: []
67
+ extensions: []
68
+ extra_rdoc_files: []
69
+ files:
70
+ - !binary |-
71
+ LmdpdGlnbm9yZQ==
72
+ - !binary |-
73
+ LnJzcGVj
74
+ - !binary |-
75
+ R2VtZmlsZQ==
76
+ - !binary |-
77
+ TElDRU5TRS50eHQ=
78
+ - !binary |-
79
+ UkVBRE1FLm1k
80
+ - !binary |-
81
+ UmFrZWZpbGU=
82
+ - !binary |-
83
+ bGliL211c3RlcmIucmI=
84
+ - !binary |-
85
+ bGliL211c3RlcmIvYmluZGluZ19leHRyYWN0b3IucmI=
86
+ - !binary |-
87
+ bGliL211c3RlcmIvZXZhbHVhdG9yLnJi
88
+ - !binary |-
89
+ bGliL211c3RlcmIvaGFzaF9leHRyYWN0b3IucmI=
90
+ - !binary |-
91
+ bGliL211c3RlcmIvbXVzdGVyYmlmaWVyLnJi
92
+ - !binary |-
93
+ bGliL211c3RlcmIvb2JqZWN0X2V4dHJhY3Rvci5yYg==
94
+ - !binary |-
95
+ bGliL211c3RlcmIvdmVyc2lvbi5yYg==
96
+ - !binary |-
97
+ bXVzdGVyYi5nZW1zcGVj
98
+ - !binary |-
99
+ c3BlYy9tdXN0ZXJiL2JpbmRpbmdfZXh0cmFjdG9yX3NwZWMucmI=
100
+ - !binary |-
101
+ c3BlYy9tdXN0ZXJiL2V2YWx1YXRvcl9zcGVjLnJi
102
+ - !binary |-
103
+ c3BlYy9tdXN0ZXJiL2hhc2hfZXh0cmFjdG9yX3NwZWMucmI=
104
+ - !binary |-
105
+ c3BlYy9tdXN0ZXJiL211c3RlcmJpZmllcl9zcGVjLnJi
106
+ - !binary |-
107
+ c3BlYy9tdXN0ZXJiL29iamVjdF9leHRyYWN0b3Jfc3BlYy5yYg==
108
+ - !binary |-
109
+ c3BlYy9tdXN0ZXJiX3NwZWMucmI=
110
+ - !binary |-
111
+ c3BlYy9zcGVjX2hlbHBlci5yYg==
112
+ homepage: ''
113
+ licenses: []
114
+ post_install_message:
115
+ rdoc_options: []
116
+ require_paths:
117
+ - lib
118
+ required_ruby_version: !ruby/object:Gem::Requirement
119
+ none: false
120
+ requirements:
121
+ - - ! '>='
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ required_rubygems_version: !ruby/object:Gem::Requirement
125
+ none: false
126
+ requirements:
127
+ - - ! '>='
128
+ - !ruby/object:Gem::Version
129
+ version: '0'
130
+ requirements: []
131
+ rubyforge_project:
132
+ rubygems_version: 1.8.23
133
+ signing_key:
134
+ specification_version: 3
135
+ summary: Compile Mustache templates to ERB
136
+ test_files:
137
+ - !binary |-
138
+ c3BlYy9tdXN0ZXJiL2JpbmRpbmdfZXh0cmFjdG9yX3NwZWMucmI=
139
+ - !binary |-
140
+ c3BlYy9tdXN0ZXJiL2V2YWx1YXRvcl9zcGVjLnJi
141
+ - !binary |-
142
+ c3BlYy9tdXN0ZXJiL2hhc2hfZXh0cmFjdG9yX3NwZWMucmI=
143
+ - !binary |-
144
+ c3BlYy9tdXN0ZXJiL211c3RlcmJpZmllcl9zcGVjLnJi
145
+ - !binary |-
146
+ c3BlYy9tdXN0ZXJiL29iamVjdF9leHRyYWN0b3Jfc3BlYy5yYg==
147
+ - !binary |-
148
+ c3BlYy9tdXN0ZXJiX3NwZWMucmI=
149
+ - !binary |-
150
+ c3BlYy9zcGVjX2hlbHBlci5yYg==