handlebars 0.0.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/.gitignore +1 -1
  2. data/.gitmodules +3 -0
  3. data/.rspec +1 -0
  4. data/Gemfile +1 -1
  5. data/README.mdown +44 -0
  6. data/Rakefile +3 -0
  7. data/handlebars.gemspec +19 -13
  8. data/lib/handlebars.rb +4 -3
  9. data/lib/handlebars/context.rb +37 -0
  10. data/lib/handlebars/version.rb +1 -1
  11. data/spec/handlebars_spec.rb +40 -0
  12. data/spike.rb +17 -0
  13. data/vendor/handlebars/.gitignore +6 -0
  14. data/vendor/handlebars/.jshintrc +50 -0
  15. data/vendor/handlebars/.npmignore +11 -0
  16. data/vendor/handlebars/Gemfile +5 -0
  17. data/vendor/handlebars/LICENSE +20 -0
  18. data/vendor/handlebars/README.markdown +315 -0
  19. data/vendor/handlebars/Rakefile +116 -0
  20. data/vendor/handlebars/bench/benchwarmer.js +149 -0
  21. data/vendor/handlebars/bench/handlebars.js +163 -0
  22. data/vendor/handlebars/bin/handlebars +139 -0
  23. data/vendor/handlebars/lib/handlebars.js +14 -0
  24. data/vendor/handlebars/lib/handlebars/base.js +101 -0
  25. data/vendor/handlebars/lib/handlebars/compiler/ast.js +103 -0
  26. data/vendor/handlebars/lib/handlebars/compiler/base.js +27 -0
  27. data/vendor/handlebars/lib/handlebars/compiler/compiler.js +808 -0
  28. data/vendor/handlebars/lib/handlebars/compiler/index.js +7 -0
  29. data/vendor/handlebars/lib/handlebars/compiler/printer.js +137 -0
  30. data/vendor/handlebars/lib/handlebars/compiler/visitor.js +13 -0
  31. data/vendor/handlebars/lib/handlebars/runtime.js +68 -0
  32. data/vendor/handlebars/lib/handlebars/utils.js +68 -0
  33. data/vendor/handlebars/package.json +25 -0
  34. data/vendor/handlebars/spec/acceptance_spec.rb +101 -0
  35. data/vendor/handlebars/spec/parser_spec.rb +264 -0
  36. data/vendor/handlebars/spec/qunit_spec.js +1067 -0
  37. data/vendor/handlebars/spec/spec_helper.rb +157 -0
  38. data/vendor/handlebars/spec/tokenizer_spec.rb +254 -0
  39. data/vendor/handlebars/src/handlebars.l +42 -0
  40. data/vendor/handlebars/src/handlebars.yy +99 -0
  41. metadata +93 -77
  42. data/README.md +0 -39
  43. data/lib/handlebars/generator.rb +0 -4
  44. data/lib/handlebars/parser.rb +0 -240
  45. data/spec/generator_spec.rb +0 -5
  46. data/spec/parser_spec.rb +0 -163
  47. data/spec/spec_helper.rb +0 -17
