musterb 0.0.1

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.
@@ -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==