@@ -0,0 +1,99 @@
1
+ %start root
2
+
3
+ %%
4
+
5
+ root
6
+ : program EOF { return $1; }
7
+ ;
8
+
9
+ program
10
+ : statements simpleInverse statements { $$ = new yy.ProgramNode($1, $3); }
11
+ | statements { $$ = new yy.ProgramNode($1); }
12
+ | "" { $$ = new yy.ProgramNode([]); }
13
+ ;
14
+
15
+ statements
16
+ : statement { $$ = [$1]; }
17
+ | statements statement { $1.push($2); $$ = $1; }
18
+ ;
19
+
20
+ statement
21
+ : openInverse program closeBlock { $$ = new yy.InverseNode($1, $2, $3); }
22
+ | openBlock program closeBlock { $$ = new yy.BlockNode($1, $2, $3); }
23
+ | mustache { $$ = $1; }
24
+ | partial { $$ = $1; }
25
+ | CONTENT { $$ = new yy.ContentNode($1); }
26
+ | COMMENT { $$ = new yy.CommentNode($1); }
27
+ ;
28
+
29
+ openBlock
30
+ : OPEN_BLOCK inMustache CLOSE { $$ = new yy.MustacheNode($2[0], $2[1]); }
31
+ ;
32
+
33
+ openInverse
34
+ : OPEN_INVERSE inMustache CLOSE { $$ = new yy.MustacheNode($2[0], $2[1]); }
35
+ ;
36
+
37
+ closeBlock
38
+ : OPEN_ENDBLOCK path CLOSE { $$ = $2; }
39
+ ;
40
+
41
+ mustache
42
+ : OPEN inMustache CLOSE { $$ = new yy.MustacheNode($2[0], $2[1]); }
43
+ | OPEN_UNESCAPED inMustache CLOSE { $$ = new yy.MustacheNode($2[0], $2[1], true); }
44
+ ;
45
+
46
+
47
+ partial
48
+ : OPEN_PARTIAL path CLOSE { $$ = new yy.PartialNode($2); }
49
+ | OPEN_PARTIAL path path CLOSE { $$ = new yy.PartialNode($2, $3); }
50
+ ;
51
+
52
+ simpleInverse
53
+ : OPEN_INVERSE CLOSE { }
54
+ ;
55
+
56
+ inMustache
57
+ : path params hash { $$ = [[$1].concat($2), $3]; }
58
+ | path params { $$ = [[$1].concat($2), null]; }
59
+ | path hash { $$ = [[$1], $2]; }
60
+ | path { $$ = [[$1], null]; }
61
+ ;
62
+
63
+ params
64
+ : params param { $1.push($2); $$ = $1; }
65
+ | param { $$ = [$1]; }
66
+ ;
67
+
68
+ param
69
+ : path { $$ = $1; }
70
+ | STRING { $$ = new yy.StringNode($1); }
71
+ | INTEGER { $$ = new yy.IntegerNode($1); }
72
+ | BOOLEAN { $$ = new yy.BooleanNode($1); }
73
+ ;
74
+
75
+ hash
76
+ : hashSegments { $$ = new yy.HashNode($1); }
77
+ ;
78
+
79
+ hashSegments
80
+ : hashSegments hashSegment { $1.push($2); $$ = $1; }
81
+ | hashSegment { $$ = [$1]; }
82
+ ;
83
+
84
+ hashSegment
85
+ : ID EQUALS path { $$ = [$1, $3]; }
86
+ | ID EQUALS STRING { $$ = [$1, new yy.StringNode($3)]; }
87
+ | ID EQUALS INTEGER { $$ = [$1, new yy.IntegerNode($3)]; }
88
+ | ID EQUALS BOOLEAN { $$ = [$1, new yy.BooleanNode($3)]; }
89
+ ;
90
+
91
+ path
92
+ : pathSegments { $$ = new yy.IdNode($1); }
93
+ ;
94
+
95
+ pathSegments
96
+ : pathSegments SEP ID { $1.push($3); $$ = $1; }
97
+ | ID { $$ = [$1]; }
98
+ ;
99
+
metadata CHANGED
@@ -1,107 +1,123 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: handlebars
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 0
8
- - 2
9
- version: 0.0.2
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ prerelease:
10
6
  platform: ruby
11
- authors:
12
- - Martin Schuerrer
7
+ authors:
8
+ - Charles Lowell
13
9
  autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
-
17
- date: 2010-09-10 00:00:00 +02:00
18
- default_executable:
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
21
- name: bundler
12
+ date: 2012-03-16 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: therubyracer
16
+ requirement: &2156214780 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 0.10.0beta1
22
+ type: :runtime
22
23
  prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
24
+ version_requirements: *2156214780
25
+ - !ruby/object:Gem::Dependency
26
+ name: commonjs
27
+ requirement: &2156214000 !ruby/object:Gem::Requirement
24
28
  none: false
25
- requirements:
26
- - - ">="
27
- - !ruby/object:Gem::Version
28
- segments:
29
- - 1
30
- - 0
31
- - 0
32
- version: 1.0.0
33
- type: :development
34
- version_requirements: *id001
35
- - !ruby/object:Gem::Dependency
36
- name: rspec
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 0.2.3
33
+ type: :runtime
37
34
  prerelease: false
38
- requirement: &id002 !ruby/object:Gem::Requirement
35
+ version_requirements: *2156214000
36
+ - !ruby/object:Gem::Dependency
37
+ name: rspec
38
+ requirement: &2156213220 !ruby/object:Gem::Requirement
39
39
  none: false
40
- requirements:
40
+ requirements:
41
41
  - - ~>
42
- - !ruby/object:Gem::Version
43
- segments:
44
- - 2
45
- - 0
46
- - 0
47
- version: 2.0.0
42
+ - !ruby/object:Gem::Version
43
+ version: '2.0'
48
44
  type: :development
49
- version_requirements: *id002
50
- description: A straight port of handlebars.js to ruby. Currently unfinished, if you've got a complete version let me know so I'll release the name to you
51
- email:
52
- - martin@schuerrer.org
45
+ prerelease: false
46
+ version_requirements: *2156213220
47
+ description: Uses the actual JavaScript implementation of Handlebars, but supports
48
+ using Ruby objects as template contexts and Ruby procs as view functions and named
49
+ helpers
50
+ email:
51
+ - cowboyd@thefrontside.net
53
52
  executables: []
54
-
55
53
  extensions: []
56
-
57
54
  extra_rdoc_files: []
58
-
59
- files:
55
+ files:
60
56
  - .gitignore
57
+ - .gitmodules
58
+ - .rspec
61
59
  - Gemfile
62
- - README.md
60
+ - README.mdown
63
61
  - Rakefile
64
62
  - handlebars.gemspec
65
63
  - lib/handlebars.rb
66
- - lib/handlebars/generator.rb
67
- - lib/handlebars/parser.rb
64
+ - lib/handlebars/context.rb
68
65
  - lib/handlebars/version.rb
69
- - spec/generator_spec.rb
70
- - spec/parser_spec.rb
71
- - spec/spec_helper.rb
72
- has_rdoc: true
73
- homepage: http://github.com/MSch/handlebars-ruby
66
+ - spec/handlebars_spec.rb
67
+ - spike.rb
68
+ - vendor/handlebars/.gitignore
69
+ - vendor/handlebars/.jshintrc
70
+ - vendor/handlebars/.npmignore
71
+ - vendor/handlebars/Gemfile
72
+ - vendor/handlebars/Gemfile.lock
73
+ - vendor/handlebars/LICENSE
74
+ - vendor/handlebars/README.markdown
75
+ - vendor/handlebars/Rakefile
76
+ - vendor/handlebars/bench/benchwarmer.js
77
+ - vendor/handlebars/bench/handlebars.js
78
+ - vendor/handlebars/bin/handlebars
79
+ - vendor/handlebars/lib/handlebars.js
80
+ - vendor/handlebars/lib/handlebars/base.js
81
+ - vendor/handlebars/lib/handlebars/compiler/ast.js
82
+ - vendor/handlebars/lib/handlebars/compiler/base.js
83
+ - vendor/handlebars/lib/handlebars/compiler/compiler.js
84
+ - vendor/handlebars/lib/handlebars/compiler/index.js
85
+ - vendor/handlebars/lib/handlebars/compiler/printer.js
86
+ - vendor/handlebars/lib/handlebars/compiler/visitor.js
87
+ - vendor/handlebars/lib/handlebars/runtime.js
88
+ - vendor/handlebars/lib/handlebars/utils.js
89
+ - vendor/handlebars/package.json
90
+ - vendor/handlebars/spec/acceptance_spec.rb
91
+ - vendor/handlebars/spec/parser_spec.rb
92
+ - vendor/handlebars/spec/qunit_spec.js
93
+ - vendor/handlebars/spec/spec_helper.rb
94
+ - vendor/handlebars/spec/tokenizer_spec.rb
95
+ - vendor/handlebars/src/handlebars.l
96
+ - vendor/handlebars/src/handlebars.yy
97
+ - vendor/handlebars/lib/handlebars/compiler/parser.js
98
+ homepage: http://github.com/cowboyd/handlebars.rb
74
99
  licenses: []
75
-
76
100
  post_install_message:
77
101
  rdoc_options: []
78
-
79
- require_paths:
102
+ require_paths:
80
103
  - lib
81
- required_ruby_version: !ruby/object:Gem::Requirement
104
+ required_ruby_version: !ruby/object:Gem::Requirement
82
105
  none: false
83
- requirements:
84
- - - ">="
85
- - !ruby/object:Gem::Version
86
- segments:
87
- - 0
88
- version: "0"
89
- required_rubygems_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
111
  none: false
91
- requirements:
92
- - - ">="
93
- - !ruby/object:Gem::Version
94
- segments:
95
- - 1
96
- - 3
97
- - 6
98
- version: 1.3.6
112
+ requirements:
113
+ - - ! '>='
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
99
116
  requirements: []
100
-
101
117
  rubyforge_project: handlebars
102
- rubygems_version: 1.3.7
118
+ rubygems_version: 1.8.17
103
119
  signing_key:
104
120
  specification_version: 3
105
- summary: handlebars.js port to ruby
106
- test_files: []
107
-
121
+ summary: Ruby bindings for the handlebars.js templating library
122
+ test_files:
123
+ - spec/handlebars_spec.rb
data/README.md DELETED
@@ -1,39 +0,0 @@
1
- Handlebars
2
- ==========
3
-
4
- Handlebars is a implementation of [handlebars.js][2], an extension of
5
- mustache by Yehuda Katz, in Ruby.
6
-
7
-
8
- Current status
9
- --------------
10
-
11
- So far only the parser has been implemented. It supports the whole
12
- handlebars syntax.
13
-
14
-
15
- Installation
16
- ------------
17
-
18
- ### [RubyGems](http://rubygems.org/)
19
-
20
- $ gem install handlebars
21
-
22
-
23
- Acknowledgements
24
- ----------------
25
-
26
- Thanks to all the [implementers][3] of the original mustache gem.
27
- Handlebars is based on their codebase and hard work.
28
-
29
-
30
- Meta
31
- ----
32
-
33
- * Code: `git clone http://github.com/MSch/handlebars-ruby`
34
- * Bugs: <http://github.com/MSch/handlebars-ruby/issues>
35
- * Gems: <http://rubygems.org/gems/handlebars>
36
-
37
- [1]:http://github.com/wycats/handlebars.js
38
- [2]:http://yehudakatz.com/2010/09/09/announcing-handlebars-js/
39
- [3]:http://github.com/defunkt/mustache/raw/master/CONTRIBUTORS
@@ -1,4 +0,0 @@
1
- class Handlebars
2
- class Generator
3
- end
4
- end
@@ -1,240 +0,0 @@
1
- require 'strscan'
2
-
3
- class Handlebars
4
- class Parser
5
- # A SyntaxError is raised when the Parser comes across unclosed
6
- # tags, sections, illegal content in tags, or anything of that
7
- # sort.
8
- class SyntaxError < StandardError
9
- def initialize(message, position)
10
- @message = message
11
- @lineno, @column, @line = position
12
- @stripped_line = @line.strip
13
- @stripped_column = @column - (@line.size - @line.lstrip.size)
14
- end
15
-
16
- def to_s
17
- <<-EOF
18
- #{@message}
19
- Line #{@lineno}
20
- #{@stripped_line}
21
- #{' ' * @stripped_column}^
22
- EOF
23
- end
24
- end
25
-
26
- # After these types of tags, all whitespace will be skipped.
27
- SKIP_WHITESPACE = [ '#', '^', '/' ]
28
-
29
- # The content allowed in a tag name.
30
- ALLOWED_CONTENT = /(\w|[.?!\/-])*/
31
-
32
- # These types of tags allow any content,
33
- # the rest only allow ALLOWED_CONTENT.
34
- ANY_CONTENT = [ '!', '=' ]
35
-
36
- attr_reader :scanner, :result
37
- attr_writer :otag, :ctag
38
-
39
- # Accepts an options hash which does nothing but may be used in
40
- # the future.
41
- def initialize(options = {})
42
- @options = {}
43
- end
44
-
45
- # The opening tag delimiter. This may be changed at runtime.
46
- def otag
47
- @otag ||= '{{'
48
- end
49
-
50
- # The closing tag delimiter. This too may be changed at runtime.
51
- def ctag
52
- @ctag ||= '}}'
53
- end
54
-
55
- # Given a string template, returns an array of tokens.
56
- def compile(template)
57
- if template.respond_to?(:encoding)
58
- @encoding = template.encoding
59
- template = template.dup.force_encoding("BINARY")
60
- else
61
- @encoding = nil
62
- end
63
-
64
- # Keeps information about opened sections.
65
- @sections = []
66
- @result = [:multi]
67
- @scanner = StringScanner.new(template)
68
-
69
- # Scan until the end of the template.
70
- until @scanner.eos?
71
- scan_tags || scan_text
72
- end
73
-
74
- if !@sections.empty?
75
- # We have parsed the whole file, but there's still opened sections.
76
- type, pos, result = @sections.pop
77
- error "Unclosed section #{type.inspect}", pos
78
- end
79
-
80
- @result
81
- end
82
-
83
- # Find {{mustaches}} and add them to the @result array.
84
- def scan_tags
85
- # Scan until we hit an opening delimiter.
86
- return unless @scanner.scan(regexp(otag))
87
-
88
- # Since {{= rewrites ctag, we store the ctag which should be used
89
- # when parsing this specific tag.
90
- current_ctag = self.ctag
91
- type = @scanner.scan(/#|\^|\/|=|!|<|>|&|\{/)
92
- @scanner.skip(/\s*/)
93
-
94
- # ANY_CONTENT tags allow any character inside of them, while
95
- # other tags (such as variables) are more strict.
96
- if ANY_CONTENT.include?(type)
97
- r = /\s*#{regexp(type)}?#{regexp(current_ctag)}/
98
- content = scan_until_exclusive(r)
99
- else
100
- content = @scanner.scan(ALLOWED_CONTENT)
101
- end
102
-
103
- # We found {{ but we can't figure out what's going on inside.
104
- # This applies to all tags except handlebar's shortened {{^}}
105
- if type != '^'
106
- error "Illegal content in tag" if content.empty?
107
- end
108
-
109
- def find_context
110
- # A space after the helper indicates a context 'switch'
111
- if @scanner.peek(1) == ' '
112
- @scanner.skip(/ /)
113
- @scanner.scan(ALLOWED_CONTENT)
114
- else
115
- nil
116
- end
117
- end
118
-
119
- # Based on the sigil, do what needs to be done.
120
- case type
121
- when '#'
122
- block = [:multi]
123
- @result << [:mustache, :section, content, find_context(), block]
124
- @sections << [content, position, @result]
125
- @result = block
126
- when '^'
127
- if content.empty?
128
- # We are dealing with handlebar's shortened {{^}}
129
-
130
- # Close the section
131
- section, pos, result = @sections.pop
132
- @result = result
133
- if section.nil?
134
- error "Inverting unopened section"
135
- end
136
-
137
- # Open a new inverted section with the same name
138
- block = [:multi]
139
- @result << [:mustache, :inverted_section, section, block]
140
- @sections << [section, position, @result]
141
- @result = block
142
- else
143
- block = [:multi]
144
- @result << [:mustache, :inverted_section, content, block]
145
- @sections << [content, position, @result]
146
- @result = block
147
- end
148
- when '/'
149
- section, pos, result = @sections.pop
150
- @result = result
151
-
152
- if section.nil?
153
- error "Closing unopened #{content.inspect}"
154
- elsif section != content
155
- error "Unclosed section #{section.inspect}", pos
156
- end
157
- when '!'
158
- # ignore comments
159
- when '='
160
- self.otag, self.ctag = content.split(' ', 2)
161
- when '>', '<'
162
- @result << [:mustache, :partial, content]
163
- when '{', '&'
164
- # The closing } in unescaped tags is just a hack for
165
- # aesthetics.
166
- type = "}" if type == "{"
167
- @result << [:mustache, :utag, content]
168
- else
169
- @result << [:mustache, :etag, content, find_context()]
170
- end
171
-
172
- # Skip whitespace and any balancing sigils after the content
173
- # inside this tag.
174
- @scanner.skip(/\s+/)
175
- @scanner.skip(regexp(type)) if type
176
-
177
- # Try to find the closing tag.
178
- unless close = @scanner.scan(regexp(current_ctag))
179
- error "Unclosed tag"
180
- end
181
-
182
- # Skip whitespace following this tag if we need to.
183
- @scanner.skip(/\s+/) if SKIP_WHITESPACE.include?(type)
184
- end
185
-
186
- # Try to find static text, e.g. raw HTML with no {{mustaches}}.
187
- def scan_text
188
- text = scan_until_exclusive(regexp(otag))
189
-
190
- if text.nil?
191
- # Couldn't find any otag, which means the rest is just static text.
192
- text = @scanner.rest
193
- # Mark as done.
194
- @scanner.clear
195
- end
196
-
197
- text.force_encoding(@encoding) if @encoding
198
-
199
- @result << [:static, text]
200
- end
201
-
202
- # Scans the string until the pattern is matched. Returns the substring
203
- # *excluding* the end of the match, advancing the scan pointer to that
204
- # location. If there is no match, nil is returned.
205
- def scan_until_exclusive(regexp)
206
- pos = @scanner.pos
207
- if @scanner.scan_until(regexp)
208
- @scanner.pos -= @scanner.matched.size
209
- @scanner.pre_match[pos..-1]
210
- end
211
- end
212
-
213
- # Returns [lineno, column, line]
214
- def position
215
- # The rest of the current line
216
- rest = @scanner.check_until(/\n|\Z/).to_s.chomp
217
-
218
- # What we have parsed so far
219
- parsed = @scanner.string[0...@scanner.pos]
220
-
221
- lines = parsed.split("\n")
222
-
223
- [ lines.size, lines.last.size - 1, lines.last + rest ]
224
- end
225
-
226
- # Used to quickly convert a string into a regular expression
227
- # usable by the string scanner.
228
- def regexp(thing)
229
- /#{Regexp.escape(thing)}/
230
- end
231
-
232
- # Raises a SyntaxError. The message should be the name of the
233
- # error - other details such as line number and position are
234
- # handled for you.
235
- def error(message, pos = position)
236
- raise SyntaxError.new(message, pos)
237
- end
238
- end
239
- end
240
-